Тут все дело в том, что ОС шедулер обладает информацией, кто кого ждет, и поэтому может подгонять, чтобы быстрее разбудить заснувший поток. По крайней мере на винде шедулер так старается делать. Поэтому может даже получиться быстрее, чем атомарные операции, т.к. там процессор молотит в холостую, а ось может вытеснить поток, который взял спинлок и зашедулить поток, который будет пытаться его взять. Но тут нужны тесты, чтобы делать какие-либо выводы.
Хочется увидеть сравнение с очередью на быстрых мьютексах (которые пытаются сначала сделать спинлоки, а затем уйти в ядро). Возможно, что такой подход будет не сильно медленнее lock-free подхода, а может и быстрее в данных тестах (кто знает?). Ну и хочется увидеть еще сравнение с wait-free single consumer/single producer.
Хм, не совсем понял. Либо SYSENTER (что есть Fast call to privilege level 0 system procedures), либо программные прерывания. Т.е. сначала утверждается, что программное прерывание, а потом — что нечто другое. Как это понимать?
И что по поводу первого вопроса о том, зачем нужно переходить в ядро?
_CxxThrowException передает управление операционной системе через программное прерывание.
Тут несколько вещей непонятно:
1. Зачем _CxxThrowException передавать управление операционной системе? Тут имеется в виду ядро, или что-то другое? Вроде как исключение можно полностью обработать в user space.
2. Управление операционной системе уже давно не передается через программное прерывание, а через SYSENTER/SYSEXIT или SYSCALL/SYSRET. Или тут рассматриваются древние процессоры с древними операционными системами?
Most calls to the DOS API are invoked using software interrupt 21h (INT 21h).
Только какое это имеет отношение к обработке исключений в Windows мне не очень понятно. Может проясните? Собственно, изначально и был вопрос про то, какая связь между программным прерыванием и exception handling. Мне всегда казалось, что используется SEH для этого.
MS VC++. Этот компилятор реализует вторую стратегию обработки… Для версии x64 вспомогательные стековые структуры по возможности переносились в .pdata, вероятно, в MS считают первую стратегию более перспективной.
А вот и нет. Следует различать x86 компилятор и x64 компилятор. x86 действительно использует вторую стратегию, а вот x64 — первую. Причем первая стратегия существенно отличается от используемой в GCC компиляторе: GCC использует таблицы, в MSVC вставляет NOP операции в код, которые практически бесплатные, т.к. процессоры их игнорируют. NOP используется как метки при раскрутке стека, чтобы позвать соответствующий деструктор.
Инициирование исключения сделано через программное прерывание.
А вообще я ожидал здесь увидеть сравнение производительности для различных компиляторов, а в результате обнаружилось достаточно поверхностное обсуждение подходов.
Энергия: 200*3600 Дж. Удельная теплоемкость воды: ~4 кДж/(кг * К), т.е. количество литров = 200*3600/(4 * 1000 * 80) ~= 2 л. Ну т.е. ошибка в 1000 раз.
Погодите, в статье речь была не про криптовалюту, а про биткоины. Если говорить про аналогии, то торренты — это криптовалюты, а некие конкретные торрент-трекеры — это биткоины. Я лично не сомневаюсь, что когда-нибудь криптовалюта заиграет, но конкретно про биткоины есть некоторые сомнения.
Тут забыли один нюанс: никто не сказал, что именно bitcoin будет «той самой валютой будущего», ведь ее можно расклонировать влегкую. Если бы она была единственной криптовалютой, и более того, поддерживаемой на официальном уровне — то тогда да, а так — лишь домыслы, основанные на сильных предположениях. Но я не отрицаю, что возможно, так все и будет. Но если никто не покажет, что текущий оборот используется для повседневных операций (как с любыми банковскими картами), то мне будет сложно поверить в хорошее будущее данной криптовалюты.
Можно сделать так: в сопрограмме устанавливать флажок по таймауту, затем по resume его проверять, и если выставлен, то кидать исключение, которое при этом можно еще и при желании обработать. Так что серьезных проблем я не вижу.
Простые запросы типа GET /hello HTTP/1.1
Т.е. клиент работал так:
1. Открывается соединение.
2. Посылается запрос.
3. Дожидается ответ, валидируется.
4. Закрывается соединение.
Понятно, что это все тоже делалось асинхронно, чтобы нагружать до 30K RPS.
У меня упрощение не является единственной целью. Помимо нее есть еще цель показать, что спрятано под капотом сопрограмм и как они стыкуются с асинхронной частью. И я не считаю приведенный код усложненным, он простой настолько, насколько это вообще возможно. Если вы считаете, что это можно сделать еще проще, тогда напишите как. Я думаю, всем это будет интересно.
Можно было бы, конечно, и на исключения забить, однако там есть несколько нюансов. Поэтому решил, что лучше с ними. И да, цель была не в нагромождении, а в упрощении.
MSVC v12:
GCC 4.8.1:
Параметры:
MSVC v12:
GCC 4.8.1
Параметры:
Судя по этим результатам, стандартная реализация всегда чуть лучше.
И что по поводу первого вопроса о том, зачем нужно переходить в ядро?
1. Зачем _CxxThrowException передавать управление операционной системе? Тут имеется в виду ядро, или что-то другое? Вроде как исключение можно полностью обработать в user space.
2. Управление операционной системе уже давно не передается через программное прерывание, а через SYSENTER/SYSEXIT или SYSCALL/SYSRET. Или тут рассматриваются древние процессоры с древними операционными системами?
MS-DOS API:
Most calls to the DOS API are invoked using software interrupt 21h (INT 21h).
Только какое это имеет отношение к обработке исключений в Windows мне не очень понятно. Может проясните? Собственно, изначально и был вопрос про то, какая связь между программным прерыванием и exception handling. Мне всегда казалось, что используется SEH для этого.
Непонятно, что это вообще такое? А вообще MSVC использует SEH — structured exception handling.
А вообще я ожидал здесь увидеть сравнение производительности для различных компиляторов, а в результате обнаружилось достаточно поверхностное обсуждение подходов.
Т.е. клиент работал так:
1. Открывается соединение.
2. Посылается запрос.
3. Дожидается ответ, валидируется.
4. Закрывается соединение.
Понятно, что это все тоже делалось асинхронно, чтобы нагружать до 30K RPS.