Performance & Scalability пост №3: thread - ресурс или нет?
От: Maxim S. Shatskih Россия  
Дата: 16.08.07 23:29
Оценка: 8 (1)
Очень часто приходится встречать мнение, что заведи в системе побольше нитей — и все будет сразу лучше. Верно ли оно?

Не всегда.

Для начала рассмотрим некий специальный случай, когда ресурсом для какой-то операции является процессор (т.е. операция есть некое длинное вычисление), и оптимизировать хочется именно ее.

Современные машины, конечно, многопроцессорны, и потому загрузить оба процессора — это то же самое, что поставить в магазине вторую кассу — сами понимаете, как упадет очередь и время ожидания в ней.

Вот тут и приходят на помощь нити. Чтобы выполнить что-то на конкретном процессоре — надо запустить нить, и привязать ее к нему по affinity, чтобы она не встала в очередь на первый процессор вслед за первой нитью (в этом случае выигрыша не будет).

Это дает реальный и серьезный выигрыш на вычислительных задачах. Здесь нить не ресурс, а дополнительная сущность, нужная для того, чтобы задействовать ресурс "процессор".

Теперь что касается использования нитей в остальных случаях.

Иногда код зовет длинные блокирующие функции (особенно если речь о вызовах в какие-то сложные чужие компоненты типа DCOM прокси). "Блокирующие" — это такие, в которых может случиться длинное — а, возможно, очень длинное — ожидание.

Ожидает, естественно, одна нить (которая в данном случае есть ресурс). Остальные — не ожидают. В этой ситуации добавление нитей реально повышает скалабильность (при правильном управлении их пулом).

Но есть и другие пути. Если надо работать с диском или сетью — то у нас есть overlapped IO, который позволяет накидать немеряну кучу запросов на разные хэндлы всего одной нитью, не блокируясь. В юниксе есть nonblocking IO, который делает сходное.

Использование этой фичи избавляет от необходимости поддерживать пул нитей, и потому есть благо. Именно из-за nonblocking IO в юниксах годами обходились без нитей.

Если код написан так, что исполняющая его нить не блокируется — то тогда не имеет смысла заводить много нитей.
Занимайтесь LoveCraftом, а не WarCraftом!
Re: Performance & Scalability пост №3: thread - ресурс или н
От: Дм.Григорьев  
Дата: 17.08.07 03:26
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

MSS>Если надо работать с диском или сетью — то у нас есть overlapped IO, который позволяет накидать немеряну кучу запросов на разные хэндлы всего одной нитью, не блокируясь. В юниксе есть nonblocking IO, который делает сходное.


MSS>Если код написан так, что исполняющая его нить не блокируется — то тогда не имеет смысла заводить много нитей.


А не получится спагетти?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
http://dimgel.ru/lib.web — thin, stateless, strictly typed Scala web framework.
Re[2]: Performance & Scalability пост №3: thread - ресурс ил
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 17.08.07 09:59
Оценка: 12 (1)
Здравствуйте, Дм.Григорьев, Вы писали:

ДГ>Здравствуйте, Maxim S. Shatskih, Вы писали:


MSS>>Если надо работать с диском или сетью — то у нас есть overlapped IO, который позволяет накидать немеряну кучу запросов на разные хэндлы всего одной нитью, не блокируясь. В юниксе есть nonblocking IO, который делает сходное.


MSS>>Если код написан так, что исполняющая его нить не блокируется — то тогда не имеет смысла заводить много нитей.


ДГ>А не получится спагетти?


Спагетти обычно не получается. Получается событийно-управляемый движок с несколькими классами событий (готовность асинхронной операции, готовность сокета к действию, срабатывание таймера, сигнал...), которые отрабатываются своими указанными обработчиками.

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

Я сейчас работаю с SIP, в котором фактически свой стек из четырёх уровней (транспортный, транзакционный, диалоговый и сессионный). Основной метод — именно такой — передача сообщений (как правило, прямым вызовом, но иногда отложенная) между реализациями уровней вверх и вниз.

