26 / 26 / 11
Регистрация: 08.08.2011
Сообщений: 1,172
1

Как ускорить регулярные выражения, не вынося их из функции

17.07.2012, 13:39. Показов 4588. Ответов 21
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день!

У меня есть функция compare(), в которой используется 50 регулярных выражений для поиска и(или) замены фрагментов.

Во время работы программы данная функция исполняется 10 тысяч раз (обрабатывает каждую строку). Таким образом, даже если в конце регулярного выражения написать RegexOptions.Compiled, то при следующей итерации функции это регулярное выражение заново будет compiled.

Я попробовал вынести регексы из функции compare() наверх - в функци "public partial class Form1 : Form", после чего программа заработала в 10 раз быстрее. Но теперь код стал очень неудобный - регулярные выражения объявлены в самом верху программы, а используются совсем в другом месте.

Каким образом можно ускорить функцию и оставить код читабельным?

Добавлено через 2 минуты
Там, где можно было использовать обычный replace, я использовал его, понятное дело.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.07.2012, 13:39
Ответы с готовыми решениями:

ЧПУ. Замена строк, регулярные выражения. Как правильно использовать переменную в регулярные выражения ?
Здравствуйте! Решил реализовать ЧПУ на своем сайте. Первый этап это замена всех реальных ссылок на...

Как Использовать регулярные выражения
Вычитал что есть какие то регулярные выражения, попробовал использовать их на практике но ничего не...

Как оформлять регулярные выражения?
Есть ли какой-нибудь мануал по их созданию? Просто никак не могу понять, как они оформляются :( ...

Как работают регулярные выражения
Нужно немного объяснить мне как работают регулярные выражения. Допустим есть String переменная и я...

21
87 / 73 / 6
Регистрация: 11.09.2011
Сообщений: 118
17.07.2012, 13:45 2
Перенесите код из функции compare в тело цикла, а регулярные выражения напишите перед циклом.
0
+B
Заблокирован
17.07.2012, 13:45 3
Цитата Сообщение от Suppir Посмотреть сообщение
Но теперь код стал очень неудобный - регулярные выражения объявлены в самом верху программы, а используются совсем в другом месте.
Что это за чушь... вверху программы? Я так понял, ты объявил поля, вместо локальных переменных? Если не нравится наверху) - перенеси их поверх твоего метода. Результат будет тем же.
0
26 / 26 / 11
Регистрация: 08.08.2011
Сообщений: 1,172
17.07.2012, 13:55  [ТС] 4
Интересное предложение, но функция compare() где-то 800 или 900 строк (сложный парсер). Соответственно, даже если мы выносим за цикл, то все равно сложно разобрать, где какие регулярки используются.

