Re[5]: На сколько затратно выбрасывание исключения
От: Sinix  
Дата: 01.03.15 17:04
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

S>>(я что-то не могу себе такой сценарий представить, но пусть будет),

PD>Такой сценарий можно себе представить, но не в дотнете. Впрочем, и в дотнете, наверное, можно, если включить unsafe код. Это "истинный" (то есть без реаллокаций) динамический массив.

Не, это уже совсем частный случай. Топикстартер, думаю, оговорил бы этот момент.
Re[5]: На сколько затратно выбрасывание исключения
От: Pavel Dvorkin Россия  
Дата: 01.03.15 17:45
Оценка:
Здравствуйте, drol, Вы писали:

D>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>throw из дотнета приводит в конечном счете к вызову нативной RaiseException из KERNELBASE.dll, а она приводит к переключению в режим ядра


D>Кто Вам это сказал ??? RaiseException совершенно не обязана переключаться в kernel mode. В случае 64-битного процесса RaiseException уходит в ядро только при подключенном отладчике, необработанном исключении и тому подобных ситуациях. Обычные же исключения обрабатываются полностью в user mode... Ну или мне счётчики kernel\user time врут...


Я не исключаю, что в x64 что-то изменилось, но хотелось бы более серьезного доказательства, нежели данные счетчиков времени. Если такие доказательства будут, я охотно поменяю свое мнение в том, что касается x64.

Пока что могу лишь сказать, что NtRaiseException как сервис ядра в x64 существует. Вот здесь ее номер даже (в смысле syscall) приведен.

http://www.evilsocket.net/2014/02/11/on-windows-syscall-mechanism-and-syscall-numbers-extraction-methods/

Правда, я не совсем понимаю, что Вы имеете в виду, говоря о необработанном исключении. RaiseException его выбрасывает, а обработка будет потом, если будет. Получается, что если обработки не будет, то управление вернется обратно в RaiseException, чтобы уйти в kernel ? Как-то странно это. Или она сама и должна заниматься обработкой исключения ? Так не ее же это дело, исключения могут и без нее возникнуть вполне. Что-то я не понимаю.
With best regards
Pavel Dvorkin
Re[6]: На сколько затратно выбрасывание исключения
От: Pavel Dvorkin Россия  
Дата: 01.03.15 17:47
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>Не, это уже совсем частный случай. Топикстартер, думаю, оговорил бы этот момент.


В том-то и дело, что я пока не пойму, что он имеет в виду под переполнением буфера. Я ему вопрос задал, если ответит — посмотрим.
With best regards
Pavel Dvorkin
Re[2]: На сколько затратно выбрасывание исключения
От: andy1618 Россия  
Дата: 01.03.15 18:45
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Запускаем, смотрим на результаты.

S>...
S>Понимаем, что с "миллионом исключений в секунду" VladD2 явно погорячился

А можно пример результатов привести?
Re[3]: На сколько затратно выбрасывание исключения
От: Sinix  
Дата: 01.03.15 19:46
Оценка: 16 (2)
Здравствуйте, andy1618, Вы писали:

A>А можно пример результатов привести?

x86
            Fast, callstack  0:     0ms, ips:   247341083,3539 :    100000
            Exc,  callstack  0:  1529ms, ips:       65377,9624 :    100000
            Fast, callstack  1:     1ms, ips:    98941327,7926 :    100000
            Exc,  callstack  1:  2898ms, ips:       34504,8774 :    100000
            Fast, callstack 10:     6ms, ips:    14998350,1815 :    100000
            Exc,  callstack 10:  4720ms, ips:       21184,1113 :    100000
            Fast, callstack 20:    15ms, ips:     6335328,9620 :    100000
            Exc,  callstack 20:  7975ms, ips:       12537,7996 :    100000
Done.


x64
            Fast, callstack  0:     0ms, ips:   154273372,4159 :    100000
            Exc,  callstack  0:  1075ms, ips:       92969,2299 :    100000
            Fast, callstack  1:     1ms, ips:    88707531,2694 :    100000
            Exc,  callstack  1:  2091ms, ips:       47807,8751 :    100000
            Fast, callstack 10:     4ms, ips:    22799297,7816 :    100000
            Exc,  callstack 10:  3148ms, ips:       31761,4567 :    100000
            Fast, callstack 20:     8ms, ips:    11827041,3473 :    100000
            Exc,  callstack 20:  5276ms, ips:       18953,0922 :    100000
Done.
Re[4]: На сколько затратно выбрасывание исключения
От: andy1618 Россия  
Дата: 01.03.15 20:58
Оценка:
Здравствуйте, Sinix, Вы писали:

