Чому команда LMAX використовувала Java та проектувала архітектуру, щоб уникнути GC будь-якою ціною?


24

Чому команда LMAX спроектувала диспетчер LMAX на Java, але всі їхні проекти вказують на мінімізацію використання GC? Якщо хтось не хоче запускати GC, то навіщо використовувати мову зібраного сміття?

Їх оптимізація, рівень апаратних знань та думка, яку вони викладають, просто приголомшливі, але чому Java?

Я не проти Java чи нічого, але чому мова GC? Чому б не використовувати щось на зразок D або будь-яку іншу мову без GC, але дозволяє ефективно використовувати код? Це команда, яка найбільше знайома з Java, чи Java має якусь унікальну перевагу, якої я не бачу?

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


6
Я дуже мало знаю про цей проект, але, здається, це є якась структура, на якій можуть будуватися інші. І якщо вам вдасться записати це на Java (і дозволити іншим кодувати на Java і отримувати переваги), тоді у вас буде набагато більша «клієнтська база», ніж якби ви написали це в D.
Joachim Sauer

6
@kadaj: Насправді не важливо, чи споживач є публічним чи внутрішнім: якщо ви зробите доступним широко відомою мовою, це буде корисніше навіть для внутрішнього розвитку. Якщо ви почнете свій (гіпотетичний) аргумент із: "Припустимо, що всі знають D так само, як і вони знають Java, ...", то ви, мабуть, чогось не вистачаєте.
Йоахім Зауер

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

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

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

Відповіді:


20

Тому що між оптимізацією продуктивності та повністю відключенням безпеки є величезна різниця

За рахунок зменшення кількості GC їх основи стають більш чуйними і можуть працювати (імовірно) швидше. Тепер оптимізація збору сміття не означає, що вони ніколи не роблять сміття. Це просто означає, що вони роблять це рідше, і коли вони це роблять, це працює дуже швидко. До таких видів оптимізації належать:

  1. Зведення до мінімуму кількості об’єктів, які переміщуються до простору, що вижив (тобто, який пережив хоча б одне сміття) за допомогою невеликих предметів, що викидаються. Об'єкти, які перемістилися до простору, що вижили, важче збирати, а збирання сміття тут колись передбачає заморожування всього СВМ.
  2. Не виділяйте занадто багато об’єктів для початку. Це може призвести до пожежі, якщо ви не будете обережні, оскільки об'єкти молодого покоління дуже дешево виділяти та збирати.
  3. Переконайтесь, що новий об’єкт вказує на старий (а не навпаки), щоб молодий об’єкт було легко зібрати, оскільки немає посилання на них, що призведе до їх збереження

Коли ви налаштовуєте продуктивність, зазвичай ви налаштовуєте якусь дуже специфічну "гарячу точку", ігноруючи код, який працює не часто. Якщо ви робите це на Java, ви можете дозволити сміттєзбірнику ще піклуватися про цей темний куточок (оскільки це не призведе до великої різниці), при цьому дуже ретельно оптимізуючи область, яка працює в тісному циклі. Таким чином, ви можете вибрати, де ви оптимізуєте, а де - ні, і таким чином можете зосередити зусилля там, де це важливо.


Тепер, якщо вимкнути повністю сміття, вибирати не можете. Ви повинні вручну утилізувати кожен предмет будь-коли. Цей метод викликають не більше одного разу на день? На Java це можна дозволити, оскільки його вплив на продуктивність незначний (можливо, нормально, щоб кожен місяць відбувався повний GC). У C ++ ви все ще просочуєтеся ресурсом, тому вам потрібно подбати навіть про цей незрозумілий метод. Отже, ви повинні заплатити ціну за управління ресурсами в кожній, окремій частині вашої програми, тоді як на Java ви можете зосередитись.


Але стає гірше.

Що робити, якщо у вас помилка, скажімо, у темному кутку вашої заявки, до якого можна отримати доступ лише у понеділок у повний місяць? Java мають високу гарантію безпеки. "Невизначеної поведінки" майже немає. Якщо ви використовуєте щось неправильно, викидається виняток, ваша програма зупиняється, і не виникає пошкодження даних. Тож ви майже впевнені, що нічого поганого не може трапитися, не помітивши.

