Re[26]: dotnet vs java 2016-2020
От: vdimas Россия  
Дата: 13.10.16 09:59
Оценка:
Здравствуйте, ·, Вы писали:

·>Ты по ссылке-то сходил? Там может ничего никуда не добавляться, тот же самый тупой new Thread().Start();.


Посмотрел. А ты сам-то смотрел? ))
Чтобы эта ветка была вызвана, у самой задачи необходимо явно установить флаг LongRunning.
Разговор ни о чем, кароч.
Re[25]: dotnet vs java 2016-2020
От: vdimas Россия  
Дата: 13.10.16 10:02
Оценка: +1
Здравствуйте, ·, Вы писали:

·>Ну и зачем тредпул для долгоиграющих тредов?


Долгоиграющие треды не нужны при хорошей степени асинхронности кода.
Они даже резко вредны.
Re[23]: dotnet vs java 2016-2020
От: vdimas Россия  
Дата: 13.10.16 10:12
Оценка:
Здравствуйте, ·, Вы писали:

V>>·>Кстати, я же тебе посылал этот линк: http://mattwarren.org/2014/06/18/measuring-the-impact-of-the-net-garbage-collector/

V>>·>Паузы бывают до 4 СЕКУНД!!!
V>>Ну вот я тебе послал линк на опции конфигурации режимов GC в ответ.
V>>Потому что да, если взять опцию Batch, то паузы будут как в оракловой джаве.
·>Ну в этой статье эти режимы и обсуждаются.
·>

But as you can see from the quote, this doesn’t get rid of pauses completely, it just minimises them. Even the SustainedLowLatency mode isn’t enough, “The collector tries to perform only generation 0, generation 1, and concurrent generation 2 collections. Full blocking collections may still occur if the system is under memory pressure.”


Ну да, раз в несколько суток, угу. А то и никогда, потому что фоновый коллектор обычно неплохо справляется, если не давать нагрузку на 1-е поколение объектов. Впрочем, я уже повторяюсь, просто напомню медицинский факт — если знать особенности дотнета и не плодить 1-е поколение, то "stop-word" может никогда и не возникнуть.

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

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


·>Т.е.? В "стандартной" версии движка тоже несколько алгоритмов с тучей параметров, которые можно покрутить.


Насколько я понял, в оракловой всего два алгоритма, остальные настройки — лишь параметры этих двух.
Re[27]: dotnet vs java 2016-2020
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.10.16 10:15
Оценка:
Здравствуйте, ·, Вы писали:

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


V>>>>·>Оно не деприкейтед. Надо же понимать, что все эти ваши таски — лишь более удобная в каких-то ситуациях обёртка поверх этих самых new Thread.

V>>>>Над thread pool, причём, там всё на lock-free и жутко заоптимизировано.
S>>·>Ну и зачем тредпул для долгоиграющих тредов?
S>> В твоем примере не долгоиграющие, а долго ожидающие. Для этого существуют async await.
·>О божемодераторе, дай сил не перейти на оскорбления.
·>Ожидающие чего??? Какой такой тредпул в LL приложении??? Можешь объяснить в какой момент времени тред с таким таском будет отдаваться в пул?
·>"while(true)" это не просто долго-, но даже вечно-играющий цикл.

В твоем примере

var threadCounter = 0;
  while (true)
  {
    var text = new string((char)random.Next(start, end + 1), 1000);
    stringCache.Set(text.GetHashCode(), text);

    // Use 80K, If we are > 85,000 bytes = LOH and we don't want these there
    var bytes = new byte[80 * 1024]; 
    random.NextBytes(bytes);
    bytesCache.Set(bytes.GetHashCode(), bytes);

    threadCounter++;
  //  Thread.Sleep(1); // So we don't thrash the CPU!!!!
//   заменяем на 
await Task.Delay(1)
// Путь дает работу другой задаче.
  }


Таких циклов обычно полно, но как правило они ожидают некое события.
Постоянной числодробилкой занимаются БД, и спец приложения. Но они и специально оптимизируются.

S>>Для долгоиграющих задач есть свой планировщик. И опция TaskCreationOptions.LongRunning

