Как ускорить awk скрипт выкусывания частей из большого xml?
От: Igor Sukhov  
Дата: 20.11.13 05:40
Оценка:
Есть awk скрипт который вытаскивает из больших xml файлов нужные куски.

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

Иногда, из за необъснимы странностей во входном файле, тег или не закрывается или еще что-то, и локальная переменная вырастает до двух мегабайт, и скорость конкатенации такой строки замедлятся в сотни раз.

Как можно переделать скрипт, чтобы его ускорить. Мне в голову приходит один способ: сохранять номера строк, на которых встретился открывающий и парный закрывающий тег, и уже во втором проходе вычитывать файл заново и выводить только нужные строки (номера которых были найдены на первом проходе. Вопрос — а можно как-то решить эту задачу за один проход.
* thriving in a production environment *
Re: Как ускорить awk скрипт выкусывания частей из большого xml?
От: jazzer Россия Skype: enerjazzer
Дата: 20.11.13 06:58
Оценка:
Здравствуйте, Igor Sukhov, Вы писали:

IS>Есть awk скрипт который вытаскивает из больших xml файлов нужные куски.


IS>Логика — простейшая, для каждой строки проверяем, не открывается на ней ли искомый тег, и если открывается, то все строки, включая ту на которой встретился закрываюший тег, добавляем в локальную переменную конкатенацией строк.


Зачем? Почему бы сразу не распечатывать?
На перле это было бы в одну строчку, типа:
print if /<tag>/../<\/tag>/;
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: Igor Sukhov  
Дата: 20.11.13 08:53
Оценка:
Здравствуйте, jazzer, Вы писали:

IS>>Есть awk скрипт который вытаскивает из больших xml файлов нужные куски.


IS>>Логика — простейшая, для каждой строки проверяем, не открывается на ней ли искомый тег, и если открывается, то все строки, включая ту на которой встретился закрываюший тег, добавляем в локальную переменную конкатенацией строк.


J>Зачем? Почему бы сразу не распечатывать?

забыл сказать, что распечатывать надо не все узлы с определяемые искомыми тегами, а только те у которых есть подтеги с определенным значением.
* thriving in a production environment *
Re[3]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: jazzer Россия Skype: enerjazzer
Дата: 20.11.13 09:09
Оценка:
Здравствуйте, Igor Sukhov, Вы писали:

J>>Зачем? Почему бы сразу не распечатывать?

IS>забыл сказать, что распечатывать надо не все узлы с определяемые искомыми тегами, а только те у которых есть подтеги с определенным значением.

Маленькая такая деталь
И подтеги на других строчках и вообще могут быть в конце главного 15-мегабайтного тега?

Тогда да, запоминать позиции — это самое правильное. Причем можно прямо там же через fseek/ftell.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: Igor Sukhov  
Дата: 20.11.13 23:37
Оценка:
Здравствуйте, jazzer, Вы писали:

J>>>Зачем? Почему бы сразу не распечатывать?

IS>>забыл сказать, что распечатывать надо не все узлы с определяемые искомыми тегами, а только те у которых есть подтеги с определенным значением.

J>Маленькая такая деталь

=)
J>И подтеги на других строчках и вообще могут быть в конце главного 15-мегабайтного тега?
нет, подтеги должны быть близко — в пределах 10 килобайт, но почему то не всегда так.

J>Тогда да, запоминать позиции — это самое правильное. Причем можно прямо там же через fseek/ftell.

а как из скрипта узнать текущее cмещение от начала файла чтобы потом передать это в fseek ?
* thriving in a production environment *
Re: Как ускорить awk скрипт выкусывания частей из большого xml?
От: zaufi Земля  
Дата: 21.11.13 01:08
Оценка:
Здравствуйте, Igor Sukhov, Вы писали:

IS>Есть awk скрипт который вытаскивает из больших xml файлов нужные куски.


