View Issue Details

IDProjectCategoryView StatusLast Update
0000636Far ManagerPanelpublic2008-11-22 22:00
Reporterchupakabra Assigned Toalexy  
PrioritynormalSeveritytweakReproducibilityN/A
Status closedResolutionfixed 
Fixed in Version1.80 alpha 1 
Summary0000636: Предложение по оптимизации обработки больших списков файлов
DescriptionПредлагаю изменения по увеличению скорости обработки больших файловых списков (патч прилагается). Суть сделанных изменений:
1. В filelist.cpp::SortList() вызываем PointToName() только тогда когда это реально нужно, т.е. при сортировке по имени файла.
2. Там же используем новую функцию PointToExt() для поиска расширения файла.
3. PointToName() изменена таким образом, чтобы работать более эффективно для длинных путей.
4. В local.cpp::StrLength() вызов lstrlenW() заменен на wcslen().
5. При компиляции с помощью cl.exe используется флаг /O2 вместо /O1.

Мои результаты замеров времени отображения большого списка файлов (текущая версия; текущая версия, собранная с /O2; пропатченная версия):
сортировка по имени: 18.6 15.1 13.9
сортировка по расширению: 19.4 15.9 14.5
без сортировки: 11.3 9.6 5.9
TagsNo tags attached.
Build597

Activities

2008-11-17 19:12

 

sort.diff (5,121 bytes)   
Index: Far.mak
===================================================================
--- Far.mak	(revision 2050)
+++ Far.mak	(working copy)
@@ -238,7 +238,7 @@
 	/D "_CRT_NON_CONFORMING_SWPRINTFS"
 
 CPP_PROJ_COMMON=$(MP) $(COMPAT64) /W3 /nologo $(FAR_ALPHA_VERSION) $(FARSYSLOG) $(FARTRY) $(DEFINES) /Gy /GF /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /J /c $(FARCMEM) $(FARALLOC) /FAcs /Fa"$(CODDIR)\\"
-CPP_PROJ_RELEASE=/MT /O1
+CPP_PROJ_RELEASE=/MT /O2
 CPP_PROJ_DEBUG=/MTd /Od /Zi
 
 LINK_COMMON=$(LINK32_LIBS) /OPT:REF /OPT:ICF $(NOWIN98) /nologo /subsystem:console /def:"$(DEF_FILE)" /out:"$(OUTDIR)\Far.exe" /map:"$(OUTDIR)\far.map" $(NODEFAULTLIB) /pdb:"$(OUTDIR)\far.pdb" /release