S>>http://stackoverflow.com/questions/26921191/how-to-pass-longrunning-flag-specifically-to-task-run
·>Что ты мне сказки рассказываешь? Я же ссылкой даже тыкнул уже. Тебе лень было посмотреть? Вот как устроен твой магический планировщик для долгоиграющих задач:
·>
·>protected internal override void QueueTask(Task task)
·>{
·>    if ((task.Options & TaskCreationOptions.LongRunning) != 0)
·>    {
·>        // Run LongRunning tasks on their own dedicated thread.
·>        Thread thread = new Thread(s_longRunningThreadWork);
·>        thread.IsBackground = true; // Keep this thread from blocking process shutdown
·>        thread.Start(task);
·>    }
·>...
·>


Ну он в бакграунде. Тогда и в тесте нужно сравнивать с фоновыми. Опять, же все решается через async await даже в твоем примере.
А уж 2000 долгоиграющих потоков это из области неправильного использования инструментов. Про 10 000 потоков я тебе давал ссылку.

Then to ensure that the objects are kept around long enough, they are both put into a Least Recently Used (LRU) cache, that holds the 2000 most recent items.


Просто сделай разные тесты. И выложи. Тогда будет более правильная картина.
и солнце б утром не вставало, когда бы не было меня
Re[28]: dotnet vs java 2016-2020
От: · Великобритания  
Дата: 13.10.16 10:24
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>>> За счет того, что состояние хранит не на стеке потока, и в регистрах, а в полях класса. А те которые в потоке с ними проще работать, так как в пуле их немного.

S>·>Какое ты увидел состояние в том коде? В каких полях какого класса?
S> А поток, что выполняет? В Task создается класс и автомат для перехода по await
В потоке эмулируется конкурентный доступ к общему кешу.

S>·>Эээ... И что? Я всё ещё не понимаю как это относится к тому коду, к особенностям работы gc и к LL?

S> Это относится к тому, что потоки это уже старое ненужное.
Ой-ё.

S>>> Кстати ветка по поводу асинхронного программирования. Как оптимизировать выполнения 10000 параллельных задач?

S>·>В случае LL выполнение 10000 параллельных задач не бывает. Не надо путать low latency и high throughput.
S> Ты привел какой то непонятный пример с огромным количеством потоков. На GC как раз влияет количество потоков, где нужно его останавливать, смотреть стек потока регистры.
К сожалению конкретных цифр я не смог найти, но в тексте написано "several threads", на случай если ты не знаешь английский переведу: "несколько потоков". Про "огромное количество потоков" ты придумал сам, с собой и спорь.
Несколько потоков это обычно для LL-применений: разные треды делают вполне конкретную и довольно разную работу: читают данные из сетевого буфера, делают какие-то вычисления, реплицируют, пишут на диск, пишут в сеть и т.п. Таких тредов как правило меньше чем ядер процессора.
10к потоков характерно для high throughput задач, когда один сервер с жалкой сотней ядер тужится эффективно обработать миллионы однотипных запросов, в таких случаях редкие зависоны на 1-2 секунды никто не замечает, в LL мире такой зависон является critical production issue и в лучшем случае персональные извинения перед клиентом.

S>В Task все данные хранятся внутри генерируемого класса. Async/await и механизм реализации в C# 5.0

S>https://habrahabr.ru/post/260217/
S> При этом пока задача вне потока выполнения код хранится в виде делегата. Никакого стека, регистров. Нужно приостановить только планировщик.
А делегат где хранится?
Ты видимо вообще не понимаешь что такое LL. Там ничего приостанавливать нельзя.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[21]: dotnet vs java 2016-2020
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 13.10.16 10:35
Оценка:
Здравствуйте, ·, Вы писали:

·>Паузы бывают до 4 СЕКУНД!!!


Вообще то и больше, до полутора минут. Вопрос только в том, сколько тебе памяти надо и какой объем надо перелопать сборщику.

·>Ну и ремарка оттуда же:

·>

Aside: In the Java world there is a commercial Pauseless Garbage Collector available from Azul Systems. It uses a patented technique to offer “Predictable, consistent garbage collection (GC) behavior” and “Predictable, consistent application response times”, but there doesn’t seem to be anything like that in the .NET space.

·>конечно, это статья двухлетней давности, может что-то и поменялось с тех пор... но я почему-то уверен, что нет.

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

Возможно в .Net Core все изменилось, не в курсе. Да и .Net Core еще ребенок
Re[29]: dotnet vs java 2016-2020
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.10.16 10:44
Оценка:
Здравствуйте, ·, Вы писали:

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


S>>>> За счет того, что состояние хранит не на стеке потока, и в регистрах, а в полях класса. А те которые в потоке с ними проще работать, так как в пуле их немного.

S>>·>Какое ты увидел состояние в том коде? В каких полях какого класса?
S>> А поток, что выполняет? В Task создается класс и автомат для перехода по await
·>В потоке эмулируется конкурентный доступ к общему кешу.
Да только в реальной жизни это делается из пула потоков. Обычная практика для ASP.Net
И таких жутких историй нет.
Но в свое время была проблема, когда изменялись данные, которые находились в старших поколениях, для них GC делал движения, для того, что бы учесть эти изменения.
И соответственно огромные тормоза при изменении огромного количества ссылок.
http://rsdn.org/forum/dotnet/415352.1
Автор: Serginio1
Дата: 20.10.03


Это нужно учитывать. Посмотри на дату. Сейчас может все по другому.
Кстати по алгоритму то и получается, что кэш

 var bytes = new byte[80 * 1024]; 
    random.NextBytes(bytes);
    bytesCache.Set(bytes.GetHashCode(), bytes);


bytesCache будет постоянно обновляться. Поэтому если bytesCache будет постоянно в 0 поколении, то и задержки будут постоянными

S>>·>Эээ... И что? Я всё ещё не понимаю как это относится к тому коду, к особенностям работы gc и к LL?

S>> Это относится к тому, что потоки это уже старое ненужное.
·>Ой-ё.
Да-да
S>>>> Кстати ветка по поводу асинхронного программирования. Как оптимизировать выполнения 10000 параллельных задач?
S>>·>В случае LL выполнение 10000 параллельных задач не бывает. Не надо путать low latency и high throughput.
S>> Ты привел какой то непонятный пример с огромным количеством потоков. На GC как раз влияет количество потоков, где нужно его останавливать, смотреть стек потока регистры.
·>К сожалению конкретных цифр я не смог найти, но в тексте написано "several threads", на случай если ты не знаешь английский переведу: "несколько потоков". Про "огромное количество потоков" ты придумал сам, с собой и спорь.

Ну я же привел те
·>Несколько потоков это обычно для LL-применений: разные треды делают вполне конкретную и довольно разную работу: читают данные из сетевого буфера, делают какие-то вычисления, реплицируют, пишут на диск, пишут в сеть и т.п. Таких тредов как правило меньше чем ядер процессора.
Что прекрасно походит под async await.
·>10к потоков характерно для high throughput задач, когда один сервер с жалкой сотней ядер тужится эффективно обработать миллионы однотипных запросов, в таких случаях редкие зависоны на 1-2 секунды никто не замечает, в LL мире такой зависон является critical production issue и в лучшем случае персональные извинения перед клиентом.

S>>В Task все данные хранятся внутри генерируемого класса. Async/await и механизм реализации в C# 5.0

S>>https://habrahabr.ru/post/260217/
S>> При этом пока задача вне потока выполнения код хранится в виде делегата. Никакого стека, регистров. Нужно приостановить только планировщик.
·>А делегат где хранится?
В обычной или асинхронной очереди.
·>Ты видимо вообще не понимаешь что такое LL. Там ничего приостанавливать нельзя.

А как ты будешь собирать мусор? Для этого нужно знать граф доступных объектов, которые кстати хранятся в стеке и регистрах.
А все, что ты описываешь, это обычный async await. И ни у кого таких историй про задержки GC 2 секунды я не слышал.
А сколько в итоге то Объектов то хранится в bytesCache.
Количество строк ограничено алфавитом, и все символы повторяются 1000 раз


processingThreads[i] = new Thread(() =>
{
  var threadCounter = 0;
  while (true)
  {
    var text = new string((char)random.Next(start, end + 1), 1000);
    stringCache.Set(text.GetHashCode(), text);

    // Use 80K, If we are > 85,000 bytes = LOH and we don't want these there
    var bytes = new byte[80 * 1024]; 
    random.NextBytes(bytes);
    bytesCache.Set(bytes.GetHashCode(), bytes);

    threadCounter++;
    Thread.Sleep(1); // So we don't thrash the CPU!!!!
  }
});


Или всю память заполнили, а потом начинаем бороться с GC?
и солнце б утром не вставало, когда бы не было меня
Отредактировано 13.10.2016 11:15 Serginio1 . Предыдущая версия . Еще …
Отредактировано 13.10.2016 10:55 Serginio1 . Предыдущая версия .
Re[24]: dotnet vs java 2016-2020
От: · Великобритания  
Дата: 13.10.16 10:51
Оценка:
Здравствуйте, vdimas, Вы писали:

V>·>Ну в этой статье эти режимы и обсуждаются.

V>·>

But as you can see from the quote, this doesn’t get rid of pauses completely, it just minimises them. Even the SustainedLowLatency mode isn’t enough, “The collector tries to perform only generation 0, generation 1, and concurrent generation 2 collections. Full blocking collections may still occur if the system is under memory pressure.”

V>Ну да, раз в несколько суток, угу. А то и никогда, потому что фоновый коллектор обычно неплохо справляется, если не давать нагрузку на 1-е поколение объектов. Впрочем, я уже повторяюсь, просто напомню медицинский факт — если знать особенности дотнета и не плодить 1-е поколение, то "stop-word" может никогда и не возникнуть.
Как часто запускается gc определяется далеко не режимом gc, а зависит от того, что происходит в приложении. Случилось что-то интересное и неожиданное — CHF gone bananaz, ликвидировали пачку аккаунтов, — вот и забурлил мусор...

V>И это я еще не проходился язвительно по самой теме этого нелепого спора, когда у нас налицо кровавая борьба с самими управляемыми средами, ы-ы-ы.

В сабже управляемые среды... Холивар managed vs non-managed сюда не относится.

V>В общем, под специфические задачи надо брать специфический инструмент. Очевидно же, что обработка потокового медиа и HFT (это похожие по характеру задачи) — не является вотчиной управляемых сред. Это та самая суровая инженерная ошибка — выбрать в кач-ве инструментария решения таких задач дотнет или джаву.

Как оказывается не всегда ошибка.

V>·>Т.е.? В "стандартной" версии движка тоже несколько алгоритмов с тучей параметров, которые можно покрутить.

V>Насколько я понял, в оракловой всего два алгоритма, остальные настройки — лишь параметры этих двух.
Четыре: SerialGC/ParallelGC/ConcMarkSweepGC/G1GC
Выбор зависит от типичного размера кучи приложения, количества ядер процессора, количества тредов в приложении, к требованиям как переживать пиковые нагрузки и т.п.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[28]: dotnet vs java 2016-2020
От: · Великобритания  
Дата: 13.10.16 11:13
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> В твоем примере

S>await Task.Delay(1)
S>// Путь дает работу другой задаче.
Но зачем?? какой задаче? Повторяю, этих задач меньше чем ядер процессора.

S> Таких циклов обычно полно, но как правило они ожидают некое события.

Такие циклы в LL обычно делают busy spin, чтобы тред не дай боже с ядра не вытеснился, а ты тут со своими пулами.

S>Постоянной числодробилкой занимаются БД, и спец приложения.

С ума сошел? Какая такая БД в LL приложении?!!

S>Но они и специально оптимизируются.

Ну БД и на Java пишутся и оптимизируются отнюдь не await-ами. Ты зациклился на своих задачах.

S> Ну он в бакграунде. Тогда и в тесте нужно сравнивать с фоновыми. Опять, же все решается через async await даже в твоем примере.

Там же даже разжевано что значит "в бакграунде": Keep this thread from blocking process shutdown. Как это влияет на gc?
А что значит в бакграунде по твоему?

S> А уж 2000 долгоиграющих потоков это из области неправильного использования инструментов. Про 10 000 потоков я тебе давал ссылку.

S> Просто сделай разные тесты. И выложи. Тогда будет более правильная картина.
Аааа. Повторяю. Эти тесты показывают вполне конкретный юзкейс — требовние LL. В таком приложении обычно 3-4 важных потока, которые никогда не спят, живут каждый на своём физическом ядре, и никому больше это ядро не отдают. Плюс ещё десяток-два всяких обслуживающих потоков, для управления, отсылки логов, статистики и т.п. Плюс есть потоки самой операционки, плюс всякое IO оборудование с прерываниями. И это всё крутится на 64-ядерном железе.
Так вот в C# вменяемой производительности для такого юзкейса добиться хорошего поведения не удаётся. Паузы достигают величин более 50мс, azul zing даёт паузы менее 1мс.
Понимаешь тут какое дело... 50мс пауза не допустима, если публично рекламируется, что "у нас latency <4мс".
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[30]: dotnet vs java 2016-2020
От: · Великобритания  
Дата: 13.10.16 11:24
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>·>В потоке эмулируется конкурентный доступ к общему кешу.

S> Да только в реальной жизни это делается из пула потоков. Обычная практика для ASP.Net
Какая взаимосвязь между ASP.Net и LL? В ASP.Net на паузу в пару секунд раз в час никто никогда не обратит внимание.

S>·>К сожалению конкретных цифр я не смог найти, но в тексте написано "several threads", на случай если ты не знаешь английский переведу: "несколько потоков". Про "огромное количество потоков" ты придумал сам, с собой и спорь.

S> Ну я же привел те
Какие те? Откуда ты их взял?

S>·>Несколько потоков это обычно для LL-применений: разные треды делают вполне конкретную и довольно разную работу: читают данные из сетевого буфера, делают какие-то вычисления, реплицируют, пишут на диск, пишут в сеть и т.п. Таких тредов как правило меньше чем ядер процессора.

S> Что прекрасно походит под async await.
Не подходит.

S>>> При этом пока задача вне потока выполнения код хранится в виде делегата. Никакого стека, регистров. Нужно приостановить только планировщик.

S>·>А делегат где хранится?
S> В обычной или асинхронной очереди.
А обычнная или асинхронная очередь где хранится?

S>·>Ты видимо вообще не понимаешь что такое LL. Там ничего приостанавливать нельзя.

S> А как ты будешь собирать мусор? Для этого нужно знать граф доступных объектов, которые кстати хранятся в стеке и регистрах.
Ага... начал двигаться в правильном направлении. Продолжай думать.

S> Или всю память заполнили, а потом начинаем бороться с GC?

Память когда нибудь заполняется. В том тесте через 5 минут, на реальном сервере через 5 часов или 5 дней, не важно. Делать всё равно что-то придётся.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[23]: dotnet vs java 2016-2020
От: vdimas Россия  
Дата: 13.10.16 11:34
Оценка:
Здравствуйте, ·, Вы писали:

V>>Что, прямо-таки торговый движок на джаве?

·>Да, FX exchange, order book, matching engine (Execution Venue), Execution Management System, market data, ITCH, и куча всякой обвязки вокруг.

Кошмар. ))

