Как эффективно запустить преобразования 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%).
Короче говоря, вот все советы / подходы, которые у меня есть до сих пор:
- Разбить целые файлы XML между подпапками (например, содержащими каждый файл 5K) и использовать это как способ запуска сценариев параллельного преобразования для каждой подпапки
- Специально используйте библиотеку Saxon-EE (позволяющую многопоточное выполнение) с
collection()
функция для разбора файлов XML - Установите в среде Java меньшее количество задач или уменьшите объем памяти на процесс
- Указание Saxon относительно совместимости листов XSLT с
libxml/libxslt
(разве это не только для XSLT1.0?) - Используйте специализированную оболочку, такую как
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, вы, вероятно, можете получить это Пройдите немного быстрее, используя свои знания о рабочей нагрузке.