← Back to team overview

kicad-developers team mailing list archive

Re: Windows performance issue

 



Le 08/08/2018 à 14:11, Jeff Young a écrit :
OK, accidental commit reverted, and attached is an updated patch.  (This time not done with diff rather than format-patch so I don’t accidentally commit it again.)



Hi Jeff,

Attached a modified patch that fixes 2  compil issues

jp charras


 common/common.cpp | 101 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 76 insertions(+), 25 deletions(-)

diff --git a/common/common.cpp b/common/common.cpp
index 407d0c465..2d5caa50e 100644
--- a/common/common.cpp
+++ b/common/common.cpp
@@ -533,11 +533,21 @@ bool std::less<wxPoint>::operator()( const wxPoint& aA, const wxPoint& aB ) cons
 #endif
 
 
-//
-// A wrapper around a wxFileName which avoids expensive calls to wxFileName::SplitPath()
-// and string concatenations by caching the path and filename locally and only resolving
-// the wxFileName when it has to.
-//
+/**
+ * Performance enhancements to file and directory operations.
+ *
+ * Note: while it's annoying to have to make copies of wxWidgets stuff and then
+ * add platform-specific performance optimizations, the following routies offer
+ * SIGNIFICANT performance benefits.
+ */
+
+/**
+ * WX_FILENAME
+ *
+ * A wrapper around a wxFileName which avoids expensive calls to wxFileName::SplitPath()
+ * and string concatenations by caching the path and filename locally and only resolving
+ * the wxFileName when it has to.
+ */
 WX_FILENAME::WX_FILENAME( const wxString& aPath, const wxString& aFilename ) :
         m_fn( aPath, aFilename ),
         m_path( aPath ),
@@ -596,10 +606,12 @@ long long WX_FILENAME::GetTimestamp()
 }
 
 
-//
-// A copy of wxMatchWild (attributed to <dalewis@xxxxxxxxxxxxxx>) modified to use
-// POSIX-file-system-encoded inputs.
-//
+/**
+ * A copy of wxMatchWild(), which wxWidgets attributes to Douglas A. Lewis
+ * <dalewis@xxxxxxxxxxxxxx> and ircII's reg.c.
+ *
+ * This version is modified to skip any encoding conversions (for performance).
+ */
 bool matchWild( const char* pat, const char* text, bool dot_special )
 {
     if ( !*text )
@@ -703,32 +715,71 @@ bool matchWild( const char* pat, const char* text, bool dot_special )
 }
 
 
+/**
+ * A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function
+ * private to src/common/filename.cpp.
+ */
+#if wxUSE_DATETIME && defined(__WIN32__) && !defined(__WXMICROWIN__)
+
+// Convert between wxDateTime and FILETIME which is a 64-bit value representing
+// the number of 100-nanosecond intervals since January 1, 1601 UTC.
+//
+// This is the offset between FILETIME epoch and the Unix/wxDateTime Epoch.
+static wxInt64 EPOCH_OFFSET_IN_MSEC = wxLL(11644473600000);
+
+static void ConvertFileTimeToWx(wxDateTime *dt, const FILETIME &ft)
+{
+    wxLongLong t(ft.dwHighDateTime, ft.dwLowDateTime);
+    t /= 10000; // Convert hundreds of nanoseconds to milliseconds.
+    t -= EPOCH_OFFSET_IN_MSEC;
+
+    *dt = wxDateTime(t);
+}
+
+#endif // wxUSE_DATETIME && __WIN32__
+
+
+/**
+ * TimestampDir
+ *
+ * This routine offers SIGNIFICANT performance benefits over using wxWidgets to gather
+ * timestamps from matching files in a directory.
+ * @param aDirPath the directory to search
+ * @param aFilespec a (wildcarded) file spec to match against
+ * @return a hash of the last-mod-dates of all matching files in the directory
+ */
 long long TimestampDir( const wxString& aDirPath, const wxString& aFilespec )
 {
     long long timestamp = 0;
 
-#ifdef __WINDOWS__
-    // wxFileName construction is egregiously slow.  Construct it once and just swap out
-    // the filename thereafter.
-    WX_FILENAME fn( aDirPath, wxT( "dummyName" ) );
-    wxDir       dir( aDirPath );
-    wxString    fullname;
+#if defined(__WIN32__)
+    // Win32 version.
+    // Save time by not searching for each path twice: once in wxDir.GetNext() and once in
+    // wxFileName.GetModificationTime().  Also cuts out wxWidgets' string-matching and case
+    // conversion by staying on the MSW side of things.
+    std::wstring filespec( aDirPath.t_str() );
+    filespec += '\\';
+    filespec += aFilespec.t_str();
+
+    WIN32_FIND_DATA findData;
+    wxDateTime      lastModDate;
 
-    if( dir.IsOpened() )
+    HANDLE fileHandle = ::FindFirstFile( filespec.data(), &findData );
+
+    if( fileHandle != INVALID_HANDLE_VALUE )
     {
-        if( dir.GetFirst( &fullname, aFilespec ) )
+        do
         {
-            do
-            {
-                fn.SetFullName( fullname );
-                timestamp += fn.GetTimestamp();
-            }
-            while( dir.GetNext( &fullname ) );
+            ConvertFileTimeToWx( &lastModDate, findData.ftLastWriteTime );
+            timestamp += lastModDate.GetValue().GetValue();
         }
+        while ( FindNextFile( fileHandle, &findData ) != 0);
     }
+
+    FindClose( fileHandle );
 #else
-    // POSIX version.  Save time by not converting between encodings -- do everything on
-    // the file-system side.
+    // POSIX version.
+    // Save time by not converting between encodings -- do everything on the file-system side.
     std::string filespec( aFilespec.fn_str() );
     std::string dir_path( aDirPath.fn_str() );
 

Follow ups

References