V>>Зашел к ним на сайт: https://www.lmax.com

V>>Там жесть...
V>>Вот сам зайди, плиз.
·>Зачем мне на сайт заходить, я и так знаю чем они занимаются... я к ним в офис заходил... регулярно.

Ну ОК, тут баланс вложений и отдачи, пусть так. HFT для бедных... почему бы и нет?


·>Не надо JNI сложные писать.


Надо, надо. Потому что JNI принципиально идёт там, где требуется эффективность, иначе он НЕ нужен.


·>Да и сам JNI тупой и простой как пробка.


Пока тебе не надо дергать методы-геттеры подаваемых как параметры объектов.


·>Отлаживается тоже элементарно, тесты же есть, а накрайняк можно и отладчиком подцепиться.


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

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


V>>Именно поэтому я порой для прототипирования юзаю дотнет, а не джаву, что всегда могу подёргать из дотнета практически любые нейтивные либы или АПИ ОС фактически даром.

·>Ну и JNA есть для ленивых.

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


·>А вообще редко что приходится дёргать, если писать серверный код, а не GUI или специфическое оборудование.


В процессе прототипирования — часто.


·>Фиг знает, я не сравнивал. Может быть. Пусть так. В любом случае не одним fix engine биржа жива.


Ну так матчить ордера в нейтиве еще эффективнее. Это же просто "плоские" структуры в памяти, в случае нейтива.


