Есть ли способ повысить скорость запуска JVM?

Говорят, что с точки зрения производительности Java в 10 раз быстрее, чем python. Это то, что я вижу из тестов тоже. Но то, что действительно сбивает с толку Java, - это время запуска JVM.

Это тест, который я сделал:

$time xlsx2csv.py Types\ of\ ESI\ v2.doc-emb-Package-9
...
<output skipped>
real    0m0.085s
user    0m0.072s
sys     0m0.013s


$time java  -jar -client /usr/local/bin/tika-app-0.7.jar -m Types\ of\ ESI\ v2.doc-emb-Package-9

real    0m2.055s
user    0m2.433s
sys     0m0.078s

Тот же файл, встроенный файл XLSX размером 12 Кб / с в Docx и Python в 25 раз быстрее! WTH!!

Это занимает 2,055 сек для Java.

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

Но что касается разбора файлов 10k+, это просто не практично..

Во всяком случае, чтобы ускорить его (я уже пробовал -client вариант, и он только ускорился так мало (20%)).

Моя другая идея? Запустите его как долго работающий демон, общайтесь через сокеты UDP или Linux-ICP локально?

6 ответов

Решение

Попробуйте Nailgun.

Примечание: я не использую это лично.

Я отсылаю вас к сообщению в блоге Мэтью Джиллиарда (mjg) на эту тему. Любые примеры кода ниже идут прямо оттуда. Я не буду приводить примеры хронометража, частично, чтобы сделать это коротким, а частично, чтобы побудить вас посетить его страницу. Мэтью работает над проектом Fn, поэтому ему очень интересно выяснить, как сохранить время запуска на низком уровне.

Видимо, есть несколько способов сделать это, и некоторые из них довольно просты. Основная идея заключается в том, что вы кэшируете цикл инициализации JVM, а не выполняете его при каждом запуске.

Класс обмена данными ( CDS)

CDS кэширует детерминированный (аппаратно-зависимый) процесс запуска JDK. Это самый простой и самый старый (с версии 1,5) трюк в книге (и не очень известный).

Из Oracle

Когда JVM запускается, общий архив отображается в память, что позволяет совместно использовать метаданные JVM только для чтения для этих классов между несколькими процессами JVM. Время запуска сокращается, что экономит затраты, поскольку восстановление общего архива происходит быстрее, чем загрузка классов.

Вы можете создать дамп вручную, запустив

⇒ java -Xshare:dump
Allocated shared space: 50577408 bytes at 0x0000000800000000
Loading classes to share ...
// ...snip ...
total   :  17538717 [100.0% of total] out of  46272512 bytes [ 37.9% used]

... а затем использовать его с

java -Xshare:on HelloJava

AOT: впереди время компиляции (Java 9+)

Из блога MJG

В тех случаях, когда CDS выполняет некоторые части загрузки классов базовых классов заранее, AOT фактически компилирует байт-код в собственный код (файл общего объекта в формате ELF) и может применяться к любому байт-коду.

Используйте SubstrateVM (Java 8+)

Не в блоге, а в демонстрации, которую он дал несколько дней назад.

Из readme:

Substrate VM - это инфраструктура, которая позволяет заранее (AOT) компилировать Java-приложения в предположении замкнутого мира в исполняемые образы или общие объекты (ELF-64 или 64-битный Mach-O).

Только что узнал о капельнице сегодня, в качестве альтернативы замене гвоздя: https://github.com/flatland/drip Также смотрите эту страницу для некоторых общих советов: см. Также https://github.com/jruby/jruby/wiki/Improving-startup-time

Измените вашу программу на модель клиент / сервер, где Java-часть - это постоянный сервер, который запускается только один раз и питается клиентом, который сообщает ему, что делать. Клиент может быть небольшим скриптом Python, сообщающим процессу сервера, какие файлы использовать. Может быть, отправлять команды через сокет или сигналы, до вас.

Гм... записать документы в каталог (если они еще не созданы) и программа Java обрабатывает их все за один раз?

Есть много способов сделать это - в основном все будет работать, если это поддерживает JVM в течение всей вашей пакетной обработки.

например, почему бы просто не изменить программу Java, чтобы пройти через все файлы и обработать их все в одном вызове JVM?

Или вы можете создать простое приложение с графическим интерфейсом в Swing и иметь какой-нибудь визуальный способ запуска пакета (например, выберите целевые каталоги, затем нажмите кнопку "Обработать все...").

Или вы можете использовать Clojure REPL в качестве сценария выполнения соответствующего задания Java....

Или вы можете создать серверный процесс с чем-то вроде Netty и отправить все ваши файлы через него....

Другие вопросы по тегам