On 16.09.2011 19:18, code8 wrote:
> A>>>соц-сети — просто балансировка на кластер. > B>Тут вообще без сомнений. Какие там нафиг нагрузки? > > ОК. Под "соц. сети" я имел ввиду сервисы, которые реализуют REST-API... > да какая вообще разница ? > Есть задача, есть требования — "много коротких, быстрых сессий".
Разница очень существенная. Эти самые "короткие быстрые REST-API сессии"
должны быть не только короткими и быстрыми, но и делать что-то
осмысленное. IRL, 99% всех приложений приходится для этого обращаться к
хранилищам данных, внешним по отношению к JVM (БД, ФС, etc.)
Как следствие, затык чаще всего получается на дисковом/сетевом IO а
совсем не при передаче данных между отдельными потоками в JVM, что на
первый взгляд и оптимизируют авторы Disruptor, хотя конечно вечер
пятницы не лучшее время для разбирательства в столь концептуальных вещах
> Это было лирическое отступление. Давайте вернёмся к задаче. > Как бы мы не убеждали себя, в её "специфичности" ситуация не изменится — > задача (есть) и чем дальше тем чаще она будет возникать. А это значит, > что нужно думать как её решать. Балансировка нагрузки это не решение > задачи. Это способ не думать о решении задачи. Сейчас этот способ > срабатывает, завтра — нет.
"Я намерен жить вечно, пока всё идёт нормально" (с).
> Я давно пишу на Java (а последние три года — только на Java). > И я хочу писать на Java hiload-проекты. Но степень "нестандартных" > решений которые приходится принимать затачивая java-проект под hiload > заставляет задуматься — а туда ли я иду ?
Расскажите в общих чертах какова ваша роль в этих предполагаемых "hiload
java-проектах", кто заказчик, какие задачи, какие альтернативы jvm
рассматривали и т.п. Очень интересная тема.
> Очень прошу — отвечать по существу вопроса — какие _техники_ вы знаете > для решения следующих проблем: > 1. GC с его Stop the world
В большинстве случаев лечится настройками.
> 2. Отсутствие "прямого" способа борьбы с False sharing > 3. Отсутствие "прямого" способа назначать thread affinity > 4. Не эффективная реализация Atomic (CMPXCHG вместо XADD) > 5. не управляемый JIT ...
Ни разу не сталкивались с такими проблемами, возможно просто не умеем
такие ситуации диагностировать. Интересно было бы послушать как
диагностировать например false sharding. Вот у нас есть приложение,
работающее в jvm (AS) допустим в линуксе каком-нибудь — на что смотреть?
--
WBR,
Serge.
Posted via RSDN NNTP Server 2.1 beta
Re[12]: Используем правильные инструменты!
От:
Аноним
Дата:
16.09.11 16:37
Оценка:
H>..., хотя конечно вечер пятницы не лучшее время для разбирательства в столь концептуальных вещах H>
зато вечер пятницы — лучшее время для пятничного троллинга
Здравствуйте, hrensgory, Вы писали:
H>On 16.09.2011 19:18, code8 wrote:
>> 2. Отсутствие "прямого" способа борьбы с False sharing >> 3. Отсутствие "прямого" способа назначать thread affinity >> 4. Не эффективная реализация Atomic (CMPXCHG вместо XADD) >> 5. не управляемый JIT ...
H>Ни разу не сталкивались с такими проблемами, возможно просто не умеем H>такие ситуации диагностировать. Интересно было бы послушать как H>диагностировать например false sharding. Вот у нас есть приложение, H>работающее в jvm (AS) допустим в линуксе каком-нибудь — на что смотреть?
Чудак-человек Я ж и говорю, что в Java нет "прямых" способов борьбы с false sharing.
Пока Вы не знаете про этот эффект — считайте Вам повезло.
Это как "эффект наблюдателя" в квантовой механике — пока его (наблюдателя) нет всё хорошо, как только он появляется — все меняется...
False sharing есть в ПО любого уровня. Просто большинству нет до него дела — гораздо важнее борьба с blocking IO и т.д...
Но в задачах, которые должны выжимать из железа максимум False sharing проявляется во всей красе... Этот эффект — следствие работы системы кэшировая CPU. Эта система обеспечивает когерентность локальных кэшей ядер. Чем больше ядер тем сильнее эффект от False sharing. Соответственно, начиная с 8-ми ядер игнорировать его нельзя уже для ПО любого уровня.
False sharing возникает когда несколько ядер читают или пишут данные, в пределах одной линии кэша (64 байта) — классический пример "массив счётчиков". Восемь потоков, каждый инкрементирует свой счётчик. Это работает в _десятки_ раз медленнее чем если бы каждый счётчик располагался в отдельной линии кэша (на расстоянии 64 байта друг от друга). Да — JIT может "оптимизировать" — разместить счётчик в регистре. Тогда False sharing не будет, но текущее значение счётчика не будет доступно из другого потока...
Чтобы убедиться, в наличии False sharing своего кода я рекомендую выполнить несколько вариантов тестирования в различной конфигурации processor affinity. И сравнить тайминги. Механизм, обеспечивающий когерентность кэшей будет проявлять себя по-разному и на тестах это видно.
Понимаю, что описал сумбурно — всё-таки, действительно, пятница-вечер, но, надеюсь, идею вы уловили
Здравствуйте, code8, Вы писали:
C>1. GC с его Stop the world
— анализ и настройка
— вынос больших статичных данных из кучи — BigMemory или NoSQL.
— Real-time Java (экзотика, но всё же)
C>2. Отсутствие "прямого" способа борьбы с False sharing
Пока не разобрался на что оно влияет в hiload.
C>3. Отсутствие "прямого" способа назначать thread affinity
Оно зачем надо? Можно GC потоки назначить.
C>4. Не эффективная реализация Atomic (CMPXCHG вместо XADD)
Это и предыдущие два пункта лечатся через OpenJDK
C>5. не управляемый JIT
В каком смысле? Настроек много всяких. Чего не хватает?
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, code8, Вы писали:
C>>1. GC с его Stop the world B>- анализ и настройка B>- вынос больших статичных данных из кучи — BigMemory или NoSQL. B>- Real-time Java (экзотика, но всё же)
C>>2. Отсутствие "прямого" способа борьбы с False sharing B>Пока не разобрался на что оно влияет в hiload.
почитайте моё предыдущее сообщение в этом треде...
C>>3. Отсутствие "прямого" способа назначать thread affinity B>Оно зачем надо? Можно GC потоки назначить.
+ к производительности, если программный поток закрепляется за аппаратным (Disruptor V2 это доказал, вы знаете где почитать
C>>4. Не эффективная реализация Atomic (CMPXCHG вместо XADD) B>Это и предыдущие два пункта лечатся через OpenJDK
а можно ссылку, что Atomic в OpenJDK реализован на XADD ?
C>>5. не управляемый JIT B>В каком смысле? Настроек много всяких. Чего не хватает?
не хватает, например, memory alignment для борьбы с false sharing
Здравствуйте, code8, Вы писали:
C>Прошу высказываться по теме: "Пригодна ли JVM для реализации высоконагруженных (скажем, 1М TPS), low-latency (<10 ms) проектов" ?
C>Сразу скажу — я знаю про LMAX и иx Disruptor. Собственно, именно поэтому и хочу узнать ВАШЕ мнение — "а тот ли инструмент использовали эти ребята для борьбы False Sharing, Blocking и Races" ?
C>P.S. Очевидные "грабли" JVM для low latency hiload — проектов: C>1. GC с его Stop the world C>2. Отсутствие "прямого" способа борьбы с False sharing C>3. Отсутствие "прямого" способа назначать thread affinity C>4. Не эффективная реализация Atomic (CMPXCHG вместо XADD) C>5. не управляемый JIT ...
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, avpavlov, Вы писали:
A>>Во всяком случае про те что я читал — все (и ММОГ и сс) были организованы именно так. Нет смысла убиваться и делать один сервер, которого рано или поздно не хватит. Проще сразу думать в сторону балансировки. B>+1. Вроде ни одной топовой MMOG, где можно собрать сотню тысяч игроков в одном месте нет. Есть уникальные решения где всё на одном сервере крутится. Но там всё равно внутренние сегментирование имеется.
есть EVE online, где мир для всех игроков единый, но там есть "естественная" точка сегментирования нагрузки на сервера — звездные системы и планеты.
Re[2]: Используем правильные инструменты!
От:
Аноним
Дата:
19.09.11 06:07
Оценка:
S>в сторону erlang смотрели?
пятница закончилась, тролль уже затих.
не кормите троллей, не будите их.
C>False sharing возникает когда несколько ядер читают или пишут данные, в пределах одной линии кэша (64 байта) — классический пример "массив счётчиков". Восемь потоков, каждый инкрементирует свой счётчик. Это работает в _десятки_ раз медленнее чем если бы каждый счётчик располагался в отдельной линии кэша (на расстоянии 64 байта друг от друга). Да — JIT может "оптимизировать" — разместить счётчик в регистре. Тогда False sharing не будет, но текущее значение счётчика не будет доступно из другого потока...
Вообще довольно интересное утверждение на счет массива.
Вот есть такая штука от Cliff Click ConcurrentAutoTable. По сути дела это атомарный счетчик, который распределяет CAS операции на массив, вместо того, чтобы обновлять один регистр. И автор утверждает следующие:
Updates are striped across an array of counters to avoid cache contention
and has been tested with performance scaling linearly up to 768 CPUs.
Что как бе говорит нам что не так все плохо.
Вообще складывается впечатление, что ты рекламируешь этот disruptor. Ты его разрабатываешь что ли? Хотя, судя по коду, там вообще кроме этого paddedlong и нет ничего. Но и там реализация довольно спорная. Наклепал филдов в класс что бы кеш линию забить и все. Тестов нет, вообще говоря. Что произойдет, если на платформе будет другой размер кеш линии? Да и выделение на регистр целой линии кеша, довольно спорное. Их, этих линий, нифига не бесконечно колличество. Где процессор будет хранить другие переменные приложения, когда все кеш линии будут заняты этими мегалонгами?
Микробенчмарки в блоге, не сильно хорошо сделаны. Но вроде действительно работет быстрее. Технику можно взять на вооружение, но носиться с ней как с писаной торбой, думаю, смысла нет.
Здравствуйте, avpavlov, Вы писали:
A>есть EVE online, где мир для всех игроков единый, но там есть "естественная" точка сегментирования нагрузки на сервера — звездные системы и планеты.
Такие "естественные" точки сегментирования везде и делают. В EVE тоже вроде ограничение до 200 кораблей в битве (т.е. сегменте)? Там вместо кластера всё по блейдам разбросано. Суть та же самая, хотя хардварно железка как бы одна.
Здравствуйте, Blazkowicz, Вы писали:
B>Такие "естественные" точки сегментирования везде и делают. В EVE тоже вроде ограничение до 200 кораблей в битве (т.е. сегменте)? Там вместо кластера всё по блейдам разбросано. Суть та же самая, хотя хардварно железка как бы одна.
Соврал. Ограничения, действительно, нет. Но при определенном количестве клиентов начинаются лаги, по причине всё той же сегментированой структуры.
Здравствуйте, code8, Вы писали:
C>Прошу высказываться по теме: "Пригодна ли JVM для реализации высоконагруженных (скажем, 1М TPS), low-latency (<10 ms) проектов" ?
Пригодна. Трейдинговые системы на ней радостно бегают и реально быстро.
C>Сразу скажу — я знаю про LMAX и иx Disruptor. Собственно, именно поэтому и хочу узнать ВАШЕ мнение — "а тот ли инструмент использовали эти ребята для борьбы False Sharing, Blocking и Races" ? C>Ребята в LMAX просто молодцы! Но нафига ???
Ну рабоает же
Думаю, что какой бы тул (более-менее адекватный, ессесно) не был выбран, все равно будут проблемы и их сложность будет примерно одинаковая. На яве одно, на плюсах или где-то еще — другое.
Не касаемо перфоменса, на яве удобно, что клиент может пользовать те же библиотеки протокола, что и сервер. Это бенефит, если клиент тоже на яве.
Здравствуйте, Nicht, Вы писали:
N>Здравствуйте, code8, Вы писали:
C>>False sharing возникает когда несколько ядер читают или пишут данные, в пределах одной линии кэша (64 байта) — классический пример "массив счётчиков". Восемь потоков, каждый инкрементирует свой счётчик. Это работает в _десятки_ раз медленнее чем если бы каждый счётчик располагался в отдельной линии кэша (на расстоянии 64 байта друг от друга). Да — JIT может "оптимизировать" — разместить счётчик в регистре. Тогда False sharing не будет, но текущее значение счётчика не будет доступно из другого потока...
N>Вообще довольно интересное утверждение на счет массива. N>Вот есть такая штука от Cliff Click ConcurrentAutoTable. По сути дела это атомарный счетчик, который распределяет CAS операции на массив, вместо того, чтобы обновлять один регистр. И автор утверждает следующие: N>
N>Updates are striped across an array of counters to avoid cache contention
N>and has been tested with performance scaling linearly up to 768 CPUs.
N>Что как бе говорит нам что не так все плохо.
насчёт записи в массив, ячейки которого размещаются в одной кэш-линии, из разных _ядер_ поясню:
— каждое ядро имеет свой кэш
— операция записи требует чтобы кэш ядра стал "хозяином" кэш-линии, в которую производится запись
— "хозяин" у кэш-линии всегда один
— если несколько ядер пишут в одну и туже кэш-линию происходит постоянная "смена хозяина"
— "смена хозяина" предполагает получение подтверждений от всех ядер (чем больше ядер-тем дольше)
фактически, это описание MESI-протокола.
но вы можете не верить — и так работает, какая разница как...
Здравствуйте, code8, Вы писали:
C>фактически, это описание MESI-протокола. C>но вы можете не верить — и так работает, какая разница как...
Что значит не верю? Я понимаю что все так и происходит, как ты говоришь. Просто мне кажется тикаие вещи надо отдавать на откуп оптимизирующему компилятору, а не писать давольно спорные костыли.
Я говорил про то, что забивать кешлинии — значит мешать оптимизирующему компилятору и процессору делать их работу. Тоесть за место того что бы гонять почти пустые кешлинии по систем басу, процессор мог бы что нибудь еще засинхронизировать, а так он по сути синхронизирует только один регистр. Опять же смущает платформозависимая реализация. И крайне смущают некомпетентные микробенчмарки в блоге.
Здравствуйте, Nicht, Вы писали:
N>Что значит не верю? Я понимаю что все так и происходит, как ты говоришь. Просто мне кажется тикаие вещи надо отдавать на откуп оптимизирующему компилятору, а не писать давольно спорные костыли. N>Я говорил про то, что забивать кешлинии — значит мешать оптимизирующему компилятору и процессору делать их работу. Тоесть за место того что бы гонять почти пустые кешлинии по систем басу, процессор мог бы что нибудь еще засинхронизировать, а так он по сути синхронизирует только один регистр. Опять же смущает платформозависимая реализация. И крайне смущают некомпетентные микробенчмарки в блоге.
круто было бы если бы "оптимизирующий" компилятор сам разруливал ситуации, когда возникает этот false sharing... только вот как это ему сделать если этот эффект проявляет себя только на runtime ?
так что хочешь-не хочешь, а когда нужно выжать 100% придется лезть руками...и кроме как гонять "пустые" кэш-линии я способа не знаю... а Вы ?
мне кажется, когда речь заходит о concurrency и scalability нужно думать в терминах "железа". а железу пофиг на биты-байты, оно кэш-линиями оперирует.
Здравствуйте, code8, Вы писали:
C>круто было бы если бы "оптимизирующий" компилятор сам разруливал ситуации, когда возникает этот false sharing... только вот как это ему сделать если этот эффект проявляет себя только на runtime ? C>так что хочешь-не хочешь, а когда нужно выжать 100% придется лезть руками...и кроме как гонять "пустые" кэш-линии я способа не знаю... а Вы ?
Ты не поверишь. В java оптимизирующий компилятор работает именно в рантайме. И как раз из за этого меня смущают плохие микробенчмарки. Они просто не дают компилятору наормально развернуться. Но, по правде сказать, я с ходу не нагуглил того что в hotspot opto есть какие — то false sharing оптимизации. Но я тут не вполне компетентен.
что не тролль, что ли? звиняй тогда
в качестве извинения — копай откуда-нибудь отсюда. там про atomic_add на xadd (сюрприз ) под linux_x86. аналог под своё найдёшь, если надо.
а с остальными своими непонятками ты уж как-нить сам )
Здравствуйте, abch-98-ru, Вы писали:
A9R>что не тролль, что ли? звиняй тогда A9R>в качестве извинения — копай откуда-нибудь отсюда. там про atomic_add на xadd (сюрприз ) под linux_x86. аналог под своё найдёшь, если надо.
о, клёва! благодарю!