Почему команда в LMAX использовала Java и проектировала архитектуру, чтобы любой ценой избежать GC?


24

Почему команда в LMAX разработала LMAX Disruptor в Java, но все их разработки сводятся к минимизации использования GC? Если кто-то не хочет запускать GC, зачем использовать язык сборки мусора?

Их оптимизация, уровень знаний об оборудовании и мысли, которые они вкладывают, просто потрясающие, но почему Java?

Я не против Java или чего-либо, но почему язык GC? Почему бы не использовать что-то вроде D или любой другой язык без GC, но позволяет эффективный код? Это то, что команда больше всего знакома с Java или у Java есть какое-то уникальное преимущество, которого я не вижу?

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


6
Я очень мало знаю об этом проекте, но, похоже, это некая основа, на которой могут основываться другие. И если вам удастся написать это на Java (и позволить другим программировать на Java и пожинать плоды), то у вас будет НАМНОГО большая «клиентская база», чем если бы вы написали это на D.
Йоахим Зауэр

6
@kadaj: на самом деле не имеет значения, является ли потребитель общедоступным или внутренним: если вы сделаете его доступным на широко известном языке, это будет более полезным, даже для внутреннего развития. Если вы начинаете свой (гипотетический) аргумент со слова «Предположим, что все знают D так же хорошо, как и Java ...», то вы, вероятно, что-то упускаете.
Йоахим Зауэр

6
Некоторым людям нравится использовать молотки для решения всевозможных проблем. Получил грубый край, который вы хотите строгать, ударьте его молотком, пока он не станет гладким. Получил винт, который тебе нужен, вбил, ударил его молотком до упора. Получил тонкий орнамент, который нужно отшлифовать, ударил молотком, а затем обвинил орнамент в «сосании». C или C ++ был бы лучшим выбором, чем D, если бы только существующая база знаний. Не уверен, почему вы даже привели D в качестве примера TBH.
gbjbaanb

2
@gbjbaanb Я упомянул D, потому что он обеспечивает сборку мусора (в тех случаях, когда необходимы абстракции высокого уровня и слишком сложно манипулировать памятью), но также позволяет осуществлять ручное управление памятью с помощью malloc и бесплатно в стиле C. D вроде как Objective-C с ARC (без реального GC), но лучше, чем это. Но да, C / C ++ будет соответствовать всем требованиям.

4
@kadaj Я вижу, что вы получили некоторое замечание за то, что подняли D, но я хочу сказать, что разочарован тоном, который используют другие, и объясняю, почему я считаю, что D занимает центральное место в рассматриваемом вопросе. Хотя D действительно не очень широко используется, D предоставляет некоторые высокоуровневые конструкции, которые я мог бы ожидать найти, скажем, в Java или C #, но не в (по крайней мере, в старом стиле) C ++. Он по-прежнему предусматривает смешивание управляемого и неуправляемого - это единственный язык, который я знаю для этого! Так что D - это не просто выбор питомца, а цель, цели которой совпадают с первоначальными вопросами вокруг GC.
J Trana

Ответы:


20

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

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

  1. Минимизация количества объектов, которые перемещаются в пространство для выживших (то есть, которые пережили хотя бы одну сборку мусора) с помощью небольших одноразовых объектов. Объект, который переместился в пространство выживших, сложнее собрать, и сборка мусора здесь иногда приводит к зависанию всей JVM.
  2. Не выделяйте слишком много объектов для начала. Это может иметь неприятные последствия, если вы не будете осторожны, поскольку объекты молодого поколения очень дешевы в размещении и сборе.
  3. Убедитесь, что новый объект указывает на старый (а не наоборот), чтобы молодой объект можно было легко собрать, поскольку нет ссылок на них, которые могли бы его сохранить

Когда вы настраиваете производительность, вы обычно настраиваете очень специфическую «горячую точку», игнорируя код, который не часто запускается. Если вы сделаете это в Java, вы можете позволить сборщику мусора по-прежнему заботиться об этом темном углу (так как он не будет иметь большого значения), в то же время очень тщательно оптимизируя область, которая работает в узком цикле. Таким образом, вы можете выбрать, где вы оптимизируете, а где нет, и таким образом вы можете сосредоточить свои усилия там, где это важно.


Теперь, если вы полностью отключите сборку мусора, вы не сможете выбрать. Вы должны вручную избавиться от каждого объекта, когда-либо. Этот метод вызывается не чаще одного раза в день? В Java вы можете позволить этому быть, так как его влияние на производительность незначительно (может быть, допустимо, чтобы полный GC происходил каждый месяц). В C ++ у вас все еще утечка ресурсов, поэтому вы должны позаботиться даже об этом неясном методе Таким образом, вы должны заплатить цену за управление ресурсами в каждой отдельной части вашего приложения, в то время как в Java вы можете сосредоточиться.


