1

Тема: Оптимізація програми

Я зацікавився циклом обробки повідомлень.
Зазвичай, середовище розробки генерує такий код:

        MSG msg;
         /*
        This is the heart of our program where all input is processed and 
        sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
        this loop will not produce unreasonably high CPU usage
    */
    while(GetMessage(&msg, NULL, 0, 0) > 0) { /* If no error is received... */
        TranslateMessage(&msg); /* Translate key codes to chars if present */
        DispatchMessage(&msg); /* Send it to WndProc */
    }
    return msg.wParam;

Я подумав, що саме з нього потрібно починати оптимізацію програми.
На сайті Майкрософт я продивився функції GetMessage() і PeekMessage().
https://docs.microsoft.com/en-us/window … getmessage
https://docs.microsoft.com/ru-ru/window … age-queues
Код з Майкрософт дуже відрізняється від згенерованого:

BOOL bRet;
HWND hWnd;
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }
}

А ось PeekMessage():

HWND hwnd; 
BOOL fDone; 
MSG msg; 
 
// Begin the operation and continue until it is complete 
// or until the user clicks the mouse or presses a key. 
 
fDone = FALSE; 
while (!fDone) 
{ 
    fDone = DoLengthyOperation(); // application-defined function 
 
    // Remove any messages that may be in the queue. If the 
    // queue contains any mouse or keyboard 
    // messages, end the operation. 
 
    while (PeekMessage(&msg, hwnd,  0, 0, PM_REMOVE)) 
    { 
        switch(msg.message) 
        { 
            case WM_LBUTTONDOWN: 
            case WM_RBUTTONDOWN: 
            case WM_KEYDOWN: 
                // 
                // Perform any required cleanup. 
                // 
                fDone = TRUE; 
        } 
    } 
} 

Мене також зацікавило, як тип BOOL (windows bool) може мати значення "-1".
Слідуюче, що я знайшов - це прискорювач.

HWND hwndMain; 
HWND hwndDlgModeless = NULL; 
MSG msg;
BOOL bRet; 
HACCEL haccel; 
// 
// Perform initialization and create a main window. 
// 
 
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        if (hwndDlgModeless == (HWND) NULL || 
                !IsDialogMessage(hwndDlgModeless, &msg) && 
                !TranslateAccelerator(hwndMain, haccel, 
                    &msg)) 
        { 
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        }
    } 
} 

А потім я цілий день шукав, як його завантажити:
https://docs.microsoft.com/ru-ru/window … celerators
І в мене залишилося багато запитань, які я хочу задати тут:
1. Для чого потрібні проскорювачі?
2. Чи можна оброблювати повідомлення не в LPRESULT CALLBACK WndProc, а прямо в головній функції?
3. Головне. Як так змінити процес обробки, щоб програма працювала швидше?
Потрібно прискорити роботу програми, щоб вона не завантажувала процесор в режимі роботи та простоювання.

Подякували: leofun011

2

Re: Оптимізація програми

cppj написав:

як тип BOOL (windows bool) може мати значення "-1".

BOOL визначений у windows.h (точніше, у windef.h) як int:

typedef int WINBOOL,*PWINBOOL,*LPWINBOOL;
typedef WINBOOL BOOL;

І в описі GetMessage є спеціальне зауваження щодо його значення.

cppj написав:

1. Для чого потрібні прискорювачі?

Для заміни повідомлень клавіатури на користувацькі, описані в меню. Тобто замість, скажімо, Ctrl+K ви отримаєте після TranslateAccelerator IDM_MY_MENU_ITEM, якщо його опишете. І вам не треба сушити голову, як два-три рази робити одне й те саме в різних місцях програми, стежити, щоб всі case-и були коректні і т.д.  Просто обробляєте свої події.

cppj написав:

2. Чи можна оброблювати повідомлення не в LPRESULT CALLBACK WndProc, а прямо в головній функції?

Загалом ви можете обробляти повідомлення прямо в циклі замість DispatchMessage. Але тоді ви втрачаєте системну обробку решти вікон вашої програми. Якщо це вас влаштовує - будь ласка.

cppj написав:

3. Головне. Як так змінити процес обробки, щоб програма працювала швидше?

Залежить від того, що робить ваша програма. Цей цикл не може сам по собі навантажувати систему, GetMessage зупиняє виконання при пустій черзі подій. Якщо у вас постійно створюються події, які змушують цей цикл навантажувати систему, то проблема не в цьому коді, а в тому, що ці події створює.
Ну і є загальне правило: не оптимізуйте код без потреби. Він у вас створює суттєве навантаження на процесор? Можна поцікавитися, як ви це визначили та наскільки суттєве навантаження? Якщо ви не певні, що проблема саме в цьому коді, просто вам він видається підозрілим - то так і пишіть; швидше за все, ви помиляєтеся. Конкретно цей фрагмент використовують практично всі віконні програми, якби він гальмував, то ви б не змогли відкрити на комп'ютері більше 2-3 вікон одночасно.

