View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000636 | Far Manager | Panel | public | 2008-11-17 19:12 | 2008-11-22 22:00 |
Reporter | chupakabra | Assigned To | alexy | ||
Priority | normal | Severity | tweak | Reproducibility | N/A |
Status | closed | Resolution | fixed | ||
Fixed in Version | 1.80 alpha 1 | ||||
Summary | 0000636: Предложение по оптимизации обработки больших списков файлов | ||||
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 | ||||
Tags | No tags attached. | ||||
Build | 597 | ||||
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 |
|
Закомитил в 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) |
|
Прикрепил исправление для ошибки, сделанной в предыдущем патче. |
|
Попутно заметил, что Far 1.80 и 1.71 по разному сортируют вот такой список файлов: !test .test |
|
Ну 1.80 по юникоду сортирует а 1.71 по OEM. Там есть отличия. |
|
Поясни, каким образом юникод влияет на порядок сортировки этих двух файлов. |
|
а ты посмотри в проводнике и фаре 1,71. будет тоже самое. поэтому в ТС 4-ре метода сортировки. |
|
http://bugs.farmanager.com/view.php?id=59 |
|
А какая функция используется в 1.71 для сравнения строк при отключенной регистрозависимой сортировке? |
|
О, это надо видеть. Так как сравнение в фаре надо делать в OEM а винда даёт тока ANSI то строится свой массив заумными методами и с помощью него происходит сортировка. Из за этого как раз сортировка только посимвольная но зато быстрая. |
|
В 1.80 надо это будет перенести тоже из за врапера 1.7 плагинов, баги 442 и 443. |
|
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; } |
|
Изменения в 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); } // �� ��������� ������ � ������ "�� ���������" (���������!) |
|
Еще заметил, что при сортировке панели плагина Far постоянно пытается вызвать плагиновскую Compare (даже если её нет), из-за неверной проверки кода возврата. Патч прилагается. |
|
Нифинга не понял вот это > 1. Исправил поведение для путей вида "\path" Оно же и так в главном while обрабатывается, нафига ещё if? |
|
Туплю, всё ок. Надо спать видимо. |
|
597 |
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 |