Как выбрать Xmx для размера кучи для проекта массового приема

#java #spring-boot

#java #spring-boot

Вопрос:

Я работаю над проектом массового приема около 5 миллионов документов (размером от 200 КБ до 3 МБ каждый) на открытом воздухе с использованием REST API и Spring Boot. Мой fat jar будет работать так в среде разработки и тестирования без каких-либо проблем:

  java -Xms64m -Xmx1G -jar MyApplication.jar --spring.config.location=file:///Users/home/config/jdbc.properties
 

Для среды Prod на сервере доступно 16 ГБ памяти. Как мне определить минимальный и максимальный размер кучи, учитывая размер каждого документа (200 КБ — 3 МБ) и их объем — 5 миллионов. Я имею в виду, каким должен быть «нормальный» минимальный максимальный размер кучи?

 java -Xms?? -Xmx?? -jar MyApplication.jar --spring.config.location=file:///Users/home/config/jdbc.properties
 

Неопределенный вопрос: если я использую -Xms64m -Xmx1G , означает ли это, что в пиковое время (когда jvm полностью разогнана) моя jvm не будет обрабатывать пакет документов размером более 1 ГБ в любой момент времени? Или, проще говоря, где этот 1 ГБ будет сожжен в этой ситуации? Или как JVM будет использовать этот 1 ГБ?

Любая соответствующая информация / ссылки в этом отношении будут высоко оценены.

Обновить:

Согласно комментариям Вишну, я нашел это (все еще пытаюсь понять): https://alvinalexander.com/blog/post/java/java-xmx-xms-memory-heap-size-control/https://www.baeldung.com/jvm-configure-stack-sizes

https://alvinalexander.com/java/java-stack-heap-definitions-memory /

А затем я попробовал пару параметров ss, как показано ниже:

 java -Xss1k -jar MyApplication.jar
 

результаты в:

 The Java thread stack size specified is too small. Specify at least 136k
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
 

И когда я попробую это:

 java -Xss136k -jar MyApplication.jar
 

Я понимаю это:

 Exception in thread "main" java.lang.StackOverflowError
    at org.springframework.boot.loader.data.RandomAccessDataFile$FileAccess.access$400(RandomAccessDataFile.java:205)
    at org.springframework.boot.loader.data.RandomAccessDataFile.read(RandomAccessDataFile.java:117)
    at org.springframework.boot.loader.data.RandomAccessDataFile.read(RandomAccessDataFile.java:102)
    at org.springframework.boot.loader.jar.CentralDirectoryFileHeader.load(CentralDirectoryFileHeader.java:82)
    at org.springframework.boot.loader.jar.CentralDirectoryFileHeader.fromRandomAccessData(CentralDirectoryFileHeader.java:183)
    at org.springframework.boot.loader.jar.JarFileEntries.getEntry(JarFileEntries.java:321)
    at org.springframework.boot.loader.jar.JarFileEntries.getEntry(JarFileEntries.java:307)
    at org.springframework.boot.loader.jar.JarFileEntries.doGetEntry(JarFileEntries.java:295)
    at org.springframework.boot.loader.jar.JarFileEntries.getEntry(JarFileEntries.java:250)
    at org.springframework.boot.loader.jar.JarFileEntries.containsEntry(JarFileEntries.java:206)
    at org.springframework.boot.loader.jar.JarFile.containsEntry(JarFile.java:240)
    at org.springframework.boot.loader.jar.JarURLConnection.get(JarURLConnection.java:263)
    at org.springframework.boot.loader.jar.Handler.openConnection(Handler.java:83)
    at java.base/java.net.URL.openConnection(URL.java:1074)
    at java.base/jdk.internal.loader.URLClassPath$Loader.getResource(URLClassPath.java:643)
    at java.base/jdk.internal.loader.URLClassPath.getResource(URLClassPath.java:314)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:455)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
    at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:550)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
    at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
    at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:550)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:458)
    at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:589)
    at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
    at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3166)
    at java.base/java.lang.Class.getDeclaredMethod(Class.java:2473)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:47)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
 

И это привело к вышеуказанной ошибке SOF от 136-240 тыс., но работало>
250 тыс.

Я знаю комментарии Вишну, и эта ошибка пытается указать на то, что происходит у меня в голове. Что это? Могу ли я получить простой (более простой или простой, будет лучше: P) ответ здесь, пожалуйста?

Опять же, я пытаюсь получить «нормальный» или «наилучший» возможный размер кучи для jar моего приложения.

Заранее большое спасибо за чтение такой пространной информации и вашу любезную помощь.

Комментарии:

1. Почему вы выбрали REST API, а не инструмент массового импорта, например?

2. Есть куча вещей, которые мы делаем на лету. Вот почему.

Ответ №1:

Сначала вам нужно решить, сколько потоков может выполняться параллельно, память стека потоков, выделенная с помощью параметра -Xss . Я думаю, что в версии 1.8 на 64 бит каждый поток имеет память по умолчанию в 1 МБ.

Попробуйте использовать параллельный GC в Java Opts, который поможет уменьшить кучу.

Комментарии:

1. Чувак.. вы действительно заставили меня почесать голову. Однако я добавил еще немного информации. Пожалуйста, взгляните и предложите с учетом вашего опыта. Спасибо.

Ответ №2:

значение -Xss, равное 1 мб, подходит для использования. при запуске приложения включите приведенную ниже команду, это поможет уменьшить размер кучи.

 -XX: UseConcMarkSweepGC
 

Поскольку ваш хост имеет максимальный объем 16 ГБ, вы можете установить максимальный размер кучи на 4 ГБ, что все равно даст вам некоторое пространство для расширения во время пика, если потребуется.