V>>·>Вот что я и пытаюсь доказать. На java (без native) возможно писать критичные к быстродействию системы, притом они только немного уступают по цифрам нативу.

V>>Уступают в 20-30 раз.
·>Даже если и так, то с c# дела будут ещё хуже.

С чего бы это?


V>>·>На c# (без native) — невозможно.

V>>Возможно и они не уступают джавовским.
V>>Ну реально, с каких это пор джава стала быстрее дотнета в сфере latency?
·>Всегда была.

Первый раз слышу за последние 14 лет. ))


V>>Или ты сравниваешь современную джаву с дотнетом от 2003-го года?

V>>Дотнет сходу вышел шустрее джавы и все года задавал ей планку. Или я пропустил какую-то важную новость вот буквально последнего года, что в джава придумали хороший оптимизатор? ))
·>JIT явы всегда был на голову выше шарпа.


Поэтому вычисления в джава вдвое сливали после выхода дотнета, угу.


V>>Вот в дотнете хороший уже есть — это виндовый Магазин, где дотнетные приложухи сурово оптимизируются в нейтив. Никакой JIT не даст сравнимый уровень оптимизации, ес-но, это всё показывает хоть какие-то результаты лишь на стадии офлайн компиляции.

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

Ну это уже троллинг как он есть. Без комментариев. ))


V>>Например, FIX-сообщение в джава — это развесистый граф объектов с кучей ссылок, а в нейтиве — сплошная область памяти.

·>Не обязательно. Почешите голову над дизайном и продумайте внутренние структуры данных.

Да какая разница? Каждое строковое значение — это отдельный объект в хипе.


V>>·>т.к. это рулится во время запуска самой jvm.

V>>Ты не можешь гарантировать, что один и тот же джавовский поток будет исполняться на одном и том же потоке ОС всё время своей жизни. Для дотнета та же засада, кста, поэтому, управлять cpu affinity можно только для потоков, создаваемых и управляемых из нейтива. Вот почему, собсно, эта область программы тоже должна жить в нейтиве.
·>Не должна. Это настраивается в инфраструктуре, на системном уровне. В самом ява-приложении не нужно. Вот тут с циферками и подробностями что и как можно настраивать: https://youtu.be/-6nrhSdu--s?t=39m28s

Ты мне не ссылки давай, а просто ответь: может ли джава-машинка гарантировать, что каждый её логический поток будет в течении всей своей жизни выполняться на одном и том же потоке ОС? Потому что везде строго предупреждают об обратном.


V>>·>Да, возможно ещё потребуется всякие тонкие настройки операционки и железа, типа irq balance и прочей магии. Но это всё инфраструктура, рулится и без явы, а какими-нибудь bash-скриптами и всяким /proc /etc.

V>>Ну так ты мне ссылку на официальные цифры твоего Rapid для их джава-движка дай, чтобы стало понятно, в каких пределах это влияет на результат.
·>Нет у меня...