A>>А можно пример результатов привести?

S>x86
S>
S>            Exc,  callstack  0:  1529ms, ips:       65377,9624 :    100000
S>            Exc,  callstack  1:  2898ms, ips:       34504,8774 :    100000
S>


Хм, а как вот это можно объяснить?
Ведь и в том и в другом случае, судя по коду, кидается 1 исключение, но при этом время увеличивается почти в 2 раза?
Re[6]: На сколько затратно выбрасывание исключения
От: drol  
Дата: 01.03.15 22:57
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>но хотелось бы более серьезного доказательства,


Я с большим интересом послушаю эти самые Ваши доказательства. Вы ведь, надеюсь, не забыли, что тезис о переходах в ядро при обычной обработке обычных исключений принадлежит Вам ?

PD>нежели данные счетчиков времени


Лично меня они пока вполне устраивают. Разница с 32-битным процессом WoW64 впечатляет более чем...

PD>Пока что могу лишь сказать, что NtRaiseException как сервис ядра в x64 существует. Вот здесь ее номер даже (в смысле syscall) приведен.


И причём здесь NtRaiseException\ZwRaiseException В приведённом Вами стеке вызовов их нет. Там только RaiseException и RtlRaiseException. Вам напомнить, что означает префикс Rtl ?

Итого, Вы пока не показали вообще ни одного факта перехода в режим ядра

PD>Правда, я не совсем понимаю, что Вы имеете в виду, говоря о необработанном исключении. RaiseException его выбрасывает, а обработка будет потом, если будет


Приехали. А что такое по-Вашему вообще "выбрасывание" ? Сакральный магический акт ?

PD>Получается, что если обработки не будет, то управление вернется обратно в RaiseException,


И когда обработка есть оно туда тоже возвращается. Причём n раз (в данном примере SEH + куча вложенных __finally\__except):

testCppExceptions.exe!main$fin$0()
msvcr120d.dll!__C_specific_handler()
ntdll.dll!RtlpExecuteHandlerForUnwind()
ntdll.dll!RtlUnwindEx()
msvcr120d.dll!__C_specific_handler()
ntdll.dll!RtlpExecuteHandlerForException()
ntdll.dll!RtlDispatchException()
ntdll.dll!KiUserExceptionDispatch()
KernelBase.dll!RaiseException()
msvcr120d.dll!_CxxThrowException()
testCppExceptions.exe!main(int argc, char * * argv)

*И эти люди преподают программирование на C\C++

PD>Или она сама и должна заниматься обработкой исключения ?


Совершенно верно...

*Понятно, что не собственно RaiseException, а то что вызывается внутри неё. Основная логика находится в RtlRaiseException и в RtlDispatchException.

PD>Так не ее же это дело, исключения могут и без нее возникнуть вполне.


Что значит "без неё" Нормальное исключение это и есть вызов кого-то из xxxRaiseException. Для "ядерных приветов" имеются оптимизации, которые передают управление сразу на уровень KiUserExceptionDispatch.

PD>Что-то я не понимаю.


Вы очень много чего не понимаете...
Re[5]: На сколько затратно выбрасывание исключения
От: drol  
Дата: 01.03.15 23:02
Оценка:
Здравствуйте, andy1618, Вы писали:

S>>            Exc,  callstack  0:  1529ms, ips:       65377,9624 :    100000
S>>            Exc,  callstack  1:  2898ms, ips:       34504,8774 :    100000

A>Хм, а как вот это можно объяснить?
A>Ведь и в том и в другом случае, судя по коду, кидается 1 исключение, но при этом время увеличивается почти в 2 раза?

Да легко. Для "пустого" стека вызовов сделана какая-нибудь оптимизация по данным. А для размера даже в 1 уже кучу выделений памяти в куче надо делать, например.
Re[4]: На сколько затратно выбрасывание исключения
От: Cynic Россия  
Дата: 01.03.15 23:11
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Что означает "буфер может переполняться" ? Мы же в управляемом коде. Если это массив и выйти за его границы, то ArrayIndexOutOfBoundsException и так выбросится. Если же что-то иное — хотелось бы знать, что именно.


Буфер это список (List<T>) который имеет ограниченное количество элементов. Надо как-то обработать ситуацию когда использующий его код хочет добавить элемент в буфер когда он уже заполнен.
:)
Re[2]: На сколько затратно выбрасывание исключения
От: Cynic Россия  
Дата: 01.03.15 23:32
Оценка:
Здравствуйте, Sinix, Вы писали

S>Правильный: читаем FDG. Лучше всю книгу, на крайний случай:

S>1. https://msdn.microsoft.com/en-us/library/ms229009(v=vs.110).aspx
S>Именно ваш случай. См tester-doer + try-parse pattern.

S>2. http://blogs.msdn.com/b/kcwalina/archive/2005/03/16/396787.aspx

S>Краткое изложение.
S>

S>Do not use exceptions for normal flow of control. Except for system failures, there should generally be a way to write code that avoids exceptions being thrown.


В общем после прочтения указанных ссылок я сделал вывод, что если речь идет о производительности, то использования исключений нужно избегать. А в остальных случаях все зависит от ситуации.
:)
Re[6]: На сколько затратно выбрасывание исключения
От: Sinix  
Дата: 02.03.15 06:04
Оценка: 2 (1)
Здравствуйте, drol, Вы писали:

D>Да легко. Для "пустого" стека вызовов сделана какая-нибудь оптимизация по данным. А для размера даже в 1 уже кучу выделений памяти в куче надо делать, например.

Там всё проще, +1 catch-throw
        if (count % CatchEvery == 1)
        {
            try
            {
                return TryCallMeCore(count - 1, fail);
            }
            catch
            {
                throw;
            }
        }
        else
        {
            return TryCallMeCore(count - 1, fail);
        }
Re[5]: На сколько затратно выбрасывание исключения
От: Sinix  
Дата: 02.03.15 06:11
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Хм, а как вот это можно объяснить?

+1 try-catch на каждые 5 вызовов, см
  if (count % CatchEvery == 1) ...


без них неинтересно, x64 без rethrow:
            Fast, callstack  0:     0ms, ips:   191607587,6605 :    100000
            Exc,  callstack  0:  1243ms, ips:       80403,9236 :    100000
            Fast, callstack  1:     0ms, ips:   201045436,2686 :    100000
            Exc,  callstack  1:  1286ms, ips:       77722,6396 :    100000
            Fast, callstack 10:     2ms, ips:    37467216,1858 :    100000
            Exc,  callstack 10:  1766ms, ips:       56604,2755 :    100000
            Fast, callstack 20:     6ms, ips:    14556888,3196 :    100000
            Exc,  callstack 20:  2231ms, ips:       44822,7042 :    100000
Done.


Машина другая, помощнее. Для сравнения на ней же, x64, с rethrow:
            Fast, callstack  0:     0ms, ips:   181356546,9713 :    100000
            Exc,  callstack  0:   942ms, ips:      106153,9572 :    100000
            Fast, callstack  1:     0ms, ips:   100421771,4400 :    100000
            Exc,  callstack  1:  1924ms, ips:       51962,0912 :    100000
            Fast, callstack 10:     3ms, ips:    25368477,1303 :    100000
            Exc,  callstack 10:  2910ms, ips:       34353,4050 :    100000
            Fast, callstack 20:     7ms, ips:    13422638,6223 :    100000
            Exc,  callstack 20:  4910ms, ips:       20364,2044 :    100000
Done.
Re[7]: На сколько затратно выбрасывание исключения
От: Pavel Dvorkin Россия  
Дата: 02.03.15 06:30
Оценка: -1
Здравствуйте, drol, Вы писали:

D>Я с большим интересом послушаю эти самые Ваши доказательства. Вы ведь, надеюсь, не забыли, что тезис о переходах в ядро при обычной обработке обычных исключений принадлежит Вам ?


Пожалуйста. Первый рисунок демонстрирует схему выбрасывания и обработки исключения.

http://www.bugbrowser.com/dev/dumpwriter/exception_lifetime.html


D>Итого, Вы пока не показали вообще ни одного факта перехода в режим ядра


См. выше.


PD>>Так не ее же это дело, исключения могут и без нее возникнуть вполне.


D>Что значит "без неё" Нормальное исключение это и есть вызов кого-то из xxxRaiseException.


Именно это и значит. При делении на 0 или access violation происходит исключение процессора, управление передается в ядро минуя вызов RaiseException в user mode. Именно о ней я и писал. Что при этом вызывается в ядре — я не обсуждал.


D>Вы очень много чего не понимаете...


Вынужден на этом дискуссию с Вами прекратить. Я не веду дискуссию с людьми, позволяющими себе агрессивный тон и переход на личности.
With best regards
Pavel Dvorkin
Re[5]: На сколько затратно выбрасывание исключения
От: Pavel Dvorkin Россия  
Дата: 02.03.15 06:40
Оценка:
Здравствуйте, Cynic, Вы писали:

PD>>Что означает "буфер может переполняться" ? Мы же в управляемом коде. Если это массив и выйти за его границы, то ArrayIndexOutOfBoundsException и так выбросится. Если же что-то иное — хотелось бы знать, что именно.


C>Буфер это список (List<T>) который имеет ограниченное количество элементов. Надо как-то обработать ситуацию когда использующий его код хочет добавить элемент в буфер когда он уже заполнен.


Если это и впрямь System.Collections.Generiс.List, то количество его элементов растет автоматически

https://msdn.microsoft.com/ru-ru/library/3wcytfd1(v=vs.110).aspx

If Count already equals Capacity, the capacity of the List<T> is increased by automatically reallocating the internal array, and the existing elements are copied to the new array before the new element is added.

Так что пока не будет OutOfMemoryException — добавляй и ни о чем не думай
With best regards
Pavel Dvorkin
Re[5]: На сколько затратно выбрасывание исключения
От: vrr  
Дата: 02.03.15 06:54
Оценка:
Здравствуйте, Cynic, Вы писали:

C>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Что означает "буфер может переполняться" ? Мы же в управляемом коде. Если это массив и выйти за его границы, то ArrayIndexOutOfBoundsException и так выбросится. Если же что-то иное — хотелось бы знать, что именно.


C>Буфер это список (List<T>) который имеет ограниченное количество элементов. Надо как-то обработать ситуацию когда использующий его код хочет добавить элемент в буфер когда он уже заполнен.


Т.е. ограниченность буфера — элемент бизнес-логики? Может, вам что-нибудь вроде циклического буфера подойдет? И почему нельзя просто игнорировать вызов добавления, к примеру?
Re[8]: На сколько затратно выбрасывание исключения
От: drol  
Дата: 02.03.15 07:40
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Пожалуйста. Первый рисунок демонстрирует схему выбрасывания и обработки исключения.


И зачем Вы приводите схему десятилетней давности для 32-битных процессов, когда речь уже давно идёт о 64-битных

D>>Что значит "без неё" Нормальное исключение это и есть вызов кого-то из xxxRaiseException.


PD>Именно это и значит. При делении на 0 или access violation происходит исключение процессора, управление передается в ядро минуя вызов RaiseException в user mode


Зачем Вы разговариваете сам с собой ? Было же написано нормальным английско-программистским языком: xxxRaiseException.

D>>Вы очень много чего не понимаете...


PD>Вынужден на этом дискуссию с Вами прекратить. Я не веду дискуссию с людьми, позволяющими себе агрессивный тон и переход на личности.


Странная какая-то у Вас реакция. Вот мне бы на Вашем месте было очень стыдно, что давно не в теме, а студентам втираю. И чтобы как можно быстрее устранить пробелы в своих знаниях я бы использовал все доступные возможности... Жаль Ваших студентов — совсем не повезло им с преподавателем...
Re[7]: На сколько затратно выбрасывание исключения
От: andy1618 Россия  
Дата: 02.03.15 10:22
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Там всё проще, +1 catch-throw


Да, точно, это я невнимательно посмотрел!
Re[4]: На сколько затратно выбрасывание исключения
От: Pavel Dvorkin Россия  
Дата: 03.03.15 04:33
Оценка:
Здравствуйте, Sinix, Вы писали:


A>>А можно пример результатов привести?


<skipped>

Впечатляет. Даже решил перепроверить. Соотношение совпадает.

Честно говоря, я не ждал, что будет настолько хуже.
With best regards
Pavel Dvorkin
Re[5]: На сколько затратно выбрасывание исключения
От: drol  
Дата: 03.03.15 05:42
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Честно говоря, я не ждал, что будет настолько хуже.


Это ещё мелочи. Под студийным отладчиком запустите...
Re[5]: На сколько затратно выбрасывание исключения
От: Sinix  
Дата: 03.03.15 06:33
Оценка: +3
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Честно говоря, я не ждал, что будет настолько хуже.

Да ненамного хуже SEH вроде

А всё просто: исключения в дотнете заточены под исключительные ситуации (сорри за фиговый каламбур). Если производительность утыкается в стоимость обработки исключений, то проблема уже на 100% не в них самих, а в непродуманной архитектуре / незнании матчасти / неправильно написанном API и тд и тп. Исключений из этого правила на практике не видел.

Ну и разумеется в крайности не надо впадать. Исключения отлично работают для отмены/отката бизнес-операций (кучу понятных оговорок про необходимость отката состояния, побочные эффекты и тд и тп пропустим). А вот писать try-catch вокруг метода проверки заказа — это уже перебор

P.S. Сорри за передоз слова "исключение". Это исключительная ситуация.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.