Index: filelist.cpp
===================================================================
--- filelist.cpp	(revision 2050)
+++ filelist.cpp	(working copy)
@@ -266,17 +266,14 @@
 {
   int RetCode;
   __int64 RetCode64;
-  const wchar_t *ChPtr1,*ChPtr2;
+  const wchar_t *Ext1,*Ext2;
   struct FileListItem *SPtr1,*SPtr2;
   SPtr1=((FileListItem **)el1)[0];
   SPtr2=((FileListItem **)el2)[0];
 
-  const wchar_t *Name1=PointToName(SPtr1->strName);
-  const wchar_t *Name2=PointToName(SPtr2->strName);
-
-  if (Name1[0]==L'.' && Name1[1]==L'.' && Name1[2]==0)
+  if (SPtr1->strName[0] && SPtr1->strName[0]==L'.' && SPtr1->strName[1] && SPtr1->strName[1]==L'.' && SPtr1->strName[2]==0)
     return(-1);
-  if (Name2[0]==L'.' && Name2[1]==L'.' && Name2[2]==0)
+  if (SPtr2->strName[0] && SPtr2->strName[0]==L'.' && SPtr2->strName[1] && SPtr2->strName[1]==L'.' && SPtr2->strName[2]==0)
     return(1);
 
   if (ListSortMode==UNSORTED)
@@ -326,19 +323,15 @@
         break;
 
       case BY_EXT:
-        ChPtr1=wcsrchr(*Name1 ? Name1+1:Name1,L'.');
-        ChPtr2=wcsrchr(*Name2 ? Name2+1:Name2,L'.');
-        if (ChPtr1==NULL && ChPtr2==NULL)
+        Ext1=PointToExt(SPtr1->strName);
+        Ext2=PointToExt(SPtr2->strName);
+        if (Ext1==NULL && Ext2==NULL)
           break;
-        if (ChPtr1==NULL)
+        if (Ext1==NULL)
           return(-ListSortOrder);
-        if (ChPtr2==NULL)
+        if (Ext2==NULL)
           return(ListSortOrder);
-        if (*(ChPtr1+1)==L'.')
-          return(-ListSortOrder);
-        if (*(ChPtr2+1)==L'.')
-          return(ListSortOrder);
-        RetCode=ListSortOrder*StrCmpI(ChPtr1+1,ChPtr2+1);
+        RetCode=ListSortOrder*StrCmpI(Ext1+1,Ext2+1);
         if(RetCode)
           return RetCode;
         break;
@@ -394,6 +387,8 @@
 
   int NameCmp;
 
+  const wchar_t *Name1=PointToName(SPtr1->strName);
+  const wchar_t *Name2=PointToName(SPtr2->strName);
   if(!ListNumericSort)
     NameCmp=ListCaseSensitive?StrCmp(Name1,Name2):StrCmpI(Name1,Name2);
   else
Index: fn.hpp
===================================================================
--- fn.hpp	(revision 2050)
+++ fn.hpp	(working copy)
@@ -557,6 +557,7 @@
 
 const wchar_t* __stdcall PointToName(const wchar_t *lpwszPath);
 const wchar_t* __stdcall PointToFolderNameIfFolder(const wchar_t *lpwszPath);
+const wchar_t* PointToExt(const wchar_t *lpwszPath);
 
 BOOL  TestParentFolderName(const wchar_t *Name);
 
Index: local.cpp
===================================================================
--- local.cpp	(revision 2050)
+++ local.cpp	(working copy)
@@ -317,7 +317,7 @@
 /*---------------------------------------*/
 int __cdecl StrLength(const wchar_t *str)
 {
-	return lstrlenW(str);
+	return (int) wcslen(str);
 }
 
 
Index: strmix.cpp
===================================================================
--- strmix.cpp	(revision 2050)
+++ strmix.cpp	(working copy)
@@ -103,15 +103,15 @@
     return NULL;
 
   const wchar_t *lpwszNamePtr = lpwszPath;
+  while ( *lpwszNamePtr ) lpwszNamePtr++;
 
-  while ( *lpwszPath )
+  while (lpwszNamePtr != lpwszPath)
   {
-    if ( *lpwszPath==L'\\' || *lpwszPath==L'/' || (*lpwszPath==L':' && lpwszPath == lpwszNamePtr+1) )
-      lpwszNamePtr = lpwszPath+1;
-
-    lpwszPath++;
+    if ( *lpwszNamePtr==L'\\' || *lpwszNamePtr==L'/' || (*lpwszNamePtr==L':' && lpwszNamePtr == lpwszPath+1) )
+      return lpwszNamePtr+1;
+    lpwszNamePtr--;
   }
-  return lpwszNamePtr;
+  return lpwszPath;
 }
 
 
@@ -139,7 +139,32 @@
   return ((*NamePtr)?NamePtr:prevNamePtr);
 }
 