Причем, у меня раньше этот парсер был написан на Perl. Там вообще по барабану - скорость огромная (в 2 раза выше c# после всех ухищрений), даже если регулярки используются в цикле. Интерпретатор сразу запоминает регулярное выражение, если в нем нет интерполируемых членов, и при последующем вызове опять применяет его.

Добавлено через 4 минуты
+B, а как объявить поверх моего метода, если сам метод не использует цикл?
Он сам вызывается в цикле.

Т.е. сейчас у меня вверху программы написано:
C#
1
Regex re39 = new Regex("(.+)/(?:20|19)(\\d\\d)$", RegexOptions.Compiled);
В функции compare() код:
C#
1
code = re39.Replace(code, "$1/$2");
расстояние между ними - строчек 500. А я бы хотел писать сразу:
C#
1
code = regex.Replace(code, (.+)/(?:20|19)(\\d\\d)$, "$1/$2");
Но тогда очень медленно работает. На perl достаточно написать:
Perl
1
$code=~ /(.+)/(?:20|19)(\d{2})$/$1\/$2/;
и это дело в цикле будет работать в два раза быстрей, чем оптимизированный вариант на c#
0
146 / 143 / 32
Регистрация: 21.01.2012
Сообщений: 545
17.07.2012, 13:58 5
регекс объявить статическим внутри метода не поможет?
1
+B
Заблокирован
17.07.2012, 14:01 6
Цитата Сообщение от KeBJIaP Посмотреть сообщение
регекс объявить статическим внетри метода не поможет?
Ты не с С++ не спутал?
Цитата Сообщение от Suppir Посмотреть сообщение
Т.е. сейчас у меня вверху программы написано:
Не проще ли выложить полный листинг и тогда уже объяснять, что не получается?
0
26 / 26 / 11
Регистрация: 08.08.2011
Сообщений: 1,172
17.07.2012, 14:03  [ТС] 7
KeBJIaP, что вы имеете в виду, можете пояснить?

Я пробовал внутри метода использовать

code = regex.Replace(code, (.+)/(?:20|19)(\\d\\d)$, "$1/$2");
и
code = regex.Replace(code, (.+)/(?:20|19)(\\d\\d)$, "$1/$2", RegexOptions|Compiled);

разницы никакой - одинаково медленно. Потому что сам метод вызывается 10 тысяч раз. Скорость увеличивается только, если вынести определения regex за пределы метода. Но тогда код невозможно читать.

Добавлено через 1 минуту
Цитата Сообщение от +B Посмотреть сообщение
Ты не с С++ не спутал?

Не проще ли выложить полный листинг и тогда уже объяснять, что не получается?
Там коммерческий алгоритм, очень сложный. Я его на Perl в течение трех лет писал и дорабатывал. Теперь на c# переношу, поэтому не могу выложить...
0
146 / 143 / 32
Регистрация: 21.01.2012
Сообщений: 545
17.07.2012, 14:13 8
Цитата Сообщение от +B Посмотреть сообщение
Ты не с С++ не спутал?
Спутал

Объяви весь метод статическим мож поможет

Добавлено через 6 минут
Можно создать статический метод для замены сразу
C#
1
2
3
4
public static void RegReplace39()
{
code = Regex.Replace(code, (.+)/(?:20|19)(\\d\\d)$, "$1/$2");
}
1
57 / 57 / 15
Регистрация: 22.09.2011
Сообщений: 319
17.07.2012, 14:15 9
Покажите весь листинг парсера
1
26 / 26 / 11
Регистрация: 08.08.2011
Сообщений: 1,172
17.07.2012, 14:20  [ТС] 10
KeBJIaP, интересно! Сегодня попробую.

Только переменная code является локальной для функции compare(). Мне кажется, в этом будет проблема.



Добавлено через 1 минуту
Цитата Сообщение от ansi_str Посмотреть сообщение
Покажите весь листинг парсера
Не Мой ник слишком хорошо знают конкуренты и коллеги. Украдут код, кто потом будет зарплату платить?
0
57 / 57 / 15
Регистрация: 22.09.2011
Сообщений: 319
17.07.2012, 14:24 11
А что такое Вы парсите - чтобы 10 тысяч раз вызывать один и тот же метод?
0
146 / 143 / 32
Регистрация: 21.01.2012
Сообщений: 545
17.07.2012, 14:31 12
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        public static class RegReplace
        {
            private static Regex reg1 = new Regex("(.19)(\\d\\d)$");
            //...
            private static Regex reg39 = new Regex("(.+)/(?:20|19)(\\d\\d)$");
            public static void Replace(int regexnum, string code, string replacement)
            { 
                Regex reg;
                switch(regexnum)
                {
                    case 1: {reg=reg1; break;}
                        //...
                    case 39: {reg=reg39; break;}
                    default: return;
                }
 
                reg.Replace(code, replacement);
            }
        }
C#
1
RegReplace.Replace(39,code,"$1/$2")
1
26 / 26 / 11
Регистрация: 08.08.2011
Сообщений: 1,172
17.07.2012, 14:36  [ТС] 13
Цитата Сообщение от ansi_str Посмотреть сообщение
А что такое Вы парсите - чтобы 10 тысяч раз вызывать один и тот же метод?
Сравниваю наполнения двух баз данных по неформальным признакам.
0
146 / 143 / 32
Регистрация: 21.01.2012
Сообщений: 545
17.07.2012, 14:37 14
Понеслась душа по кочкам)
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
        public static class RegReplace
        {
            private static Regex[] regg = new Regex[]
            {
            new Regex("sdfsd") //1
            };
            public static void Replace(int regexnum, string code, string replacement)
            {
                if (regexnum >= regg.Length)
                    return;
                Regex reg = regg[regexnum-1];
                reg.Replace(code, replacement);
            }
        }