все это мне напоминает про "забивание гвоздей микроскопом", только несколько наоборот... например "починка смартфона, кувалдой" )
--
xslt разве не справляется с поставленной задачей? населектить в нем нужных тегов плевое дело и более надежно, чем не предназначенными для парса XML средствами (а также лекго адаптируемо к практически любым будущим изменениям)
тормозит?
Re[5]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: jazzer Россия Skype: enerjazzer
Дата: 21.11.13 01:54
Оценка:
Здравствуйте, Igor Sukhov, Вы писали:

IS>Здравствуйте, jazzer, Вы писали:


J>>>>Зачем? Почему бы сразу не распечатывать?

IS>>>забыл сказать, что распечатывать надо не все узлы с определяемые искомыми тегами, а только те у которых есть подтеги с определенным значением.

J>>Маленькая такая деталь

IS>=)
J>>И подтеги на других строчках и вообще могут быть в конце главного 15-мегабайтного тега?
IS>нет, подтеги должны быть близко — в пределах 10 килобайт, но почему то не всегда так.

J>>Тогда да, запоминать позиции — это самое правильное. Причем можно прямо там же через fseek/ftell.

IS>а как из скрипта узнать текущее cмещение от начала файла чтобы потом передать это в fseek ?

Если ты про awk — понятия не имею, имхо, это невозможно там. Я бы для начала выкинул это старье нафиг и заюзал либо перл, либо специализированные инструмент типа xslt.
В перле, когда сматчил начало тега — просто зовешь tell и запоминаешь позицию. Когда нашел свой подтег — делаешь tell опять, вычисляешь разницу (длину) и зовешь seek на начало фрагмента и затем read с длиной.

Но в перле, опять же, все может работать и без этих приседаний, простым аккумулированием строки, как ты делал изначально. Перл все-таки на порядок более продвинутый инструмент, чем awk. Попробуй просто переписать свой awk-скрипт на перл — вполне возможно, удивишься, что все работает и так.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: Igor Sukhov  
Дата: 21.11.13 02:54
Оценка:
Здравствуйте, zaufi, Вы писали:

IS>>Есть awk скрипт который вытаскивает из больших xml файлов нужные куски.


Z>все это мне напоминает про "забивание гвоздей микроскопом", только несколько наоборот... например "починка смартфона, кувалдой" )

Z>--
Z>xslt разве не справляется с поставленной задачей? населектить в нем нужных тегов плевое дело и более надежно, чем не предназначенными для парса XML средствами (а также лекго адаптируемо к практически любым будущим изменениям)
Z>тормозит?

я же сказал что xml большой. несомненно у меня есть код который решает ту же задачу в 5 строчек через парсинг ДОМа, но памяти жрет по 50 гигов, что в принципе ок, но все равно долго. авк построчно делает все тоже самое только быстрее. ну и да — будущие изменения для меня пока не приоритет.
* thriving in a production environment *
Re[6]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: Igor Sukhov  
Дата: 21.11.13 03:20
Оценка:
Здравствуйте, jazzer, Вы писали:

J>>>Маленькая такая деталь

IS>>=)
J>>>И подтеги на других строчках и вообще могут быть в конце главного 15-мегабайтного тега?
IS>>нет, подтеги должны быть близко — в пределах 10 килобайт, но почему то не всегда так.

J>>>Тогда да, запоминать позиции — это самое правильное. Причем можно прямо там же через fseek/ftell.

IS>>а как из скрипта узнать текущее cмещение от начала файла чтобы потом передать это в fseek ?

J>Если ты про awk — понятия не имею, имхо, это невозможно там. Я бы для начала выкинул это старье нафиг и заюзал либо перл, либо специализированные инструмент типа xslt.


xslt? какой например?

J>В перле, когда сматчил начало тега — просто зовешь tell и запоминаешь позицию. Когда нашел свой подтег — делаешь tell опять, вычисляешь разницу (длину) и зовешь seek на начало фрагмента и затем read с длиной.


J>Но в перле, опять же, все может работать и без этих приседаний, простым аккумулированием строки, как ты делал изначально. Перл все-таки на порядок более продвинутый инструмент, чем awk. Попробуй просто переписать свой awk-скрипт на перл — вполне возможно, удивишься, что все работает и так.