Пффф... ну тогда можно строить произвольные предположения об "эффективности Джава". Тут уже сколько фантазии хватит.


·>Но в любом случае Fix gateway не самый быстрый и важный компонет биржи, да и дистрибьютится он на ура.


На стороне клиента и сервера важна связка ордера и соответствующего сетевого сообщения. Т.е., FIX-движки (а часто FAST-кодирование или аналогичное сверху) — они не вещи в себе, они должны обеспечивать именно такую связку.


V>>Но по ссылкам, данным мною, кста, помимо самих цифр latency есть графики РАЗБРОСА значений. Просто посмотри на них и сравни. У хороших движков разброс минимален. Можно сказать, что его и нет вовсе. С чудовищным разбросом результатов по Джава это сравнивать нельзя.

·>Что-то туплю. Где там графики? Или надо обязательно SDK качать?

Я дал ссылки на репорты от совместной лаборатории Intel+OnX, там таблицы результатов + графики.


V>>Т.е. это специфический GC, который лечит клиническую кривизну кода, когда обычные явовские движки уходят в своп на десятки секунд. Ну, блин, в дотнете и проблемы-то такой с момента выхода версии 4.5 нет.

·>Как минимум стоит заметить, что zing появился в 2010, а 4.5 вышел в 2012.
·>Да и собственно по цифрам zing таки впереди.

Для клиентского софта соответственно заточенный дотнетный GC вышел одновременно с дотнетом 4.0.
А все эти брокерские конторы — они же клиенты и есть.


V>>Если памяти каюк и сотни миллионов объектов на освобождение, то деваться некуда.

V>>Я делал синтетические тесты и на джаве и на дотнете с генерацией объектов и отправки их в другой поток.
·>Ну так лучше не делать вообще в LL-коде. Disruptor же есть.

Дык, Disruptor именно это и делает.

Тут фишка в том, что объект в джава (я испытывал оракловую), будучи "потерянным" текущим потоком, перестаёт быть объектом 0-го поколения. По-другому объяснить наблюдаемое я не мог, бо если пихать в очередь того же самого потока, то всё в джаве пашет гладко.


V>>Так вот, дотнетный движок легко справляется с 0-м поколением даже из "чужого" для объекта потока, а в джаве, похоже, такие объекты улетают в 1-е поколение, затем быстро упираемся в потолок и начинается сплошное GC. При том, что дотнетный тест может работать вечно без пауз — в фоне прекрасно всё чистится. Вот чтобы ты знал — для таких сценариев и нужен твой zing.

·>Ну не совсем. В Яве такой же подход с 0-м и 2-м поколением, а zing нужен т.к. кроме LL-важного потока в приложении бывает всякое разное, что таки может внезапно намусорить.

Ну я так и сказал, что для лечения непродуманности.

А ведь, казалось бы, data flow в этой области надо вылизывать еще на уровне концепта максимально тщательно, а не применять стандартный джавовский подход: наколенный эксперимент -> рефакторинг -> продакшен. )))


V>>Далее. Отсутствие в Джаве value-типов делает среднюю джавовскую прогу намного развесистее в памяти, чем аналогичную на дотнете, где многое можно размещать по значению. Да, я в курсе про хот-спот и реальный эффект от него. Он мизерный, в сравнении с эффектом от продуманного разработчиком графа на value-types дотнета.

·>Да, есть такое. Но можно граф поуменьшить, и байт-буферы использовать.

С байт-буфером будет сериализация-десериализация на каждый чих. В общем, что в джаве до сих пор нет value-типов — это серьезный косяк, как по мне.
Тут несколько лет назад был знатный срач по дотнету, где я просто показал эффект от уменьшения косвенности всего вдвое — там быстродействие подскочило в 2.4 раза.

Некоторые коллеги высказали мне кучу "фе" за эдакое "байтодрочерство", но факт остаётся фактом — управляемые среды так мощно сливают нейтиву в том числе из-за чудовищной лишней косвенности. КАЖДАЯ коллекция объектов дотнета или джавы — это сразу ТРИ уровня косвенности: сама коллекция является ref-типом, внутри себя содержит ref-array, который внутри себя содержит ref-объекты. В нейтиве в таких сценариях зачастую один уровень косвенности или даже ни одного (если с ограничением на макс. размер коллекции).


V>>Да я верю, спасибо за наводку, было интересно почитать про алгоритмы сборки мусора zing.

V>>Это круто, согласен... Перерасход памяти, правда, черезчур (на т.н. "фантомные страницы") и слишком много жутко дорогих Access Violation (на каждый неверно помеченный объект). Собственно, на этом AV построен сам принцип его работы. Оригинально, чо! )) Я в очередной раз порадовался, что большую часть времени имею дело с нейтивом...
·>Ага, и тем более радостно, что не с шарпом. Там даже альтернативную VM или специфичный сброщик мусора хрен запилишь.

Ну, я уже рядом напоминал, что под каждую нишу нужно брать наиболее подходящий инструмент. Я не отрицаю потенциальной мощи и серьезного влияния управляемых сред на IT-индустрию, я просто показываю (даже в этом споре), что не надо пихать их туда, где им не место.
Re[26]: dotnet vs java 2016-2020
От: · Великобритания  
Дата: 13.10.16 11:36
Оценка:
Здравствуйте, vdimas, Вы писали:

V>·>Ну и зачем тредпул для долгоиграющих тредов?

V>Долгоиграющие треды не нужны при хорошей степени асинхронности кода.
V>Они даже резко вредны.
Они нужны для LL.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[31]: dotnet vs java 2016-2020
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.10.16 11:43
Оценка:
Здравствуйте, ·, Вы писали:

S>> Или всю память заполнили, а потом начинаем бороться с GC?

·>Память когда нибудь заполняется. В том тесте через 5 минут, на реальном сервере через 5 часов или 5 дней, не важно. Делать всё равно что-то придётся.

Ne кстати не заметил

