Сообщение Re[5]: Разработка на чистом C от 31.10.2016 15:04
Изменено 31.10.2016 15:07 Pavel Dvorkin
Здравствуйте, push, Вы писали:
P>Вы либо пытаетесь ввести в заблуждение, либо не до конца понимаете оптимизацию в с++. Тут даже без компиляции очевидно, что код с ErrorCodeFunction вырезается (и это абсолютно никак не связано с кодами возврата). В реальной функции ничего не вырезается.
Вырезается только в Release, о чем я ясно написал. Цитирую себя
PD>Компилировать в Debug. Для Release Error code time будет просто 0, так как компилятор выкинет весь этот код с вызовом функции. Выкинуть код с исключением он не может.
Поэтому я и проводил сравнения в Debug, где ничго не вырезается. Для чистоты эксперимента.
Вот disassembly кода в Debug
P>В случае кодов возврата вам требуется проверять код каждый раз и для каждой функции, и вне зависимости от успеха/неудачи.
Верно. Но это всего лишь одна-две команды, что по сравнению с набором команд самой функции не очень большой оверхед, если функция мало-мальски сложная. Стоит функцию чуть-чуть изменить — и мы получим на десяток или сотню команд больше или меньше. Я уж не говорю, что будет, если в функции есть хотя бы линейный цикл — в этом случае это время сравнения есть просто O(1) на фоне O(N).
Есть и еще один момент. Коды возврата можно и не анализировать, если в данной ситуации он несущественен. Например, булевская функция delete может возвращать true, если удалили и false — если нет того, что нужно удалить. Но если мне все равно (а мне может быть все равно, так как мне надо, чтобы удаляемого там больше не было, и мне не важно, нет его теперь там потому, что удалили или потому, что и не было до попытки удалить), то я могу и игнорировать код возврата. Исключение не проигнорируешь.
P>Учитывая, что количество неудач по сравнению с количеством успешного выполнения функций ничтожно мало — то и накладные расходы на исключения фактически можно считать равными нулю. И нулю не только по сравнению с кодами возврата, а вообще в принципе. Потому что, при успехе накладных расходов почти нет, а при неудаче важность потребления процессорного времени по сравнению с важностью обработки ошибки стремиться к нулю.
А вот с этим могу согласиться. Действительно, пример мой довольно искусственный — так реально не бывает. Но я лишь хотел показать, что выброс исключения сравнительно недешевая вещь. Если оно и впрямь происходит очень-очень редко, то оверхедом на него можно пренебречь. Впрочем, это верно для чего угодно при условии, что это что угодно происходит очень-очень редко (и, конечно, само не занимает много времени). Если же не очень редко — тут все будет иначе.
Я не противник исключений, отнюдь нет. Я просто хотел напомнить, что это довольно затратный механихзм и об этом надо помнить.
P>Вы либо пытаетесь ввести в заблуждение, либо не до конца понимаете оптимизацию в с++. Тут даже без компиляции очевидно, что код с ErrorCodeFunction вырезается (и это абсолютно никак не связано с кодами возврата). В реальной функции ничего не вырезается.
Вырезается только в Release, о чем я ясно написал. Цитирую себя
PD>Компилировать в Debug. Для Release Error code time будет просто 0, так как компилятор выкинет весь этот код с вызовом функции. Выкинуть код с исключением он не может.
Поэтому я и проводил сравнения в Debug, где ничго не вырезается. Для чистоты эксперимента.
Вот disassembly кода в Debug
for (int i = 0; i < count; i++)
0021159A mov dword ptr [ebp-3Ch],0
002115A1 jmp wmain+6Ch (02115ACh)
002115A3 mov eax,dword ptr [ebp-3Ch]
002115A6 add eax,1
002115A9 mov dword ptr [ebp-3Ch],eax
002115AC mov eax,dword ptr [ebp-3Ch]
002115AF cmp eax,dword ptr [count]
002115B2 jge wmain+85h (02115C5h)
{
int result = ErrorCodeFunction(count);
002115B4 mov eax,dword ptr [count]
002115B7 push eax
002115B8 call ErrorCodeFunction (02111D1h)
002115BD add esp,4
002115C0 mov dword ptr [ebp-48h],eax
}
002115C3 jmp wmain+63h (02115A3h)P>В случае кодов возврата вам требуется проверять код каждый раз и для каждой функции, и вне зависимости от успеха/неудачи.
Верно. Но это всего лишь одна-две команды, что по сравнению с набором команд самой функции не очень большой оверхед, если функция мало-мальски сложная. Стоит функцию чуть-чуть изменить — и мы получим на десяток или сотню команд больше или меньше. Я уж не говорю, что будет, если в функции есть хотя бы линейный цикл — в этом случае это время сравнения есть просто O(1) на фоне O(N).
Есть и еще один момент. Коды возврата можно и не анализировать, если в данной ситуации он несущественен. Например, булевская функция delete может возвращать true, если удалили и false — если нет того, что нужно удалить. Но если мне все равно (а мне может быть все равно, так как мне надо, чтобы удаляемого там больше не было, и мне не важно, нет его теперь там потому, что удалили или потому, что и не было до попытки удалить), то я могу и игнорировать код возврата. Исключение не проигнорируешь.
P>Учитывая, что количество неудач по сравнению с количеством успешного выполнения функций ничтожно мало — то и накладные расходы на исключения фактически можно считать равными нулю. И нулю не только по сравнению с кодами возврата, а вообще в принципе. Потому что, при успехе накладных расходов почти нет, а при неудаче важность потребления процессорного времени по сравнению с важностью обработки ошибки стремиться к нулю.
А вот с этим могу согласиться. Действительно, пример мой довольно искусственный — так реально не бывает. Но я лишь хотел показать, что выброс исключения сравнительно недешевая вещь. Если оно и впрямь происходит очень-очень редко, то оверхедом на него можно пренебречь. Впрочем, это верно для чего угодно при условии, что это что угодно происходит очень-очень редко (и, конечно, само не занимает много времени). Если же не очень редко — тут все будет иначе.
Я не противник исключений, отнюдь нет. Я просто хотел напомнить, что это довольно затратный механихзм и об этом надо помнить.
Re[5]: Разработка на чистом C
Здравствуйте, push, Вы писали:
P>Вы либо пытаетесь ввести в заблуждение, либо не до конца понимаете оптимизацию в с++. Тут даже без компиляции очевидно, что код с ErrorCodeFunction вырезается (и это абсолютно никак не связано с кодами возврата). В реальной функции ничего не вырезается.
Вырезается только в Release, о чем я ясно написал. Цитирую себя
PD>Компилировать в Debug. Для Release Error code time будет просто 0, так как компилятор выкинет весь этот код с вызовом функции. Выкинуть код с исключением он не может.
Поэтому я и проводил сравнения в Debug, где ничго не вырезается. Для чистоты эксперимента.
Вот disassembly кода в Debug
P>В случае кодов возврата вам требуется проверять код каждый раз и для каждой функции, и вне зависимости от успеха/неудачи.
Верно. Но это всего лишь одна-две команды, что по сравнению с набором команд самой функции не очень большой оверхед, если функция мало-мальски сложная. Стоит функцию чуть-чуть изменить — и мы получим на десяток или сотню команд больше или меньше. Я уж не говорю, что будет, если в функции есть хотя бы линейный цикл — в этом случае это время сравнения есть просто O(1) на фоне O(N).
Есть и еще один момент. Коды возврата можно и не анализировать, если в данной ситуации он несущественен. Например, булевская функция delete может возвращать true, если удалили и false — если нет того, что нужно удалить. Но если мне все равно (а мне может быть все равно, так как мне надо, чтобы удаляемого там больше не было, и мне не важно, нет его теперь там потому, что удалили или потому, что и не было до попытки удалить), то я могу и игнорировать код возврата. Исключение не проигнорируешь.
P>Учитывая, что количество неудач по сравнению с количеством успешного выполнения функций ничтожно мало — то и накладные расходы на исключения фактически можно считать равными нулю. И нулю не только по сравнению с кодами возврата, а вообще в принципе. Потому что, при успехе накладных расходов почти нет, а при неудаче важность потребления процессорного времени по сравнению с важностью обработки ошибки стремиться к нулю.
А вот с этим могу согласиться. Действительно, пример мой довольно искусственный — так реально не бывает. Но я лишь хотел показать, что выброс исключения сравнительно недешевая вещь. Если оно и впрямь происходит очень-очень редко, то оверхедом на него можно пренебречь. Впрочем, это верно для чего угодно при условии, что это что угодно происходит очень-очень редко (и, конечно, само не занимает много времени). Если же не очень редко — тут все будет иначе.
Я не противник исключений, отнюдь нет. Я просто хотел напомнить, что это довольно затратный механизм и об этом надо помнить.
P>Вы либо пытаетесь ввести в заблуждение, либо не до конца понимаете оптимизацию в с++. Тут даже без компиляции очевидно, что код с ErrorCodeFunction вырезается (и это абсолютно никак не связано с кодами возврата). В реальной функции ничего не вырезается.
Вырезается только в Release, о чем я ясно написал. Цитирую себя
PD>Компилировать в Debug. Для Release Error code time будет просто 0, так как компилятор выкинет весь этот код с вызовом функции. Выкинуть код с исключением он не может.
Поэтому я и проводил сравнения в Debug, где ничго не вырезается. Для чистоты эксперимента.
Вот disassembly кода в Debug
for (int i = 0; i < count; i++)
0021159A mov dword ptr [ebp-3Ch],0
002115A1 jmp wmain+6Ch (02115ACh)
002115A3 mov eax,dword ptr [ebp-3Ch]
002115A6 add eax,1
002115A9 mov dword ptr [ebp-3Ch],eax
002115AC mov eax,dword ptr [ebp-3Ch]
002115AF cmp eax,dword ptr [count]
002115B2 jge wmain+85h (02115C5h)
{
int result = ErrorCodeFunction(count);
002115B4 mov eax,dword ptr [count]
002115B7 push eax
002115B8 call ErrorCodeFunction (02111D1h)
002115BD add esp,4
002115C0 mov dword ptr [ebp-48h],eax
}
002115C3 jmp wmain+63h (02115A3h)P>В случае кодов возврата вам требуется проверять код каждый раз и для каждой функции, и вне зависимости от успеха/неудачи.
Верно. Но это всего лишь одна-две команды, что по сравнению с набором команд самой функции не очень большой оверхед, если функция мало-мальски сложная. Стоит функцию чуть-чуть изменить — и мы получим на десяток или сотню команд больше или меньше. Я уж не говорю, что будет, если в функции есть хотя бы линейный цикл — в этом случае это время сравнения есть просто O(1) на фоне O(N).
Есть и еще один момент. Коды возврата можно и не анализировать, если в данной ситуации он несущественен. Например, булевская функция delete может возвращать true, если удалили и false — если нет того, что нужно удалить. Но если мне все равно (а мне может быть все равно, так как мне надо, чтобы удаляемого там больше не было, и мне не важно, нет его теперь там потому, что удалили или потому, что и не было до попытки удалить), то я могу и игнорировать код возврата. Исключение не проигнорируешь.
P>Учитывая, что количество неудач по сравнению с количеством успешного выполнения функций ничтожно мало — то и накладные расходы на исключения фактически можно считать равными нулю. И нулю не только по сравнению с кодами возврата, а вообще в принципе. Потому что, при успехе накладных расходов почти нет, а при неудаче важность потребления процессорного времени по сравнению с важностью обработки ошибки стремиться к нулю.
А вот с этим могу согласиться. Действительно, пример мой довольно искусственный — так реально не бывает. Но я лишь хотел показать, что выброс исключения сравнительно недешевая вещь. Если оно и впрямь происходит очень-очень редко, то оверхедом на него можно пренебречь. Впрочем, это верно для чего угодно при условии, что это что угодно происходит очень-очень редко (и, конечно, само не занимает много времени). Если же не очень редко — тут все будет иначе.
Я не противник исключений, отнюдь нет. Я просто хотел напомнить, что это довольно затратный механизм и об этом надо помнить.