Как эффективно запустить преобразования XSLT для большого количества файлов параллельно?

Мне нужно регулярно преобразовывать большое количество XML-файлов (минимум 100 КБ) в одной папке каждый раз (в основном, из распакованного входного набора данных), и я хотел бы узнать, как сделать это максимально эффективным способом. Мой технологический стек состоит из XLT и библиотек Saxon XSLT Java, вызываемых из сценариев Bash. И он работает на сервере Ubuntu с 8 ядрами и Raid SSD с 64 Гб оперативной памяти. Имейте в виду, что я прекрасно справляюсь с XSLT, но я все еще нахожусь в процессе изучения Bash и того, как правильно распределить нагрузки для таких задач (и Java в этот момент тоже почти слово).

Ранее я создал пост по этой проблеме, так как мой подход казался очень неэффективным и фактически нуждался в помощи для правильной работы (см. Этот пост SOF). Много комментариев позже, имеет смысл представлять проблему иначе, поэтому этот пост. Мне было предложено несколько решений, одно из которых в настоящее время работает намного лучше моего, но оно все же может быть более элегантным и эффективным.

Теперь я запускаю это:

printf -- '-s:%s\0' input/*.xml | xargs -P 600 -n 1 -0 java -jar saxon9he.jar -xsl:some-xslt-sheet.xsl

Я установил 600 процессов на основе некоторых предыдущих тестов. Если подняться выше, это приведет к ошибкам памяти в Java. Но сейчас он использует только от 30 до 40 Гб оперативной памяти (хотя все 8 ядер работают на 100%).

Короче говоря, вот все советы / подходы, которые у меня есть до сих пор:

  1. Разбить целые файлы XML между подпапками (например, содержащими каждый файл 5K) и использовать это как способ запуска сценариев параллельного преобразования для каждой подпапки
  2. Специально используйте библиотеку Saxon-EE (позволяющую многопоточное выполнение) с collection() функция для разбора файлов XML
  3. Установите в среде Java меньшее количество задач или уменьшите объем памяти на процесс
  4. Указание Saxon относительно совместимости листов XSLT сlibxml/libxslt (разве это не только для XSLT1.0?)
  5. Используйте специализированную оболочку, такую ​​как xmlsh

Я могу справиться с решением № 2, и оно должно позволить напрямую управлять циклом и загружать JVM только один раз; #1 кажется более неуклюжим, и мне все еще нужно улучшить в Bash (распределение нагрузки и производительность, решение относительных / абсолютных путей); № 3, № 4 и № 5 являются совершенно новыми для меня, и мне может понадобиться больше объяснений, чтобы понять, как справиться с этим.

Любой вклад будет принята с благодарностью.

2 ответа

Попробуйте использовать xsltproc инструмент командной строки от libxslt, Он может принимать несколько XML-файлов в качестве аргументов. Чтобы это так называть, сначала нужно создать выходной каталог. Попробуйте назвать это так:

mkdir output
xsltproc -o output/ some-xslt-sheet.xsl input/*.xml

"самый эффективный из возможных способов" требует много и обычно не является разумной целью. Я сомневаюсь, например, что вы были бы готовы приложить усилия 6 месяцев, чтобы повысить эффективность процесса на 3%. То, что вы ищете, это способ сделать это, который соответствует целям производительности и может быть реализован с минимальными усилиями. А сама "эффективность" вызывает вопросы о том, каковы ваши показатели.

Я вполне уверен, что предложенный мной проект с одним преобразованием, обрабатывающим все файлы с использованием collection() и xsl:result-document (которые распараллелены в Saxon-EE), способен дать хорошие результаты и, вероятно, это будет гораздо меньше работы, чем единственный другой подход, который я рассмотрю, а именно - написать приложение Java, содержащее "логику управления": хотя, если вы хорошо пишете многопоточные приложения Java, вы, вероятно, можете получить это Пройдите немного быстрее, используя свои знания о рабочей нагрузке.

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