Чому розмір купи фіксується на спільних машинах?


20

Хто-небудь може мені пояснити, чому JVM (я не перевіряв занадто багато, але я ніколи не бачив жодного, який би не робив це так) потрібно працювати на фіксованому розмірі купи? Я знаю, що це легше реалізувати на простому суміжному купі, але зараз JVM Sun вже більше десяти років, тому я б очікував, що вони встигли це вдосконалити.

Необхідність визначення максимального розміру пам'яті вашої програми під час запуску здається такою справою 1960-х років, і тоді виникають погані взаємодії з керуванням віртуальною пам'яттю ОС (отримання GC замінених даних, неможливість визначити, скільки пам’яті є процес Java Насправді, використовуючи ОС, витрачається величезна кількість простору VM (я знаю, вам не байдуже на ваших фантазійних 48-бітних машинах ...)). Я також здогадуюсь, що різні сумні спроби побудувати невеликі операційні системи всередині JVM (сервери додатків EE, OSGi) принаймні частково винні в цій обставині, тому що запуск декількох процесів Java в системі незмінно призводить до марних ресурсів, оскільки вам доведеться дайте кожному з них пам'ять, яку він може використати на піку.

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


Дизайн серверів прикладних програм EE мав би ідеальний сенс навіть без цієї "обставини", оскільки сам JVM потребує певного простору, а перемикання між потоками дешевше, ніж перемикання між процесами - ось одна з речей, яка зробила Java в кінці 90-х.
Майкл Боргвардт

Це люб'язно, я здибався, і мені цікаво, скільки думок ти вклав у це. Наприклад, як змінилася б взаємодія GC / swap, якби у вас не було межі купи? Як витрачається простір VM? Ви отримуєте свій 2 / 3Gb простір, вживаєте ви його чи ні, і якщо ви розсуваєте межі цього простору, не має значення, маєте ви фіксовану чи плаваючу купу. З цього приводу, як кілька JVM витрачають що-небудь, крім swap (який повинен бути налаштований відповідним чином для цілі машини)?
kdgregory

2
Це свого роду рент, але про це повідомляють роки щоденного досвіду написання та експлуатації платформи на базі Java. Якщо ви не зробите своп (тому що це зробить вашу систему безвідповідальною протягом 20 хвилин, поки у процесі зниклого не вистачить місця для виділення) і вимкнено перезавантаження комірки з міркувань стабільності (вбивця OOM не дуже добре підбирає жертв ), ви дбаєте про простір VM, і всупереч тому, що люди мають на увазі, запуск Java VM з -Xmx2048m негайно виділить 2 ГБ віртуальної пам’яті (принаймні в моєму Sun JVM для Linux) для програми з однією змінною.
темель

Відмінне запитання. Цікавилося те саме. Але який із «фактів», представлених тут у питаннях відповіді, є правильним?
Мартін Ба

Для реакцій, які ви шукали, просто просуньтесь до сонця про відслідковування помилок ... наприклад, тут , тут і тут . Прочитайте їх і відчуйте обурену лють :)
Основні

Відповіді:


23

Ви неправі. Розмір купівлі JVM не фіксований, а лише обмежений:

  • -Xmx встановлює максимальний об'єм пам'яті
  • -Xms встановлює мінімальний об'єм пам'яті

Встановлення верхньої межі необхідно з кількох причин. По-перше, він повідомляє сміттєзбірнику, коли починати діяти. По-друге, це заважає JVM засмічувати всю машину, витрачаючи занадто багато пам'яті. Мінімальний розмір купи, мабуть, корисний для того, щоб зарезервувати кількість пам'яті, якій потрібна програма, щонайменше, щоб запобігти втраті пам’яті (оскільки інші процеси споживають занадто багато).


9
no min - це не за замовчуванням, щоб уникнути повільного запуску, коли потрібно виділити багато, внаслідок чого багаторазове збільшення купівлі, підказка буде мати справу з фізичним тараном, який закінчується
храповиком урод

@ratchetfreak, що було моєю другою здогадкою ;-)
user281377

@ user281377 Якщо це так, то як C # може працювати добре, не маючи максимальний об'єм пам'яті?
cmorse

cmorse: Я можу лише здогадуватися. Можливо, Java орієнтована на великі сервери, де багато додатків діляться ресурсами і суворо дотримуються обмежень, тоді як .net швидше робиться для ПК та менших, більш виділених серверів.
користувач281377