Но это еще хуже.

Что если у вас есть ошибка, скажем, в темном углу вашего приложения, доступ к которой возможен только в понедельник в полнолуние? У Java есть сильная гарантия безопасности. Существует практически нет "неопределенного поведения". Если вы используете что-то неправильно, выдается исключение, ваша программа останавливается, и повреждение данных не происходит. Таким образом, вы уверены, что ничего плохого не произойдет, если вы не заметите.

Но в чем-то вроде D у вас может быть плохой доступ к указателю или переполнение буфера, и вы можете повредить вашу память, но ваша программа не будет знать (вы отключили безопасность, помните?) И продолжит работать с ее неправильным данные, и делать какие-то довольно неприятные вещи и портить ваши данные, и вы не знаете, и по мере того, как происходит все больше коррупции, ваши данные становятся все более и более неправильными, а затем внезапно ломаются, и это было в жизненно важном приложении, и некоторые ошибки произошли в вычислении ракеты, и поэтому он не работает, а ракеты взрываются, а кто - то умирает, и ваша компания находится в первой странице каждой газеты и ваша точка босс его палец к вам сказать «Вы находитесь инженер, который предложил использовать D для оптимизации производительности, почему вы не задумывались о безопасности?«И это твоя вина. Ты убил этих людей своей глупой попыткой выступить.


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

Отключение безопасности стоит. Быть родным не всегда имеет смысл. Иногда гораздо проще и безопаснее просто немного оптимизировать безопасный язык, чтобы пойти ва-банк с языком, на котором вы можете застрелиться в ногу. Правильность и безопасность во многих случаях превосходят несколько наносекунд, которые вы могли бы списать, полностью исключив ГХ. Disruptor может быть использован в тех ситуациях, так что я думаю , что LMAX-биржа сделала правильный вызов.

Но как насчет D в частности? У вас есть GC, если вы хотите для темных углов, а подмножество SafeD (о котором я не знал до редактирования) удаляет неопределенное поведение (если вы не забываете его использовать!).

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

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


2
В оригинальном посте специально упоминается D. На самом деле между C ++ и D существует довольно большая разница в отношении гранулярности выбора. Даже если вы решите использовать полный набор функций в подмножестве SafeD, я думаю, вы получите гораздо больший контроль над определенными аспектами сбора и синхронизации (включение / отключение, сбор, сведение к минимуму). Проверьте стратегии Digital Mars для управления памятью!
J Trana

2
Lmax намеренно делает шаг в сторону безопасности, которую обеспечивает Java
Джеймс

Это было бы отличным ответом, за исключением того, что Java не лицензируется для критически важного программного обеспечения. Если у вас есть ядерный реактор, он будет написан на C ++, а не на Java, что исключает весь аспект «безопасности».
gbjbaanb

@gbjbaanb, [цитата нужна]. Стандарты / рекомендации по надежности, которые я видел, рекомендуют сначала избегать C / C ++ в пользу других языков; и, если попасть в них, то использовать строго ограниченные версии языков (MISRA и т. д.). И как только вы принимаете ограничения, я не понимаю, почему вы не можете сделать то же самое с любым другим языком. Если вы подумали об упоминании Java Licence «не для ядерных объектов» в разделе «ОГРАНИЧЕНИЯ», похоже, что это изменилось некоторое время назад, а теперь вместо этого просто говорится что-то вроде «будь осторожен, а не наша ответственность». Тем не менее, я предполагаю (...)
hmijail

(...) оригинальная формулировка была похожа на лицензии gcc и clang: никаких гарантий для каких-либо конкретных целей. Таким образом, вы не будете использовать их для чего-то нуждающегося в надежности, и вместо этого вам нужно будет использовать какой-нибудь сертифицированный компилятор, если не использовать весь конкретный язык для работы (Ада?).
hmijail

4

Кажется, причина того, что он написан на Java, заключается в том, что у них есть собственный опыт работы с Java, и он, вероятно, был написан (хотя он все еще находится в активной разработке) до того, как C ++ начал действовать вместе с C ++ 0x / 11.

Их код на самом деле является только Java по названию, они используют sun.misc.Unsafe, что немного противоречит точке зрения Java, и безопасность якобы дает. Я написал порт C ++ для Disruptor, и он превосходит Java-код, который они поставляют (я не тратил много времени на настройку JVM).

