1

Тема: AHK: Можно ли ускорить парсинг?

Есть файл в котором 250 000 строк по 10 символов. Нужно анализировать строки сравнивая содержимое одних с другими.  Я читаю файл в память с помощью
FileRead
и разбиваю на строки с помощью


Loop , Parse, text_file, `n
 {
 stroka%A_index% :=  A_LoopField
 }

  Парсится очень долго: 4-5 секунд.  Я понимаю, что 2,6 МБ - это приличный объём, но всё же хочу спросить  можно ли как-то ускорить процесс?

2

Re: AHK: Можно ли ускорить парсинг?

Loop, read, %файл%



Нужно анализировать строки сравнивая содержимое одних с другими

подробнее

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

3 (изменено: Next, 2013-07-03 19:18:18)

Re: AHK: Можно ли ускорить парсинг?

Ок. Подробно.

Есть 1000 файлов. В них в  каждой строке в виде трёх чисел от 000 до 256 записаны RGB-цвета точек квадрата 500х500 точек.
  Для примера:

...
232140191
017116155
183231127
050202236
241014239
203199212
120148147
143023164
117046254
006054064
098088123
100181231
111237136
198178063
040037074
200077175
005057036
...

  Всего получается 250 000 строк.

Задача. Нужно найти точки с определёнными критериями и проверить точки, которые их окружают.
Допустим в координатах
x125 y358
есть чёрная точка и нужно проверить сколько ещё таких же точек есть вокруг неё.  Т.е. нужно проверить квадрат 3х3 с углами в точках  x124 y357 и  x126 y358.

  Для этого нужно найти в файле строки соответствующие этим точкам и проверить их. Важное обстоятельство в том, что при парсинге, если обнаружена искомая точка,  то проверять нужно в том числе и 4 точки до которых дело ещё не дошло, и мы о них ничего не знаем.


Сначала я  читал файлы с помощью
Loop, Read,
а проверял соседние точки  с помощью
FileReadLine

Очень медленно.

Стал читать файл целиком с помощью
FileRead,
и проверял соседние точки  с помощью
FileReadLine

Очень медленно. Я грешил на  FileReadLine, и сделал иначе.



Читаю сейчас сразу файл в переменную и все строки загоняю в отдельные переменные


...
FileRead, text_file, %A_LoopFileFullPath%

Loop , Parse, text_file, `n
 {
 stroka%A_index% :=  A_LoopField
 }
...

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

Долго. 4-6 секунд на файл. 1000 файлов - более 80 минут. После проверки оказалось, что основную массу времени занимает именно парсинг - 4.5 секунд.

Ничего более подходящего для этой процедуры в справке не нашёл. 

Можно ли как-то ускорить сам парсинг?  Может есть какие-то глобальные настройки или что-то другое?

4

Re: AHK: Можно ли ускорить парсинг?

Если я правильно понял, то координатам точки соответствует расстояние описывающей её строки от начала файла — или от начала буфера, куда считан файл. Нужно вычислить это расстояние и считать строку. Нет необходимости разносить все строки по переменным. Для считывания строки по её адресу есть функция StrGet.

5 (изменено: serzh82saratov, 2013-07-03 20:00:06)

Re: AHK: Можно ли ускорить парсинг?

Ну во первых применить 

SetBatchLines -1

увеличит скорость в 3-4  раза.

все строки загоняю в отдельные переменные

зачем?

FileRead считать все файлы в одну переменную, далее RegExMatch. Должно быть быстрее.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

6

Re: AHK: Можно ли ускорить парсинг?

YMP пишет:

Для считывания строки по её адресу есть функция StrGet.

  Спасибо, попробую с ней разобраться.




serzh82saratov пишет:

далее RegExMatch. Должно быть быстрее.

  Простите, а как её тут можно применить?

7

Re: AHK: Можно ли ускорить парсинг?

Как узнать адрес для StrGet так и не понял.   

8

Re: AHK: Можно ли ускорить парсинг?

serzh82saratov пишет:

Ну во первых применить 

SetBatchLines -1

увеличит скорость в 3-4  раза.

  Наверное даже в 5 раз быстрее.  Спасибо!

9

Re: AHK: Можно ли ускорить парсинг?

Next пишет:

Как узнать адрес для StrGet так и не понял.   