0
26 / 26 / 11
Регистрация: 08.08.2011
Сообщений: 1,172
17.07.2012, 14:40  [ТС] 15
Цитата Сообщение от KeBJIaP Посмотреть сообщение
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        public static class RegReplace
        {
            private static Regex reg1 = new Regex("(.19)(\\d\\d)$");
            //...
            private static Regex reg39 = new Regex("(.+)/(?:20|19)(\\d\\d)$");
            public static void Replace(int regexnum, string code, string replacement)
            { 
                Regex reg;
                switch(regexnum)
                {
                    case 1: {reg=reg1; break;}
                        //...
                    case 39: {reg=reg39; break;}
                    default: return;
                }
 
                reg.Replace(code, replacement);
            }
        }
C#
1
RegReplace.Replace(39,code,"$1/$2")
Мне кажется, этот код ничем не отличается от определения регулярок выше метода.
Т.е. все равно у вас регулярки определяются вверху, а используются на много страниц ниже.

Мне же интересно, можно ли записывать регексы внутри метода так, чтобы код было легко читать и скорость была приличной.
0
57 / 57 / 15
Регистрация: 22.09.2011
Сообщений: 319
17.07.2012, 14:51 16
А как Вы из баз делаете сравнение по времени работы наполнения баз данных?
0
26 / 26 / 11
Регистрация: 08.08.2011
Сообщений: 1,172
17.07.2012, 14:59  [ТС] 17
В одной базе данных такой документ:

Закон Краснодарского края от 31.05.2005 N 870-КЗ
(ред. от 02.03.2012)
<О государственной гражданской службе Краснодарского края>
(принят ЗС КК 25.05.2005)

В другой базе данных документ выглядит так:
Краевой Закон от 31 мая 2005 г. N 870-К3 "О государственной гражданской службе Краснодарского края"

Необходимо находить одинаковые документы в двух БД, потом сравнивать атрибуты этих документов. Вариантов написания названий документов, различных особенностей очень много в каждом регионе. Необходимо все учитывать. В каждой базе данных по 5 млн. документов. Делаются "кусочные" сравнения по каждому региону.
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
17.07.2012, 15:03 18
Цитата Сообщение от Suppir Посмотреть сообщение
Мне же интересно, можно ли записывать регексы внутри метода так, чтобы код было легко читать и скорость была приличной.
Регулярки кешируются сами если использовать статические методы
C#
1
  Regex.  Replace()
там же рядом есть свойство управляющее кол-вом сохраняемых регулярок
C#
1
 Regex.CacheSize
там конечно свои заморочки есть, где-то в интернетах целую статью видел про это кеширование
0
26 / 26 / 11
Регистрация: 08.08.2011
Сообщений: 1,172
17.07.2012, 15:07  [ТС] 19
m0nax, так я и так использую
C#
1
code = Regex.Replace(code, (.+)/(?:20|19)(\\d\\d)$, "$1/$2");
или как-то по-другому нужно?

А в каком месте нужно применять Regex.CacheSize?
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
17.07.2012, 15:09 20
regex и Regex разные вещи, первый это название переменной, а второй имя класса
0
17.07.2012, 15:09
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.07.2012, 15:09
Помогаю со студенческими работами здесь

Как работают регулярные выражения?
Здравствуйте, только начал изучать регулярные выражения PCRE. И не могу найти годную для ума...

Как составляются регулярные выражения?
Здравствуйте, до меня не как не допрет как работает регулятор выражений. Допустим есть строки. ...

Как вставить картинку, регулярные выражения
Здраствуйте, столкнулся с такой задачей, У нас есть файл deferate.xspf: &lt;?xml version=&quot;1.0&quot;...

Как Регулярные Выражения Прикрутить К Lotusscript?
вобщем ситуация следующая есть проверка поля под ява скрипт, и занимает изза регулярного выражения...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru