Здравствуйте, Serginio1, Вы писали:
S> Я не думаю, что для MS интересно делать WPF кроссплатформенным учитывая процент декстопов на котором стоит Windows. S>А вот для мобильных устройств будут развивать Xamarin Forms.
S> А вот для серверов WPF не нужен, а интересны им юниксы линуксы именно из-за облаков.
Ты всё правильно пишешь. ) Нюанс только в том, что все эти твои тезисы опять же только подтверждают мой изначальный тезис. )))
Здравствуйте, ·, Вы писали:
·>Во как. Ты оказывается имел в виду не "хип GC" (чтобы это не значило), а область (area, generation) кучи.
Я имел ввиду именно другую кучу, в точности аналогичной нейтивной.
Я вижу, что у тебя затык на самом слове "куча", хотя это слово интуитивно понятно, ИМХО.
"Кучей" в менеджере памяти физически является набор страниц, взятый у операционки.
Дефолтный менеджер нейтивной кучи в виндах живет в Kernel32.dll, в линухах он живет в glibc.so.
·>И что ты хотел сказать-то этим?
Что большие объекты (т.е. память под них) обрабатываются джавовским GC по-другому, а именно — в точности как нейтивные.
Именно что RTFM, потом спорь.
По твоей ссылке нет противоречий моим словам.
V>>·>Бывает off-heap подход, но это не об объектах и их размерах, а по сути это просто in memory database. И off-heap как раз используется для хранения данных огромного кол-ва _мелких_ объектов. V>>>>Чем куча GC отличается от обычной? V>>·>Откуда я знаю что такое "обычная куча", этот термин ты придумал. V>>Этому термину больше лет чем тебе. ·>Ну какая разница когда ты его придумал.
Придумываешь тут только ты от незнания.
V>>·>Скажем, в zing куча операционки может не использоваться, и там есть ядрённый модуль, который выделяет Java-кучу прямо в физической памяти. V>>А бывает как-то иначе? )) ·>Бывает.
Не бывает. ))
У операционки с защищённой памятью всегда аллоцируется сначала адресное пространство, а потом коммитится, по мере надобности, её отображение на физическую память.
V>>Ясно, понятий ровно ноль. V>>В обычной куче есть только две операции — выделение и освобождение памяти. ·>Можно ссылку на понятие "обычная куча"?
V>>В куче GC дополнительно есть операции перемещения объектов, с целью уплотнения (дефрагментации). ·>GC и дефрагментация вещи ортогональные.
Для Джавы и дотнета они неразрывные.
V>>Так вот, основной профит от GC как раз в этой дефрагментации, иначе не получится затем выделять память простым инкрементом указателя. Но эта фишка не работает для больших объектов, бо они выделяются в тех областях памяти, где дефрагментация не производится. ·>Как эти области памяти называются? Ссылку плз. ·>Ты наверное путаешь с dotnet LOH, там да, есть какие-то особенности.
Я ничего не путаю и в LOH никаких особенностей нет, — это обычная куча как куча, которая в современных менеджерах памяти представлена деревом на основе бинарного представления части адреса объекта. Просто конкретно MS дала этой куче название в своей реализации GC, чтобы как-то отделить, сугубо терминологически, её от основной кучи GC.
Upd
Про дотнет пишут то же, что и про джаву, кста:
Any allocation greater than or equal to 85,000 bytes goes on the LOH. Copying large objects has a performance penalty, so the LOH is not compacted unlike the SOH. Another defining characteristic is that the LOH is only collected during a generation 2 collection.
В точности аналогично, кароч, и лично мне здесь не видится ничего удивительного.
Здравствуйте, vdimas, Вы писали:
V>·>Во как. Ты оказывается имел в виду не "хип GC" (чтобы это не значило), а область (area, generation) кучи. V>Я имел ввиду именно другую кучу, в точности аналогичной нейтивной.
В jvm есть только одна куча для объектов, называется Java Heap.
V>Я вижу, что у тебя затык на самом слове "куча", хотя это слово интуитивно понятно, ИМХО. V>"Кучей" в менеджере памяти физически является набор страниц, взятый у операционки. V>Дефолтный менеджер нейтивной кучи в виндах живет в Kernel32.dll, в линухах он живет в glibc.so.
Да пусть где угодно живёт. В нейтивной куче ява-объекты не живут, они живут в ява-куче (которая _может_ располагаться в нативной, это уже является деталями реализации конкретной VM).
V>·>И что ты хотел сказать-то этим? V>Что большие объекты (т.е. память под них) обрабатываются джавовским GC по-другому, а именно — в точности как нейтивные.
От размера может зависеть в какой области кучи выделится объект — YG, TLAB, OG. Это всё части (поколения) одной и той же кучи. Понятия нативной кучи в JVM нет, это деталь реализации.
V>>>·>Нет никаких "обычных куч" в Яве. Есть только Java Heap. И все объекты живут именно там, независимо от размера. V>>>Это не так. V>·>Это так. RTFM: https://docs.oracle.com/cd/E13150_01/jrockit_jvm/jrockit/geninfo/diagnos/garbage_collect.html V>Именно что RTFM, потом спорь. V>По твоей ссылке нет противоречий моим словам.
Там ровно одна куча для объектов. Есть другие блоки памяти, которые JVM может запросить у операционки (т.е. из нативной кучи) — код методов, стеки тредов, нативных хендлеров и т.п. Но не объектов ява.
V>>>·>Скажем, в zing куча операционки может не использоваться, и там есть ядрённый модуль, который выделяет Java-кучу прямо в физической памяти. V>>>А бывает как-то иначе? )) V>·>Бывает. V>Не бывает. )) V>У операционки с защищённой памятью всегда аллоцируется сначала адресное пространство, а потом коммитится, по мере надобности, её отображение на физическую память.
Ещё раз повторяю. В zing используется специальный ядреный модуль, который выделяет память прямо в _физической_ памяти, минуя виртуальную память операционки (чтобы исключить влияние оперционки на обращения к памяти, т.к. page faults создают latency spikes).
V>>>Ясно, понятий ровно ноль. V>>>В обычной куче есть только две операции — выделение и освобождение памяти. V>·>Можно ссылку на понятие "обычная куча"? V>https://msdn.microsoft.com/en-us/library/windows/desktop/aa366599(v=vs.85).aspx
И как там можно расположить ява-объекты? А под linux, как я понимаю, надо wine ставить, чтобы был доступ к HeapCreate?
V>>>В куче GC дополнительно есть операции перемещения объектов, с целью уплотнения (дефрагментации). V>·>GC и дефрагментация вещи ортогональные. V>Для Джавы и дотнета они неразрывные.
Ими можно крутить независимо. Не знаю на счёт дотнета, но в яве дефрагметацию можно просто отключить. Так что таки разрывные.
V>·>Как эти области памяти называются? Ссылку плз. V>·>Ты наверное путаешь с dotnet LOH, там да, есть какие-то особенности. V>Я ничего не путаю и в LOH никаких особенностей нет, — это обычная куча как куча, которая в современных менеджерах памяти представлена деревом на основе бинарного представления части адреса объекта. Просто конкретно MS дала этой куче название в своей реализации GC, чтобы как-то отделить, сугубо терминологически, её от основной кучи GC.
Конечно нет, если не считать особенностью то, что в java нет LOH, по крайней мере в оракловой VM.
V>Upd V>Про дотнет пишут то же, что и про джаву, кста: V>
V>Any allocation greater than or equal to 85,000 bytes goes on the LOH. Copying large objects has a performance penalty, so the LOH is not compacted unlike the SOH. Another defining characteristic is that the LOH is only collected during a generation 2 collection.
Где такое про джаву пишут?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
V>>Я не хуже тебя представляю, что там с потоками в Джава и как оно устроено. И при чем тут язык или системные библиотеки. ·>А что причём? Твоё личное мнение?
А какое тут вообще может быть мнение? ))
Программист должен уметь различать сущности языка (например "класс") и экземпляры сущностей (конкретный класс Thread).
Я хорошо понимаю причины твоего упорства, т.к. в стандарт языка Джава входит не только описание самого языка, но и минимальной инфраструктуры вокруг него. Однако, не надо путать одно с другим. Если уж говорить о synchronized, то, скорее, надо говорить об обязательном Мониторе в реализации инфраструктуры, чем о Thread, бо Монитор прекрасно работает даже когда мы вызываем джавовский код из потока, созданного не через джавовский класс Thread.
V>>А для борьбы с глупостью стоило посмотреть на язык go, где потоки встроены в сам язык. ·>Каким образом они там "встроены"? Судя по твоим рассужениям так же — часть библиотеки.
Из моих рассуждений следует ровно противоположное. А из твоих рассуждений следует лишь одно — ты много пишешь здесь и мало читаешь вовне. ))
Таки, посмотри на go, там есть на что взглянуть. Собственно, само название языка — это название конструкции по запуску нового вычислительного потока/задачи в этом языке.
V>>·>Ещё намёк — в каком пакете находится класс Thread? V>>Плевать с большой колокольни. ·>Плюй, не плюй, а факт остаётся фактом.
Факт чего? Имени собственного пакета?
V>>·>А вот всякие сетевые сокеты, файлы, коллекции, регекспы и прочее — да, это часть стандартной библиотеки, а не языка. V>>Я правильно понимаю, что от одного лишь имени собственного пакета "lang" у тебя малость зрение меняется? ·>А у тебя зрение меняется когда факты противоречат твоим убеждениям.
Так ты мне факты не показал еще.
V>>Треды — это отъемлимая часть аж бегом. V>>Ты демонстрируешь тут повадки новичков в Джаве, которые на голубом глазу путают язык и VM. ·>Ну погугли что такое monitorenter/monitorexit и описание поведения других инструкций в многопоточном окружении.
Нашел что просить погуглить. Ты бы еще "мама мыла раму" попросил погуглить.
Лучше погугли железные реализации джава-машинки и что там было реализовано в железе, а что нет. И почему именно так.
V>>·>Причём тут вообще сокеты? Зачем ты упомянул их? Как они с протоколами HTTP или FIX связаны? V>>Напрямую связаны, ес-но. ·>Нет, конечно, не связаны. Или у тебя есть какие-то доказательства?
Конечно есть. Это сетевая модель OSI.
Прямо по этой фразе и гуглить.
Собсно, в описаниях самих протоколов четко прописывается на каких уровнях модели OSI обитают эти протоколы.
V>>·>В смысле у вас только IOCP сокеты в нативе V>>В смысле виденные мною HTTP-серваки на дотнете используют такие сетевые ср-ва (асинхронный IO), которые были разработаны в нейтиве. ·>Не путай HTTP-сервер и HTTP-протокол.
Не виляй.
·>на джаве обычно есть pure-java реализация стандартными средствами и нативные модули для работы со специфичными под конкретную систему нативными имплементациями, если есть что-то специфичное, конечно.
Бессмысленное бла-бла-бла.
V>>
V>>Стандартный цикл обращения объектов через межпоточный буфер и обратно в "пул" реализованы как две встречных очереди
V>>Тут стоило помедитировать. Это СТАНДАРТНЫЙ подход. Это, блин, сверх-мега-стандартный подход для таких вещей. Это база, уровень 0. )) ·>Где в дизрапторе происходит генерация объектов? Что ты вообще назвал генерацией объектов?
Это ты назвал, я тут причем?
V>>Две встречные очереди образуют "кольцо". Эдакие чётки, как у попа, только вместо пальцев правой и левой руки у нас производитель и потребитель. Один берет из пула объект, подготавливает его и пихает "туда". Другой обрабатывает и пихает "обратно". ·>Что-то какое-то странное представление. Обычная очередь, одна, как в ларёк за пивом. Очереди образуют кольцо?.. Брр. Как-то всё переусложнено.
Ты называешь это сложным?
ОК.
V>>Чем ring-buffer отличается от двух встречных очередей? Да ничем, кроме того, что реализован не на связанном одностороннем списке объектов, а через прибитый к реализации массив фиксированного размера, что считается самой худшей схемой из всех известных. )) Ну, кроме случая, где генерирование и потребление происходит заведомо с одинаковой скоростью, ·>Нет, когда потребление в среднем не медленнее продьюсинга.
Интересует как раз не в среднем.
V>>как при воспроизведении аудио, например. Более того, запись и чтение из кольцевого буфера на один CAS дороже, чем в стандартной схеме межпотокового буфера. Ну и, самое главное, часто мы имеем обращение к одной и той же линейке кеша из разных потоков (ядер) в такой схеме, что до 6 раз (в среднем) тормозит любую межпоточность. Ладно аудио, там десятки-сотня пакетов в секунду от силы, но для HFT это смерть. )) ·>Там в одну линейку _пишут_ только продьюсеры, консьюмеры только читают.
Это ты так расписался в отсутствии представления о "когерентности кеша"? ))
Потребители читают записанные объекты в любой схеме, ес-но, но эта операция происходит чуть "позже" и не особо тормозит быстродействие, а вот обращение к двум курсорам чтения/записи в случае кольцевого буфера идёт одновременное с обоих потоков и является главным тормозом двунаправленной очереди на основе кольцевого буфера. Причем, это если в буфере хранятся только "константные" ссылки на объекты. Потому что в случае непосредственной перекачки данных через кольцевой буфер всё еще намного печальнее. Почему, собсно, эта схема и не популярна.
·>В приведённом тобой тесте было три продьюсера.
Да хоть десять для lock-free.
·>Тут уже мало что можно сделать иначе. В случае одного продьюсера дизраптор действительно раскочегаривается по полной.
Если ты работаешь в этой области, то должен знать, что во многих биржах идёт минимум 2 UDP-фида для данных и их, таки, положено слушать из РАЗНЫХ потоков в силу особенностей работы UDP. А сами пакету сваливать затем в один поток обработки. "Раскочегаренная" обычная схема на lock-free очередях даёт менее микросекунды средней задержки (чиста для инфы).
·>Собственно это как раз одно из преимуществ дизраптора, что он дружелюбен к железу, учитывает все эти кеши и прочие нумы.
Дисраптор — это роспись в нубстве. Я уже высказывал своё мнение:
V>>>>Это и есть дисраптор. Это его базовый Lego-кубик (один из 3-х, вернее, с идентичным интерфейсом). V>>·>А доказать? V>>Я всё доказал, пояснив общее устройство такой схемы (две встречных очереди). ·>Я не понимаю почему ты это называешь двумя очередями. В тесте на который ты привёл — очередь одна. В один конец происходит добавление, с другого конца забирают. Никакого "возвращения" нет.
V>>Я, конечно, могу ошибаться, но мне кажется, что тебя сбивает с толку именно ring buffer. Он в этой схеме вообще не причем, но кажется тебе главной деталью. ·>Конечно главная деталь.
Ну вот ты и спалился.
·>Потому что это не очередь. По ринг-буферу могут ползать сразу несколько потребителей.
Это зависит от реализации. Есть разные реализации межпоточных очередей:
(producer-consumer)
— один-один
— много-много
— один-много
— много-один
Последняя схема является самой эффективной в реализации и является, по офигенному случайному стечению технических обстоятельств, самой востребованной. Ну и покрывает предыдущий вариант тоже, ес-но.
Много-много — самая затратная схема, профит от которой зачастую сильно сомнительный и требует пересмотреть всю схему прохождения данных верхнего уровня.
·>И их можно огораживать барьерами — потребители C и D могут отработать только после того, как отработали предыдущие A и B (притом не важно — в каком порядке — A/B или B/A). Вот тут с картиночками: http://martinfowler.com/articles/lmax.html
Да пофиг на подробности реализации. Каждая дополнительная фича в этой схеме — это дополнительные тормоза.
В стандартной "раскочегаренной" схеме где пара потоков пишет, а один читает, каждый поток-producer умудряется сделать до 30-40 млн итераций в секунду, а consumer в два раза больше.
В тесте происходит следующее:
Два потока-производителя вынимают из личного пула объект и ставят в очередь.
Поток-потребитель вынимает объект из очереди и возвращает каждый объект в его личный пул.
И тут чем меньше дополнительных операций, тем лучше, бо счет идёт на считанные единицы машинных команд на операцию.
·>Т.е. этот один единственный паттерн позволяет реализовывать довольно сложное взаимодействие между множествами тредов просто складывая их как кубики.
Паттернов много. Понятно, что "много-много" — самый универсальный, но и самый тормозной, при том, что нужен крайне редко, если включать голову.
Ты не понял о каком балансе речь, вестимо.
У нас источником данных является producer. Их несколько. На каком-то из них периодически случается всплеск трафика, соответственно, пул должен вырасти только у этого producer-а. Балансить надо объкты м/у личными пулами, а в дисрапторе такой баланс физически невозможен.
Т.е. ты говоришь уже о распределении нагрузки по потребителям, считая, что потребители могут не справляться.
Но! Одни и те же данные (принадлежащие одному и тому же набору) будет неэффективно обрабатывать параллельно из разных потоков, бо эти потоки будут встречаться на разделяемых хранилищах этих данных и тормозить еще больше. В общем, такая схема работает тем с большими издержками, чем больше трафик. Поэтому, самой эффективной схемой из всех возможных в случае нескольких потоков является конвейер. Это тоже основы жанра высокоэффективной обработки данных, — любые числодробилки построены именно так и никак иначе. Потому что чем выше трафик, тем более дешевой будет каждая операция на конвейере, ведь в случае наличия данных в межпоточной lock-free очереди обращение к ней фактически бесплатное — ровно в две машинные команды без всяких барьеров памяти и дорогих interlocked-операций.
ОК, я посмотрел схему в комментах и увидел знакомый сценарий.
Собсно, это самый популярный сценарий "много-один".
V>>Писали нубы, нихрена не соображающие в устройстве современных систем. )) ·>Голословно.
Законы HFT-жанра специфичны в том, что свои ноу-хау никто не раскрывает, бо это конкурентное преимущество на этом тесном рынке.
Раз они выложили дисраптор в паблик, значит им он больше не нужен. Се ля ви.
По-видимому, они нашли более эффективную модель и я хорошо понимаю — какую именно.
А вы подбираете за ними объедки, судя по всему.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>>Да не обязательно CRTP — обычный std::partition_point это уже статический полиморфизм. EP>·>Ну method overloading это тоже статический полиморфизм. EP>Верно. EP>·>Может внутренняя имплементация не так элегантна как в Плюсах, но Arrays.binarySearch внешне выглядит точно так же. EP>Внешне Arrays.binarySearch выглядит как борьба с языком — ибо там ручная перегрузка на каждый тип, при видимо одинаковой реализации.
О красоте можно потом поговорить. Так в чём же динамика? Всё ровно то же, что и в Плюсах пока.
EP>·>Интересно. А что с этим можно делать? Чем литерал "lambda"_s лучше lambda_s? EP>Тем что это строка, её можно парсить, выделять подстроки, она может быть частью большей строки. EP>Собственно во втором примере
это видно: строится compile-time map<имя переменной, значение>, далее парсится интерполированная строка в которой на переменные ссылаются по именам, по этим именам из map достаются значения и выводятся (всё в compile-time, поэтому и ASM идентичен ручному print каждой части). EP>Всё тоже самое можно было сделать в runtime, через std::map — но тогда ошибки типа ссылки внутри строки на неправильную переменную отлавливались бы в runtime, не говоря уже о penalty.
Ок, понятно теперь. compile-time вычисления. Да, интересная фича. Но не понимаю как наличие этой фичи в С++ делает джаву динмической. В Скале тоже есть куча подобных фич. Она менее динамична?
EP>·>Так любом ЯП это форма на первом месте. Когда текст программы выглядит _ожиданно_, принцип наименьшего удивления. EP>·>ЯП в первую очередь нужен не для компьютера (который может отлавливать ошибки), а для человека, чтобы он читая текст программы сразу понимал что делается в данной строчке кода, плюс IDE в помощь в наборе/навигации кода. Поэтому форма чрезвычайно важна. EP>Именно потому что форма важна dynamic и является полезным, так даёт лаконичность и выразительность. Но, опять таки, с точки зрения обсуждаемой проблемы статики/динамики/отлова ошибок — разницы с "exampleMethod1" нет
Правильно. Но почему вдруг джава стала более динамичной из-за этого?
EP>>>Ещё раз. Куда должна перейти IDE по "person.name"? EP>·>В том то и дело что некуда. Потому что это по сути текст в выводе программы, как и "John". EP>И в чём тогда претензия? В обоих вариантах переходить некуда
В том что идентично выглядящие конструкции xml_root.person.name и realDeclaredClass.person.name означают совершенно разные вещи, по-разному компилируются, работают по-разному и т.п. Форма не соответствует содержанию.
EP>>>Почему ратуем? Я лишь заявляю что статика на C++ намного доступнее и используется намного чаще чем на Java. И да — больше статики обычно означает больше проверок выполняемых компилятором. EP>>>При этом динамические фишки вполне имеют своё применение (в то числе C# dynamic) — я например сам использую в том числе Python и Lisp EP>·>Ок, я наверное просто к терминологии прикапываюсь. Выразительность системы типов я не отношу к статичности/динамичности. Ты, видимо, относишь (мне непонятно почему). В общепринятой терминологии так не принято. EP>Речь про фактический код. Если в одной программе List<Object> и постоянные динамические касты, а в другой List<Derived> и никаких кастов — то первая более динамическая чем вторая. При этом речи о том что такой язык имеет динамическую типизацию не идёт — это всё та же статическая типизация.
И к чему это тогда? И на Плюсах можно писать std::vector<void *>. В том то и дело, что даже в этом твоём понимании меняется динамичность конкретного написнного кода, а не самого языка. Формально-то как-то сможешь дать определение? "Динамичность языка — это...?" Можешь ссылку дать.
EP>>>·>Ну пока ещё не добавили. А runtime рефлексия заменяет compile-time при наличии runtime кодогенерации. EP>>>Не заменяет. В частности ошибки у тебя будут ловится только на стадии runtime кодогенерации EP>·>Какие конкретно ошибки? EP>Те которые ловит compile-time рефлексия. Например сериализация основанная на ней может поймать ошибки вида сериализации не реализованных базовых типов на этапе компиляции. Если же ты будет делать это через runtime рефлексию, даже с какой-угодно последующей кодогерацией — то эти ошибки у тебя проявятся уже на этапе работы приложения, так как поезд compile-time уже ушёл.
А конкретнее? Вот у нас есть класс "class Person {String name;}". В рантайме мы генерим сериализатор в XML. Какие ошибки будут ловиться|не ловиться?
EP>·>И что, например, у тебя сможет поймать компилятор в xml_root.person.name = 3.1415926;? EP>Пример xml_root.person.name вообще-то из другой области.
Я просто хочу чтобы ты объяснил что за ошибки ты хочешь ловить в компайл-тайме.
EP>·>Т.е. что инфрасткрутура более сложная для Плюсов — ты согласен? EP>Инфраструктура более сложная — это как раз таки основной момент, а не то что ты там думаешь про утечки, segfault или кодогенерацию. Собрать все зависимости на всех платформах, интерфейсы для всех сторонних языков, из этого всего на каждой платформе слепить пакеты — вот трудоёмкая и муторная задача. Если же сторонних зависимостей мало, а тем более платформ — то особо никаких инфраструктргых проблем нет. EP>Но кодогенерация например на Python вообще проблемой не является, так как подключается элементарно (например CMake автоматом сгенерирует нужные правила что для MSVS, что для make, etc) — это ты пытаешься хоть к чему-нибудь придраться.
Ну python на винде например обычно не стоит. А ещё у него две основные версии, не совсем совместимые. Инфраструктура java — проще: скачал IDE, скачал исходник (с помошью этой же IDE) — готово. Вот собствено в этом и мой тезис. Неужели не согласен?
EP>>>·>Какой смысл от него в Яве? EP>>>Я тебе объясняю что в Java не dynamic_cast'а нет (как ты утверждаешь), а наоборот static_cast'а. EP>·>Ах. в этом смысле... Ты говоришь, как будто это что-то хорошее. static_cast даёт UB, и хорошо что нет. EP>Я не говорю что это хорошее или плохое, я говорю что именно dynamic_cast в Java есть.
Трудно сказать... Почему он именно dynamic? Там просто cast, и он работает не так как Плюсовый. Неужели только потому, что падает в рантайме сразу, а не делает хз что как в Плюсах?
Т.е. если я буду касты в java-коде использовать так:
try{String s = (String)unknownTypeVar;}
catch(ClassCastException) {doRandomStuff();}
То каст внезапно станет более статичным?
EP>>>То что невозможно генерировать код в runtime. EP>·>Ну так невозможно же. Вызов компилятора из командной строки это не кодогенерация. EP>Это компиляция, а кодогенерация может происходить на один этап ранее, тоже в runtime
Кодогенерация это вовсе не обязательно генерация исходника на Плюсах. Можно генерить|модифицировать прямо байт-код.
EP>>>·>Фигня какая-то. На C++ написан JVM JIT, но как мне кажется, что это не значит, что сам C++ умеет JIT. EP>>>Ещё раз — смотри Cling — это JIT для языка C++. EP>·>Ок, но это не часть языка. EP>А что по твоему часть языка? То что в ISO? И какой там ISO у Java?
Да, для Плюсов это "The C++ Standard", для джавы — JLS.
EP>И почему вообще нужно ограничиваться сферической "частью языка", когда для решения реальных проблем это не имеет значения?
Имеет значение для надёжности решения, когда у тебя вдруг всё ВНЕЗАПНО не поломается со следующим минорным релизом компилятора|тулзов|етс.
EP>>>·>что это не значит, что сам C++ умеет JIT. EP>>>Что значит сам умеет? C++ отранслированный в JavaScript и запущенный в V8 — он как, умеет JIT или нет? EP>·>Не умеет. Это не часть языка. EP>x64, x32, arm, pgo, constant propagation, etc, etc — тоже не часть языка, значит C++ "их не умеет"? EP>Ну тогда он и нативный код не умеет — шах и мат
Это реализации Стандарта. Притом от хорошей реализации требуется, что некая конструкция языка работает именно так как описано в стандарте, на всех этих платформах.
Т.е. если ты пишешь "int i=2+2" — ты обязан получить i==4, иначе это не С++. То же и в Java. Пишешь ClassLoader.defineClass — он должен работать как описано в спеке. Как генерировать код в С++ — да никак, никто ничего в языке не обещает.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>>Речь как раз о том, что в разных языках различные по удобству средства выражения статики. В некоторых, типа Python — и вовсе сплошная динамика. В других же типа Java — есть статика, но акцент смещён в сторону динамики. В третьих сильная статика — например C++, D, Nemerle. EP>·>Интересная классификация. А C куда отнесёшь? EP>В C статика очень плохо выражается, очень часто используют штуки типа стирания типов (void* и т.п.), при этом даже без всяких динамический проверок — это скорее отдельная категория.
Всё чудесатее и чудесатее. «Человек есть животное на двух ногах, лишённое перьев... и с плоскими ногтями»
EP>>>Ярчайший пример для иллюстрации — первые версии Java и C# — в них не было Generic'ов, и коллекции представляли из себя по сути List<Object> — так вот получались сплошные касты, хотя казалось бы задача чисто статическая, и языки статически типизированные. EP>·>Касты не означают динамику, каст это приведение типов. Динамика это возможность изменения типов объектов в рантайм. EP>Какого именно изменения? monkey patch или что?
Не только. Добавить|удалить метод, например, и подобное.
EP>·> Тип _объекта_ ни в одном из перечисленных языков менять нельзя (только в Питоне). Object o = new String() — тип "o" будет тип String, изменить ты это не сможешь, хоть лопни. EP>А что будет в Python по-твоему?
Можно, например, класс поменять (у некоторых объектов) присвоением __class__ к чему-нибудь другому. А ещё типы переменных меняются (x=5, x="5"), точнее у переменных нет типа.
EP>·>Разница между C++ и Java будет лишь в том, что неверное приведение типа в C++ — UB, а в Java — exception. Всё. EP>Это тебя опять куда-то не в ту сторону понесло. Убери из C++ все UB конструкции, статических проверок от этого не уменьшится, compile time map никуда не исчезнет
Что тогда будет делать static_cast для неприводимых типов?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Serginio1, Вы писали:
S>>> Я так понимаю, что это аналог NGEN которому огромное количество лет и с теми же недостатками. S>·>Насколько я знаю, главный недостаток NGEN для мобильных девайсов в том, что его нет. Вот что пишут о .NET Micro Framework: S>·>
The CLR is an interpreter rather than a just-in-time compiler, and uses a simpler mark-and-sweep garbage collector instead of a generational approach.
S>·>Т.е. вообще тупой интерпретатор с примитивным GC. Вот они и стали пилить этот самый .net native. S> .Net Native сейчас идет под UWP Что такое приложение UWP? S>Там не только мобильные устройства. .NET Micro Framework это другое Microsoft .NET Framework во встраиваемых приложениях <br />
<span class='lineQuote level1'>S></span>.
А что на мобильниках? Или мобильников с dotnet не было что-ли ещё в природе (до .net native)?
S>·>Зависимость от фреймворка сама по себе ничем не плохо. AOT не означает, что нужно непременно собирать нативные бинарники и распространять их магазином. В ART сделано оптимально — финальная компиляция (из байткода в натив) сделана на девайсе, в момент установки. Т.е. установленная программа — нативный код — проблем с батареей и со стартом приложения нет. .net native предлагает распространять нативные бинарники изначально, что может серьёзно увеличить нагрузку на апп-сторы в случае большого числа вариантов девайсов или версий этого самого .net native. S> Ну моделей смартфонов то немного, и держать для каждой модели скомпилированные файлы. Это же не миллионы. И речь пока идет только об UWP которые только на продуктах MS, и Xamarin для IPhone. Да даже если для андроида, то это не огромное количестао аппаратов.
Каждая новая модель (точнее платформа) — это ещё по одному бинарику для _каждого_ приложения в апп-сторе. Т.е. десяток платформ (у андроида их вроде даже больше) — десятикратная нагрузка на апп-стор.
Конечно, если MS будет выпускать только одну-две модели (как аппл) или надеяться, что приложений будет не так много (как в вин-мобильном апп-сторе), то может и прокатит.
S>А вот выхлоп за счет более оптимизируещего компилятора он есть.
Какой ещё "более" оптимизирующий компилятор? Более чем что?
S>·>Так что из того что ты написал — нет ничего нового (ну кроме COM для linux), это уже несколько лет успешно работает на java платформе, этот самый .net native просто попытка догнать, и (лично моё мнение) не самая удачная, поживём — увидим.
S> Есть альтернативное решение. По сути это аналог С++ со сборкой мусора. Я уже приводил тебе ссылки на stack stackalloc
Круто конечно, но в java пошли другим путём. Вместо усложнения языка — улучшают JIT. Этот самый stackalloc делается автоматически в некотоых случаях, благодаря escape analysis.
S> Так что развитие идет, и главное увеличивается конкуренция которая стимулирует постоянное улучшение продуктов.
Это да.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, vdimas, Вы писали:
V>·>А что причём? Твоё личное мнение? V>А какое тут вообще может быть мнение? )) V>Программист должен уметь различать сущности языка (например "класс") и экземпляры сущностей (конкретный класс Thread).
В стандарт входит не только Thread, но и понятие многопоточности, специальные ключевые слова языка, поведение различных языковых конструкций и т.п. А ещё есть JMM.
V>Я хорошо понимаю причины твоего упорства, т.к. в стандарт языка Джава входит не только описание самого языка, но и минимальной инфраструктуры вокруг него.
Какую ещё "инфраструктуру" ты имеешь в виду?
V>Однако, не надо путать одно с другим. Если уж говорить о synchronized, то, скорее, надо говорить об обязательном Мониторе в реализации инфраструктуры, чем о Thread, бо Монитор прекрасно работает даже когда мы вызываем джавовский код из потока, созданного не через джавовский класс Thread.
Может и работает, но не обязан. Это уже за рамками стандарта, особенности конкретной имплементации JVM, ты не можешь на это полагаться.
А если ты имеешь в виду взаимодействие через JNI — ну так это тоже стандарт, он кстати тоже содержит в себе описание многопоточности. Но тогда формально код будет таки джавовкий, просто вызванный через JNI.
V>>>А для борьбы с глупостью стоило посмотреть на язык go, где потоки встроены в сам язык. V>·>Каким образом они там "встроены"? Судя по твоим рассужениям так же — часть библиотеки. V>Из моих рассуждений следует ровно противоположное. А из твоих рассуждений следует лишь одно — ты много пишешь здесь и мало читаешь вовне. )) V>Таки, посмотри на go, там есть на что взглянуть. Собственно, само название языка — это название конструкции по запуску нового вычислительного потока/задачи в этом языке.
В смысле наличие специального оператора запуска потока — признак встроености? А наличие ключевого syncronized — внезапно нет.
V>>>·>Ещё намёк — в каком пакете находится класс Thread? V>>>Плевать с большой колокольни. V>·>Плюй, не плюй, а факт остаётся фактом. V>Факт чего? Имени собственного пакета?
Да, т.к. java.lang это зарезервированный пакет для классов относящихся к языку.
V>>>Треды — это отъемлимая часть аж бегом. V>>>Ты демонстрируешь тут повадки новичков в Джаве, которые на голубом глазу путают язык и VM. V>·>Ну погугли что такое monitorenter/monitorexit и описание поведения других инструкций в многопоточном окружении. V>Нашел что просить погуглить. Ты бы еще "мама мыла раму" попросил погуглить.
А как ещё адекватно реагировать на глупости?
V>Лучше погугли железные реализации джава-машинки и что там было реализовано в железе, а что нет. И почему именно так.
Причём тут они? Почему опять изворачиваешься? Почему я опять должен гадать что ты хочешь сказать?
V>>>·>Причём тут вообще сокеты? Зачем ты упомянул их? Как они с протоколами HTTP или FIX связаны? V>>>Напрямую связаны, ес-но. V>·>Нет, конечно, не связаны. Или у тебя есть какие-то доказательства V>Конечно есть. Это сетевая модель OSI. V>Прямо по этой фразе и гуглить. V>Собсно, в описаниях самих протоколов четко прописывается на каких уровнях модели OSI обитают эти протоколы.
OSI как раз и диктует, что application layer protocol (HTTP, FIX) ничего не знает о деталях transport layer protocol (TCP/UDP). Поэтому HTTP/FIX должно быть пофик какие там сокеты IOCP/Winsock/etc.
V>>>В смысле виденные мною HTTP-серваки на дотнете используют такие сетевые ср-ва (асинхронный IO), которые были разработаны в нейтиве. V>·>Не путай HTTP-сервер и HTTP-протокол. V>Не виляй.
Я не виляю, это просто ты фантазируешь. Как минимум — HTTP-протокл не обязательно обозначает сервер, HTTP-клиенты тоже бывают.
V>·>на джаве обычно есть pure-java реализация стандартными средствами и нативные модули для работы со специфичными под конкретную систему нативными имплементациями, если есть что-то специфичное, конечно. V>Бессмысленное бла-бла-бла.
Ну перечитай. Что непонятно-то?
V>>>Тут стоило помедитировать. Это СТАНДАРТНЫЙ подход. Это, блин, сверх-мега-стандартный подход для таких вещей. Это база, уровень 0. )) V>·>Где в дизрапторе происходит генерация объектов? Что ты вообще назвал генерацией объектов? V>Это ты назвал, я тут причем?
Ну зачем врать-то нак нагло? Твоя цитата? "Я делал синтетические тесты и на джаве и на дотнете с генерацией объектов и отправки их в другой поток. Дык, Disruptor именно это и делает. "
V>>>Две встречные очереди образуют "кольцо". Эдакие чётки, как у попа, только вместо пальцев правой и левой руки у нас производитель и потребитель. Один берет из пула объект, подготавливает его и пихает "туда". Другой обрабатывает и пихает "обратно". V>·>Что-то какое-то странное представление. Обычная очередь, одна, как в ларёк за пивом. Очереди образуют кольцо?.. Брр. Как-то всё переусложнено. V>Ты называешь это сложным? V>ОК.
Я называю сложным твоё объяснение. Зачем в твоём объяснении две очереди? И как собственно _две_ очереди ты предлагаешь сцеплять в "кольцо"? Одну очень — понятно — конец сцепляешь с началом. А с двумя что делать?
V>>>как при воспроизведении аудио, например. Более того, запись и чтение из кольцевого буфера на один CAS дороже, чем в стандартной схеме межпотокового буфера. Ну и, самое главное, часто мы имеем обращение к одной и той же линейке кеша из разных потоков (ядер) в такой схеме, что до 6 раз (в среднем) тормозит любую межпоточность. Ладно аудио, там десятки-сотня пакетов в секунду от силы, но для HFT это смерть. )) V>·>Там в одну линейку _пишут_ только продьюсеры, консьюмеры только читают. V>Это ты так расписался в отсутствии представления о "когерентности кеша"? ))
Почему это тебя так беспокоит? Ты хочешь об этом поговорить?
V>Потребители читают записанные объекты в любой схеме, ес-но, но эта операция происходит чуть "позже" и не особо тормозит быстродействие, а вот обращение к двум курсорам чтения/записи в случае кольцевого буфера идёт одновременное с обоих потоков и является главным тормозом двунаправленной очереди на основе кольцевого буфера.
Кольцевой буфер однонаправленный. Можно двигаться только в одном направлении.
V> Причем, это если в буфере хранятся только "константные" ссылки на объекты. Потому что в случае непосредственной перекачки данных через кольцевой буфер всё еще намного печальнее. Почему, собсно, эта схема и не популярна.
Ты о lazySet что-ли рассказываешь?
V>·>В приведённом тобой тесте было три продьюсера. V>Да хоть десять для lock-free.
Что lock-free? дизраптор может работать lock-free...
V>·>Тут уже мало что можно сделать иначе. В случае одного продьюсера дизраптор действительно раскочегаривается по полной. V>Если ты работаешь в этой области, то должен знать, что во многих биржах идёт минимум 2 UDP-фида для данных и их, таки, положено слушать из РАЗНЫХ потоков в силу особенностей работы UDP. А сами пакету сваливать затем в один поток обработки. "Раскочегаренная" обычная схема на lock-free очередях даёт менее микросекунды средней задержки (чиста для инфы).
Обычно несколько хостов (шлюзы к клиентам), которые всё валят в UDP, а один поток на другом хосте (бизнес-логика) уже всё жрёт в одну харю.
V>·>Потому что это не очередь. По ринг-буферу могут ползать сразу несколько потребителей. V>Это зависит от реализации. Есть разные реализации межпоточных очередей: V>(producer-consumer) V>- один-один V>- много-много V>- один-много V>- много-один
V>Последняя схема является самой эффективной в реализации и является, по офигенному случайному стечению технических обстоятельств, самой востребованной. Ну и покрывает предыдущий вариант тоже, ес-но.
И как именно её реализуют?
V>Много-много — самая затратная схема, профит от которой зачастую сильно сомнительный и требует пересмотреть всю схему прохождения данных верхнего уровня.
На самом верхнем уровне именно так: многоОрдеров-многоМаркетДаты. Но да, между ними стоит собственно одинОрдербук.
V>·>И их можно огораживать барьерами — потребители C и D могут отработать только после того, как отработали предыдущие A и B (притом не важно — в каком порядке — A/B или B/A). Вот тут с картиночками: http://martinfowler.com/articles/lmax.html V>Да пофиг на подробности реализации. Каждая дополнительная фича в этой схеме — это дополнительные тормоза.
Что значит "фича"?
V>В стандартной "раскочегаренной" схеме где пара потоков пишет, а один читает, каждый поток-producer умудряется сделать до 30-40 млн итераций в секунду, а consumer в два раза больше. V>В тесте происходит следующее:
В каком тесте?
V>Два потока-производителя вынимают из личного пула объект и ставят в очередь. V>Поток-потребитель вынимает объект из очереди и возвращает каждый объект в его личный пул. V>И тут чем меньше дополнительных операций, тем лучше, бо счет идёт на считанные единицы машинных команд на операцию.
А "пул" как устроен? "возвращает каждый объект в его личный пул" — т.е. в соотвествующий пул потока-производителя? Как поток потребитель его находит?
V>·>Т.е. этот один единственный паттерн позволяет реализовывать довольно сложное взаимодействие между множествами тредов просто складывая их как кубики. V>Паттернов много. Понятно, что "много-много" — самый универсальный, но и самый тормозной, при том, что нужен крайне редко, если включать голову.
"много-много" это не единственная схема реализуемая на дизрапторе. "один-один" тоже реализуется.
V>>>По последнему. Без ring buffer можно организовать НЕСКОЛЬКО веток consumer-producer с ОДНИМ всего пулом у каждого producer и хорошим автоматическим load balancing, в то время как в случае кольцевого буфера у нас пул объектов привязан к конкретной ПАРЕ consumer-producer, а не к именно producer (ведь пул нужен именно ему). V>·>Нет, RTFM. V>·>Вот скажем 2 продьюсера делают балансинг на 2 консьюмера https://github.com/LMAX-Exchange/disruptor/blob/master/src/perftest/java/com/lmax/disruptor/workhandler/TwoToTwoWorkProcessorThroughputTest.java
V>Ты не понял о каком балансе речь, вестимо. V>У нас источником данных является producer. Их несколько. На каком-то из них периодически случается всплеск трафика, соответственно, пул должен вырасти только у этого producer-а. Балансить надо объкты м/у личными пулами, а
Можно поставить по дизраптору каждому продьюсеру — пусть растёт личный ринг-буфер, если надо. Но что это даст?
V>в дисрапторе такой баланс физически невозможен.
Он там не применим, т.к. "пула" нет, всё что за пределами занятого сегмента кольца — общий пул продьюсеров.
V>Т.е. ты говоришь уже о распределении нагрузки по потребителям, считая, что потребители могут не справляться.
Так обычно под балансировкой именно это и понимают, видимо меня опять телепатия подвела.
V>Но! Одни и те же данные (принадлежащие одному и тому же набору) будет неэффективно обрабатывать параллельно из разных потоков, бо эти потоки будут встречаться на разделяемых хранилищах этих данных и тормозить еще больше. В общем, такая схема работает тем с большими издержками, чем больше трафик. Поэтому, самой эффективной схемой из всех возможных в случае нескольких потоков является конвейер. Это тоже основы жанра высокоэффективной обработки данных, — любые числодробилки построены именно так и никак иначе. Потому что чем выше трафик, тем более дешевой будет каждая операция на конвейере, ведь в случае наличия данных в межпоточной lock-free очереди обращение к ней фактически бесплатное — ровно в две машинные команды без всяких барьеров памяти и дорогих interlocked-операций.
Если будут встречаться на разделяемых ресурсах, то да, балансировка смысла не имеет. Но ведь могут и не встречаться... зависит исключительно от задачи.
V>>>Кинь мне плиз мою ссылку. V>·>https://github.com/LMAX-Exchange/disruptor/blob/master/src/perftest/java/com/lmax/disruptor/queue/ThreeToOneQueueThroughputTest.java V>ОК, я посмотрел схему в комментах и увидел знакомый сценарий. V>Собсно, это самый популярный сценарий "много-один".
Т.е. ты наконец-то согласен, что данный тест не тест дизраптора?
V>·>Голословно. V>Законы HFT-жанра специфичны в том, что свои ноу-хау никто не раскрывает, бо это конкурентное преимущество на этом тесном рынке. V>Раз они выложили дисраптор в паблик, значит им он больше не нужен. Се ля ви.
V>По-видимому, они нашли более эффективную модель и я хорошо понимаю — какую именно.
Опять фантазии.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
V>>>>Тут стоило помедитировать. Это СТАНДАРТНЫЙ подход. Это, блин, сверх-мега-стандартный подход для таких вещей. Это база, уровень 0. )) V>>·>Где в дизрапторе происходит генерация объектов? Что ты вообще назвал генерацией объектов? V>>Это ты назвал, я тут причем? ·>Ну зачем врать-то нак нагло? Твоя цитата? "Я делал синтетические тесты и на джаве и на дотнете с генерацией объектов и отправки их в другой поток. Дык, Disruptor именно это и делает. "
Да, отправляет в другой поток.
·>Я называю сложным твоё объяснение. Зачем в твоём объяснении две очереди? И как собственно _две_ очереди ты предлагаешь сцеплять в "кольцо"? Одну очень — понятно — конец сцепляешь с началом. А с двумя что делать?
кошмар
V>>·>Там в одну линейку _пишут_ только продьюсеры, консьюмеры только читают. V>>Это ты так расписался в отсутствии представления о "когерентности кеша"? )) ·>Почему это тебя так беспокоит? Ты хочешь об этом поговорить?
кошмар
V>>Потребители читают записанные объекты в любой схеме, ес-но, но эта операция происходит чуть "позже" и не особо тормозит быстродействие, а вот обращение к двум курсорам чтения/записи в случае кольцевого буфера идёт одновременное с обоих потоков и является главным тормозом двунаправленной очереди на основе кольцевого буфера. ·>Кольцевой буфер однонаправленный. Можно двигаться только в одном направлении.
кошмар
V>> Причем, это если в буфере хранятся только "константные" ссылки на объекты. Потому что в случае непосредственной перекачки данных через кольцевой буфер всё еще намного печальнее. Почему, собсно, эта схема и не популярна. ·>Ты о lazySet что-ли рассказываешь?
жесть
V>>·>Потому что это не очередь. По ринг-буферу могут ползать сразу несколько потребителей. V>>Это зависит от реализации. Есть разные реализации межпоточных очередей: V>>(producer-consumer) V>>- один-один V>>- много-много V>>- один-много V>>- много-один
V>>Последняя схема является самой эффективной в реализации и является, по офигенному случайному стечению технических обстоятельств, самой востребованной. Ну и покрывает предыдущий вариант тоже, ес-но. ·>И как именно её реализуют?
тут я неточно выразился, много-один покрывает так же один-один, ес-но.
про реализацию на простейшем lock-free контейнере уже писал.
V>>Много-много — самая затратная схема, профит от которой зачастую сильно сомнительный и требует пересмотреть всю схему прохождения данных верхнего уровня. ·>На самом верхнем уровне именно так: многоОрдеров-многоМаркетДаты. Но да, между ними стоит собственно одинОрдербук.
ордербук один на инструмент, т.е. на один инструмент не надо кучи потоков.
самих инструментов сотни/тысячи
данные так не идут, они идут по непересекающимся рынкам/разделам, там негде взяться общей очереди много-ко-многим
V>>·>И их можно огораживать барьерами — потребители C и D могут отработать только после того, как отработали предыдущие A и B (притом не важно — в каком порядке — A/B или B/A). Вот тут с картиночками: http://martinfowler.com/articles/lmax.html V>>Да пофиг на подробности реализации. Каждая дополнительная фича в этой схеме — это дополнительные тормоза. ·>Что значит "фича"?
кошмар
V>>В стандартной "раскочегаренной" схеме где пара потоков пишет, а один читает, каждый поток-producer умудряется сделать до 30-40 млн итераций в секунду, а consumer в два раза больше. V>>В тесте происходит следующее: ·>В каком тесте?
V>>Два потока-производителя вынимают из личного пула объект и ставят в очередь. V>>Поток-потребитель вынимает объект из очереди и возвращает каждый объект в его личный пул. V>>И тут чем меньше дополнительных операций, тем лучше, бо счет идёт на считанные единицы машинных команд на операцию. ·>А "пул" как устроен? "возвращает каждый объект в его личный пул" — т.е. в соотвествующий пул потока-производителя? Как поток потребитель его находит?
рука-лицо
V>>·>Т.е. этот один единственный паттерн позволяет реализовывать довольно сложное взаимодействие между множествами тредов просто складывая их как кубики. V>>Паттернов много. Понятно, что "много-много" — самый универсальный, но и самый тормозной, при том, что нужен крайне редко, если включать голову. ·>"много-много" это не единственная схема реализуемая на дизрапторе. "один-один" тоже реализуется.
ну конечно, достаточно писать одним потоком и читать одним потоком, только для этого сценария не нужен двухстадийный CAS с той самой большой вероятностью отатов
V>>Ты не понял о каком балансе речь, вестимо. V>>У нас источником данных является producer. Их несколько. На каком-то из них периодически случается всплеск трафика, соответственно, пул должен вырасти только у этого producer-а. Балансить надо объкты м/у личными пулами, а ·>Можно поставить по дизраптору каждому продьюсеру — пусть растёт личный ринг-буфер, если надо. Но что это даст?
ничего, такая схема не работает
V>>в дисрапторе такой баланс физически невозможен. ·>Он там не применим, т.к. "пула" нет, всё что за пределами занятого сегмента кольца — общий пул продьюсеров.
верно, нубство как есть
V>>Т.е. ты говоришь уже о распределении нагрузки по потребителям, считая, что потребители могут не справляться. ·>Так обычно под балансировкой именно это и понимают, видимо меня опять телепатия подвела.
тоже верно, поэтому я однозначно указал, что надо балансировать ))
да и вообще, в контексте было обсуждение процесса перекачки данных, а не обработки, поэтому речь шла о балансе ресурсов для такой перекачки
·>Если будут встречаться на разделяемых ресурсах, то да, балансировка смысла не имеет. Но ведь могут и не встречаться...
а если не встречаются, то нет смысла прогонять через многие ко многим
в случае многие-ко-многим балансировка выполняется, считай, на каждое сообщение, а нам все-равно один конкретный ордер-бук надо из одного потока обрабатывать, поэтому выгодней балансировать редко и целыми инструментами или рынками.
V>>·>Голословно. V>>Законы HFT-жанра специфичны в том, что свои ноу-хау никто не раскрывает, бо это конкурентное преимущество на этом тесном рынке. V>>Раз они выложили дисраптор в паблик, значит им он больше не нужен. Се ля ви. V>>По-видимому, они нашли более эффективную модель и я хорошо понимаю — какую именно. ·>Опять фантазии.
http://stackoverflow.com/questions/18164769/windows-phone-8-native-and-clr-runtime
S>>·>Зависимость от фреймворка сама по себе ничем не плохо. AOT не означает, что нужно непременно собирать нативные бинарники и распространять их магазином. В ART сделано оптимально — финальная компиляция (из байткода в натив) сделана на девайсе, в момент установки. Т.е. установленная программа — нативный код — проблем с батареей и со стартом приложения нет. .net native предлагает распространять нативные бинарники изначально, что может серьёзно увеличить нагрузку на апп-сторы в случае большого числа вариантов девайсов или версий этого самого .net native. S>> Ну моделей смартфонов то немного, и держать для каждой модели скомпилированные файлы. Это же не миллионы. И речь пока идет только об UWP которые только на продуктах MS, и Xamarin для IPhone. Да даже если для андроида, то это не огромное количестао аппаратов. ·>Каждая новая модель (точнее платформа) — это ещё по одному бинарику для _каждого_ приложения в апп-сторе. Т.е. десяток платформ (у андроида их вроде даже больше) — десятикратная нагрузка на апп-стор. ·>Конечно, если MS будет выпускать только одну-две модели (как аппл) или надеяться, что приложений будет не так много (как в вин-мобильном апп-сторе), то может и прокатит.
Один раз скопилировали под плптформу и её уже устанавливают на миллионы устройств. Какая нафин нагрузка? Найти в Базе нужную модель?
S>>А вот выхлоп за счет более оптимизируещего компилятора он есть. ·>Какой ещё "более" оптимизирующий компилятор? Более чем что?
S>>·>Так что из того что ты написал — нет ничего нового (ну кроме COM для linux), это уже несколько лет успешно работает на java платформе, этот самый .net native просто попытка догнать, и (лично моё мнение) не самая удачная, поживём — увидим.
S>> Есть альтернативное решение. По сути это аналог С++ со сборкой мусора. Я уже приводил тебе ссылки на stack stackalloc ·>Круто конечно, но в java пошли другим путём. Вместо усложнения языка — улучшают JIT. Этот самый stackalloc делается автоматически в некотоых случаях, благодаря escape analysis.
Угу вместо того, что бы 1 раз оптимизировать нужно каждый раз оптимизировать. При этом SIMD операций нет.
stackalloc программист сам знает где вставить, зачем мучать JIT компилятор.
Ну да лпадно. По твоему C++ умер. Осталасть только Java в том числе и на симках
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, ·, Вы писали:
EP>>>>Да не обязательно CRTP — обычный std::partition_point это уже статический полиморфизм. EP>>·>Ну method overloading это тоже статический полиморфизм. EP>>Верно. EP>>·>Может внутренняя имплементация не так элегантна как в Плюсах, но Arrays.binarySearch внешне выглядит точно так же. EP>>Внешне Arrays.binarySearch выглядит как борьба с языком — ибо там ручная перегрузка на каждый тип, при видимо одинаковой реализации. ·>О красоте можно потом поговорить. Так в чём же динамика? Всё ровно то же, что и в Плюсах пока.
Ты сам привёл пример без динамики и теперь спрашиваешь в чём динамика.
EP>>·>Интересно. А что с этим можно делать? Чем литерал "lambda"_s лучше lambda_s? EP>>Тем что это строка, её можно парсить, выделять подстроки, она может быть частью большей строки. ... ·>Ок, понятно теперь. compile-time вычисления. Да, интересная фича. Но не понимаю как наличие этой фичи в С++ делает джаву динмической.
Ты спросил про std::map — я показал что даже для него есть более статичный подход, с большим количеством compile-time проверок проверок.
EP>>·>Ок, я наверное просто к терминологии прикапываюсь. Выразительность системы типов я не отношу к статичности/динамичности. Ты, видимо, относишь (мне непонятно почему). В общепринятой терминологии так не принято. EP>>Речь про фактический код. Если в одной программе List<Object> и постоянные динамические касты, а в другой List<Derived> и никаких кастов — то первая более динамическая чем вторая. При этом речи о том что такой язык имеет динамическую типизацию не идёт — это всё та же статическая типизация. ·>И к чему это тогда? И на Плюсах можно писать std::vector<void *>.
В первых версиях Java это был единственный вариант, и поэтому использовали такие динамические построения, несмотря на то что в языке по прежнему была статическая типизации. Сейчас добавили, но это лишь один из примеров.
·>В том то и дело, что даже в этом твоём понимании меняется динамичность конкретного написнного кода, а не самого языка. Формально-то как-то сможешь дать определение? "Динамичность языка — это...?" Можешь ссылку дать.
Повторю то что сказал с самого начала:
EP>Твой оппонент говорит о том (и с чем я согласен), что в коде на управляемых языках программисты как раз склонны к излишнему динамизму по сравнению с C++ — в котором например статический полиморфизм используется повсеместно.
Возражения на этот тезис есть?
EP>>>>·>Ну пока ещё не добавили. А runtime рефлексия заменяет compile-time при наличии runtime кодогенерации. EP>>>>Не заменяет. В частности ошибки у тебя будут ловится только на стадии runtime кодогенерации EP>>·>Какие конкретно ошибки? EP>>Те которые ловит compile-time рефлексия. Например сериализация основанная на ней может поймать ошибки вида сериализации не реализованных базовых типов на этапе компиляции. Если же ты будет делать это через runtime рефлексию, даже с какой-угодно последующей кодогерацией — то эти ошибки у тебя проявятся уже на этапе работы приложения, так как поезд compile-time уже ушёл. ·>А конкретнее? Вот у нас есть класс "class Person {String name;}". В рантайме мы генерим сериализатор в XML. Какие ошибки будут ловиться|не ловиться?
Я же говорю: "ошибки вида сериализации не реализованных базовых типов". То есть например String может не поддерживаться.
EP>>·>Т.е. что инфрасткрутура более сложная для Плюсов — ты согласен? EP>>Инфраструктура более сложная — это как раз таки основной момент, а не то что ты там думаешь про утечки, segfault или кодогенерацию. Собрать все зависимости на всех платформах, интерфейсы для всех сторонних языков, из этого всего на каждой платформе слепить пакеты — вот трудоёмкая и муторная задача. Если же сторонних зависимостей мало, а тем более платформ — то особо никаких инфраструктргых проблем нет. EP>>Но кодогенерация например на Python вообще проблемой не является, так как подключается элементарно (например CMake автоматом сгенерирует нужные правила что для MSVS, что для make, etc) — это ты пытаешься хоть к чему-нибудь придраться. ·>Ну python на винде например обычно не стоит.
Так он и не факт что на других OS стоит. Но при разработке обычно тот или иной язык скриптов всегда есть
·>А ещё у него две основные версии, не совсем совместимые.
С этим тоже нет проблем — virtualenv.
·>Инфраструктура java — проще: скачал IDE, скачал исходник (с помошью этой же IDE) — готово. Вот собствено в этом и мой тезис. Неужели не согласен?
Относительно кодогенерации (например на Python) — нет, не согласен — ибо ставится в одну команду package manager. А то что в общем кроссплатформенная инфраструктура со всеми зависимостями сложнее — так я это сам выше написал, буквально в сообщении на которое ты ответил — мне что опять себя цитировать?
EP>>>>·>Какой смысл от него в Яве? EP>>>>Я тебе объясняю что в Java не dynamic_cast'а нет (как ты утверждаешь), а наоборот static_cast'а. EP>>·>Ах. в этом смысле... Ты говоришь, как будто это что-то хорошее. static_cast даёт UB, и хорошо что нет. EP>>Я не говорю что это хорошее или плохое, я говорю что именно dynamic_cast в Java есть. ·>Трудно сказать... Почему он именно dynamic? Там просто cast, и он работает не так как Плюсовый.
В чём по-твоему отличие в контексте дискуссии?
·>Неужели только потому, что падает в рантайме сразу, а не делает хз что как в Плюсах?
На C++ в одной из форм вылетает исключение std::bad_cast, в другой nullptr.
·>·>Т.е. если я буду касты в java-коде использовать так: ·>
·>try{String s = (String)unknownTypeVar;}
·>catch(ClassCastException) {doRandomStuff();}
·>
·>То каст внезапно станет более статичным?
Чтоа?
EP>>>>Ещё раз — смотри Cling — это JIT для языка C++. EP>>·>Ок, но это не часть языка. EP>>А что по твоему часть языка? То что в ISO? И какой там ISO у Java? ·>Да, для Плюсов это "The C++ Standard", для джавы — JLS. EP>>И почему вообще нужно ограничиваться сферической "частью языка", когда для решения реальных проблем это не имеет значения? ·>Имеет значение для надёжности решения, когда у тебя вдруг всё ВНЕЗАПНО не поломается со следующим минорным релизом компилятора|тулзов|етс.
Я правильно тебя понял что все Maven'ы, IDE, и т.п. на помойку?
EP>>>>·>что это не значит, что сам C++ умеет JIT. EP>>>>Что значит сам умеет? C++ отранслированный в JavaScript и запущенный в V8 — он как, умеет JIT или нет? EP>>·>Не умеет. Это не часть языка. EP>>x64, x32, arm, pgo, constant propagation, etc, etc — тоже не часть языка, значит C++ "их не умеет"? EP>>Ну тогда он и нативный код не умеет — шах и мат ·>Это реализации Стандарта.
x64, x32, arm, pgo, constant propagation, etc, etc — это тоже реализация стандарта. Также как и JIT Cling
·>Притом от хорошей реализации требуется, что некая конструкция языка работает именно так как описано в стандарте, на всех этих платформах. ·>Т.е. если ты пишешь "int i=2+2" — ты обязан получить i==4, иначе это не С++. То же и в Java. Пишешь ClassLoader.defineClass — он должен работать как описано в спеке. Как генерировать код в С++ — да никак, никто ничего в языке не обещает.
V>>>·>Где в дизрапторе происходит генерация объектов? Что ты вообще назвал генерацией объектов? V>>>Это ты назвал, я тут причем? V>·>Ну зачем врать-то нак нагло? Твоя цитата? "Я делал синтетические тесты и на джаве и на дотнете с генерацией объектов и отправки их в другой поток. Дык, Disruptor именно это и делает. " V>Да, отправляет в другой поток.
Опять юлишь, изворачиваешься. Вот с контекстом:
Если памяти каюк и сотни миллионов объектов на освобождение, то деваться некуда.
Я делал синтетические тесты и на джаве и на дотнете с генерацией объектов и отправки их в другой поток.
Что же такое "генерация объектов"? Откуда в дисрапторе "сотни миллионов объектов на освобождение"?
V>>>Последняя схема является самой эффективной в реализации и является, по офигенному случайному стечению технических обстоятельств, самой востребованной. Ну и покрывает предыдущий вариант тоже, ес-но. V>·>И как именно её реализуют? V>тут я неточно выразился, много-один покрывает так же один-один, ес-но.
Правда по производительности они отличаются.
V>про реализацию на простейшем lock-free контейнере уже писал.
Дай ссылку на нормальное описание. У тебя со священниками двух двунаправленных очередей что-то не очень получилось описать.
V>>>Много-много — самая затратная схема, профит от которой зачастую сильно сомнительный и требует пересмотреть всю схему прохождения данных верхнего уровня. V>·>На самом верхнем уровне именно так: многоОрдеров-многоМаркетДаты. Но да, между ними стоит собственно одинОрдербук. V>ордербук один на инструмент, т.е. на один инструмент не надо кучи потоков. V>самих инструментов сотни/тысячи
Это ты о equities, там да попроще, и таких жестких требований нет.
V>данные так не идут, они идут по непересекающимся рынкам/разделам, там негде взяться общей очереди много-ко-многим
Это относительно простой сценарий. В случае же FX инструментов не так много, притом прут масс-ордера по нескольким ордербукам одновременно, да и >90% трафика прёт в один-единственный EUR/USD ордербук.
V>·>"много-много" это не единственная схема реализуемая на дизрапторе. "один-один" тоже реализуется. V>ну конечно, достаточно писать одним потоком и читать одним потоком, только для этого сценария не нужен двухстадийный CAS с той самой большой вероятностью отатов
Где ты нашел двустадийный CAS?
V>>>Т.е. ты говоришь уже о распределении нагрузки по потребителям, считая, что потребители могут не справляться. V>·>Так обычно под балансировкой именно это и понимают, видимо меня опять телепатия подвела. V>тоже верно, поэтому я однозначно указал, что надо балансировать )) V>да и вообще, в контексте было обсуждение процесса перекачки данных, а не обработки, поэтому речь шла о балансе ресурсов для такой перекачки
Так говори сразу словами, а не телепатируй.
Почему это работает лучше? Есть какие-нибудь тесты в паблике?
V>·>Если будут встречаться на разделяемых ресурсах, то да, балансировка смысла не имеет. Но ведь могут и не встречаться... V>а если не встречаются, то нет смысла прогонять через многие ко многим V>в случае многие-ко-многим балансировка выполняется, считай, на каждое сообщение, а нам все-равно один конкретный ордер-бук надо из одного потока обрабатывать, поэтому выгодней балансировать редко и целыми инструментами или рынками.
К чему ты это? Разные задачи — разные решения. Ты хочешь сказать, не бывает задач, требующих такой балансировки?
V>>>·>Голословно. V>>>Законы HFT-жанра специфичны в том, что свои ноу-хау никто не раскрывает, бо это конкурентное преимущество на этом тесном рынке. V>>>Раз они выложили дисраптор в паблик, значит им он больше не нужен. Се ля ви. V>>>По-видимому, они нашли более эффективную модель и я хорошо понимаю — какую именно. V>·>Опять фантазии. V>циничная реальность
Как я понимаю, хоть каких-либо подтверждений слов я так и не дождусь, товарищ фантазёр..
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Serginio1, Вы писали:
S>>>·>Т.е. вообще тупой интерпретатор с примитивным GC. Вот они и стали пилить этот самый .net native. S>>> .Net Native сейчас идет под UWP Что такое приложение UWP? S>>>Там не только мобильные устройства. .NET Micro Framework это другое Microsoft .NET Framework во встраиваемых приложениях <br />
<span class='lineQuote level3'>S>>></span>. S>·>А что на мобильниках? Или мобильников с dotnet не было что-ли ещё в природе (до .net native)? S> Был .Net Compact Framework,
Там был NGEN?
S>затем пришел WinRt
А он вообще "был"? Вроде умер не родившись... Там вообще вроде С++. Причём тут сабж?
S> и CoreClr https://msdn.microsoft.com/en-us/library/windows/apps/jj681690(v=vs.105).aspx S>http://stackoverflow.com/questions/14247142/what-framework-does-windows-phone-7-and-windows-phone-8-support S>С кучей профилей. S> http://stackoverflow.com/questions/18164769/windows-phone-8-native-and-clr-runtime
Но там же твой ненавистный JIT. ngen разве был?
S>>> Ну моделей смартфонов то немного, и держать для каждой модели скомпилированные файлы. Это же не миллионы. И речь пока идет только об UWP которые только на продуктах MS, и Xamarin для IPhone. Да даже если для андроида, то это не огромное количестао аппаратов. S>·>Каждая новая модель (точнее платформа) — это ещё по одному бинарику для _каждого_ приложения в апп-сторе. Т.е. десяток платформ (у андроида их вроде даже больше) — десятикратная нагрузка на апп-стор. S>·>Конечно, если MS будет выпускать только одну-две модели (как аппл) или надеяться, что приложений будет не так много (как в вин-мобильном апп-сторе), то может и прокатит. S> Один раз скопилировали под плптформу и её уже устанавливают на миллионы устройств. Какая нафин нагрузка? Найти в Базе нужную модель?
Я не о количестве самих устройств. Почитай внимательно что я пишу. Компилировать _каждое_ приложение под _каждую_ платформу _каждой_ версией фреймворка. Тот же андроид и под армы, и под интелы, и под 32 бита, и под 64. Конечно, если будет одна единственная платформа и версия фреймворка, то проблем со сборкой будет меньше, я это и говорил. Но это имеет свои недостатки.
S>>>А вот выхлоп за счет более оптимизируещего компилятора он есть. S>·>Какой ещё "более" оптимизирующий компилятор? Более чем что?
Ы?
S>>> Есть альтернативное решение. По сути это аналог С++ со сборкой мусора. Я уже приводил тебе ссылки на stack stackalloc S>·>Круто конечно, но в java пошли другим путём. Вместо усложнения языка — улучшают JIT. Этот самый stackalloc делается автоматически в некотоых случаях, благодаря escape analysis. S>Угу вместо того, что бы 1 раз оптимизировать нужно каждый раз оптимизировать.
Это плохо не всегда. Иногда это хорошо.
S>При этом SIMD операций нет.
А в .net native есть?
S>stackalloc программист сам знает где вставить, зачем мучать JIT компилятор.
Компилятор железный, его не жалко мучить. А программисты денег хотят за мучения.
S> Ну да лпадно. По твоему C++ умер. Осталасть только Java в том числе и на симках
Причём тут C++?? Сабж-то читал? stackalloc добавили в Плюсы??
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>>>>Да не обязательно CRTP — обычный std::partition_point это уже статический полиморфизм. EP>>>·>Ну method overloading это тоже статический полиморфизм. EP>>>Верно. EP>>>·>Может внутренняя имплементация не так элегантна как в Плюсах, но Arrays.binarySearch внешне выглядит точно так же. EP>>>Внешне Arrays.binarySearch выглядит как борьба с языком — ибо там ручная перегрузка на каждый тип, при видимо одинаковой реализации. EP>·>О красоте можно потом поговорить. Так в чём же динамика? Всё ровно то же, что и в Плюсах пока. EP>Ты сам привёл пример без динамики и теперь спрашиваешь в чём динамика.
Я лишь ответил на твой пример, что мол "обычный std::partition_point это уже статический полиморфизм." И зачем ты мне это рассказал? В java ровно то же.
EP>с большим количеством compile-time проверок проверок.
Да, ок. Кстати, к javac можно annotation processors писать, для большего кол-ва compile-time проверок.
EP>>>Речь про фактический код. Если в одной программе List<Object> и постоянные динамические касты, а в другой List<Derived> и никаких кастов — то первая более динамическая чем вторая. При этом речи о том что такой язык имеет динамическую типизацию не идёт — это всё та же статическая типизация. EP>·>И к чему это тогда? И на Плюсах можно писать std::vector<void *>. EP>В первых версиях Java это был единственный вариант, и поэтому использовали такие динамические построения, несмотря на то что в языке по прежнему была статическая типизации. Сейчас добавили, но это лишь один из примеров.
Это какой-то слабый аргумент. А вон в С++ был MFC и прочий ATL.
EP>·>В том то и дело, что даже в этом твоём понимании меняется динамичность конкретного написнного кода, а не самого языка. Формально-то как-то сможешь дать определение? "Динамичность языка — это...?" Можешь ссылку дать. EP>Повторю то что сказал с самого начала:
Ну всё-таки. Хочется определения. Иначе получается "двуногое без перьев" — и доказывай что хошь.
EP>
EP>>Твой оппонент говорит о том (и с чем я согласен), что в коде на управляемых языках программисты как раз склонны к излишнему динамизму по сравнению с C++ — в котором например статический полиморфизм используется повсеместно.
EP>Возражения на этот тезис есть?
Я возражаю на счёт "склонны". Да, динамика пишется проще на Яве, поэтому её выбирают с более лёгким сердцем, но явно существуют программисты которые "не склонны" — это в основном зависит от самих программистов и решаемых задач, а не от ЯП. Но более "динамичным" язык это не делает. Хотя фиг знает что ты под этим понимаешь. Мне так никто толком значение этого термина не указал.
EP>·>А конкретнее? Вот у нас есть класс "class Person {String name;}". В рантайме мы генерим сериализатор в XML. Какие ошибки будут ловиться|не ловиться? EP>Я же говорю: "ошибки вида сериализации не реализованных базовых типов". То есть например String может не поддерживаться.
А, понятно. Я под базовым типом почему-то подумал о наследовании. Да, такое не проверяется компилятором из коробки. А как Плюсы проверяют? (только без внешних тулзов и дополнительной разметки, плиз, иначе под явой можно просто запилить небольшой тест, инфраструктурный код или annotation processor, который проверит всё что надо во время билда).
EP>>>Но кодогенерация например на Python вообще проблемой не является, так как подключается элементарно (например CMake автоматом сгенерирует нужные правила что для MSVS, что для make, etc) — это ты пытаешься хоть к чему-нибудь придраться. EP>·>Ну python на винде например обычно не стоит. EP>Так он и не факт что на других OS стоит. Но при разработке обычно тот или иной язык скриптов всегда есть
И добавление кодогенерации — ещё один камушек в тяжелось инфраструктуры, когда как в java это тупо часть языка.
EP>·>Инфраструктура java — проще: скачал IDE, скачал исходник (с помошью этой же IDE) — готово. Вот собствено в этом и мой тезис. Неужели не согласен? EP>Относительно кодогенерации (например на Python) — нет, не согласен — ибо ставится в одну команду package manager. А то что в общем кроссплатформенная инфраструктура со всеми зависимостями сложнее — так я это сам выше написал, буквально в сообщении на которое ты ответил — мне что опять себя цитировать?
Ну вот, это я и пытался доказать. А мне тут кто-то заявлял что java-инфраструктура сложнее и дороже.
EP>>>·>Ах. в этом смысле... Ты говоришь, как будто это что-то хорошее. static_cast даёт UB, и хорошо что нет. EP>>>Я не говорю что это хорошее или плохое, я говорю что именно dynamic_cast в Java есть. EP>·>Трудно сказать... Почему он именно dynamic? Там просто cast, и он работает не так как Плюсовый. EP>В чём по-твоему отличие в контексте дискуссии?
В том-то и дело что нет отличия. И наличие каста не делает яву динамичнее.
EP>·>Неужели только потому, что падает в рантайме сразу, а не делает хз что как в Плюсах? EP>На C++ в одной из форм вылетает исключение std::bad_cast, в другой nullptr.
Это же dynamic_cast... — опять доказываешь мне динамичность С++?
EP>·>Да, для Плюсов это "The C++ Standard", для джавы — JLS. EP>>>И почему вообще нужно ограничиваться сферической "частью языка", когда для решения реальных проблем это не имеет значения? EP>·>Имеет значение для надёжности решения, когда у тебя вдруг всё ВНЕЗАПНО не поломается со следующим минорным релизом компилятора|тулзов|етс. EP>Я правильно тебя понял что все Maven'ы, IDE, и т.п. на помойку?
IDE — опциональны, можешь в emacs/vi пилить, можешь eclipse, можешь idea. Мавен/gradle — часть проекта (исходник) в котором указаны версии компонент и они сами выкачиваются, а не внешние зависимости, которые должны быть ручками установлены, разные версии в зависимости от операционки, правильной версии с правильными компонентами/етс.
EP>>>x64, x32, arm, pgo, constant propagation, etc, etc — тоже не часть языка, значит C++ "их не умеет"? EP>>>Ну тогда он и нативный код не умеет — шах и мат EP>·>Это реализации Стандарта. EP>x64, x32, arm, pgo, constant propagation, etc, etc — это тоже реализация стандарта. Также как и JIT Cling
Ну, но не стандарт ведь.
EP>·>Притом от хорошей реализации требуется, что некая конструкция языка работает именно так как описано в стандарте, на всех этих платформах. EP>·>Т.е. если ты пишешь "int i=2+2" — ты обязан получить i==4, иначе это не С++. То же и в Java. Пишешь ClassLoader.defineClass — он должен работать как описано в спеке. Как генерировать код в С++ — да никак, никто ничего в языке не обещает. EP>Так там и про нативный код ничего нет
И, как ни странно, C++ и не обязан в нативный код компиляться. Что не так-то?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
·>Здравствуйте, Serginio1, Вы писали:
S>>>>·>Т.е. вообще тупой интерпретатор с примитивным GC. Вот они и стали пилить этот самый .net native. S>>>> .Net Native сейчас идет под UWP Что такое приложение UWP? S>>>>Там не только мобильные устройства. .NET Micro Framework это другое Microsoft .NET Framework во встраиваемых приложениях <br />
<span class='lineQuote level4'>S>>>></span>. S>>·>А что на мобильниках? Или мобильников с dotnet не было что-ли ещё в природе (до .net native)? S>> Был .Net Compact Framework, ·>Там был NGEN?
Не знаю. S>>затем пришел WinRt ·>А он вообще "был"? Вроде умер не родившись... Там вообще вроде С++. Причём тут сабж?
Ты бы хоть ссылку почитал. Зачем я стараюсь?
модель программирования от Microsoft, являющаяся основой для разработки приложений в стиле Метро в операционной системе Windows 8[1][2]. WinRT поддерживает разработку на C++ (обычно с использованием расширения языка Component Extensions, C++/CX), управляемых языках C# и VB.NET, а также JavaScript.
Универсальная платформа Windows (англ. Universal Windows Platform, сокр. UWP) — платформа, созданная Microsoft и впервые представленная в Windows 10. Целью данной платформы является помощь в создании универсальных приложений Windows[en], запускаемых как на Windows 10, так и на Windows 10 Mobile без изменения в коде. Есть поддержка создания таких приложений на C++, C#, VB.NET и XAML. API реализован в C++ и поддерживается в C++, VB.NET, C#, F# и JavaScript.[1] Разработанная как расширение для Windows Runtime платформа была представлена в Windows Server 2012 и Windows 8, где позволяла запускать приложения на разных аппаратных платформах.[2]
S>> и CoreClr https://msdn.microsoft.com/en-us/library/windows/apps/jj681690(v=vs.105).aspx S>>http://stackoverflow.com/questions/14247142/what-framework-does-windows-phone-7-and-windows-phone-8-support S>>С кучей профилей. S>> http://stackoverflow.com/questions/18164769/windows-phone-8-native-and-clr-runtime ·>Но там же твой ненавистный JIT. ngen разве был?
Еще раз NGEN и .Net Native это разные вещи.
Из-за рефлексии нельзя многе оптимизировать компилятору. И по сути NGEN приводит только к снижению затрат на загрузку, но по сути то компилятор то тот же JIT.
S>>>> Ну моделей смартфонов то немного, и держать для каждой модели скомпилированные файлы. Это же не миллионы. И речь пока идет только об UWP которые только на продуктах MS, и Xamarin для IPhone. Да даже если для андроида, то это не огромное количестао аппаратов. S>>·>Каждая новая модель (точнее платформа) — это ещё по одному бинарику для _каждого_ приложения в апп-сторе. Т.е. десяток платформ (у андроида их вроде даже больше) — десятикратная нагрузка на апп-стор. S>>·>Конечно, если MS будет выпускать только одну-две модели (как аппл) или надеяться, что приложений будет не так много (как в вин-мобильном апп-сторе), то может и прокатит. S>> Один раз скопилировали под плптформу и её уже устанавливают на миллионы устройств. Какая нафин нагрузка? Найти в Базе нужную модель? ·>Я не о количестве самих устройств. Почитай внимательно что я пишу. Компилировать _каждое_ приложение под _каждую_ платформу _каждой_ версией фреймворка. Тот же андроид и под армы, и под интелы, и под 32 бита, и под 64. Конечно, если будет одна единственная платформа и версия фреймворка, то проблем со сборкой будет меньше, я это и говорил. Но это имеет свои недостатки.
Ну и сколько этих самых платформ? То есть твой хваленый JIT справляется, а С++ компилятор нет? Мало того многие приложения на С++ распространяются в исходниках, что бы компилировались под машину.
S>>>>А вот выхлоп за счет более оптимизируещего компилятора он есть. S>>·>Какой ещё "более" оптимизирующий компилятор? Более чем что? ·>Ы?
Еще раз. Кроме инлайнинга, оптимизации алгоритмов. Есть еще и проблема с рефлексией? которые тоже не дают обширное поле для оптимизации https://msdn.microsoft.com/Ru-ru/library/dn600640(v=vs.110).aspx
S>>>> Есть альтернативное решение. По сути это аналог С++ со сборкой мусора. Я уже приводил тебе ссылки на stack stackalloc S>>·>Круто конечно, но в java пошли другим путём. Вместо усложнения языка — улучшают JIT. Этот самый stackalloc делается автоматически в некотоых случаях, благодаря escape analysis. S>>Угу вместо того, что бы 1 раз оптимизировать нужно каждый раз оптимизировать. ·>Это плохо не всегда. Иногда это хорошо.
S>>При этом SIMD операций нет. ·>А в .net native есть?
Не знаю. Но там используется С++ компилятор который это умеет. S>>stackalloc программист сам знает где вставить, зачем мучать JIT компилятор. ·>Компилятор железный, его не жалко мучить. А программисты денег хотят за мучения.
Ну программист использует await или Linq, а stackalloc ничем не сложнее
S>> Ну да лпадно. По твоему C++ умер. Осталасть только Java в том числе и на симках ·>Причём тут C++?? Сабж-то читал? stackalloc добавили в Плюсы??
Еще раз для .Net Native используется С++ компилятор. А stackalloc в плюсах по умолчанию. Там особой разницы между структурами и классами нет. За исключением new
Кроме того появятся ref returns
Локальные переменные и возвращаемые значения по ссылке
Теперь можно не только передать параметры в метод по ссылке (с помощью ключевого слова ref), но и возвратить данные из метода по ссылке, а также сохранить в локальной переменной тоже по ссылке.
public ref int Find(int number, int[] numbers)
{
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i] == number)
{
return ref numbers[i]; // возвращаем ссылку на место хранения, а не значение элемента массива
}
}
throw new IndexOutOfRangeException($"{nameof(number)} не найден");
}
int[] array = { 1, 15, -39, 0, 7, 14, -12 };
ref int place = ref Find(7, array); // ссылка на место, где находится 7 в массиве
place = 9; // заменяем 7 на 9
WriteLine(array[4]); // выведет 9
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, ·, Вы писали:
V>>·>Ну зачем врать-то нак нагло? Твоя цитата? "Я делал синтетические тесты и на джаве и на дотнете с генерацией объектов и отправки их в другой поток. Дык, Disruptor именно это и делает. " V>>Да, отправляет в другой поток. ·>Опять юлишь, изворачиваешься.
это ты тормозишь уже десятки постов
·>
Если памяти каюк и сотни миллионов объектов на освобождение, то деваться некуда.
·>Я делал синтетические тесты и на джаве и на дотнете с генерацией объектов и отправки их в другой поток.
·>Что же такое "генерация объектов"?
Действительно!
·>Откуда в дисрапторе "сотни миллионов объектов на освобождение"?
А при чем тут та цитата и дисраптор, если в той ветке мы обсуждали GC?
V>>тут я неточно выразился, много-один покрывает так же один-один, ес-но. ·>Правда по производительности они отличаются.
Нет. Реализация идентична.
V>>про реализацию на простейшем lock-free контейнере уже писал. ·>Дай ссылку на нормальное описание. У тебя со священниками двух двунаправленных очередей что-то не очень получилось описать.
Описать у меня получилось. Это у тебя не получилось осмыслить. ))
Если в голове представить тяжело, то что помешало нарисовать на листике большую окружность (ring-buffer), на этой окружности нарисовать кружочки поменьше (элементы буфера), отметить произвольные два из них (желательно не соседние) стрелками с подписями W и R, нарисовать вдоль большой окружности стрелку в произвольном направлении вращения, обозначающую направления движения курсоров W и R и увидеть, что по направлению движения от W до R у нас будет очередь свободных ячеек, а от R до W — очередь ячеек с данными, итого две встречных очереди: от W до R и обратно.
Опять рука-лицо, заметь.
Собственно, сама схема из двух очередей для такого сценария — это классика жанра. А вот реализация на кольцевом буфере — нубство как есть, по следующим причинам:
— этот буфер обычно растёт только в сторону увеличения;
— наличие операции вынужденого роста буфера делает запись в такую очередь вдвое дороже;
— если операции увеличения буфера нет, то получаем блокировку на стороне записи в пиковые моменты и можем просрать пакеты UDP, скажем;
— для целей переиспользования памяти выгодней брать те её линейки, что есть уже в кеше, т.е. наиболее выгодным устройством пула объектов является структура с характеристикой LIFO, но не в коем случае не FIFO.
— м/у чтением объекта из очереди и смещением курсора чтения еще "что-то дорогостоящее" происходит, как минимум interlocked exchange для замены объекта из ячейки "пустым" экземпляром, если мы не перекачиваем данные прямо в области памяти кольцевого буфера.
— если же по кольцевому буферу (по его области памяти) передавать непосредственно данные, то происходящее будет резко тормозиться схемой поддержки когерентности линеек кешей для разных ядер проца, ведь операция доступа к одной и той же линейке кеша из двух потоков будет самой популярной при этом сценарии.
V>>ордербук один на инструмент, т.е. на один инструмент не надо кучи потоков. V>>самих инструментов сотни/тысячи ·>Это ты о equities, там да попроще, и таких жестких требований нет.
Пофиг на вид инструмента от слова совсем.
V>>данные так не идут, они идут по непересекающимся рынкам/разделам, там негде взяться общей очереди много-ко-многим ·>Это относительно простой сценарий. В случае же FX инструментов не так много
Это вы не на тех биржах обитаете.
·>притом прут масс-ордера по нескольким ордербукам одновременно, да и >90% трафика прёт в один-единственный EUR/USD ордербук.
По единичной позиции EUR/USD никогда не генерится более 30-40 тыс матчей в секунду. Для HFT это не нагрузка, а холостой ход.
Если у вас эти цифры составляют 90% трафика, то ты НЕ знаешь, что такое HFT.
V>>·>"много-много" это не единственная схема реализуемая на дизрапторе. "один-один" тоже реализуется. V>>ну конечно, достаточно писать одним потоком и читать одним потоком, только для этого сценария не нужен двухстадийный CAS с той самой большой вероятностью отатов ·>Где ты нашел двустадийный CAS?
В схеме ring-buffer.
V>>да и вообще, в контексте было обсуждение процесса перекачки данных, а не обработки, поэтому речь шла о балансе ресурсов для такой перекачки ·>Так говори сразу словами, а не телепатируй. ·>Почему это работает лучше? Есть какие-нибудь тесты в паблике?
Результаты тестов я тебе давал. Цифры в полтора-два раза лучше других топов.
V>>в случае многие-ко-многим балансировка выполняется, считай, на каждое сообщение, а нам все-равно один конкретный ордер-бук надо из одного потока обрабатывать, поэтому выгодней балансировать редко и целыми инструментами или рынками. ·>К чему ты это? Разные задачи — разные решения. Ты хочешь сказать, не бывает задач, требующих такой балансировки?
Бывает, конечно. Когда стоимость обработки сообщения (задачи) на многие порядки превышает стоимость обслуживания межпоточной очереди, то да, имеет смысл балансить буквально каждую задачу. Но! даже при таком подходе есть разные алгоритмы наиболее дешевого баланса. Самый популярный на сегодня — это алгоритм work stealing. Очевидно, что твой дисраптор никакого алгоритма шедуллинга не выполняет вообще для сценария многие-ко-многим, реализуя заведомо наихудшую (дефолтную) стратегию из всех известных на сегодня.
·>Как я понимаю, хоть каких-либо подтверждений слов я так и не дождусь, товарищ фантазёр..
Подтверждения я тебе уже приводил.
А сейчас своим хамством ты банально выпрашиваешь исходник на блюдечке с голубой каёмочкой.
И зачем тогда ТЫ, как программист, нужен в области программирования HFT, если ты после всего разжёванного даже не состоянии проглотить и породить такой исходник сам? Вот какая от тебя там польза, если ты НАСТОЛЬКО далёк от темы управления ресурсами современного железа?
Причём, у тебя беда не в том, что ты прямо сейчас инфой не владеешь, это как раз излечимо при желании, упорстве и хорошо работающей голове. Беда у тебя в самом целеполагании — тебе это всё НЕ интересно. Но ведь невозможно быть профи в том, что неинтересно, верно?
Если памяти каюк и сотни миллионов объектов на освобождение, то деваться некуда.
V>·>Я делал синтетические тесты и на джаве и на дотнете с генерацией объектов и отправки их в другой поток.
V>·>Что же такое "генерация объектов"? V>Действительно!
Ну и?
V>·>Откуда в дисрапторе "сотни миллионов объектов на освобождение"? V>А при чем тут та цитата и дисраптор, если в той ветке мы обсуждали GC?
Так это тебя спросить надо. Обсуждали gc, а ты упомянул дизраптор. Так зачем упомянул-то? Так в каком месте-то дизраптор генерит сотни миллионов объектов на освобождение?
V>>>тут я неточно выразился, много-один покрывает так же один-один, ес-но. V>·>Правда по производительности они отличаются. V>Нет. Реализация идентична.
Понятно что идентична. Но работает с разной скоростью.
V>>>про реализацию на простейшем lock-free контейнере уже писал. V>·>Дай ссылку на нормальное описание. У тебя со священниками двух двунаправленных очередей что-то не очень получилось описать. V>Описать у меня получилось. Это у тебя не получилось осмыслить. ))
V>Если в голове представить тяжело, то что помешало нарисовать на листике большую окружность (ring-buffer), на этой окружности нарисовать кружочки поменьше (элементы буфера), отметить произвольные два из них (желательно не соседние) стрелками с подписями W и R, нарисовать вдоль большой окружности стрелку в произвольном направлении вращения, обозначающую направления движения курсоров W и R и увидеть, что по направлению движения от W до R у нас будет очередь свободных ячеек, а от R до W — очередь ячеек с данными, итого две встречных очереди: от W до R и обратно.
Ты всё ещё уверен, что очереди двунаправленные?
V>Опять рука-лицо, заметь.
Вот такая картинка:
Правильно?
V>Собственно, сама схема из двух очередей для такого сценария — это классика жанра. А вот реализация на кольцевом буфере — нубство как есть, по следующим причинам:
Не понял. Ты выше что описал — кольцевой буфер или две очереди?
V>- этот буфер обычно растёт только в сторону увеличения; V>- наличие операции вынужденого роста буфера делает запись в такую очередь вдвое дороже; V>- если операции увеличения буфера нет, то получаем блокировку на стороне записи в пиковые моменты и можем просрать пакеты UDP, скажем;
Это значит что читатель не справляется. Тут два варианта — либо блокировать писателей, либо начать дропать пакеты (оба варианта поддерживаются в disruptor). Третьего не дано.
V>- для целей переиспользования памяти выгодней брать те её линейки, что есть уже в кеше, т.е. наиболее выгодным устройством пула объектов является структура с характеристикой LIFO, но не в коем случае не FIFO.
Тогда читатели и писатели будут конкурентно бороться за одну линейку кеша. А так получается твой любимый конвеер.
V>- м/у чтением объекта из очереди и смещением курсора чтения еще "что-то дорогостоящее" происходит, как минимум interlocked exchange для замены объекта из ячейки "пустым" экземпляром, если мы не перекачиваем данные прямо в области памяти кольцевого буфера. V>- если же по кольцевому буферу (по его области памяти) передавать непосредственно данные, то происходящее будет резко тормозиться схемой поддержки когерентности линеек кешей для разных ядер проца, ведь операция доступа к одной и той же линейке кеша из двух потоков будет самой популярной при этом сценарии.
V>>>ордербук один на инструмент, т.е. на один инструмент не надо кучи потоков. V>>>самих инструментов сотни/тысячи V>·>Это ты о equities, там да попроще, и таких жестких требований нет. V>Пофиг на вид инструмента от слова совсем.
Не совсем пофиг с технической т.з, распределение нагрузки разное. Т.к. разные инструменты ведут себя по-разному. Сток торгуется медленно, дай боже 1 ордер в минуту (зато миллионы инструментов), а валюты — сотни/тысячи ордеров в секунду от каждого клиента (но инструментов только несколько сот).
V>>>данные так не идут, они идут по непересекающимся рынкам/разделам, там негде взяться общей очереди много-ко-многим V>·>Это относительно простой сценарий. В случае же FX инструментов не так много V>Это вы не на тех биржах обитаете.
Биржи на биржах не обитают LMAX — сама по себе FX-биржа.
V>·>притом прут масс-ордера по нескольким ордербукам одновременно, да и >90% трафика прёт в один-единственный EUR/USD ордербук. V>По единичной позиции EUR/USD никогда не генерится более 30-40 тыс матчей в секунду. Для HFT это не нагрузка, а холостой ход. V>Если у вас эти цифры составляют 90% трафика, то ты НЕ знаешь, что такое HFT.
Я же написал не матчи, а ордера. Большинство этих ордеров — cancel-replace mass orders, т.е. смена цены или размера ордеров, притом для пачки инструментов сразу (атомарно). И это порождает туеву хучу market data.
Трейдов да, относительно немного.
V>>>·>"много-много" это не единственная схема реализуемая на дизрапторе. "один-один" тоже реализуется. V>>>ну конечно, достаточно писать одним потоком и читать одним потоком, только для этого сценария не нужен двухстадийный CAS с той самой большой вероятностью отатов V>·>Где ты нашел двустадийный CAS? V>В схеме ring-buffer.
А точнее?
V>·>Так говори сразу словами, а не телепатируй. V>·>Почему это работает лучше? Есть какие-нибудь тесты в паблике? V>Результаты тестов я тебе давал. Цифры в полтора-два раза лучше других топов.
Ты давал FIX engine, насколько я помню.
V>>>в случае многие-ко-многим балансировка выполняется, считай, на каждое сообщение, а нам все-равно один конкретный ордер-бук надо из одного потока обрабатывать, поэтому выгодней балансировать редко и целыми инструментами или рынками. V>·>К чему ты это? Разные задачи — разные решения. Ты хочешь сказать, не бывает задач, требующих такой балансировки? V>Бывает, конечно. Когда стоимость обработки сообщения (задачи) на многие порядки превышает стоимость обслуживания межпоточной очереди, то да, имеет смысл балансить буквально каждую задачу. Но! даже при таком подходе есть разные алгоритмы наиболее дешевого баланса. Самый популярный на сегодня — это алгоритм work stealing. Очевидно, что твой дисраптор никакого алгоритма шедуллинга не выполняет вообще для сценария многие-ко-многим, реализуя заведомо наихудшую (дефолтную) стратегию из всех известных на сегодня.
Это вообще-то scheduling algorithm, а не метод перекачки данных между потоками. Дизраптор _может_ использоваться совместно с work stealing, а можно что-то другое заюзать, ту же BlockingQueue.
V>·>Как я понимаю, хоть каких-либо подтверждений слов я так и не дождусь, товарищ фантазёр.. V>Подтверждения я тебе уже приводил. V>А сейчас своим хамством ты банально выпрашиваешь исходник на блюдечке с голубой каёмочкой.
Какой исходник? Я хочу услышать хоть какое-нибудь подтверждение твоих слов, что в LMAX больше не используют дизраптор: "Раз они выложили дисраптор в паблик, значит им он больше не нужен".
V>И зачем тогда ТЫ, как программист, нужен в области программирования HFT, если ты после всего разжёванного даже не состоянии проглотить и породить такой исходник сам? Вот какая от тебя там польза, если ты НАСТОЛЬКО далёк от темы управления ресурсами современного железа?
Ты всё разжевываешь только телепатически. А пишешь какие-то обрывки и не читаешь что тебе пишут.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Serginio1, Вы писали:
S>>>·>А что на мобильниках? Или мобильников с dotnet не было что-ли ещё в природе (до .net native)? S>>> Был .Net Compact Framework, S>·>Там был NGEN? S> Не знаю.
Ну дык.
S>·>А он вообще "был"? Вроде умер не родившись... Там вообще вроде С++. Причём тут сабж? S> Ты бы хоть ссылку почитал. Зачем я стараюсь? S>
S> модель программирования от Microsoft, являющаяся основой для разработки приложений в стиле Метро в операционной системе Windows 8[1][2]. WinRT поддерживает разработку на C++ (обычно с использованием расширения языка Component Extensions, C++/CX), управляемых языках C# и VB.NET, а также JavaScript.
А, ну да. И там тоже JIT, никакого AOT: "CLR provides services like JIT-compilation code and garbage collection".
Так что похоже, что проблема ngen не в том, что он плохой, а в том что его никогда не было для мобильных платформ.
S>·>Но там же твой ненавистный JIT. ngen разве был? S> Еще раз NGEN и .Net Native это разные вещи. S>Из-за рефлексии нельзя многе оптимизировать компилятору. И по сути NGEN приводит только к снижению затрат на загрузку, но по сути то компилятор то тот же JIT.
Это как? ngen вроде работает до запуска приложения. Как оно может JIT?
S>>> Один раз скопилировали под плптформу и её уже устанавливают на миллионы устройств. Какая нафин нагрузка? Найти в Базе нужную модель? S>·>Я не о количестве самих устройств. Почитай внимательно что я пишу. Компилировать _каждое_ приложение под _каждую_ платформу _каждой_ версией фреймворка. Тот же андроид и под армы, и под интелы, и под 32 бита, и под 64. Конечно, если будет одна единственная платформа и версия фреймворка, то проблем со сборкой будет меньше, я это и говорил. Но это имеет свои недостатки. S> Ну и сколько этих самых платформ? То есть твой хваленый JIT справляется, а С++ компилятор нет? Мало того многие приложения на С++ распространяются в исходниках, что бы компилировались под машину.
Я точно не знаю, вроде больше десятка платформ.
Какой "мой хвалёный JIT"? Очередной раз повторяю — в ART сделали AOT. А до этого был Dalvik с JIT; что интересно переход был абсолютно прозрачным, они заменили реализацию платформы, а андроид-программисты вообще это не заметили, те же бинарики просто стали работать на новой платформе, уже с AOT вместо JIT. А не этот пипец от майкрософт, когда они каждый год-два выпускают новую несовместимую технологию (ты уж штук пять назвал).
S>>>·>Какой ещё "более" оптимизирующий компилятор? Более чем что? S>·>Ы? S> Еще раз. Кроме инлайнинга, оптимизации алгоритмов. Есть еще и проблема с рефлексией? которые тоже не дают обширное поле для оптимизации S>https://msdn.microsoft.com/Ru-ru/library/dn600640(v=vs.110).aspx
А какая проблема с рефлекией в Java на Андроиде? Просто она работает значительно медленнее, но никаких модификаций кода не требуется.
S>·>А в .net native есть? S> Не знаю. Но там используется С++ компилятор который это умеет. S>>>stackalloc программист сам знает где вставить, зачем мучать JIT компилятор. S>·>Компилятор железный, его не жалко мучить. А программисты денег хотят за мучения. S> Ну программист использует await или Linq, а stackalloc ничем не сложнее
await/linq даёт более красивый, короткий, читабельный код. stackalloc — это просто средство ручной оптимизации.
S>Кроме того появятся ref returns
Интересная фича. Спасибо.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
·>Ты всё ещё уверен, что очереди двунаправленные?
На твоём рисунке даже нарисованы две стрелочки навстречу друг другу.
V>>Собственно, сама схема из двух очередей для такого сценария — это классика жанра. А вот реализация на кольцевом буфере — нубство как есть, по следующим причинам: ·>Не понял. Ты выше что описал — кольцевой буфер или две очереди?
А какая м/у ними разница?
·>Это значит что читатель не справляется. Тут два варианта — либо блокировать писателей, либо начать дропать пакеты (оба варианта поддерживаются в disruptor). Третьего не дано.
Третье — это увеличивать очередь для моментов пиковых нагрузок. Желательно задешево.
И желательно затем, после спадания пика нагрузки, вот эту всю выделенную для такого увеличения память не прогонять через кеши проца, обходясь тем самым минимумом.
Ты мне можешь показать, кста, участок в коде, где disruptor увеличивает размер своего буфера?
А то я увидел лишь несколько реализаций блокирующих стратегий, что есть полная ж-па, ес-но.
V>>- для целей переиспользования памяти выгодней брать те её линейки, что есть уже в кеше, т.е. наиболее выгодным устройством пула объектов является структура с характеристикой LIFO, но не в коем случае не FIFO. ·>Тогда читатели и писатели будут конкурентно бороться за одну линейку кеша. А так получается твой любимый конвеер.
А если объект улетит из L1 кеша в случае длинного кольцевого буфера, то это будет совсем ж-па. На выбор.
Если в обеих очередях хотя бы один элемент, то уже не принципиально даже на максимальной загрузке, пакеты даже по 10-гигабитной сетке приходят с конечной скоростью.
Для обеспечения такого буфферного элемента СНАЧАЛА текущее сообщение пуляют в очередь, а ЗАТЕМ берут из пула элемент "на будущее" и в него уже пишут следующие пришедшие данные. Т.е. не должно быть задержки по приходу сообщения, а между самим сообщениями в сети всё-равно есть задержки.
·>Не совсем пофиг с технической т.з, распределение нагрузки разное. Т.к. разные инструменты ведут себя по-разному. Сток торгуется медленно, дай боже 1 ордер в минуту (зато миллионы инструментов), а валюты — сотни/тысячи ордеров в секунду от каждого клиента (но инструментов только несколько сот).
А валюта разбита на кучу конкретных инструментов, та же пара USD/EUR разбита по датам исполнения, а по каждому конкретному инструменту всё-равно свой ордербук.
V>>·>притом прут масс-ордера по нескольким ордербукам одновременно, да и >90% трафика прёт в один-единственный EUR/USD ордербук. V>>По единичной позиции EUR/USD никогда не генерится более 30-40 тыс матчей в секунду. Для HFT это не нагрузка, а холостой ход. V>>Если у вас эти цифры составляют 90% трафика, то ты НЕ знаешь, что такое HFT. ·>Я же написал не матчи, а ордера.
Все ордера не нужны для поддержания, нужны топовые, а там картинка меняется только при каждом матче, ведь матчатся всегда только и исключительно топовые.
А если подключиться к каналу, по которому шлют вообще все ордера, то такой канал на самой бирже идёт в виде крупных батчей с ОЧЕНЬ большими задержками от момента постановки/снятия/изменения самих ордеров. Большими в сравнении с тем самым HFT. Т.е. торговать по событиям в этом фиде заведомо нелепо — этот фид нужен для оценки общего состояния рынка, разве что. Мало ли где там в конце хвоста кто-то что-то присунул ("в конце" означает "дал худшую цену"). Даже если ты мгновенно на это среагируешь (на худшую цену) до неё очередь дойдёт ой как не скоро.
·>Большинство этих ордеров — cancel-replace mass orders, т.е. смена цены или размера ордеров, притом для пачки инструментов сразу (атомарно). И это порождает туеву хучу market data.
Да какая разница? Биржа всё-равно матчит последовательно и с конечной скоростью.
И да, повторюсь, на биржах, типа NASDAQ (и вообще на всех OMnet-based), инфа о конкретных ЧУЖИХ ордерах приходит сильно с запозданием от реалтаймовой market data.
V>>>>·>"много-много" это не единственная схема реализуемая на дизрапторе. "один-один" тоже реализуется. V>>>>ну конечно, достаточно писать одним потоком и читать одним потоком, только для этого сценария не нужен двухстадийный CAS с той самой большой вероятностью отатов V>>·>Где ты нашел двустадийный CAS? V>>В схеме ring-buffer. ·>А точнее?
А сам?
Везде идут последовательности при записи, типа таких:
sequencer.tryNext()/next() — тут CAS
затем
tryPublishEvents()/publishEvents() в теле которых опять
sequencer.tryNext()/next()
После обработки события в случае множества потребителей опять будет многостадийный CAS в случае, если потребители закончат обработку не в той последовательности, в которой взяли данные из кольцевого буфера. Посмотри на операции вокруг SequnceGoup и вызывающей её publish со стороны обработчика данных.
V>>Результаты тестов я тебе давал. Цифры в полтора-два раза лучше других топов. ·>Ты давал FIX engine, насколько я помню.
Оно же на чем-то построено? ))
V>>Бывает, конечно. Когда стоимость обработки сообщения (задачи) на многие порядки превышает стоимость обслуживания межпоточной очереди, то да, имеет смысл балансить буквально каждую задачу. Но! даже при таком подходе есть разные алгоритмы наиболее дешевого баланса. Самый популярный на сегодня — это алгоритм work stealing. Очевидно, что твой дисраптор никакого алгоритма шедуллинга не выполняет вообще для сценария многие-ко-многим, реализуя заведомо наихудшую (дефолтную) стратегию из всех известных на сегодня. ·>Это вообще-то scheduling algorithm, а не метод перекачки данных между потоками.
Данные перекачиваются не для того, чтобы любоваться ими, а чтобы их обрабатывать.
Там всей разницы, что в случае перекачки "абстрактных задач" мы перекачиваем пару {данные, обработчик}, а в нашем случае обработчик считается известным.
·>Дизраптор _может_ использоваться совместно с work stealing, а можно что-то другое заюзать, ту же BlockingQueue.
Не может, у него алгоритм чтения текущего возможного элемента тупой до посинения — берется минимальный по номеру из последовательности.
Кароч, кое-какая оптимизация там есть — это попытка забирать данные батчами. Это удешевляет схему в пересчёте на сообщение. Но эта оптимизация для конкретного этого дисраптора хороша только в случае единичного обработчика, потому что, если обработчиков много, то освободившиеся обработчики не будут иметь доступа к необработанным еще сообщениям другого, притормаживающего обработчика; свободные обработчики тупо опять полезут в буфер, вместо того, чтобы как можно быстрее обработать принятые ранее и уже "перекаченные" данные. Т.е. основной фишки "work stealing" он не может.
·>Какой исходник? Я хочу услышать хоть какое-нибудь подтверждение твоих слов, что в LMAX больше не используют дизраптор: "Раз они выложили дисраптор в паблик, значит им он больше не нужен".
Так я уже своё мнение озвучивал. Полезное Ноу-хау никто выкладывать не будет.
·>Ты всё разжевываешь только телепатически. А пишешь какие-то обрывки и не читаешь что тебе пишут.
Самое главное, что после получения новой инфы ты, вместо того, чтобы что-то порыть по теме, задалбываешь меня подколками разной степени провокационности (а докажи? а ссылку? сам придумал?) в попытках заставить меня таскать для тебя подробности из Интернета. Фокус стар как мир и выдаёт лентяев сходу. Ну я примерно 10% таких просьб исполняю, сугубо из альтруистических побуждений и корпоративной солидарности... но совесть же тоже иметь надо? ))
S>Универсальная платформа Windows (англ. Universal Windows Platform, сокр. UWP) — платформа, созданная Microsoft и впервые представленная в Windows 10. Целью данной платформы является помощь в создании универсальных приложений Windows[en], запускаемых как на Windows 10, так и на Windows 10 Mobile без изменения в коде. Есть поддержка создания таких приложений на C++, C#, VB.NET и XAML. API реализован в C++ и поддерживается в C++, VB.NET, C#, F# и JavaScript.[1] Разработанная как расширение для Windows Runtime платформа была представлена в Windows Server 2012 и Windows 8, где позволяла запускать приложения на разных аппаратных платформах.[2]
Встречал уже на этом форуме глупые ожидания какого-то прорыва от UWP. Но пока ни один из фанатов данного подхода не смог ответить на один мой простейший вопрос: кто и зачем будет сейчас разрабатывать приложения под UWP? UWP позволяет писать приложения работающие на win10 и win10 mobile (мёртвой платформе). А банальные древние win32 приложения позволяют писать приложения работающие на win10 и на всех старых виндах (которые кстати пока ещё даже популярнее win10). Соответственно совершенно непонятно кто в своём уме будет тратить ресурсы на переобучение под новую технологию, которая в итоге принесёт гораздо меньше пользы чем старая.
Сразу отмечу, что я критикую не саму абстрактную идею универсальных приложений (сама то по себе идея не плохая и теоретически даже имела бы некие шансы на успех скажем в 2007-ом году, когда MinMobile занимала 2-ое место на рынке смартфонов), а конкретный бизнес подход в конкретный момент времени. Сейчас я не вижу ни единой разумной причины для перехода независимых разработчиков на UWP. Вот переход с win32 на некий инструмент (не важно что это конкретное — есть несколько принципиально разных подхода), позволяющий писать приложения сразу и под Windows (желательно всех версий) и под Android, наоборот кажется крайне актуальным.
S> Еще раз для .Net Native используется С++ компилятор.
Вот уже не первый раз встречаю это утверждение на форуме, но при этом без всякой расшифровки. А она очевидно весьма нужна, т.к. всё же там явно подразумевается не создание некого транслятора C# в C++, а нечто другое. А раз нечто другое, то это требует ещё отдельного исследования эффективности.