Адрес переменной, куда считан файл, узнаётся оператором &.


addr := &Var

Это и будет адрес буфера с текстом. Прибавьте к нему смещение нужной строки от начала и получите её адрес. Если версия AutoHotkey юникодная, то каждый символ занимает 2 байта. Между строками два невидимых символа, возврат каретки и перевод строки, т.е. 4 байта. Если версия не юникодная, тогда считайте по 1 байту на символ.

10

Re: AHK: Можно ли ускорить парсинг?

Простите, а как её тут можно применить?

Когда пойму это:

Next пишет:

Нужно найти точки с определёнными критериями и проверить точки, которые их окружают.
Допустим в координатах
x125 y358
есть чёрная точка и нужно проверить сколько ещё таких же точек есть вокруг неё.  Т.е. нужно проверить квадрат 3х3 с углами в точках  x124 y357 и  x126 y358.

  Для этого нужно найти в файле строки соответствующие этим точкам и проверить их. Важное обстоятельство в том, что при парсинге, если обнаружена искомая точка,  то проверять нужно в том числе и 4 точки до которых дело ещё не дошло, и мы о них ничего не знаем.

и привязку оного, к приведённому набору цифр, то наверное скажу.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

11 (изменено: YMP, 2013-07-04 14:13:33)

Re: AHK: Можно ли ускорить парсинг?

Вот для примера две функции, получающие цвет по координатам и координаты по цвету. Написаны в предположении, что АНК юникодный и точки квадрата в файле описаны ряд за рядом, а не колонка за колонкой.


file = d:\prog\temp\colors.txt
FileRead, buf, %file%

color = 241014233

If CoordsFromColor(color, x, y)
    MsgBox, X: %x% Y: %y%
Else
    MsgBox, Цвет не найден

ColorFromCoords(color, x, y)

MsgBox, Color: %color%


CoordsFromColor(color, ByRef x, ByRef y)
{
    global buf
    pos := InStr(buf, color)
    If (pos = 0)
        Return False
    pos := (pos - 1) // 11
    x := Mod(pos, 500)
    y := pos // 500
    Return True
}

ColorFromCoords(ByRef color, x, y)
{
    global buf
    addr := &buf + (y * 500 + x) * 22
    color := StrGet(addr, 9)
}

12

Re: AHK: Можно ли ускорить парсинг?

serzh82saratov пишет:

Простите, а как её тут можно применить?

Когда пойму это:

  Для примера.  Это фрагмент квадрата 500х500. Проверяется очередная точка. Её координаты относительно начала квадрата 125х358. Нужно определить цвета соседних точек.  Они расположены в квадрате 3x3 c центром, расположенным в проверяемой точке.

http://s017.radikal.ru/i410/1307/dd/540145b50fc9.jpg

13 (изменено: serzh82saratov, 2013-07-04 15:02:51)

Re: AHK: Можно ли ускорить парсинг?

Видимо я глуп. Но мне надо объяснять на цифрах (алгоритме). На пальцах (картинках) я не пойму. Вы сейчас предлагаете мне выработать некий новый алгоритм вычисления. Или объяснить свой?
Я не вижу отношения к приведённым ранее "текстам".


У вас есть одна строка (весь текст 250 файлов), в которой надо найти нужную цифру.?
Дальнейшие критерии поиска остальных строк, исходя из найденной - мне всё таки не ясны.
Картинки это хорошо. Работаем то с текстом.
Как в строке с набором цветов, определяется их принадлежность к координатам.?

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

14 (изменено: Next, 2013-07-04 15:53:13)

Re: AHK: Можно ли ускорить парсинг?

Извините, что так путано объясняю. Попробую ещё раз.


Цвет каждой точки записаны в одну строку. Каждая новая строка - новый цвет. Всего точек 500х500. В файле первые 500 строк - первый ряд точек,  501-я строка  цвет первой точки во втором ряду. Цвет точки 125х358 находится в строке №179125 = 500 x 358 + 125.
  Чтобы узнать не является ли точка, ниже обрабываемой  в данный момент 125х358, чёрной, нужно вычислить её строку и прочитать её. В нашем случае это строка 179625 = 125 + 359 x 500.

15

Re: AHK: Можно ли ускорить парсинг?