да не хочется лезть в перл только потому что строчки объединяются так медленно. не думаю что в перле это будет сильно быстрее, реализация наверняка одинаковая. подумалось — самое простое это начать складывать в массив и объединять строки непосредсвенно перед выводом...
* thriving in a production environment *
Re[7]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: jazzer Россия Skype: enerjazzer
Дата: 21.11.13 06:28
Оценка: +1
Здравствуйте, Igor Sukhov, Вы писали:

IS>>>а как из скрипта узнать текущее cмещение от начала файла чтобы потом передать это в fseek ?


J>>Если ты про awk — понятия не имею, имхо, это невозможно там. Я бы для начала выкинул это старье нафиг и заюзал либо перл, либо специализированные инструмент типа xslt.


IS>xslt? какой например?

xsltproc, емнип... но я его на большие файлы не натравлял никогда

J>>В перле, когда сматчил начало тега — просто зовешь tell и запоминаешь позицию. Когда нашел свой подтег — делаешь tell опять, вычисляешь разницу (длину) и зовешь seek на начало фрагмента и затем read с длиной.


IS>да не хочется лезть в перл только потому что строчки объединяются так медленно. не думаю что в перле это будет сильно быстрее, реализация наверняка одинаковая. подумалось — самое простое это начать складывать в массив и объединять строки непосредсвенно перед выводом...


Ну по моему опыту, сколько я не писал скриптов в awk — всегда приходилось переделывать в перл. Просто потому что awk слишком ограниченный и примитивный. Так что в какой-то момент я просто забил — выигрыша от awk никакого, только головная боль и необходимость помнить еще один язык. (Единственный плюс — будет работать в ортодоксальных посиксовых инсталляциях, в которых не предполагается наличие перла.) Так что, имхо, "лезть в перл" на порядок продуктивнее, чем "лезть в awk".
Но хозяин — барин, конечно же.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[8]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: Igor Sukhov  
Дата: 22.11.13 04:32
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Здравствуйте, Igor Sukhov, Вы писали:


IS>>>>а как из скрипта узнать текущее cмещение от начала файла чтобы потом передать это в fseek ?


J>>>Если ты про awk — понятия не имею, имхо, это невозможно там. Я бы для начала выкинул это старье нафиг и заюзал либо перл, либо специализированные инструмент типа xslt.


IS>>xslt? какой например?

J>xsltproc, емнип... но я его на большие файлы не натравлял никогда
ок, будем знать. но на больших файлах оно все равно умрет, т.к. реализовтать выборку по xpath выражения в потоковом режиме или невозможно или каждое выражение придется вычислять за новый проход по файлу.

J>>>В перле, когда сматчил начало тега — просто зовешь tell и запоминаешь позицию. Когда нашел свой подтег — делаешь tell опять, вычисляешь разницу (длину) и зовешь seek на начало фрагмента и затем read с длиной.


IS>>да не хочется лезть в перл только потому что строчки объединяются так медленно. не думаю что в перле это будет сильно быстрее, реализация наверняка одинаковая. подумалось — самое простое это начать складывать в массив и объединять строки непосредсвенно перед выводом...


J>Ну по моему опыту, сколько я не писал скриптов в awk — всегда приходилось переделывать в перл. Просто потому что awk слишком ограниченный и примитивный. Так что в какой-то момент я просто забил — выигрыша от awk никакого, только головная боль и необходимость помнить еще один язык. (Единственный плюс — будет работать в ортодоксальных посиксовых инсталляциях, в которых не предполагается наличие перла.) Так что, имхо, "лезть в перл" на порядок продуктивнее, чем "лезть в awk".

J>Но хозяин — барин, конечно же.
awk гораздо проще, учить перл ради одной проблемы лениво. хотя в awk обнаружилась интересная вещь — т.к. массивы ассоциативные, то индексы в for o in c выражениях выбираются в каком-то внутреннем (для массива) порядке и их приходися сортировать вручную . в перле такого же конечно нет
* thriving in a production environment *
Re[9]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: dilmah США  
Дата: 22.11.13 04:52
Оценка:
IS>awk гораздо проще, учить перл ради одной проблемы лениво. хотя в awk обнаружилась интересная вещь — т.к. массивы ассоциативные, то индексы в for o in c выражениях выбираются в каком-то внутреннем (для массива) порядке и их приходися сортировать вручную . в перле такого же конечно нет