Но в свое время была проблема, когда изменялись данные, которые находились в старших поколениях, для них GC делал движения, для того, что бы учесть эти изменения.
И соответственно огромные тормоза при изменении огромного количества ссылок.
http://rsdn.org/forum/dotnet/415352.1
Автор: Serginio1
Дата: 20.10.03


Это нужно учитывать. Посмотри на дату. Сейчас может все по другому.
Кстати по алгоритму то и получается, что кэш

 var bytes = new byte[80 * 1024]; 
    random.NextBytes(bytes);
    bytesCache.Set(bytes.GetHashCode(), bytes);


bytesCache будет постоянно обновляться. Поэтому если bytesCache будет постоянно в 0 поколении, то и задержки будут постоянными

Суть в том, что bytesCache никаким кэшем не является.
Можно кстати для интереса не менять ссылки, а копировать содержимое. Благо размер походит.
Просто в реалиях
1. Кэш изменяется редко.
2. Не генерируется и не записывается такое количество в кэш.

Вот кстати статья про
«барьер записи» (write barrier), который сводится к обновлению card table, если адрес записываемого объекта находится в эфемерном сегменте (ephemeral segment), т.е. является молодым объектом 0-го или 1-го поколений.

https://habrahabr.ru/post/155847/
и солнце б утром не вставало, когда бы не было меня
Отредактировано 13.10.2016 12:04 Serginio1 . Предыдущая версия .
Re[31]: dotnet vs java 2016-2020
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.10.16 11:44
Оценка:
Здравствуйте, ·, Вы писали:

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


S>>·>В потоке эмулируется конкурентный доступ к общему кешу.

S>> Да только в реальной жизни это делается из пула потоков. Обычная практика для ASP.Net
·>Какая взаимосвязь между ASP.Net и LL? В ASP.Net на паузу в пару секунд раз в час никто никогда не обратит внимание.

To trigger garbage collection, the test program also runs several threads, each executing the code below. In a loop, each thread creates a large string and a byte array, to simulate what a web server might be doing when generating a response to a web request (for instance from de-serialising some Json and creating a HTML page). Then to ensure that the objects are kept around long enough, they are both put into a Least Recently Used (LRU) cache, that holds the 2000 most recent items.

и солнце б утром не вставало, когда бы не было меня
Re[27]: dotnet vs java 2016-2020
От: vdimas Россия  
Дата: 13.10.16 12:05
Оценка:
Здравствуйте, ·, Вы писали:

V>>·>Ну и зачем тредпул для долгоиграющих тредов?

V>>Долгоиграющие треды не нужны при хорошей степени асинхронности кода.
V>>Они даже резко вредны.
·>Они нужны для LL.

Ошибка. Не нужны. Потому что характер работы системы точно такой же — реакция на внешние события.
Re[25]: dotnet vs java 2016-2020
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 13.10.16 12:42
Оценка:
Здравствуйте, Cyberax, Вы писали:

Ф>>Почти не зависит: чтобы это было возможно, нужно чтобы СУБД все свои действия сразу писала на диск. А на практике оно чаще всего откладывает запись (доступ к диску так оптимизируют)

C>ЩИТО?

Где, по твоему, БД хранит буфер транзакций и в какой момент она его сбрасывает на диск ?

Ф>>да и сама запись не мгновенно происходит, и это не атомарная операция — это во-первых.

C>Атомарная.

Похоже, вы про разные вещи говорите.

Ф>>А во-вторых часть данных может писаться не в БД, а в файлы, которые лежат рядом...

C>А это не проблема БД.

Спасибо, капитан. Это проблема юзера — старые файлы повреждены, новых нет. Что делать ?
Re[28]: dotnet vs java 2016-2020
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 13.10.16 12:47
Оценка:
Здравствуйте, vdimas, Вы писали:

V>>>·>Ну и зачем тредпул для долгоиграющих тредов?

V>>>Долгоиграющие треды не нужны при хорошей степени асинхронности кода.
V>>>Они даже резко вредны.
V>·>Они нужны для LL.

V>Ошибка. Не нужны. Потому что характер работы системы точно такой же — реакция на внешние события.


И давно у тебя создание да пробуждение потока стало дешовой операцией ?
Re[24]: dotnet vs java 2016-2020
От: · Великобритания  
Дата: 13.10.16 12:47
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Кошмар. ))

Что?

V>·>Зачем мне на сайт заходить, я и так знаю чем они занимаются... я к ним в офис заходил... регулярно.

V>Ну ОК, тут баланс вложений и отдачи, пусть так. HFT для бедных... почему бы и нет?
Обеспечивать качество и стабильность проще с управяемыми средами. В общем есть свои достоинства, причём тут бедность?..

V>·>Не надо JNI сложные писать.

V>Надо, надо. Потому что JNI принципиально идёт там, где требуется эффективность, иначе он НЕ нужен.
Он идёт в основном там, где есть что-то системнозависимое. Конечно, может быть есть какие-то числодробилки, типа видеокодеков, но тоже непонятно откуда там возьмётся сложный JNI — отдал массив байт, забрал массив байт.

V>·>Да и сам JNI тупой и простой как пробка.

V>Пока тебе не надо дергать методы-геттеры подаваемых как параметры объектов.
А что, из какого-нибудь pure C геттеры из c# дёргаются как-то проще?
Подавай что-то более удобное, массив байт, например. В общем бывают всякие ситуации, но далеко не всегда требуется весь ужас которым тут меня ты пытаешься запугать.

V>·>Отлаживается тоже элементарно, тесты же есть, а накрайняк можно и отладчиком подцепиться.

V>Тут проблема в разрыве второго рода. В джаве так любят рефакторинг, что малейшего чиха затем твой собственный JNI начинает затем тупо бегать по памяти. ))
В джаве любят хорошее покрытие тестами. Пусть бегает, дальше первого же прогона тестов не убежит.

V>И с отладкой там ж-па, потому что из нейтивного отладчика не видно, правильно ли дергаются методы и поля джавовского объекта. Со студией в плане одновременной отладки нейтивного и дотнетного кода тут не сравнить.