Тем не менее, принципы, которым следует нарушитель, не зависят от языка, например, не ожидайте кода C ++ с низкой задержкой, который выделяет или освобождает из кучи.


Можете ли вы указать на вашу реализацию? Я видел пару таких повторных реализаций, которые заявили о более высокой производительности, но оба обманывают с упрощениями: например, жесткое соединение 1 производитель + 1 потребитель вместо того, чтобы быть мультипроизводителем / потребителем, способным, как оригинальный Disruptor. Сам автор Disruptor упомянул в потоке групп Google, что производительность может быть улучшена с помощью параметров проводного соединения в версии Java.
hmijail

4

Этот вопрос утверждает неверную предпосылку как факт, а затем приводит аргумент об этой неверной предпосылке.

Давайте разберемся с этим ... "все их точки дизайна сводят к минимуму использование GC" - просто не соответствует действительности. Инновация в разрушителе имеет мало общего с GC. Разрушитель работает, потому что его дизайн ловко учитывает, как работают современные компьютеры - что встречается гораздо реже, чем можно было бы ожидать. См. Выступление Клифф Клик http://www.azulsystems.com/events/javaone_2009/session/2009_J1_HardwareCrashCourse.pdf для обсуждения.

Общеизвестно, что LMax являются клиентами Azul. Я знаю из первых рук, что с Azul GC просто нет, даже с кучей в 175 ГБ.


В этом есть доля правды. Они перезапускают виртуальную машину каждую ночь, чтобы избежать большой коллекции. Это то, что написал Мартин Фаулер, так или иначе, и он не дурак: «Как и вся система, разрушители отскакивают за одну ночь. Этот отскок в основном делается для того, чтобы стереть память, чтобы меньше шансов на дорогостоящее событие сбора мусора во время торговли». martinfowler.com/articles/lmax.html
JimmyJames

2
Не совсем. Раньше мы запускали ручной GC каждую ночь в 5-минутном перерыве в торговле и настраивались так, чтобы это был единственный основной GC за день. Это стало излишним с Азул Цин. (Источник: я работал в LMAX до недавнего времени)
Том Джонсон

@ TomJohnson Люблю получать внутри совок. Вы говорите, что описание Мартина Фаулера неверно? Возможно ли решение развилось со временем?
JimmyJames

2
Я говорю, что он был не совсем прав в некоторых мелких деталях. Мы никогда не отказывали нашим системам ежедневно, но мы провели некоторую уборку в конце дня.
Том Джонсон

3

Они должны думать о низком уровне

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

Хотя он очень эффективен, он может привести к ряду ошибок, поскольку его очень легко испортить ...

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

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

Для сравнения, язык программирования высокого уровня изолирует семантику исполнения компьютерной архитектуры от спецификации программы, что упрощает разработку ...


3

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

Мы считаем, что язык и платформа Java имеют много преимуществ по сравнению с C / C ++, и мы разработали и протестировали некоторые компоненты Java со сверхнизкой задержкой, чтобы доказать это. Мы поговорим о методах, используемых для этого в этой статье: Разработка Java без GC .


2
Существуют сборщики мусора, подходящие для систем реального времени. Сборщик по умолчанию JVM может не быть, но это не означает, что GC вообще не подходит для реального времени. Но обычный режим также malloc/freeне подходит для реального времени, так как время выделения не ограничено из-за фрагментации.
Довал

1
Мы выступаем за использование быстрых пулов объектов для всего, поэтому после прогрева распределение не происходит.
rdalmeida

2

LMAX - это высокопроизводительная библиотека обмена сообщениями между потоками.

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

Использование C или C ++ не является хорошим вариантом, если вы не хотите ограничивать пользователей одной ОС, поскольку в них не определена модель потоков.

В наши дни Java является стандартом для многих программных разработок, поэтому, если у вас нет веских причин, это лучший выбор. (Когда в Риме делают, как римляне ...)

Написание высокопроизводительного программного обеспечения на Java (или C #) часто делается, чтобы доказать свою точку зрения…


1
Новый стандарт C ++ 11 поддерживает многопоточность ...
Кейси

@Casey, а сколько реальных компиляторов C ++ его используют? И сколько стоят эти компиляторы. Может быть, через 20 лет это будет полезно, до тех пор, пока вы не можете зависеть от этого.
Ян

Disruptor довольно часто использует sun.misc.Unsafe, что показывает, что вы не можете написать код с малой задержкой на Java без погружения пальца в землю C
James

3
Gcc поддерживает потоки C ++ и это бесплатно
James

@Ian: 2 года спустя и все широко используемые компиляторы поддерживают его;). Даже те, которые бесплатны.
Rutix
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.