Рекурсивный вызов дублированного скрипта Bash, делающий невозможным доступ к ресурсам

Изменить: Этот пост теперь рассматривается по-новому, так как проблема должна быть представлена ​​немного по-другому. Это здесь: Как я могу эффективно выполнять преобразования XSLT для большого количества файлов параллельно?

Я застрял в попытках распараллелить процесс, и после некоторого времени, потраченного на него, я хотел бы попросить некоторую помощь...

По сути, у меня есть много XML-файлов для преобразования с использованием определенного листа XSLT. Но лист использует вызов (очень медленного) API для извлечения дополнительных данных, и взятие всего пакета XML за один раз займет (очень) много времени.

Поэтому я разбил все файлы из исходной "входной" папки в подпапку, содержащую примерно 5000 файлов XML, и также скопировал следующий скрипт Bash в каждую подпапку:

for f in *.xml
do
  java -jar ../../saxon9he.jar -xsl:../../some-xslt-sheet.xsl -s:$f
done

И я вызываю каждый процесс, для каждой папки, из "корневой" папки, содержащей вместе "входную" папку, библиотеку Saxon и лист XSLT:

find input -type d -exec sh {}/script.sh \;

Но я получаю эту ошибку:

Unable to access jarfile ../../saxon9he.jar

Я предполагаю, что это происходит из-за того, что я работаю из "корневой" папки, когда вызываемые скрипты находятся ниже в каталогах. Я мог бы решить проблему (если я прав), скопировав все ресурсы в каждой подпапке, но я нашел решение, делающее мой текущий подход еще более неуклюжим.

Спасибо всем, кто мог бы иметь идею и заставить меня понять это!

2 ответа

Во-первых, вы действительно не хотите инициализировать новую виртуальную машину Java для запуска каждого преобразования: обычно это занимает гораздо больше времени, чем выполнение самого преобразования. Чтобы представить это в перспективе, для "типичных" преобразований вы часто будете видеть время инициализации Java 3 секунды, время компиляции таблицы стилей 300 мс, время преобразования 10 мс. Так что, если вы можете найти способ сделать это, только инициализируя Java и скомпилировав таблицу стилей один раз, ваше общее время для документов 10K будет 2 минуты, а не 10 часов.

Существуют различные способы достижения этого, но все они включают использование чего-то другого, кроме сценария оболочки, для управления процессом. Самым простым, на мой взгляд, является управление им из самого XSLT с помощью функции collection() для доступа ко всем файлам в каталоге. Это дает дополнительный бонус, если вы используете Saxon-EE, что файлы будут обрабатываться (анализироваться) параллельно с использованием всех ядер на вашей машине, что может ускорить процесс еще в 4 раза или около того. Вам просто нужно добавить точку входа в таблицу стилей примерно так:

<xsl:template name="main">
  <xsl:for-each select="collection('file:///my/dir?select=*.xml;recurse=yes')!saxon:discard-document(.)">
    <xsl:result-document href="....">
      <xsl:apply-templates/>
    </xsl:result-document>
  </xsl:for-each>
</xsl:template>

Вызов saxon:discard-document является необязательным, но поскольку он делает документы пригодными для сбора мусора, это означает, что у вас меньше шансов исчерпать память.

Другой подход к написанию цикла управления заключается в использовании специализированной оболочки, такой как xmlsh.

Попробуйте сделать так, чтобы ввести каталог для каждого аргумента и вызвать скрипт в нем:

for d in */script.sh
do
  (
    cd "$(basename "$d")"
    sh ./script.sh
  )
done
Другие вопросы по тегам