По алгоритму, думаю можно смотреть ответ YMP. Из того что я понял в этом коде я делаю вывод, что он всё понял правильно.

16

Re: AHK: Можно ли ускорить парсинг?

YMP пишет:

Адрес переменной, куда считан файл, узнаётся оператором &.


addr := &Var

Это и будет адрес буфера с текстом. Прибавьте к нему смещение нужной строки от начала и получите её адрес. Если версия AutoHotkey юникодная, то каждый символ занимает 2 байта. Между строками два невидимых символа, возврат каретки и перевод строки, т.е. 4 байта. Если версия не юникодная, тогда считайте по 1 байту на символ.

  У меня Win7. Значит в строке 10 символов: 9 - цвет и 1 перевод строки. Пробовал по всякому. Находится почему-то то, чего в файле нет.
  Я попробовал даже читать подряд, пока поймаю существующую строку:



FileRead, text_file, D:\путь\str.txt
addr := &text_file
loop, 200
    {
    addr := addr + A_index
    MsgBox, % "Stroka: "  StrGet(addr, 10, 0)
    }

   Выдаётся вообще по одной цифре "0", то "5".   Что я делаю неправильно?

17

Re: AHK: Можно ли ускорить парсинг?

Ускорять обработку (читай: оптимизировать) нужно не с середины, а с начала, если имеется такая возможность. Возникает вопрос о происхождении текстового файла с цветами точек, заданными к тому же в десятичном, а не в HEX формате, что было бы еще как-то понятно. Использование именно такого варианта обусловлено какими причинами, если не секрет? Дело в том, что если описать этот массив точек в двоичном формате (4 байта на точку - для скорости), то файл займет меньше мегабайта, что уже даст прирост по скорости чтения.  А загрузив его в переменную, можно извлекать цвета нужных точек посредством NumGet, или же вообще поручить это процедуре в машинных кодах, получив значительный прирост в производительности скрипта.

18

Re: AHK: Можно ли ускорить парсинг?

Irbis пишет:

Использование именно такого варианта обусловлено какими причинами, если не секрет?

  Секрета нет. Причина одна - неумение использовать более продвинутые варианты. Хотя начинал конечно с вида "FF9A12", но увидев, что я иногда не в состоянии обработать нужным образом такие величины, всё равно каждый раз преобразую в "010 223 107", а потом назад "шифрую" в HEX, просто перешёл на тот вариант, который обсуждается.

  Спасибо за совет, но пока я воспользоваться им не в состоянии.

19 (изменено: Irbis, 2013-07-04 17:25:43)

Re: AHK: Можно ли ускорить парсинг?

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

d := A_IsUnicode ? 22 : 11
FileRead, text_file, %A_ScriptDir%\str.txt
addr := &text_file - d
loop 200
   MsgBox % "Stroka: " . StrGet(addr+=d, 9)

20 (изменено: YMP, 2013-07-04 17:49:14)

Re: AHK: Можно ли ускорить парсинг?

Next пишет:

  У меня Win7. Значит в строке 10 символов: 9 - цвет и 1 перевод строки.

А как это связано с Win7? У меня, кстати, тоже она. AutoHotkey юникодный. В строке 11 2-байтных символов — 9 цвет и 2 новая строка: возврат каретки и перевод строки. В байтах длина строки будет 22.

У меня ваш код работает после таких исправлений:

FileRead, text_file, D:\путь\str.txt
addr := &text_file
loop, 10
    {
    MsgBox, % "Stroka: "  StrGet(addr, 9)
    addr := addr + 22
    }

21 (изменено: Irbis, 2013-07-04 17:44:17)

Re: AHK: Можно ли ускорить парсинг?

в коде поста #19 исправил первую строку )) Почему-то вместо "22 : 11" отправил вариант "16 : 8"


YMP, тогда уж

addr := addr + 22

иначе при каждой итерации addr будет прирастать на всё бОльшую величину, а не на фиксированный шаг.

22

Re: AHK: Можно ли ускорить парсинг?

Irbis
Да, верно. Исправил.

23

Re: AHK: Можно ли ускорить парсинг?


loop, 250000
    {
    var := StrGet(addr, 9)
    addr := addr + 22
    }    

  Всё вместе занимает меньше полсекунды. Очень мощная штука. Спасибо!