+const wchar_t* PointToExt(const wchar_t *lpwszPath)
+{
+  if ( !lpwszPath )
+    return NULL;
 
+  const wchar_t *lpwszEndPtr = lpwszPath;
+  while ( *lpwszEndPtr ) lpwszEndPtr++;
+  const wchar_t *lpwszExtPtr = lpwszEndPtr;
+
+  while (lpwszExtPtr != lpwszPath)
+  {
+    if ( *lpwszExtPtr==L'.' )
+    {
+      if ( *(lpwszExtPtr-1)==L'\\' || *(lpwszExtPtr-1)==L'/' || *(lpwszExtPtr-1)==L':' )
+        return lpwszEndPtr;
+      else
+        return lpwszExtPtr;
+    }
+    if ( *lpwszExtPtr==L'\\' || *lpwszExtPtr==L'/' || *lpwszExtPtr==L':' )
+      return lpwszEndPtr;
+    lpwszExtPtr--;
+  }
+  return lpwszEndPtr;
+}
+
+
 /* $ 10.05.2003 IS
    + ������� CmpName �� ��� ����� �������� skippath ������
    - �����: *Name*.* �� ������� Name
sort.diff (5,121 bytes)   

alexy

2008-11-17 19:58

administrator   bugnote:0001973

Закомитил в 583 + заодно мелкая оптимизация проверки на ".."

2008-11-19 11:16

 

sort2.patch (631 bytes)   
Index: filelist.cpp
===================================================================
--- filelist.cpp	(revision 2080)
+++ filelist.cpp	(working copy)
@@ -325,11 +325,11 @@
       case BY_EXT:
         Ext1=PointToExt(SPtr1->strName);
         Ext2=PointToExt(SPtr2->strName);
-        if (Ext1==NULL && Ext2==NULL)
+        if (*Ext1==0 && *Ext2==0)
           break;
-        if (Ext1==NULL)
+        if (*Ext1==0)
           return(-ListSortOrder);
-        if (Ext2==NULL)
+        if (*Ext2==0)
           return(ListSortOrder);
         RetCode=ListSortOrder*StrCmpI(Ext1+1,Ext2+1);
         if(RetCode)
sort2.patch (631 bytes)   

chupakabra

2008-11-19 11:17

developer   bugnote:0001986

Прикрепил исправление для ошибки, сделанной в предыдущем патче.

chupakabra

2008-11-19 12:42

developer   bugnote:0001987

Попутно заметил, что Far 1.80 и 1.71 по разному сортируют вот такой список файлов:
!test
.test

alexy

2008-11-19 12:52

administrator   bugnote:0001988

Ну 1.80 по юникоду сортирует а 1.71 по OEM. Там есть отличия.

chupakabra

2008-11-19 13:33

developer   bugnote:0001989

Поясни, каким образом юникод влияет на порядок сортировки этих двух файлов.

samlyukov

2008-11-19 14:10

reporter   bugnote:0001990

а ты посмотри в проводнике и фаре 1,71. будет тоже самое.
поэтому в ТС 4-ре метода сортировки.

samlyukov

2008-11-19 14:17

reporter   bugnote:0001991

http://bugs.farmanager.com/view.php?id=59

chupakabra

2008-11-19 14:55

developer   bugnote:0001992

А какая функция используется в 1.71 для сравнения строк при отключенной регистрозависимой сортировке?

alexy

2008-11-19 14:58

administrator   bugnote:0001993

О, это надо видеть. Так как сравнение в фаре надо делать в OEM а винда даёт тока ANSI то строится свой массив заумными методами и с помощью него происходит сортировка. Из за этого как раз сортировка только посимвольная но зато быстрая.

alexy

2008-11-19 15:01

administrator   bugnote:0001994

В 1.80 надо это будет перенести тоже из за врапера 1.7 плагинов, баги 442 и 443.

alexy

2008-11-19 15:42

administrator   bugnote:0001995

Fixed. 588.

2008-11-21 22:43

 

strmix.patch (789 bytes)   
Index: strmix.cpp
===================================================================
--- strmix.cpp	(revision 2101)
+++ strmix.cpp	(working copy)
@@ -102,16 +102,21 @@
   if ( !lpwszPath )
     return NULL;
 
+  if ( *lpwszPath!=0 && *(lpwszPath+1)==L':' ) lpwszPath+=2;
+
   const wchar_t *lpwszNamePtr = lpwszPath;
   while ( *lpwszNamePtr ) lpwszNamePtr++;
 
   while (lpwszNamePtr != lpwszPath)
   {
-    if ( *lpwszNamePtr==L'\\' || *lpwszNamePtr==L'/' || (*lpwszNamePtr==L':' && lpwszNamePtr == lpwszPath+1) )
+    if ( *lpwszNamePtr==L'\\' || *lpwszNamePtr==L'/' )
       return lpwszNamePtr+1;
     lpwszNamePtr--;
   }
-  return lpwszPath;
+  if ( *lpwszPath==L'\\' || *lpwszPath==L'/' )
+    return lpwszPath+1;
+  else
+    return lpwszPath;
 }
 
 
strmix.patch (789 bytes)   

chupakabra

2008-11-21 22:47

developer   bugnote:0002014

Изменения в PointToName():
1. Исправил поведение для путей вида "\path"
2. Проверка на ':' теперь производится не в цикле, а один раз в начале функции.

2008-11-21 23:34

 

filelist.patch (628 bytes)   
Index: filelist.cpp
===================================================================
--- filelist.cpp	(revision 2103)
+++ filelist.cpp	(working copy)
@@ -307,11 +307,10 @@
     int RetCode=CtrlObject->Plugins.Compare(hSortPlugin,&pi1,&pi2,ListSortMode+(SM_UNSORTED-UNSORTED));
     apiFreeFindData(&pi1.FindData);
     apiFreeFindData(&pi2.FindData);
-    if (RetCode==-3)
+    if (RetCode==-2)
       hSortPlugin=NULL;
     else
-      if (RetCode!=-2)
-        return(ListSortOrder*RetCode);
+      return(ListSortOrder*RetCode);
   }
 
   // �� ��������� ������ � ������ "�� ���������" (���������!)
filelist.patch (628 bytes)   

chupakabra

2008-11-21 23:37

developer   bugnote:0002015

Еще заметил, что при сортировке панели плагина Far постоянно пытается вызвать плагиновскую Compare (даже если её нет), из-за неверной проверки кода возврата. Патч прилагается.

alexy

2008-11-21 23:45

administrator   bugnote:0002016

Нифинга не понял вот это
> 1. Исправил поведение для путей вида "\path"
Оно же и так в главном while обрабатывается, нафига ещё if?

alexy

2008-11-21 23:47

administrator   bugnote:0002017

Туплю, всё ок. Надо спать видимо.

alexy

2008-11-22 10:59

administrator   bugnote:0002018

597

Issue History

Date Modified Username Field Change
2008-11-17 19:12 chupakabra New Issue
2008-11-17 19:12 chupakabra File Added: sort.diff
2008-11-17 19:25 alexy Status new => assigned
2008-11-17 19:25 alexy Assigned To => alexy
2008-11-17 19:58 alexy Note Added: 0001973
2008-11-17 19:58 alexy Status assigned => feedback
2008-11-18 12:06 chupakabra Status feedback => resolved
2008-11-18 12:06 chupakabra Resolution open => fixed
2008-11-18 12:30 alexy Build => 583
2008-11-18 12:30 alexy Status resolved => closed
2008-11-18 12:30 alexy Fixed in Version => 1.80 alpha 1
2008-11-19 11:15 chupakabra Status closed => assigned
2008-11-19 11:15 chupakabra Resolution fixed => reopened
2008-11-19 11:16 chupakabra File Added: sort2.patch
2008-11-19 11:17 chupakabra Note Added: 0001986
2008-11-19 12:42 chupakabra Note Added: 0001987
2008-11-19 12:52 alexy Note Added: 0001988
2008-11-19 13:33 chupakabra Note Added: 0001989
2008-11-19 14:10 samlyukov Note Added: 0001990
2008-11-19 14:17 samlyukov Note Added: 0001991
2008-11-19 14:55 chupakabra Note Added: 0001992
2008-11-19 14:58 alexy Note Added: 0001993
2008-11-19 15:01 alexy Note Added: 0001994
2008-11-19 15:42 alexy Note Added: 0001995
2008-11-19 15:42 alexy Status assigned => feedback
2008-11-19 16:09 chupakabra Status feedback => resolved
2008-11-19 16:09 chupakabra Resolution reopened => fixed
2008-11-19 21:08 alexy Build 583 => 588
2008-11-19 21:08 alexy Status resolved => closed
2008-11-21 22:43 chupakabra Status closed => assigned
2008-11-21 22:43 chupakabra Resolution fixed => reopened
2008-11-21 22:43 chupakabra File Added: strmix.patch
2008-11-21 22:47 chupakabra Note Added: 0002014
2008-11-21 23:34 chupakabra File Added: filelist.patch
2008-11-21 23:37 chupakabra Note Added: 0002015
2008-11-21 23:45 alexy Note Added: 0002016
2008-11-21 23:47 alexy Note Added: 0002017
2008-11-22 10:59 alexy Note Added: 0002018
2008-11-22 10:59 alexy Status assigned => feedback
2008-11-22 14:56 chupakabra Status feedback => resolved
2008-11-22 14:56 chupakabra Resolution reopened => fixed
2008-11-22 22:00 alexy Build 588 => 597
2008-11-22 22:00 alexy Status resolved => closed