Але в чомусь на зразок D у вас може бути поганий доступ до вказівника або переповнення буфера, і ви можете пошкодити пам’ять, але програма не знатиме (ви вимкнули безпеку, пам’ятаєте?) І буде продовжувати працювати з її неправильним Дані, зробіть якісь неприємні речі і зіпсуйте ваші дані, і ви цього не знаєте, і як більше корупції трапляється, ваші дані стають все більш неправильними, а потім раптом вони ламаються, і це було в критичному для життя додатку, і деякі помилки сталися в обчисленні ракети, і тому він не працює, а ракети вибухають, а хто - то вмирає, і ваша компанія знаходиться в першій сторінці кожної газети і ваша точка бос його палець до вам сказати «Ви перебуваєте інженер, який запропонував нам використовувати D для оптимізації продуктивності, чому ж ви не думали про безпеку?». І це ваша вина. Ви вбили тих людей , з дурною спробою виконання.


Гаразд, добре, більшість часу це набагато менш драматично, ніж це. Але навіть критично важливий бізнес-додаток або просто програма GPS або, скажімо, урядовий веб-сайт охорони здоров’я може призвести до досить негативних наслідків, якщо у вас є помилки. Застосування мови, яка або перешкоджає їм повністю, або невдачі, коли вони трапляються, зазвичай є дуже хорошою ідеєю.

Існує вартість вимкнення запобіжного обладнання. Їхати рідним не завжди має сенс. Іноді набагато простіше і безпечніше просто оптимізувати трохи безпечну мову, щоб перейти на мову, куди ви можете стріляти в ногу великого часу. Коректність та безпека у багатьох випадках козирять кілька наносекунд, які ви б зняли, усунувши GC повністю. 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 споживач, а не багатопродюсер / споживач, здатний, як оригінальний Disrupor. Автор Disrupor сам згадував у потоці груп Google, що продуктивність може бути покращена за допомогою параметрів проводки у версії Java.
hmijail

4

Це питання констатує неправильну передумову як факт, а потім робить аргумент щодо цієї неправильної передумови.

Дозволяє занурюватися в це .. "всі їхні конструктивні моменти до мінімізації використання GC" - просто не відповідає дійсності. Нововведення в руйнівнику мало стосується GC. Зруйнувач виконує свої функції, оскільки його дизайн розумно розглядає, як працюють сучасні комп’ютери - щось набагато рідше, ніж можна було очікувати. Див. Розмови Cliff Click http://www.azulsystems.com/events/javaone_2009/session/2009_J1_HardwareCrashCourse.pdf для обговорення.

Загальновідомо, що LMax є замовниками Azul. Я знаю з перших вуст, що з Azul GC - це просто незахищеність даних - навіть із групою 175 Гб.


У цьому є зерно правди. Вони перезапускають VM щовечора, щоб уникнути великої колекції. Так писав Мартін Фаулер, і все-таки він не піддається думці: "Як і в іншій системі, руйнівники відскакують за ніч. Цей відбій в основному робиться для того, щоб витерти пам'ять, щоб менше було шансів на дорогу подію сміття під час торгів". martinfowler.com/articles/lmax.html
JimmyJames

2
Не зовсім. Ми використовували вручну GC щовечора в 5-хвилинному торговому розриві і налаштовувались так, що було б єдиним головним GC за день. Це стало зайвим з Azul Zing. (Джерело: Я працював у 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не підходить і в режимі реального часу, оскільки час розподілу не обмежений через фрагментацію.
Doval

1
Ми радимо використовувати швидкі об’єктивні пули для всього, щоб не виділятись після розігріву.
rdalmeida

2

LMAX - це високоефективна бібліотека обміну повідомленнями між потоками.

Щоб бути корисним, хтось інший повинен написати код, щоб змусити кожну нитку виконувати корисну роботу. Зважаючи на те, що код, швидше за все, знаходиться на Java або C #, і тоді дуже мало вибору мови, яка добре взаємодіє з ними.

Використання C або C ++ не є хорошим варіантом, якщо ви не хочете обмежити своїх користувачів однією ОС, оскільки в них не визначена модель різьблення.

Java є стандартом для розробки програмного забезпечення в наші дні, тому, якщо у вас немає вагомих причин, інакше це, як правило, найкращий вибір. (Коли в Римі роблять, як римляни ...)

Запис програмного забезпечення високої продуктивності на Java (або на C #) часто робиться для доказу моменту ...


1
Новий стандарт C ++ 11 підтримує багатопотоковість ...
Casey

@Casey, і скільки компіляторів реального світу C ++ використовують його? І скільки коштують ці компілятори. Можливо, через 20 років це стане в нагоді, до цього часу ви не можете від цього залежати.
Ян

Disruptor використовує sun.misc.Unsafe зовсім небагато, що свідчить про те, що ви справді не можете написати код з низькою затримкою на Яві, не зануривши палець у землю C
James

3
Gcc підтримує теми C ++ і це безкоштовно
James

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