Загвоздки против построения всего в одной нити (или одной на процессор/ядро) следующие:

1. Некоторые библиотеки принципиально построены так, что не могут работать в рамках событийно-управляемого подхода. Особенно это часто для SQL. Для них на каждый одновременный запрос требуется нить. Поэтому строится пул нитей, запрос уходит через общее состояние пробуждая спящую нить, ответ приходит в нить событийного движка, ретранслируясь в пробуждающее его событие.

2. Есть загвоздка с рядом ядерных операций, которые не могут быть заказаны асинхронно. В юниксах это, например, SysV IPC. Во всех системах — чтение/запись диска не напрямую (read/ReadFile/etc.), а через page fault замапленного в память файла.

3. Иногда всё-таки неудобно понимать автомат, в который преобразован линейный код. Слишком громоздко, слишком много промежуточных состояний на каждый мелкий чих. Не знаю, можно ли это назвать "спагетти", но бывает.
The God is real, unless declared integer.
Re[2]: Performance & Scalability пост №3: thread - ресурс ил
От: remark Россия http://www.1024cores.net/
Дата: 17.08.07 10:09
Оценка:
Здравствуйте, Дм.Григорьев, Вы писали:

MSS>>Если код написан так, что исполняющая его нить не блокируется — то тогда не имеет смысла заводить много нитей.


ДГ>А не получится спагетти?


Это зависит от программиста. Если программист — итальянец, то получится


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Performance & Scalability пост №3: thread - ресурс или н
От: remark Россия http://www.1024cores.net/
Дата: 17.08.07 10:23
Оценка: 1 (1) +2
Здравствуйте, Maxim S. Shatskih, Вы писали:

MSS>Вот тут и приходят на помощь нити. Чтобы выполнить что-то на конкретном процессоре — надо запустить нить, и привязать ее к нему по affinity, чтобы она не встала в очередь на первый процессор вслед за первой нитью (в этом случае выигрыша не будет).


В общем случае affinity надо избегать. Иначе будет обратный результат.
affinity — это вставляние палок в колёсы ОС. Она перестаёт мочь делать "оптимальный" шедулинг. И в общем же случае шедулинг ОС делает вполне нормальный — т.е. она не будет ставить 2 готовых к выполнению потока на одно ядро, если второе свободно — это бред.

Если делаешь affinity, то надо сразу брать всю ответственность на себя — т.е. самому же делать шедулинг и load-balancing. А всё это не тривиальные вещи. Поэтому есть вольшая вероятность сделать только хуже.



MSS>Если код написан так, что исполняющая его нить не блокируется — то тогда не имеет смысла заводить много нитей.


Это спорный вопрос.
Во-первых, блокировка может произойти абсолютно в любом месте. Пример — paging fault из-за отсутствия страницы в памяти.
Во-вторых, блокировки могут происходить в операциях ОС, которые заявлены как не блокирующие. Т.е. неблокирующая отправка в сеть не блокируется только для отправки данных в сеть, при это нет гарантии, что она не заблокируется при выделении памяти, или при доступе к какому-то внутреннему объекту ядра и т.д.
Да и вообще любая синхронизация с использованием блокирующих примитивов может блокироваться.

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


з.ы. несмотря на критические посты, в целом — +1. Со всем остальным согласен. И вообще приятно почитать не глупые вопросы, а когда кто-нибудь пишет свой опыт.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Performance & Scalability пост №3: thread - ресурс ил
От: Maxim S. Shatskih Россия  
Дата: 17.08.07 11:48
Оценка:
ДГ>А не получится спагетти?

Это вопрос стиля кодирования, а не архитектуры.

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