Можно и оба отладчика подцепить одновременно — ява и нейтив.

V>>>Именно поэтому я порой для прототипирования юзаю дотнет, а не джаву, что всегда могу подёргать из дотнета практически любые нейтивные либы или АПИ ОС фактически даром.

V>·>Ну и JNA есть для ленивых.
V>Да, есть. До полноценного использования доросло только к 2010-му примерно (уже опоздало для меня лично) и все-равно, лишние сущности плодить приходится + все вызовы динамические, т.е. как полноценная замена JNI не прокатывает.
Не знаю, мне вообще не приходилось клепать навороченные JNI, обычно это тонкие обёртки над нативными либами или обращение к какой-то простенькой системной api.

V>·>А вообще редко что приходится дёргать, если писать серверный код, а не GUI или специфическое оборудование.

V>В процессе прототипирования — часто.
Может у тебя специфика такая, хз. Это не типично для явы.

V>·>Фиг знает, я не сравнивал. Может быть. Пусть так. В любом случае не одним fix engine биржа жива.

V>Ну так матчить ордера в нейтиве еще эффективнее. Это же просто "плоские" структуры в памяти, в случае нейтива.
Так говорю же. Жестких LL сервисов всего пара — EV и EMS. А обвязки вокруг этого ещё штук 40 сервисов, включая пост-трейд проверки, генераторы отчётов, архиваторы данных, субд, http client/server, и т.д. и т.п. Гораздо удобнее когда оно всё написано на одном языке и прозрачно взаимодействует друг с другом, чем мешанина кучи технологий. Или ты предлагаешь веб-приложения тоже на нейтиве лабать?

V>>>Или ты сравниваешь современную джаву с дотнетом от 2003-го года?

V>>>Дотнет сходу вышел шустрее джавы и все года задавал ей планку. Или я пропустил какую-то важную новость вот буквально последнего года, что в джава придумали хороший оптимизатор? ))
V>·>JIT явы всегда был на голову выше шарпа.
V>
V>Поэтому вычисления в джава вдвое сливали после выхода дотнета, угу.
И именно для этого дотнет без нативного нутра не используется?

V>>>Вот в дотнете хороший уже есть — это виндовый Магазин, где дотнетные приложухи сурово оптимизируются в нейтив. Никакой JIT не даст сравнимый уровень оптимизации, ес-но, это всё показывает хоть какие-то результаты лишь на стадии офлайн компиляции.

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

V>>>Например, FIX-сообщение в джава — это развесистый граф объектов с кучей ссылок, а в нейтиве — сплошная область памяти.

V>·>Не обязательно. Почешите голову над дизайном и продумайте внутренние структуры данных.
V>Да какая разница? Каждое строковое значение — это отдельный объект в хипе.
Не используйте строковые значения. Есть даже интерфейс CharSequence. Ну или даже char[]. Хотя зачем строки в FIX? там вроде только ascii. byte[] сгодится. А если так нужны строки — их можно и в пул сложить.

V>>>Ты не можешь гарантировать, что один и тот же джавовский поток будет исполняться на одном и том же потоке ОС всё время своей жизни. Для дотнета та же засада, кста, поэтому, управлять cpu affinity можно только для потоков, создаваемых и управляемых из нейтива. Вот почему, собсно, эта область программы тоже должна жить в нейтиве.

V>·>Не должна. Это настраивается в инфраструктуре, на системном уровне. В самом ява-приложении не нужно. Вот тут с циферками и подробностями что и как можно настраивать: https://youtu.be/-6nrhSdu--s?t=39m28s
V>Ты мне не ссылки давай, а просто ответь: может ли джава-машинка гарантировать, что каждый её логический поток будет в течении всей своей жизни выполняться на одном и том же потоке ОС? Потому что везде строго предупреждают об обратном.
Общий стандарт явы — нет, но данная реализация машинки для данной инфраструктуры — да, может гарантировать. LL-система это не только ява код, но и вся инфраструктура включая всё железо, вплоть до каждого кабеля.

V>>>·>Да, возможно ещё потребуется всякие тонкие настройки операционки и железа, типа irq balance и прочей магии. Но это всё инфраструктура, рулится и без явы, а какими-нибудь bash-скриптами и всяким /proc /etc.

V>>>Ну так ты мне ссылку на официальные цифры твоего Rapid для их джава-движка дай, чтобы стало понятно, в каких пределах это влияет на результат.
V>·>Нет у меня...
V>Пффф... ну тогда можно строить произвольные предположения об "эффективности Джава". Тут уже сколько фантазии хватит.
У меня есть примеры когда ява используется как основной язык LL-системы. А шарп в лучшем случае как нашлёпка над нейтивом. Этого достаточно, конкретные цифры не так важны.

V>·>Но в любом случае Fix gateway не самый быстрый и важный компонет биржи, да и дистрибьютится он на ура.

V>На стороне клиента и сервера важна связка ордера и соответствующего сетевого сообщения. Т.е., FIX-движки (а часто FAST-кодирование или аналогичное сверху) — они не вещи в себе, они должны обеспечивать именно такую связку.
От сетевого сообщения там нужен только sequence number для связки. Порванная из-за проблем в сети сессия может восстановиться на другом сервере с другим клиентом.

V>>>Но по ссылкам, данным мною, кста, помимо самих цифр latency есть графики РАЗБРОСА значений. Просто посмотри на них и сравни. У хороших движков разброс минимален. Можно сказать, что его и нет вовсе. С чудовищным разбросом результатов по Джава это сравнивать нельзя.

V>·>Что-то туплю. Где там графики? Или надо обязательно SDK качать?
V>Я дал ссылки на репорты от совместной лаборатории Intel+OnX, там таблицы результатов + графики.
Я помню только ссылки на onixs.biz. Я что-то пропустил? Повтори, плз.

V>·>Как минимум стоит заметить, что zing появился в 2010, а 4.5 вышел в 2012.