вообще говоря, awk не рассчитан на standalone использование.
Нормальное использование awk -- в пайпе в перемешку с другими шелловскими утилитами, тем же sort.
Скажем, многие вещи проще сделать двумя-тремя awk объединенными через пайп, чем пытаться все зафигачить в один монструозный awk скрипт.
Re[10]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: Igor Sukhov  
Дата: 22.11.13 05:38
Оценка:
Здравствуйте, dilmah, Вы писали:


IS>>awk гораздо проще, учить перл ради одной проблемы лениво. хотя в awk обнаружилась интересная вещь — т.к. массивы ассоциативные, то индексы в for o in c выражениях выбираются в каком-то внутреннем (для массива) порядке и их приходися сортировать вручную . в перле такого же конечно нет


D>вообще говоря, awk не рассчитан на standalone использование.

D>Нормальное использование awk -- в пайпе в перемешку с другими шелловскими утилитами, тем же sort.
в контексте моей задачи это как будет выражаться. например у меня есть гигабайтовый xml файл,
если я грепом вытащу куски которые в которых будет нужная мне информация а потом это все pipe in в awk скрипт — то это думаешь будет быстрее???
в таком случае awk скрипту придется перебрать 10 мегабайт а не гигабайт... строк.

D>Скажем, многие вещи проще сделать двумя-тремя awk объединенными через пайп, чем пытаться все зафигачить в один монструозный awk скрипт.

не всегда. проще использовать и поддерживать один простой скрипт чем 3 простых скрипта.
* thriving in a production environment *
Re[11]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: dilmah США  
Дата: 22.11.13 06:14
Оценка:
IS>в контексте моей задачи это как будет выражаться. например у меня есть гигабайтовый xml файл,
IS>если я грепом вытащу куски которые в которых будет нужная мне информация а потом это все pipe in в awk скрипт — то это думаешь будет быстрее???
IS>в таком случае awk скрипту придется перебрать 10 мегабайт а не гигабайт... строк.

раз уж речь зашла за скорость, то попробуй менять локаль.
В С локали (export LC_ALL=C) все будет быстрее, а для некоторый версий grep/awk (скажем, тех версий которые стоят у меня на работе) на *порядки* быстрее чем в US_UTF8 и других локалях.




D>>Скажем, многие вещи проще сделать двумя-тремя awk объединенными через пайп, чем пытаться все зафигачить в один монструозный awk скрипт.

IS>не всегда. проще использовать и поддерживать один простой скрипт чем 3 простых скрипта.

ну awk скрипт же не обязан в отдельном файле.
Я имею в виду что у тебя будет один shell скрипт который содержит пайпы, состоящие из множества коротких (заинлайненных) awk-скриптов..
Re[9]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: jazzer Россия Skype: enerjazzer
Дата: 22.11.13 08:00
Оценка:
Здравствуйте, Igor Sukhov, Вы писали:

IS>awk гораздо проще, учить перл ради одной проблемы лениво. хотя в awk обнаружилась интересная вещь — т.к. массивы ассоциативные, то индексы в for o in c выражениях выбираются в каком-то внутреннем (для массива) порядке и их приходися сортировать вручную . в перле такого же конечно нет


Синтаксис очень похож, перл же создавался как объединение всех существовавших на тот момент текст-ориентированных утилит, включая awk.
Ради смеха можешь попробовать http://perldoc.perl.org/a2p.html

Ну и можешь еще кинуть свой awk-скрипт сюда, я покажу, как он будет выглядеть на перле.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[10]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: dilmah США  
Дата: 22.11.13 08:11
Оценка:
J>Ну и можешь еще кинуть свой awk-скрипт сюда, я покажу, как он будет выглядеть на перле.

у awk (помимо концептуальной чистоты) есть еще мимнимум одно важное преимущество перед перлом -- awk это часть стандарта POSIX, а перл -- это часть никакого стандарта.
Re[11]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: jazzer Россия Skype: enerjazzer
Дата: 22.11.13 08:45
Оценка:
Здравствуйте, dilmah, Вы писали:


J>>Ну и можешь еще кинуть свой awk-скрипт сюда, я покажу, как он будет выглядеть на перле.


D>у awk (помимо концептуальной чистоты) есть еще минимум одно важное преимущество перед перлом -- awk это часть стандарта POSIX, а перл -- это часть никакого стандарта.


Так я про это упомянул. Имхо, преимущество совершенно неважное, если только ты не пишешь скрипт, который будет работать ты не знаешь где. Если ты пишешь скрипт для себя — нафиг POSIX не уперся.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[11]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: jazzer Россия Skype: enerjazzer
Дата: 22.11.13 12:20
Оценка:
Здравствуйте, Igor Sukhov, Вы писали:

IS>Здравствуйте, dilmah, Вы писали:



IS>>>awk гораздо проще, учить перл ради одной проблемы лениво. хотя в awk обнаружилась интересная вещь — т.к. массивы ассоциативные, то индексы в for o in c выражениях выбираются в каком-то внутреннем (для массива) порядке и их приходися сортировать вручную . в перле такого же конечно нет


D>>вообще говоря, awk не рассчитан на standalone использование.

D>>Нормальное использование awk -- в пайпе в перемешку с другими шелловскими утилитами, тем же sort.
IS>в контексте моей задачи это как будет выражаться. например у меня есть гигабайтовый xml файл,
IS>если я грепом вытащу куски которые в которых будет нужная мне информация а потом это все pipe in в awk скрипт — то это думаешь будет быстрее???

Дарю безумную идею: начинаешь копировать теги независимо от того, что внутри. В начале каждого тега запоминаешь размер выходного файла. Пока копируешь — проверяешь, нужно ли внутри то, что тебе нужно, и взводишь флажок. Когда тег закончился — проверяешь флажок: если не установлен — закрываешь файл, делаешь файлу truncate -s предыдущий размер (откатывая таким образом записанный тег) и переоткрываешь файл. Достаточно грепа

На перле можешь попробовать вот так (у меня сработало, по крайней мере, печатаем тег <tag>, если внутри нашлось <GOOD>):
BEGIN{
  $p=$f=$i=0; #position,found,inside
  open(out,">","out.xml")
}
($p,$i)=(tell out,1) if/<tag>/; # <tag> begin
print out if $i;          # print if inside
$f=1 if $i && /<GOOD>/;   # check for <GOOD>
if (/<\/tag>/) {          # <tag> end
  if(!$f) {               # if <GOOD> wasn't found
    seek out,$p,SEEK_CUR;   # unwind/truncate out file
    truncate out,$p
  }
  $i=$f=0
}


запускать perl -n имя_скрипта

то же самое в одну строчку, полная команда, можешь попробовать прогнать на своем гигафайле:
cat test.xml | perl -ne 'BEGIN{$p=$f=$i=0;open(out,">","out.xml")}($p,$i)=(tell out,1)if/<tag>/;print out if$i;$f=1if$i&&/<GOOD>/;if(/<\/tag>/){if(!$f){seek out,$p,SEEK_CUR;truncate out,$p}$i=$f=0}'
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Как ускорить awk скрипт выкусывания частей из большого xml?
От: wildwind Россия  
Дата: 22.11.13 15:46
Оценка:
Здравствуйте, Igor Sukhov, Вы писали:

IS>забыл сказать, что распечатывать надо не все узлы с определяемые искомыми тегами, а только те у которых есть подтеги с определенным значением.


sgrep не поможет?
Re: Как ускорить awk скрипт выкусывания частей из большого xml?
От: wildwind Россия  
Дата: 22.11.13 16:00
Оценка:
Здравствуйте, Igor Sukhov, Вы писали:

IS>Иногда, из за необъснимы странностей во входном файле, тег или не закрывается или еще что-то, и локальная переменная вырастает до двух мегабайт, и скорость конкатенации такой строки замедлятся в сотни раз.


Если проблема именно в конкатенации, можно складывать строки в массив. На пробовал?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.