Писать "как проще" — оно хорошо до известных пределов.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[3]: Performance & Scalability пост №3: thread - ресурс ил
От: Maxim S. Shatskih Россия  
Дата: 17.08.07 11:57
Оценка:
N>Спагетти обычно не получается. Получается событийно-управляемый движок с несколькими классами событий (готовность асинхронной операции, готовность сокета к действию, срабатывание таймера, сигнал...), которые отрабатываются своими указанными обработчиками.

Ну примерно.

N>Основной вопрос — в правильной конверсии линейной последовательности действий в автомат.


Угу. В низкоуровневом софте вообще все основные пути на стейт-машинах.

N>Я сейчас работаю с SIP,


я писал имплементацию SIP 1.0 клиента в 2004 году.

N>1. Некоторые библиотеки принципиально построены так, что не могут работать в рамках событийно-управляемого подхода. Особенно это часто для SQL. Для них на каждый одновременный запрос требуется нить. Поэтому строится пул нитей, запрос уходит через общее состояние пробуждая спящую нить, ответ приходит в нить событийного движка, ретранслируясь в пробуждающее его событие.


Я и говорил, что вот в этом случае таки имеет смысл пул нитей. Но в низкоуровневом софте — совсем не обязательно.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[2]: Performance & Scalability пост №3: thread - ресурс ил
От: Maxim S. Shatskih Россия  
Дата: 17.08.07 12:57
Оценка:
Affinity надо использовать только тогда, когда точно знаешь, что делаешь. Это да.

R>affinity — это вставляние палок в колёсы ОС. Она перестаёт мочь делать "оптимальный" шедулинг. И в общем же случае шедулинг ОС делает вполне нормальный — т.е. она не будет ставить 2 готовых к выполнению потока на одно ядро, если второе свободно — это бред.


Критерии оптимальности шедулинга? критерии, заложенные дизайнерами ОС — "чтобы всем хватило в каком-то условном общем случае".

Является ли это критерием для разработчика конкретного кода, где высоки требования к производительности? нет.

И вообще, в таких вопросах, как тонкая оптимизация на производительность, меньше надо думать в русле "все сделано за тебя", а больше — в русле "что на самом деле происходит".

R>Если делаешь affinity, то надо сразу брать всю ответственность на себя — т.е. самому же делать шедулинг и load-balancing.


Не все так плохо. Вот конкретный случай тяжелой вычислительной работы. Раскидай по N нитям, каждая на своем процессоре по affinity — и будет оптимально.

R>Во-первых, блокировка может произойти абсолютно в любом месте. Пример — paging fault из-за отсутствия страницы в памяти.


Это ненадолго. Под "блокировкой" понимается все же блокировка на какое-то значительное время.

R>Да и вообще любая синхронизация с использованием блокирующих примитивов может блокироваться.


Выполнение короткого участка кода (типа "положить в контейнер") под локом практически никогда не считается блокировкой.

Другое дело, если, например, из-под лока таки приходится делать дисковый IO, как это у нас с FCB locks. Там да, там этот лок считается блокирующим, и запросы, пытающиеся взять этот лок, откидываются на исполнение в пул нитей.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[3]: Performance & Scalability пост №3: thread - ресурс ил
От: remark Россия http://www.1024cores.net/
Дата: 17.08.07 23:09
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

MSS>Affinity надо использовать только тогда, когда точно знаешь, что делаешь. Это да.


R>>affinity — это вставляние палок в колёсы ОС. Она перестаёт мочь делать "оптимальный" шедулинг. И в общем же случае шедулинг ОС делает вполне нормальный — т.е. она не будет ставить 2 готовых к выполнению потока на одно ядро, если второе свободно — это бред.


MSS>Критерии оптимальности шедулинга? критерии, заложенные дизайнерами ОС — "чтобы всем хватило в каком-то условном общем случае".


Да, именно так. И опять же в общем случае ОС справляется с задачей достаточно хорошо, чтобы не давать людям общий совет "устанавливайте thread affinity".