@ user281377: Програми Java, які я використав, у яких не вистачає простору купи, як правило, справляються з цим дуже погано, як правило, просто виходять з ладу або дуже сильно розгортаються після цього. І ASP.net працює на великих і малих серверах просто чудово. Чого я насправді не отримую, це те, що за замовчуванням Java застосовує цей ліміт. Мені б хотілося почути міркування, що стоять за їх рішенням ... Я впевнений, що у них були вагомі причини.
cmorse

6

Я думаю, що відповідь має щось спільне з спадщиною Java. Спочатку він був розроблений як мова, що використовується для вбудованих систем, де, очевидно, ресурси обмежені, і ви не хочете, щоб процеси просто збивали все, що є в наявності. Це також допомагає при системному адмініструванні, оскільки полегшує надання ресурсів на сервері, якщо ви можете встановити ліміти ресурсів. Я бачу, що останні JVM, схоже, використовують кілька безперервних груп, хоча, звичайно, все це представляє собою єдину купу вашого коду.

(FWIW, вам потрібно було вказати вимоги до пам'яті програми відповідно до версій MacOS перед Дарвіном MacOS [все одно до системи 7, яка була останньою, яку я використовував], що було добре до 80-х.)


1
+1 - за те, що є (1) єдиною відповіддю, яка насправді стосувалась питання, і (2) є правдоподібною.
kdgregory

2

Потрібно надати GC певний механізм, який підкаже, коли його запустити, інакше ваша програма заповнить весь віртуальний простір пам'яті. Є багато альтернативних способів запустити GC: минулий час, кількість виділень, кількість завдань, можливо, інші, про які я зараз не можу придумати. ІМО жоден із них не такий гарний, як просто встановлення межі пам’яті та запуск GC, коли виділений простір потрапить на цю межу.

Ключ - встановити правильні межі. Я розглядаю -msяк "ось скільки пам'яті потрібно моєму додатку", і -mxяк "це ніколи не повинно перевищувати цю кількість". У виробничому розгортанні вони повинні бути близькими, якщо не рівними, і базуватися на фактичних, розмірених вимогах.

Ваші занепокоєння щодо "витраченої" віртуальної пам'яті невірно: це віртуальна, вона (майже) безкоштовна. Так, надання купі занадто великого виділення означає, що ви не можете запустити стільки потоків або завантажити стільки файлів, нанесених на пам'ять. Але це частина дизайну додатків: у вас є дефіцитні ресурси, вам потрібно розділити їх таким чином, що дозволяє вашій програмі працювати. У купі "С-стилю", яка буде розширюватися, поки ви не потрапите на верхню частину пам'яті, основне питання те саме, вам просто не доведеться думати про це, поки ви не потрапите в біду.

Єдине, що велика купа може "витратити" - це місце для заміни, тому що всі сегменти, що записуються, вимагають зобов'язання від свопу. Але це є частиною системи дизайну: якщо ви хочете, щоб в одному і тому ж вікні працювало багато JVM, або збільште своп, або зменшіть їх кучу. Якщо вони почнуть молотити, то ви намагаєтеся зробити занадто багато з системою; придбайте більше пам’яті (і якщо ви все ще працюєте з 32-розрядним процесором, купіть нову коробку).


1
Але поріг для запуску GC не повинен мати нічого спільного з фіксованим порогом, який загальне використання пам'яті програмою не може перевищувати. (Насправді це, мабуть, не повинно; якщо у вас є велика купа і ви можете GC лише тоді, коли вона заповнена, ви обов'язково маєте рідкісні, але тривалі періоди GC). Дивіться покоління сміття.
Бен

@Ben - так, ти маєш рацію. І моє друге речення вказує, що є альтернативи. Однак я не погоджуюся, що купа фіксованого розміру - це неправильний спосіб управління GC у загальному випадку. Правильно налаштований JVM використовує "правильний" розмір купи; на моєму досвіді тривалі паузи GC трапляються, коли JVM не був належним чином налаштований. І часто «правильний» розмір купи набагато менший, ніж ви могли подумати.
kdgregory

-2

Як каже користувач281377, ви вказуєте лише верхню межу обсягу пам'яті, яку може використовувати ваш процес . Звичайно, саме додаток захопить лише потрібний йому простір.

Чи має існувати верхня межа за замовчуванням чи ні - це інше питання, як для, так і проти.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.