Проблемы пространства кучи Gradle с большим стандартным выводом - PullRequest
1 голос
/ 07 февраля 2020

Когда я строю свой проект с Gradle, результаты теста огромны, и я хотел бы сохранить их. Поэтому я активировал показ выходных потоков:

test {
    testLogging.showStandardStreams = true
}

К сожалению, похоже, что Gradle не может обрабатывать большие стандартные выходы. Для демонстрации я создал минимальный пример: https://github.com/DaGeRe/stdout-test Это проект, создающий большие стандартные выходные данные в тесте с помощью

@Test
public void test() {
   long start = System.currentTimeMillis();
   for (int i = 0; i < 200; i++) {
      for (int j = 0; j < 10000; j++) {
         long current = System.currentTimeMillis() - start;
          System.out.println("This is a simple logging output: " + i + " " + j + " " + current);
      }
   }
}

Если я запускаю его в стандартном проекте maven, он заканчивается примерно через 2 минуты:

reichelt@reichelt-desktop:~/workspaces/stdout-test$ time mvn test &> mvn.txt

real    1m34,130s
user    0m31,333s
sys     1m12,296s

Если я запускаю его в gradle к time ./gradlew test &> gradle.txt, он вообще не завершается sh (в разумные сроки), и вывод содержит много Expiring Daemon because JVM heap space is exhausted. Одним из способов временного решения этой проблемы было бы увеличение кучи памяти (как предлагается здесь: пространство JVM исчерпано при построении проекта через gradle ), но -Xmx4g ничего не меняет в соответствии с моими экспериментами, и это, очевидно, будет не масштабируется для больших выходов. Кроме того, выполнение ./gradlew -i test не меняет поведения.

Проект также содержит файлы примеров для выходных данных из maven (https://github.com/DaGeRe/stdout-test/blob/master/mvn.txt) и gradle (https://github.com/DaGeRe/stdout-test/blob/master/gradle.txt* 1026). * - процесс был прерван через ~ 10 минут) и создан один из градеров дампов кучи (https://github.com/DaGeRe/stdout-test/blob/master/java_pid10812.hprof.tar). Текущее время в журнале регистрации событий незначительно увеличивается (третий номер выхода каждой строки). Поэтому я предполагаю, что gradle в основном имеет проблемы с печатью на стандартный вывод и не выполняет программу.

Это показывает, что, хотя у gradle возникают некоторые проблемы с печатью на стандартный вывод, кажется, что он не блокирует выполнение теста. Есть ли какой-нибудь переключатель или параметр, который я мог бы дать gradle, который заставляет gradle напрямую печатать на стандартный вывод вместо того, чтобы выполнять его интенсивную обработку памяти? К сожалению, я не нашел ничего в документации (https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html).

РЕДАКТИРОВАТЬ Только что завершил тестовый запуск на сервере:

reichelt@r147:~/workspaces/dissworkspace/stdout-test$ time ./gradlew test &> gradle.txt

real    28m17,959s
user    216m37,351s
sys     0m12,410s

Завершается за исключением:

    This is a simple logging output: 89 7842 1416
    This is a simple logging output: 89 7843 1416
    This is a simple logging output: 89 7844 1416
    This is a simple logging output: 89 7845 1416
    This is a simple logging output: 89 7846 1416
FAILURE: Build failed with an exception.

* What went wrong:
GC overhead limit exceeded

1 Ответ

0 голосов
/ 07 февраля 2020

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

Прежде всего, я могу воспроизвести вашу проблему OutOfMemory из вашего Github хранилище. Я немного погуглил, и, хотя есть и другие сообщения об OOM, ни у одного из них не было решения. Я думаю, что это просто ограничение в Gradle при включении showStandardStreams. Я попытался поиграться с типом вывода консоли и несколькими другими параметрами, но ни один из них не дал эффекта.

Однако, отключив showStandardStreams, я бы не получил OOM. Даже после увеличения числа итераций с 200 * 10000, которое вы указали, до 1000 * 10000. Это работало нормально, и вывод был сохранен в файл .bin,. xml и. html для последующей проверки.

Более того, Gradle запустил его более чем в два раза быстрее, чем Maven на моем machine:

λ time ./gradlew test &> gradle.txt

real    1m23.113s
user    0m0.015s
sys     0m0.031s

λ time mvn test &> mvn.txt

real    3m6.671s
user    0m0.183s
sys     0m0.566s

Не уверен, почему между ними такая большая разница.

Хотя я полностью согласен, что было бы неплохо использовать showStandardStreams для больших выходов, как По умолчанию Maven, кажется, это просто невозможно, если вы не можете позволить себе соответственно увеличить максимальный размер кучи. С другой стороны, сохранение результата в отчете также довольно приятно, чего вы не получаете от плагина Surefire в Maven.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...