MSS>Является ли это критерием для разработчика конкретного кода, где высоки требования к производительности? нет.


MSS>И вообще, в таких вопросах, как тонкая оптимизация на производительность, меньше надо думать в русле "все сделано за тебя", а больше — в русле "что на самом деле происходит".


Да. Только твоя фраза "установите thread affinity" будет трактоваться людьми неверно. Просто установить thread affinity — плохо. Понимать, что происходит, установить thread affinity, сделать свой грамотный load-balancing — хорошо.


R>>Если делаешь affinity, то надо сразу брать всю ответственность на себя — т.е. самому же делать шедулинг и load-balancing.


MSS>Не все так плохо. Вот конкретный случай тяжелой вычислительной работы. Раскидай по N нитям, каждая на своем процессоре по affinity — и будет оптимально.


А если работа не совсем одинаково размера? Ну например, работа включает в себя запрос к БД, запрос может обрабатываться в БД на порядок разное время.
А если ещё какая-то программа периодически подгружает одно ядро на 50%?
Статические алгоритмы распределения патологически не рулят в данной ситуации, т.к. не учитывают того, что реально происходит в системе. Единственный вариант — вводить динамический контроль и обратную связь. Дальше самое интересное — какой алгоритм применить и как сделать, что бы этот алгоритм не вносил больших накладных расходов? И как его хорошо реализовать и протестировать и настроить под разными нагрузками и в разных условиях?


R>>Во-первых, блокировка может произойти абсолютно в любом месте. Пример — paging fault из-за отсутствия страницы в памяти.


MSS>Это ненадолго.


10 мс. Смотри сам.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Performance & Scalability пост №3: thread - ресурс ил
От: Maxim S. Shatskih Россия  
Дата: 18.08.07 12:49
Оценка:
R>А если работа не совсем одинаково размера? Ну например, работа включает в себя запрос к БД, запрос может обрабатываться в БД на порядок разное время.

Запрос к БД не есть тяжелая по процессору задача, а я говорил именно о последних.

MSS>>Это ненадолго.


R>10 мс. Смотри сам.


10мс кластер из 16 страниц с диска прочесть? 6.4MB/s дискового IO? не верю.

К тому же часто используемые страницы не уйдут в своп/дискард никогда, пока трешинг не наступит.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[3]: Performance & Scalability пост №3: thread - ресурс ил
От: BulatZiganshin  
Дата: 18.08.07 15:10
Оценка:
N>Спагетти обычно не получается. Получается событийно-управляемый движок с несколькими классами событий (готовность асинхронной операции, готовность сокета к действию, срабатывание таймера, сигнал...), которые отрабатываются своими указанными обработчиками.

у вас как-то "всё для фронта, всё для победы". ищете самые сложные пути лишь бы не потерять ни процента производительности

если вспомнить, как реализуются библиотеки лёгких тредов, то они как раз и преобразуют простой, естественно написанный код хоть с тысячами нитей в такую событийно управляемую систему, где каждая лёгкая нить продолжает исполняться когда её i/o закончен.

берёте такую библиотеку и пожалуйста — у вас готовая система, которой удобно пользоваться программисту и не страдает проихводительность. при использовании такой системы думать о сложностях шедулинга, пулах нитей вообще не приходится — библиотека запускает в начале работы по одной реальной нити на процессор, а программисты используют столько тредов, сколько им нужно. эрланг так работает, например


R>10 мс. Смотри сам.


>10мс кластер из 16 страниц с диска прочесть? 6.4MB/s дискового IO? не верю.


это disk seek time. проверено на архиваторе — если надо сжать кучу мелких файлов, то время упаковки = кол-ву файлов/100
Люди, я люблю вас! Будьте бдительны!!!
Re[4]: Performance & Scalability пост №3: thread - ресурс ил
От: Maxim S. Shatskih Россия  
Дата: 18.08.07 19:39
Оценка:
BZ>у вас как-то "всё для фронта, всё для победы". ищете самые сложные пути лишь бы не потерять ни процента производительности