V>·>Да и собственно по цифрам zing таки впереди.
V>Для клиентского софта соответственно заточенный дотнетный GC вышел одновременно с дотнетом 4.0.
V>А все эти брокерские конторы — они же клиенты и есть.
Так у них там UI в основном... какой там LL?..

V>>>Если памяти каюк и сотни миллионов объектов на освобождение, то деваться некуда.

V>>>Я делал синтетические тесты и на джаве и на дотнете с генерацией объектов и отправки их в другой поток.
V>·>Ну так лучше не делать вообще в LL-коде. Disruptor же есть.
V>Дык, Disruptor именно это и делает.
Ты что-то не то смотришь. Это просто перф-тест для juc queue, для сравнения. В дизрапторе используется ring buffer преаллоцированных объектов (то самое 2-е поколение), к которому магией обеспечивается эксклюзивный доступ из всяких разных тредов.

V>Тут фишка в том, что объект в джава (я испытывал оракловую), будучи "потерянным" текущим потоком, перестаёт быть объектом 0-го поколения. По-другому объяснить наблюдаемое я не мог, бо если пихать в очередь того же самого потока, то всё в джаве пашет гладко.

Хз, не знаю, много разных объяснений. Может escape analysis мутит или Thread Local Area. В любом случае, это не самый лучший подход для организации многопоточности.

V>>>Так вот, дотнетный движок легко справляется с 0-м поколением даже из "чужого" для объекта потока, а в джаве, похоже, такие объекты улетают в 1-е поколение, затем быстро упираемся в потолок и начинается сплошное GC. При том, что дотнетный тест может работать вечно без пауз — в фоне прекрасно всё чистится. Вот чтобы ты знал — для таких сценариев и нужен твой zing.

V>·>Ну не совсем. В Яве такой же подход с 0-м и 2-м поколением, а zing нужен т.к. кроме LL-важного потока в приложении бывает всякое разное, что таки может внезапно намусорить.
V>Ну я так и сказал, что для лечения непродуманности.
V>А ведь, казалось бы, data flow в этой области надо вылизывать еще на уровне концепта максимально тщательно, а не применять стандартный джавовский подход: наколенный эксперимент -> рефакторинг -> продакшен. )))
Ну может быть какой-нибудь nasdaq и может вылизывать годами, но не все это могут себе позволить.

V>>>Далее. Отсутствие в Джаве value-типов делает среднюю джавовскую прогу намного развесистее в памяти, чем аналогичную на дотнете, где многое можно размещать по значению. Да, я в курсе про хот-спот и реальный эффект от него. Он мизерный, в сравнении с эффектом от продуманного разработчиком графа на value-types дотнета.

V>·>Да, есть такое. Но можно граф поуменьшить, и байт-буферы использовать.
V>С байт-буфером будет сериализация-десериализация на каждый чих.
Данные обычно плоские и фиксированной ширины. Просто обращаешься по фиксированным смещениям, сериализация тривиальна и быстра.

V>В общем, что в джаве до сих пор нет value-типов — это серьезный косяк, как по мне.

Да, не удобно. Всякиеп proposals постоянно висят, но это не так всё просто — каким образом оно скажется на оптимизатор и сборщик мусора...

V>Тут несколько лет назад был знатный срач по дотнету, где я просто показал эффект от уменьшения косвенности всего вдвое — там быстродействие подскочило в 2.4 раза.

V>Некоторые коллеги высказали мне кучу "фе" за эдакое "байтодрочерство", но факт остаётся фактом — управляемые среды так мощно сливают нейтиву в том числе из-за чудовищной лишней косвенности. КАЖДАЯ коллекция объектов дотнета или джавы — это сразу ТРИ уровня косвенности: сама коллекция является ref-типом, внутри себя содержит ref-array, который внутри себя содержит ref-объекты. В нейтиве в таких сценариях зачастую один уровень косвенности или даже ни одного (если с ограничением на макс. размер коллекции).
Да, это недостаток управляемых сред, но бенефиты нередко значительно перевешивают этот недостаток.

V>·>Ага, и тем более радостно, что не с шарпом. Там даже альтернативную VM или специфичный сброщик мусора хрен запилишь.

V>Ну, я уже рядом напоминал, что под каждую нишу нужно брать наиболее подходящий инструмент. Я не отрицаю потенциальной мощи и серьезного влияния управляемых сред на IT-индустрию, я просто показываю (даже в этом споре), что не надо пихать их туда, где им не место.
Я не хочу переходить на спор о неуправляемых средах, в сабже этого нет.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[28]: dotnet vs java 2016-2020
От: · Великобритания  
Дата: 13.10.16 12:59
Оценка:
Здравствуйте, vdimas, Вы писали:

V>>>Долгоиграющие треды не нужны при хорошей степени асинхронности кода.

V>>>Они даже резко вредны.
V>·>Они нужны для LL.
V>Ошибка. Не нужны. Потому что характер работы системы точно такой же — реакция на внешние события.
Не просто реакция, а мгновенная реакция, без всяких задержек. А поэтому нет роскоши подождать пока в пуле появится свободный поток, пока этот поток подрузит контекст, пока операционка подберёт для него свободное ядро процессора, пока процессор подгрузит данные из другой numa ноды и т.д. и т.п.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[23]: dotnet vs java 2016-2020
От: Lexey Россия  
Дата: 13.10.16 13:07
Оценка:
Здравствуйте, ·, Вы писали:

·>Тормозной он и корявый. Плюс win-only (а mono ещё хуже).


Не особо тормозной и гораздо менее корявый, чем Ява.

·>А если ты считаешь что это всё неправда и c# — торт, то как ты объяснишь полное наличие отстутствия HFT систем на шарпе?


Видимо, бессмысленностью их разработки на Шарпе (когда есть возможность написать на плюсах).
Критичную по перфомансу промышленную автоматизацию я на Шарпе лично писал и оптимизировал (там не было таких заморочек с latency как в HFT, но были жесткие требования на общее время обработки большого потока информации).
"Будь достоин победы" (c) 8th Wizard's rule.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.