View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001723 | Far Manager | Keyboard | public | 2011-03-01 15:32 | 2013-02-28 08:04 |
Reporter | sezal | Assigned To | vskirdin | ||
Priority | normal | Severity | minor | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Platform | Linux | OS | Ubuntu | OS Version | 10.10 |
Product Version | 2.0 | ||||
Summary | 0001723: загрузка CPU в режиме простоя | ||||
Description | под линукс/Wine Far прекрасно работает, но в режиме простоя загружает на 30% процессор. Судя по всему причиной является основной цикл keyboard.cpp::GetInputRecord, который *каждую* милисекунду вызывает PluginSynchroManager.Process() и несколько других второстепенных проверок. Я не специалист в области разработки таких приложений, но прощу обратить внимание на этот тикет, т.к. это проблема не только linux-пользователей - под windows она просто менее заметна, но имеет место. Мое субъективное видение оптимизации основного цикла: 1. увеличение зарержки хотя бы до 10мс (keyboard.cpp:827) 2. если п.1 не возможен по каким-то причинам, то целесообразно оставить в основном цикле только Console.PeekInput + самые-самы важные проверки. 3. PluginSynchroManager.Process() не вызывать так часто, т.к. он судя по всему использует ресурсоемкие вещи - мютексы. Перенести его в уже имеющийся блок if (!(LoopCount & 15)) { } 4. второстепенные вещи как IsZoomed, IsFullscreen, Events.EnvironmentChangeEvent.Signaled и т.п. вызывать не чаще чем раз в 100мс. Вкладываю логи всех вызовов в отладочном режиме wine в режиме простоя: far_wine_debug.txt - 3 основных цикла - закономерность налицо. far_wine_full_debug.txt - один основной цикл, но с максимальной детализацией. | ||||
Tags | No tags attached. | ||||
Build | 2354 | ||||
|
far_wine_debug.txt (1,871 bytes)
user32.IsZoomed(0001004e) ret=00488846 KERNEL32.GetConsoleDisplayMode(0034ec98) ret=0040c14d KERNEL32.WaitForSingleObject(0000006c,00000000) ret=004f6402 KERNEL32.WaitForSingleObject(00000068,00000000) ret=004888ae KERNEL32.GetStdHandle(fffffff6) ret=0040c535 KERNEL32.PeekConsoleInputW(0000002b,006202cc,00000001,0034ece4) ret=0040c548 KERNEL32.Sleep(00000001) ret=00488935 KERNEL32.GetStdHandle(fffffff6) ret=0040bd88 KERNEL32.GetConsoleMode(0000002b,0034eca0) ret=0040c011 KERNEL32.WaitForSingleObject(00000050,ffffffff) ret=004da03a KERNEL32.ReleaseMutex(00000050) ret=004da074 KERNEL32.GetConsoleWindow() ret=0048883f user32.IsZoomed(0001004e) ret=00488846 KERNEL32.GetConsoleDisplayMode(0034ec98) ret=0040c14d KERNEL32.WaitForSingleObject(0000006c,00000000) ret=004f6402 KERNEL32.WaitForSingleObject(00000068,00000000) ret=004888ae KERNEL32.GetStdHandle(fffffff6) ret=0040c535 KERNEL32.PeekConsoleInputW(0000002b,006202cc,00000001,0034ece4) ret=0040c548 KERNEL32.Sleep(00000001) ret=00488935 KERNEL32.GetStdHandle(fffffff6) ret=0040bd88 KERNEL32.GetConsoleMode(0000002b,0034eca0) ret=0040c011 KERNEL32.WaitForSingleObject(00000050,ffffffff) ret=004da03a KERNEL32.ReleaseMutex(00000050) ret=004da074 KERNEL32.GetConsoleWindow() ret=0048883f user32.IsZoomed(0001004e) ret=00488846 KERNEL32.GetConsoleDisplayMode(0034ec98) ret=0040c14d KERNEL32.WaitForSingleObject(0000006c,00000000) ret=004f6402 KERNEL32.WaitForSingleObject(00000068,00000000) ret=004888ae KERNEL32.GetStdHandle(fffffff6) ret=0040c535 KERNEL32.PeekConsoleInputW(0000002b,006202cc,00000001,0034ece4) ret=0040c548 KERNEL32.Sleep(00000001) ret=00488935 KERNEL32.GetStdHandle(fffffff6) ret=0040bd88 KERNEL32.GetConsoleMode(0000002b,0034eca0) ret=0040c011 KERNEL32.WaitForSingleObject(00000050,ffffffff) ret=004da03a KERNEL32.ReleaseMutex(00000050) ret=004da074 KERNEL32.GetConsoleWindow() ret=0048883f |
|
far_wine_full_debug.txt (2,818 bytes)
Call user32.IsZoomed(0001004e) ret=00488846 set_window_info( flags=0000, is_unicode=0, handle=0001004e, style=00000000, ex_style=00000000, id=00000000, instance=00000000, user_data=00000000, extra_offset=-1, extra_size=0, extra_value=00000000 ) set_window_info() = 0 { old_style=34ce0000, old_ex_style=00000100, old_instance=68340000, old_user_data=00000000, old_extra_value=00000000, old_id=00000000 } Ret user32.IsZoomed() retval=00000000 ret=00488846 Call KERNEL32.GetConsoleDisplayMode(0034ec98) ret=0040c14d trace:console:GetConsoleDisplayMode semi-stub: 0x34ec98 Ret KERNEL32.GetConsoleDisplayMode() retval=00000001 ret=0040c14d Call KERNEL32.WaitForSingleObject(0000006c,00000000) ret=004f6402 select( flags=4, cookie=0034e998, signal=0000, prev_apc=0000, timeout=0, result={}, handles={006c} ) select() = TIMEOUT { timeout=1cbd2cc96d0135a (+0.0000000), call={APC_NONE}, apc_handle=0000 } Ret KERNEL32.WaitForSingleObject() retval=00000102 ret=004f6402 Call KERNEL32.WaitForSingleObject(00000068,00000000) ret=004888ae select( flags=4, cookie=0034e9a8, signal=0000, prev_apc=0000, timeout=0, result={}, handles={0068} ) select() = TIMEOUT { timeout=1cbd2cc96d0154e (+0.0000000), call={APC_NONE}, apc_handle=0000 } Ret KERNEL32.WaitForSingleObject() retval=00000102 ret=004888ae Call KERNEL32.GetStdHandle(fffffff6) ret=0040c535 Ret KERNEL32.GetStdHandle() retval=0000002b ret=0040c535 Call KERNEL32.PeekConsoleInputW(0000002b,006202cc,00000001,0034ece4) ret=0040c548 read_console_input( handle=0028, flush=0 ) read_console_input() = 0 { read=0, rec={} } Ret KERNEL32.PeekConsoleInputW() retval=00000001 ret=0040c548 Call KERNEL32.Sleep(00000001) ret=00488935 Ret KERNEL32.Sleep() retval=00000000 ret=00488935 Call KERNEL32.GetStdHandle(fffffff6) ret=0040bd88 Ret KERNEL32.GetStdHandle() retval=0000002b ret=0040bd88 Call KERNEL32.GetConsoleMode(0000002b,0034eca0) ret=0040c011 get_console_mode( handle=0028 ) get_console_mode() = 0 { mode=152 } Ret KERNEL32.GetConsoleMode() retval=00000001 ret=0040c011 Call KERNEL32.WaitForSingleObject(00000050,ffffffff) ret=004da03a select( flags=4, cookie=0034e988, signal=0000, prev_apc=0000, timeout=infinite, result={}, handles={0050} ) select() = 0 { timeout=infinite, call={APC_NONE}, apc_handle=0000 } Ret KERNEL32.WaitForSingleObject() retval=00000000 ret=004da03a Call KERNEL32.ReleaseMutex(00000050) ret=004da074 release_mutex( handle=0050 ) release_mutex() = 0 { prev_count=00000001 } Ret KERNEL32.ReleaseMutex() retval=00000001 ret=004da074 Call KERNEL32.GetConsoleWindow() ret=0048883f get_console_input_info( handle=0000 ) get_console_input_info() = 0 { history_mode=0, history_size=50, history_index=0, edition_mode=0, input_cp=0, output_cp=0, win=0001004e, title=L"" } Ret KERNEL32.GetConsoleWindow() retval=0001004e ret=0048883f |
|
keyboard.diff (2,200 bytes)
Index: keyboard.cpp =================================================================== --- keyboard.cpp (revision 5783) +++ keyboard.cpp (working copy) @@ -736,27 +736,33 @@ for (;;) { - // "�����" �� ����������/�������������� ���� ������� - if (ZoomedState!=IsZoomed(Console.GetWindow()) && IconicState==IsIconic(Console.GetWindow())) - { - ZoomedState=!ZoomedState; - ChangeVideoMode(ZoomedState); - } + if (!(LoopCount & 15 )) + { + // "�����" �� ����������/�������������� ���� ������� + if (ZoomedState!=IsZoomed(Console.GetWindow()) && IconicState==IsIconic(Console.GetWindow())) + { + ZoomedState=!ZoomedState; + ChangeVideoMode(ZoomedState); + } - bool CurrentFullscreenState=IsFullscreen(); - if(CurrentFullscreenState && !FullscreenState) - { - ChangeVideoMode(25,80); - } - FullscreenState=CurrentFullscreenState; + bool CurrentFullscreenState=IsFullscreen(); + if(CurrentFullscreenState && !FullscreenState) + { + ChangeVideoMode(25,80); + } + FullscreenState=CurrentFullscreenState; + + } + if (!(LoopCount & 127 )) + { + Window.Check(); - Window.Check(); - - if(Events.EnvironmentChangeEvent.Signaled()) - { - ReloadEnvironment(); - } - + if(Events.EnvironmentChangeEvent.Signaled()) + { + ReloadEnvironment(); + } + } + Console.PeekInput(*rec, 1, ReadCount); /* $ 26.04.2001 VVM @@ -824,7 +830,7 @@ } ScrBuf.Flush(); - Sleep(1); + Sleep(10); // �������� ������� ������� ����������� �� if (Opt.Mouse) // � ����� �� ��� �������??? @@ -916,12 +922,12 @@ rec->EventType=KEY_EVENT; return(KEY_IDLE); } - } - if (PluginSynchroManager.Process()) - { - memset(rec,0,sizeof(*rec)); - return KEY_NONE; + if (PluginSynchroManager.Process()) + { + memset(rec,0,sizeof(*rec)); + return KEY_NONE; + } } LoopCount++; |
|
вложил патч. Загрузка упала до 0-1% |
|
предлагаю следующее. после устаканивая Far 3.x я этот патч применю "на покататься" - а там видно будет. сейчас пока сложно что-то сказать... |
|
> Мое субъективное видение оптимизации основного цикла: Моё не менее субъективное видение оптимизации основного цикла: 1. Оптимизировать wine::IsZoomed(); 2. Оптимизировать wine::GetConsoleDisplayMode(); 3. Оптимизировать wine::WaitForSingleObject(); 4. Оптимизировать wine::GetStdHandle(); 5. Оптимизировать wine::ReleaseMutex(); 6. Оптимизировать wine::GetConsoleWindow(). |
|
куда лучше сослаться на кривой wine и в основном цикле напрягать процессор с задержкой 1мс вызывая кучу ненужных проверок. Я специализируюсь в другой области, но мне хватило 10 минут, чтобы понять, что основной цикл фар далеко не оптимален, а wine просто проявил это. Для своих нужд я уже собрал фар, поделился своими мыслями, патчем. Ваше дело оптимизировать его или нет. |
|
> куда лучше сослаться на кривой wine и в основном цикле напрягать процессор с задержкой 1мс вызывая кучу ненужных проверок Я вот ни в одном windows загрузки процессора не наблюдаю. Следовательно, вызываемые функции в wine реализованы хуже, чем в windows. Поэтому да, wine именно кривой. > Для своих нужд я уже собрал фар, поделился своими мыслями, патчем. Рад за вас, честно. Но вы не первый и не последний, желающий "улучшить" работу программ в wine правкой этих программ. А если бы вы поделитесь патчем с разработчиками wine - как ни странно, стало бы лучше сразу всем - и пользователям новых версий far, и пользователям старых версий far (которые уже никто править не будет), и пользователям стапицот других программ, выполняющих подобные элементарные проверки в основном цикле. |
|
Обнаружил загрузку CPU 30-40% Host OS: Debian GNU/Linux, Oracle VirtualBox 4.1.0 Guest OS: Windows XP SP3 Far20b1807.x86.20110203.msi при работе одновременно с Embarcadero Delphi XE 15.0 процессор загружен на 30-40%, причём вся загрузка числится за Far (не важно с плагинами или без). Выгрузка Delphi XE или Far - освобождает процессор. Только при наличии XE - Far ест процессор. Возможно MS реализация WaitForSingleObject(); ReleaseMutex(); вызывает инструкции с lock префиксом, которые внутри Virtualbox обрабатываются неоптимально. Физический процессор без аппаратной виртуализации (Pentium D 915) См. картинку: Основной поток Far проводит всё время в ядре вызывая огромное количество переключений контекстов. |
|
|
|
В VMWare загрузка еще выше! Пожалуйста, исправьте эту ошибку! Пользоваться Far в виртуальной операционной системе фактически невозможно. Можно ли где-то переписать пропатченную версию Far? |
|
пробуйте -- http://mini-gnu.googlecode.com/files/Far3-Mantis1723-32.7z |
|
В VirtualBox 4.1.8 проблема сократилась до 0.8-6% CPU Вроде бы они там свой Guru Meditation переписали (сократили накладные расходы на системные вызовы) Попробовал скачанный файл http://mini-gnu.googlecode.com/files/Far3-Mantis1723-32.7z - загрузка ещё меньше (периодически пробуждается 0.9-2%) |
|
"на покататься" -- 2353 |
|
3.0 build 2354 x86 - OK 0.8% CPU периодически Context Switch delta - 50 ... 200 |
|
закрываем Инц? |
|
imho - можно. хотя частично оптимизацию пришлось откатить из-за 0002045. но сами виртуальные машины со времени заведения инца ведут себя гораздо лучше. |
Date Modified | Username | Field | Change |
---|---|---|---|
2011-03-01 15:32 | sezal | New Issue | |
2011-03-01 15:32 | sezal | File Added: far_wine_debug.txt | |
2011-03-01 15:33 | sezal | File Added: far_wine_full_debug.txt | |
2011-03-08 12:19 | sezal | File Added: keyboard.diff | |
2011-03-08 12:21 | sezal | Note Added: 0006490 | |
2011-03-09 09:13 | vskirdin | Assigned To | => vskirdin |
2011-03-09 09:13 | vskirdin | Status | new => assigned |
2011-03-09 09:14 | vskirdin | Note Added: 0006502 | |
2011-03-09 09:52 | DrKnS | Note Added: 0006503 | |
2011-03-09 10:10 | sezal | Note Added: 0006504 | |
2011-03-09 10:25 | DrKnS | Note Added: 0006507 | |
2011-08-24 16:02 | antonk | Note Added: 0007516 | |
2011-08-24 16:04 | antonk | Note Edited: 0007516 | |
2011-08-24 16:14 | antonk | File Added: Screenshot-9.png | |
2011-08-24 16:20 | antonk | Note Edited: 0007516 | |
2011-12-01 05:03 | 2useven10 | Relationship added | related to 0001927 |
2011-12-01 07:59 | altaveron | Note Added: 0008016 | |
2011-12-01 10:16 | 2useven10 | Note Added: 0008017 | |
2012-01-05 15:42 | antonk | Note Added: 0008317 | |
2012-01-05 15:47 | antonk | Note Edited: 0008317 | |
2012-01-05 15:49 | antonk | Note Edited: 0008317 | |
2012-01-09 14:26 | 2useven10 | Note Added: 0008329 | |
2012-01-10 13:27 | antonk | Note Added: 0008348 | |
2012-03-09 07:21 | 2useven10 | Relationship added | related to 0002045 |
2012-04-27 12:56 | vskirdin | Note Added: 0009070 | |
2012-04-27 13:28 | 2useven10 | Note Added: 0009072 | |
2013-02-28 08:04 | vskirdin | Build | => 2354 |
2013-02-28 08:04 | vskirdin | Status | assigned => closed |
2013-02-28 08:04 | vskirdin | Resolution | open => fixed |