Подякували: leofun01, cppj2

3

Re: Оптимізація програми

Ну і взагалі: вашу IDE, включно із типовими шматками коду, розробляли програмісти явно вищого за нас двох рівня. Вони вирішили, що цей код має виглядати саме так. Так, можливо, що ваш випадок - нетиповий, і вам треба змінювати саме цей шматок коду; але спершу я б переконався, що проблеми виникли саме там, а не у вас.
Що ж до оптимізацій, послідовність має бути така:
1. Напишіть код. Переконайтеся, що він робочий. Оптимізувати неробочий код (в т.ч. ненаписаний) не має сенсу.
2. Переконайтеся, що код легко читається. Оптимізація коду зі змінними на кшталт TextEdit13 - ще те задоволення.
3. Знайдіть вузькі місця. Оптимізація по швидкості в 10 разів коду, що витрачає 100 мс 1 раз при запуску - це гірше, ніж оптимізація на 10% коду, що витрачає 100 нс по 100000 разів на секунду.
4. Перевірте, що у вузьких місцях виконується оптимальний для цього місця алгоритм. В принципі, алгоритм варто обирати на початку, але під час програмування можуть статися певні зміни.
5. І тільки коли ви дійдете до цього місця, можете починати переглядати загальноприйняті речі. При цьому бажано знати асемблер і порівнювати згенерований в різних випадках код.
Ну то що у вас із п.1?

4

Re: Оптимізація програми

Я говорю про будь-які програми.
Мені просто цікаво, чи можна якось спростити цей цикл обробки повідовлень?
Щоб програма прямо літала.

5 Востаннє редагувалося koala (10.03.2019 18:11:23)

Re: Оптимізація програми

Звісно, можна. Не робіть віконного інтерфейсу, а пишіть ПЗ для літаків - програми прямо літатимуть.
Ні, ну серйозно - що значить "прямо літала"? Ви серйозно думаєте, що ваш гівнокод гальмує через системні функції, а не через вашу власну криворукість?

Подякували: ExPy1

6

Re: Оптимізація програми

Ви б мене не принижували. А то, бачу Ви не думаєте, що буде потім.
У мене ще не має ніякого коду. Про який гівнокод можна говорити? І про яку криворукість?
Я задав питання - значить мав отримати відповідь.
Спершу я отримав відповідь, а далі - приниження.
Я не говорю про свій код. Я просто помітив, що деякі програми, написані на мові асемблер, працюють швидше, ніж на C++. І займають менше місця (пуста програма на C++ 40kb, на asm 1540b). Я подумав, може можна на C++ оптимізувати точно так само програму.

7

Re: Оптимізація програми

cppj написав:

деякі програми, написані на мові асемблер, працюють швидше, ніж на C++. І займають менше місця (пуста програма на C++ 40kb, на asm 1540b).

Швидкість виконання і розмір програми залежить від компілятора і його налаштувань, а не від мови програмування.

cppj написав:

Я подумав, може можна на C++ оптимізувати точно так само програму.

Можна.
Налаштуйте компілятор для генерації виконуваного файлу як "Release" (~6.5 KB) а не як "Debug" (~30 KB). Додайте параметри оптимізації ( /O1 | /O2 | /Ox ). І не вносьте додаткової інформації про програму (debug info, manifest).
На виході отримаєте програму, яка займає менше ніж 4 KB.
Якщо для вас 4 KB - забагато, тоді пошукайте собі інший компілятор.

Подякували: cppj, koala2

8

Re: Оптимізація програми

Ні, 4кб не забагато, дякую!
Проте, після слів koala настрій зіпсувався. Не розумію, для чого розводити конфлікт на рівному місці?

9

Re: Оптимізація програми

Пане, гівнокод пишуть усі програмісти. Профі просто пишуть його рідше і менше, а новачки - більше. А те, що ви хочете "оптимізувати" код, який ви ще не написали, свідчить про те, що ви новачок. Крім того, це свідчить про те, що ви не прочитали моєї відповіді, що не дуже чемно.
Ну і так, деякі програми на асемблері працюють швидше. Залежить від того, хто і як їх пише. І, до речі, "менше" - не синонім "швидше"; наприклад, функції без inline зменшують розмір, а з inline збільшують швидкість.

Про поради пана leofun01 - там все правильно, але ви маєте розуміти, чому так. Debug-версія призначена для пошуку помилок, Release - це кінцевий результат. Мається на увазі, що ви будете програмувати і перевіряти в режимі Debug, а перед випуском готової програми скомпілювати все в Release.

Подякували: leofun011

10

Re: Оптимізація програми

У мене Release.

11

Re: Оптимізація програми

cppj написав:

... пуста програма на C++ ...

Computerphile