Есть такие места в коде, где это оправдано. Мои посты — как раз о них. Естественно, никто не будет выжимать максимум из IOCTL_DISK_GET_DRIVE_GEOMETRY или тому подобной операции query property. Но есть и критические места, о них и пишу.

BZ>берёте такую библиотеку и пожалуйста — у вас готовая система, которой удобно пользоваться программисту и не страдает проихводительность. при использовании такой системы думать о сложностях шедулинга, пулах нитей вообще не приходится — библиотека запускает в начале работы по одной реальной нити на процессор, а программисты используют столько тредов, сколько им нужно. эрланг так работает, например


Можно и так. В виндах были фиберы, но, как я помню, WaitForSingleObject стопил все фиберы текущей нити, потому это — совсем "не то". Вот что "то" — это юзер-модные реализации pthreads.
Занимайтесь LoveCraftом, а не WarCraftом!
Re[5]: Performance & Scalability пост №3: thread - ресурс ил
От: Cyberax Марс  
Дата: 18.08.07 19:53
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

BZ>>берёте такую библиотеку и пожалуйста — у вас готовая система, которой удобно пользоваться программисту и не страдает проихводительность. при использовании такой системы думать о сложностях шедулинга, пулах нитей вообще не приходится — библиотека запускает в начале работы по одной реальной нити на процессор, а программисты используют столько тредов, сколько им нужно. эрланг так работает, например

MSS>Можно и так. В виндах были фиберы, но, как я помню, WaitForSingleObject стопил все фиберы текущей нити, потому это — совсем "не то". Вот что "то" — это юзер-модные реализации pthreads.
Фибры — это и есть почти что user-mode pthreads. То есть, ты их сам должен переключать. Если ты делаешь выполняешь блокирующуюся операцию — сам виноват.
Sapienti sat!
Re[6]: Performance & Scalability пост №3: thread - ресурс ил
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.08.07 07:12
Оценка:
Здравствуйте, Cyberax, Вы писали:

MSS>>Можно и так. В виндах были фиберы, но, как я помню, WaitForSingleObject стопил все фиберы текущей нити, потому это — совсем "не то". Вот что "то" — это юзер-модные реализации pthreads.

C>Фибры — это и есть почти что user-mode pthreads.

Буква 'p', по-моему, лишняя. pthreads не предполагают кооперативный режим.

C> То есть, ты их сам должен переключать. Если ты делаешь выполняешь блокирующуюся операцию — сам виноват.
The God is real, unless declared integer.
Re[4]: Performance & Scalability пост №3: thread - ресурс ил
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.08.07 07:13
Оценка: +1
Здравствуйте, BulatZiganshin, Вы писали:

N>>Спагетти обычно не получается. Получается событийно-управляемый движок с несколькими классами событий (готовность асинхронной операции, готовность сокета к действию, срабатывание таймера, сигнал...), которые отрабатываются своими указанными обработчиками.

BZ>у вас как-то "всё для фронта, всё для победы". ищете самые сложные пути лишь бы не потерять ни процента производительности

Не вижу оснований для подобного вывода. Что сложного в обычном событийном движке и автоматах?

BZ>если вспомнить, как реализуются библиотеки лёгких тредов, то они как раз и преобразуют простой, естественно написанный код хоть с тысячами нитей в такую событийно управляемую систему, где каждая лёгкая нить продолжает исполняться когда её i/o закончен.

BZ>берёте такую библиотеку и пожалуйста — у вас готовая система, которой удобно пользоваться программисту и не страдает проихводительность. при использовании такой системы думать о сложностях шедулинга, пулах нитей вообще не приходится — библиотека запускает в начале работы по одной реальной нити на процессор, а программисты используют столько тредов, сколько им нужно. эрланг так работает, например ;)

