Автор Тема: AutoIt 3.3.6.0 - тормозят регулярные выражения  (Прочитано 8434 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967
  • Репутация: 61
    • Награды
Запускаю свою программу TrayGREP - а она стала в 2 - 3 раза медленней работать, чем в версии 3.3.4.0. Программа активно использует функции:
Код: AutoIt [Выделить]

Кто столкнулся с тормозами регекспов в новой версии - в чем здесь может быть дело?
« Последнее редактирование: Март 23, 2010, 11:56:37 от Suppir »

Русское сообщество AutoIt

AutoIt 3.3.6.0 - тормозят регулярные выражения
« Отправлен: Март 23, 2010, 09:29:51 »

VitAl2013

  • Гость
точно 3.6.6.0?

Оффлайн asdf8 [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 560
  • Репутация: 151
    • Награды
Проверил StringRegExp от версии 3.3 до 3.3.6
Действительно есть замедление работы от версии к версии.
Получилось, что 3.3.6 в среднем на 17% медленнее, чем 3.3

А StringReplace - наоборот, стала работать на пару процентов быстрее
« Последнее редактирование: Март 23, 2010, 11:38:48 от asdf8 »

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
Имеется в виду свежая версия 3.3.6.0.

В моем приложении примерно 95% процессорного времени тратится на обработку текста регулярными выражениями. Замедление в несколько раз по сравнению с версией 3.3.4.0 :(
« Последнее редактирование: Март 23, 2010, 11:55:25 от Suppir »

Русское сообщество AutoIt

Re: AutoIt 3.3.6.0 - тормозят регулярные выражения
« Ответ #3 Отправлен: Март 23, 2010, 11:50:12 »

Оффлайн asdf8 [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 560
  • Репутация: 151
    • Награды
в чем здесь может быть дело?

Лучше, конечно увидеть код (желательно небольшой пример), чтоб воспроизвести проблему. Угадывать можно долго, например - жадные регекспы.

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
Код программы:

Код: AutoIt [Выделить]
#Include <Misc.au3>

;~ Предотвращаем запуск двух копий программы
if _Singleton("test",1) = 0 Then
    TrayTip ("AutoIt", "TreyGREP уже запущен", 1)
    sleep(1000)
    TrayTip("clears any tray tip","",0)
    Exit
EndIf


;~ Добавляем пользовательское меню в трей
TraySetState ( 1 )
Opt("TrayMenuMode", 1)

;~ Устанавливаем хоткеи. Так как раскладка может быть и русской и английской, дублируем хоткеи для обеих раскладок
HotKeySet("^x", "_Replace")
HotKeySet("^ч", "_Replace")
HotKeySet("^+x", "_Exit")
HotKeySet("^+ч", "_Exit")

;~ Объявление переменных и массивов
Global $i, $a, $Text
Dim $Search[1000][2]
Dim $Matches, $Splited

;~ Путь к ini-файлу
$IniFile = @ScriptDir & "\" & "TrayGREP.ini"

;~ Создаем меню в трее
$Edit = TrayCreateItem("Редактировать список замен")
$Exit = TrayCreateItem("Выход")

;~ Если ini не найден...
if not FileExists($IniFile) Then
    TrayTip ("AutoIt", "Не могу найти файл ""TrayGREP.ini""", 1)
    sleep(2000)
    TrayTip("clears any tray tip","",0)
    Exit
Else   
   
    $in = FileOpen("TrayGREP.ini", 0)
    $line = FileReadLine($in, 1)
    if $line <> "TrayGREP v.1.0. Автор идеи и разработчик - Suppir." Then
        TrayTip ("AutoIt", "Информация о разработчике была повреждена", 1)
        sleep(3000)
        TrayTip("clears any tray tip","",0)
        TrayTip ("AutoIt", "Восстановите информацию или скачайте утилиту заново", 1)
        sleep(3000)
        TrayTip("clears any tray tip","",0)
        Exit
    EndIf  
EndIf  

;~ Подсказки в трее пользователю
TrayTip ("AutoIt", "TrayGREP запущен", 1)
sleep(2000)
;~ Подсказки внеобходимо убирать вручную
TrayTip("clears any tray tip","",0)

;~ Основной цикл программы
While 1
    Switch TrayGetMsg()
   
;~  Если выбрали "редактировать список замен"...
    Case $Edit
;~      То открываем ini блокнотом. Здесь может быть проблема, если для открывания ini назначена другая программа
        ShellExecute ($IniFile)
        TrayItemSetState ( $Edit, 4 )
;~  Если выбрали "выйти", завершаем программу
    Case $Exit
        TrayItemSetState ( $Edit, 4 )
        _Exit()
    EndSwitch
WEnd

;~ Функция завершения программы
Func _Exit()
   
    TrayTip ("AutoIt", "Завершение работы TrayGREP", 1)
    Sleep(1000)
    Exit
   
EndFunc


;~ Функция замены текста
Func _Replace()
   
;~  Если в буфере обмена ничего нет, то давать предупреждение
    if ClipGet() = "" Then
        TrayTip ("AutoIt", "Буфер пустой!", 1)
        sleep(1000)
        TrayTip("clears any tray tip","",0)

    Else
;~      Считываем ini-файл. Здесь может быть проблема. Если запустить программу, а потом удалить ini, то функция не будет работать
        $in = FileOpen("TrayGREP.ini", 0)
        while 1
;~          Читаем строки в ini последовательно
            local $i
            $line = FileReadLine($in)
            If @error = -1 Then ExitLoop
           
;~          Если находим строку "найти то-то", то запоминаем регексп в двумерный массив $Search[][]
;~          Левый элемент массива равен "найти", правый - "заменить"
            $Matches = StringRegExp($line, "^Найти:(.+)", 1)  
            If @error = 0 Then
                $Search[$i][0] = $Matches[0]
                ContinueLoop
            EndIf  
       
;~          Если находим строку "Заменить на:" после которой сразу конец строки, то задаем значение переменной $Search[$i][1] = "".
;~          Если этого не делать, то поиск в таких случаях не будет работать.
            $Matches = StringRegExp($line, "^Заменить на:$", 1)
            If @error = 0 Then
                $Search[$i][1] = ""
                $i += 1
                ContinueLoop
            EndIf
       
;~          Запоминаем переменную замены
            $Matches = StringRegExp($line, "^Заменить на:(.+)", 1)
            If @error = 0 Then
                $Search[$i][1] = $Matches[0]
                $i += 1
                ContinueLoop
            EndIf
        wend   


        TrayTip ("AutoIt", "Произвожу замену...", 1)
;~      Берем строку из буфера
        $Text = ClipGet()
;~      И разрезаем ее в массив по символам конца строки. Если этого не делать, то замена будет производиться только для первого встреченного абзаца.
        $Splited = StringSplit($Text, @CRLF, 1)
        $Text = ""
       
;~      На каждую строку в массиве $Splited применяем регулярные выражения из массива $Search
        For $x = 1 to UBound($Splited)-1
            for $i = 0 to UBound($Search) - 1
                    $Splited[$x] = StringRegExpReplace($Splited[$x], $Search[$i][0], $Search[$i][1])
            Next
;~          После чего склеиваем строки обратно 
            if $Text = "" Then
                $Text = $Splited[$x]
            Else
                $Text = $Text & @CRLF & $Splited[$x]
            EndIf
        Next

;~      И записываем результат в буфер обмена
        ClipPut($Text)
        TrayTip ("AutoIt", "Замена произведена", 1)
        sleep(1000)
        TrayTip("clears any tray tip","",0)

    EndIf
EndFunc


;~ необходимо добавить функции
;~ 1) объявление вспомогательных переменных в ini
;~ 2) поддержка таблиц MS Word в буфере
 




Примеры регулярных выражений из ini-файла:

Найти:(№|N)[ °]*(\d)
Заменить на:N $2

Найти: +
Заменить на:

Найти:(^)\s+
Заменить на:$1

Найти:\s+$
Заменить на:

Найти:^\s+$
Заменить на:

Найти:(\d)г\.
Заменить на:$1 г.

Найти:(\d)г
Заменить на:$1 г.

Найти:(\d)года
Заменить на:$1 года

Найти: (ул|г|пос|пер)\.(\S)
Заменить на: $1. $2

Найти: (п|ч|ст)\.(\d)
Заменить на: $1. $2

Найти:N°
Заменить на:N

Найти:(\d)м
Заменить на:$1 м

Найти:(\d)м\.
Заменить на:$1 м.

Найти:""
Заменить на:"

Найти:—|–
Заменить на:-

Найти:^\s+(\d)
Заменить на:$1

Найти: (\d{4})-(\d{4}) г
Заменить на: $1 - $2 г

Найти:(\d+)\.(\D)
Заменить на:$1. $2

Найти:п р и к а з ы в а ю
Заменить на:приказываю

Найти:П Р И К А З Ы В А Ю
Заменить на:приказываю
« Последнее редактирование: Март 23, 2010, 12:46:43 от Suppir »

Оффлайн asdf8 [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 560
  • Репутация: 151
    • Награды
Suppir попробуй заменить функцию:

Код: AutoIt [Выделить]
;~ Функция замены текста
Func _Replace()
;~  Если в буфере обмена ничего нет, то давать предупреждение
    if ClipGet() = "" Or Not FileExists(@ScriptDir & "\" & "TrayGREP.ini") Then
        TrayTip ("AutoIt", "Буфер пустой!", 1)
        sleep(1000)
        TrayTip("clears any tray tip","",0)

    Else
;~      Считываем ini-файл. Здесь может быть проблема. Если запустить программу, а потом удалить ini, то функция не будет работать
        $in = FileRead("TrayGREP.ini")
        $patern = '(Найти:.+?[\r\n]+Заменить на:[^\r\n]*)'
        $Search = StringRegExp($in, $patern, 3)
;~      Exit
        TrayTip ("AutoIt", "Произвожу замену...", 1)
;~      Берем строку из буфера
        $Text = ClipGet()
        If $Text Then
            If IsArray($Search) Then
                $patern = 'Найти:(.+?)[\r\n]+Заменить на:(.*)'
                For $i = 0 To UBound($Search) - 1
                    $sSearch = StringRegExpReplace($Search[$i], $patern, '\1')
                    $sReplace = StringRegExpReplace($Search[$i], $patern, '\2')
                    ConsoleWrite('!>' & $sSearch & '-->' & $sReplace & @LF)
                    $Text = StringRegExpReplace($Text, '(?m)' & $sSearch, $sReplace)
                Next
;~          И записываем результат в буфер обмена
            ClipPut($Text)
            TrayTip ("AutoIt", "Замена произведена", 1)
            sleep(1000)
            TrayTip("clears any tray tip","",0)
            EndIf
        EndIf
    EndIf
EndFunc
 


Как будет по скорости?

И еще: в коде несколько раз встречается FileOpen и нету FileClose, как раз, между версиями менялась работа с файлами, мне кажется из-за этого и проблемы.
« Последнее редактирование: Март 23, 2010, 14:43:02 от asdf8 »

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
Попробую на домашнем компе (т.к. уже снес версию 3.3.6.0). Позже отпишусь.

Русское сообщество AutoIt

Re: AutoIt 3.3.6.0 - тормозят регулярные выражения
« Ответ #7 Отправлен: Март 23, 2010, 14:45:33 »

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
Быстро работает, спасибо!

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
Re: AutoIt 3.3.6.0 - тормозят регулярные выражения
« Ответ #9, Отправлен: Апрель 01, 2010, 16:16:14 »
Две проблемы:
1) в измененном тексте теперь вместо разделителей строк "\n" мягкие переносы строк;
2) если в тексте были пустые строки, то они исчезли.

Оффлайн asdf8 [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 560
  • Репутация: 151
    • Награды
Re: AutoIt 3.3.6.0 - тормозят регулярные выражения
« Ответ #10, Отправлен: Апрель 01, 2010, 16:51:43 »
Цитировать
Две проблемы

надо подкорректировать регулярные выражения в ini-файле, ^ и $ в моем примере обозначают "\n".
Например выражение  равно "\n\s+\n", а "\s" включает в себя и "\r" - вот и получаются мягкие переносы строк и удаление пустых строк ("\n\s+\n" включает "\n\r\n"). Если заменить "^\s+$" на Найти:"(^)[\t ]+([\r\n])" Заменить на:"\1\2" будет работать нормально. Ну и остальные регекспы проверить.

Оффлайн Suppir [?]

  • Продвинутый
  • ***
  • Сообщений: 967

  • Автор темы
  • Репутация: 61
    • Награды
Re: AutoIt 3.3.6.0 - тормозят регулярные выражения
« Ответ #11, Отправлен: Апрель 01, 2010, 17:48:18 »
ясно...

Русское сообщество AutoIt

Re: AutoIt 3.3.6.0 - тормозят регулярные выражения
« Ответ #11 Отправлен: Апрель 01, 2010, 17:48:18 »

 

Похожие темы

  Тема / Автор Ответов Последний ответ
13 Ответов
19733 Просмотров
Последний ответ Декабрь 14, 2014, 15:25:47
от alex33
0 Ответов
9997 Просмотров
Последний ответ Февраль 13, 2011, 00:26:49
от CreatoR
36 Ответов
13536 Просмотров
Последний ответ Июль 12, 2012, 23:22:05
от CreatoR
3 Ответов
2365 Просмотров
Последний ответ Июнь 09, 2013, 21:51:04
от PACHOM
0 Ответов
1438 Просмотров
Последний ответ Октябрь 11, 2013, 10:13:46
от gezan1
7 Ответов
2205 Просмотров
Последний ответ Февраль 17, 2016, 22:25:54
от Alofa
0 Ответов
734 Просмотров
Последний ответ Февраль 17, 2016, 17:43:01
от Yashied
14 Ответов
2377 Просмотров
Последний ответ Январь 09, 2017, 00:04:11
от Dessan
2 Ответов
625 Просмотров
Последний ответ Апрель 04, 2017, 10:43:35
от Alofa
5 Ответов
366 Просмотров
Последний ответ Июнь 20, 2018, 17:53:09
от Alofa