О да, эрланг упомянули. Вы хоть сами-то в курсе, что в нём полностью событийно-управляемое построение, а разные процессы — средство обеспечения надёжности, а отнюдь не удобства написания в традиционном стиле? Или уже забыли?;))))
The God is real, unless declared integer.
Re[7]: Performance & Scalability пост №3: thread - ресурс ил
От: Cyberax Марс  
Дата: 19.08.07 18:51
Оценка:
netch80 wrote:
> MSS>>Можно и так. В виндах были фиберы, но, как я помню,
> WaitForSingleObject стопил все фиберы текущей нити, потому это — совсем
> "не то". Вот что "то" — это юзер-модные реализации pthreads.
> C>Фибры — это и есть почти что user-mode pthreads.
> Буква 'p', по-моему, лишняя. pthreads не предполагают кооперативный режим.
Это смотря какие. Есть и кооперативные реализации (сам использовал лет 5
назад такую), которые на setjml/longjmp работают.
Posted via RSDN NNTP Server 2.1 beta
Sapienti sat!
Re[8]: Performance & Scalability пост №3: thread - ресурс ил
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 19.08.07 18:55
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>netch80 wrote:

>> MSS>>Можно и так. В виндах были фиберы, но, как я помню,
>> WaitForSingleObject стопил все фиберы текущей нити, потому это — совсем
>> "не то". Вот что "то" — это юзер-модные реализации pthreads.
>> C>Фибры — это и есть почти что user-mode pthreads.
>> Буква 'p', по-моему, лишняя. pthreads не предполагают кооперативный режим.
C>Это смотря какие. Есть и кооперативные реализации (сам использовал лет 5
C>назад такую), которые на setjml/longjmp работают.

Они нестандартны. А что они "есть" я знаю — с libc_r довелось поработать:)
The God is real, unless declared integer.
Re[5]: Performance & Scalability пост №3: thread - ресурс ил
От: BulatZiganshin  
Дата: 19.08.07 20:16
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

BZ>>у вас как-то "всё для фронта, всё для победы". ищете самые сложные пути лишь бы не потерять ни процента производительности


MSS>Есть такие места в коде, где это оправдано. Мои посты — как раз о них. Естественно, никто не будет выжимать максимум из IOCTL_DISK_GET_DRIVE_GEOMETRY или тому подобной операции query property. Но есть и критические места, о них и пишу.


мне кажется, вы ошибаетесь и ваша ошибка состоит в том, что вы принимаете "высокопроизводительный" и "мы будем экономить на всём, на чём только можно" как синонимы. приведу пример со своей колокольни — лет 15 назад я занимался оптимизацией программ и выделывал головокружительные ассемблерные трюки. но если сейчас меня спросят "как сейчас оптимизировать?" я скажу, что самое важное — это считать кеш-промахи, даже выбор ЯП по сравнению с этим второстепенен. людей, для которых это очевидно и им дейстивтельно нужны ассемблерные трюки — практически нет

вот также и вы излагаете свой богатый опыт оптимизации высокопроизводительных систем. но при это упор имхо надо делать на архитектурную оптимизацию, на общие принципы, а не конкретные выполняемые вручную трюки типа affinity mask и автоматов. этой низкоуровневой оптимизацией должна заниматься библиотека, ОС и т.д. — наша задача в большинстве случаев просто выбрать подходящую. людей же, для которых ваши высокоуровневые рассуждения очевидны, но возможностей современных библиотек недостаточно и им действительно нужны тонкости ручного шедулинга — пренебрежимо мало

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


BZ>>берёте такую библиотеку и пожалуйста — у вас готовая система, которой удобно пользоваться программисту и не страдает проихводительность. при использовании такой системы думать о сложностях шедулинга, пулах нитей вообще не приходится — библиотека запускает в начале работы по одной реальной нити на процессор, а программисты используют столько тредов, сколько им нужно. эрланг так работает, например


MSS>Можно и так. В виндах были фиберы, но, как я помню, WaitForSingleObject стопил все фиберы текущей нити, потому это — совсем "не то". Вот что "то" — это юзер-модные реализации pthreads.


дак всего лишь надо сделать обёртку вокруг WaitForSingleObject и прчих неудобных операций. т.е. написать свою библиотечку в/в. думаю, это гораздо проще и результатом будет пользоваться удобней, чем работать в event-driven модели на *прикладном* уровне
Люди, я люблю вас! Будьте бдительны!!!
Re[5]: Performance & Scalability пост №3: thread - ресурс ил
От: BulatZiganshin  
Дата: 19.08.07 20:29
Оценка:
Здравствуйте, netch80, Вы писали:

N>Здравствуйте, BulatZiganshin, Вы писали:


N>>>Спагетти обычно не получается. Получается событийно-управляемый движок с несколькими классами событий (готовность асинхронной операции, готовность сокета к действию, срабатывание таймера, сигнал...), которые отрабатываются своими указанными обработчиками.

BZ>>у вас как-то "всё для фронта, всё для победы". ищете самые сложные пути лишь бы не потерять ни процента производительности

N>Не вижу оснований для подобного вывода. Что сложного в обычном событийном движке и автоматах?


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

BZ>>если вспомнить, как реализуются библиотеки лёгких тредов, то они как раз и преобразуют простой, естественно написанный код хоть с тысячами нитей в такую событийно управляемую систему, где каждая лёгкая нить продолжает исполняться когда её i/o закончен.

BZ>>берёте такую библиотеку и пожалуйста — у вас готовая система, которой удобно пользоваться программисту и не страдает проихводительность. при использовании такой системы думать о сложностях шедулинга, пулах нитей вообще не приходится — библиотека запускает в начале работы по одной реальной нити на процессор, а программисты используют столько тредов, сколько им нужно. эрланг так работает, например

N>О да, эрланг упомянули. Вы хоть сами-то в курсе, что в нём полностью событийно-управляемое построение, а разные процессы — средство обеспечения надёжности, а отнюдь не удобства написания в традиционном стиле? Или уже забыли?)))


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

в ghc создаётся сколько угодно лёгких тредов. RTS для их исполнения создаёт определённое кол-во тредов ОС. переключение между лёгкими тредами выполняется по таймеру. если лёгкий тред начал i/o, то операция иниццируется и её хендл добавлется в список для select/WaitMultipleObjects, а лёгкий тред переклдючают в состояние ожидания. специальный тред ОС ждёт окончания этих операций и разблокирует соответствующие лёгкие треды. таким образом, веб-сервер к примеру обслуживает сотни клиентов, используя совершенно естеественный, прямолинейно написанный код:

Writing High-Performance Server Applications in Haskell, Case Study: A Haskell Web Server, [http://www.haskell.org/~simonmar/papers/web-server.ps.gz]
Люди, я люблю вас! Будьте бдительны!!!
Re[5]: Performance & Scalability пост №3: thread - ресурс ил
От: remark Россия http://www.1024cores.net/
Дата: 19.08.07 21:36
Оценка:
Здравствуйте, Maxim S. Shatskih, Вы писали:

R>>А если работа не совсем одинаково размера? Ну например, работа включает в себя запрос к БД, запрос может обрабатываться в БД на порядок разное время.


MSS>Запрос к БД не есть тяжелая по процессору задача, а я говорил именно о последних.


А что делать с первыми?

MSS>>>Это ненадолго.


R>>10 мс. Смотри сам.


MSS>10мс кластер из 16 страниц с диска прочесть? 6.4MB/s дискового IO? не верю.


Основное время на позиционирование головки. Позиционирование головки — 8мс. А дальше можно хоть с бесконечной скоростью данные считывать — результат будет прежним — 8 мс.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.