Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.90/20: Рейтинг темы: голосов - 20, средняя оценка - 4.90
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81

Скорость выполнения функции в 2-ух вариантах

26.08.2021, 23:27. Показов 4302. Ответов 33
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Функция a_IsFindForbWord() выполняется в несколько раз быстрее, чем b_IsFindForbWord():

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
bool a_IsFindForbWord()
{
    char str[] = "философия знак новое!территория субъект стих.забота дождь политика доля.";
 
    char *piece = strtok(str, ". :)(;?,!*\"'-+=");
 
    while (piece != nullptr)
    {
        for (const auto &element : forb_words)
        {
            if (strcmp(piece, element.c_str()) == 0)
            {
                return true;
            }
        }
    
        piece = strtok(0, ". :)(;?,!*\"'-+=");
    }
 
    return false;
}


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
bool b_IsFindForbWord()
{
    std::string str_source = "философия знак новое!территория субъект стих.забота дождь политика доля.";
 
    std::regex words_regex("[^\\. :)(;?,!*\"'-+=]+");
 
    auto begin = std::sregex_iterator(str_source.begin(), str_source.end(), words_regex);
    auto end = std::sregex_iterator();
 
    for (auto i = begin; i != end; ++i)
    {
        std::smatch match = *i;
 
        std::string word_from_source = match.str();
 
        //printf("word_from_source = '%s'\n", word_from_source.c_str());
 
        for (const auto &element : forb_words)
        {
            if (word_from_source == element.c_str())
            {
                return true;
            }
        }
    }
 
    return false;
}


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
    setlocale(LC_ALL, "ru");
 
    // Загрузка слов. Записывает в вектор строк forb_words слова (кол-во ~ 5000) из файла .ini
    LoadingForbiddenWords();
 
    // Вычисления
    unsigned int t1 = GetTickCount();
 
    for (int i = 0; i < 100000; i++)
    {
        a_IsFindForbWord();
        // b_IsFindForbWord();
    }
 
    unsigned int t2 = GetTickCount();
 
    printf("Время работы программы = %d", t2 - t1);
 
    _getch();
 
    return 0;
}


Результат теста:
a_IsFindForbWord(): 10203 (10 секунд)
b_IsFindForbWord(): 67596 (67 секунд)

Мне бы хотелось оставить ф-ию b_IsFindForbWord() для своей программы, но не могу понять - почему она такая медленная? Почитал форум немного и наткнулся, что как-то тормозит цикл где regex_iterator - Медленная работа regex (1-ый пост в конце). Как быть?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.08.2021, 23:27
Ответы с готовыми решениями:

Скорость выполнения функции
У меня в классе Resp() есть функция H_c() которая скачивает с некого сайта каптчу и распознает ее. Я сделал так: public function...

Скорость выполнения функции (IndexOf, if)
Здравствуйте! Подскажите пожалуйста, что экономичней использовать в программе: &quot;if&quot; или &quot;IndexOf&quot;, и на сколько? И...

Уменьшить время выполнения работы программы, увеличить скорость выполнения
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace...

33
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
26.08.2021, 23:43
Цитата Сообщение от leo7755 Посмотреть сообщение
почему она такая медленная?
Потому что содержит много тяжеловесных операций:
1) Динамическое выделение памяти
2) Построение автомата по регулярному паттерну
3) Применение автомата к последовательности


Цитата Сообщение от leo7755 Посмотреть сообщение
Как быть?
Ну вот построение автомата (разбор паттерна к регулярке) можно и вынести из функции и не делать его каждый раз.
То же касается строки входных данных, зачем они там в явном виде? Пусть это будет параметр std::string_view, и вы разгрузите функцию, дадите ей гибкость работать с разными данными, не обязательно динамическими.
1
 Аватар для YUEN HOIFEF
252 / 185 / 47
Регистрация: 31.01.2021
Сообщений: 934
27.08.2021, 01:19
(67 секунд
Целую минуту? Разделить долбаную небольшую строку.?
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
28.08.2021, 01:44  [ТС]
DrOffset,
вынес за функцию, в глобальную область пару строк, а именно
C++
1
2
std::regex words_regex("[^\\. :)(;?,!*\"'-+=]+");
std::string str_source = "философия знак новое!территория субъект стих.забота дождь политика доля.";
И ничего не поменялось по сути. А str_source такая, потому что для 'теста'. В оригинале она в параметрах функции, т.е.
C++
1
bool b_IsFindForbWord(std::string str_source)
Опять же скорость лучше не стала. А то, что выполняется ряд сложных действий для регулярки - я об этом не подумал, но поверю знающим.
Честно говоря strtok меня особо не смущает, но думал, что вариант есть получше и даже побыстрее..

YUEN HOIFEF,
да, но ведь в тесте вызывается 100 тысяч раз. и в векторе строк ~ 5000 слов перебирать необходимо
0
Заблокирован
28.08.2021, 03:37
Цитата Сообщение от leo7755 Посмотреть сообщение
forb_words
Это словарь ? находится в векторе (std::vector)?
Вот тут можно и оптимизировать "чуток". Если поменять его на std::set.

Добавлено через 9 минут
Цитата Сообщение от leo7755 Посмотреть сообщение
Честно говоря strtok меня особо не смущает
Надо лишь помнить что :
Важно понимать, что функция strtok() модифицирует строку, на которую указывает str1. Каж­дый раз, когда найдена лексема, на месте, где был найден ограничитель, помещается нулевой символ. Таким образом strtok() продвигается вдоль строки.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
28.08.2021, 11:39
Цитата Сообщение от leo7755 Посмотреть сообщение
скорость лучше не стала
Покажите как сделали, только не отрывком, а полным кодом.
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
29.08.2021, 02:32
Цитата Сообщение от leo7755 Посмотреть сообщение
но не могу понять - почему она такая медленная?
Во-первых, вы замеры проводили при сборке в Debug или в Release? Без оптимизаций компилятора, STL сильно тупит, особенно это заметно в Visual Studio.
Во-вторых, как уже упомянули, во втором варианте есть лишние выделения памяти. От них можно избавиться, например, вот так:
C++
1
2
3
auto& word_from_source = match[0];
//...
if (word_from_source == element)
И в-третьих, вы предоставили неполные данные. В приведенном вами коде нечему выполняться 10 и 67 секунд.
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
18.09.2021, 15:39  [ТС]
Цитата Сообщение от nonedark2008 Посмотреть сообщение
замеры проводили при сборке в Debug или в Release?
Release

Цитата Сообщение от nonedark2008 Посмотреть сообщение
Без оптимизаций компилятора, STL сильно тупит, особенно это заметно в Visual Studio
оптимизация не проводилась

Цитата Сообщение от DrOffset Посмотреть сообщение
а полным кодом
Цитата Сообщение от nonedark2008 Посмотреть сообщение
вы предоставили неполные данные
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
static std::vector<std::string> forb_words;
 
void LoadingForbiddenWords()
{
    char char_path[MAX_PATH];
    GetModuleFileNameA(0, char_path, sizeof (char_path) / sizeof (char_path[0]));
 
    std::string str_path = char_path;
    std::string path_rezult = regex_replace(str_path, std::regex("[A-Za-z0-9]+.exe"), "chat_test.ini");
 
    std::ifstream handle;
    handle.open(path_rezult);
 
    if (handle)
    {
        forb_words.clear();
 
        std::string source;
 
        while (!handle.eof())
        {
            getline(handle, source);
 
            if (source[0] == 0 || source[0] == '#' || source[0] == ';'
                || (source[0] == '/' && source[1] == '/'))
            {
                continue;
            }
 
            int pos = source.find("=");
 
            std::string sub = source.substr(pos + 1);
 
            sub = regex_replace(sub, std::regex(" |\t"), "");
 
            forb_words.push_back(sub);
        }
    }
    handle.close();
}
 
bool a_IsFindForbWord()
{
    char str[] = "философия знак новое!территория субъект стих.забота дождь политика доля.";
 
    char *piece = strtok(str, ". :)(;?,!*\"'-+=");
 
    while (piece != nullptr)
    {
        for (const auto &element : forb_words)
        {
            if (strcmp(piece, element.c_str()) == 0)
            {
                return true;
            }
        }
 
        piece = strtok(0, ". :)(;?,!*\"'-+=");
    }
 
    return false;
}
 
std::regex words_regex("[^\\. :)(;?,!*\"'-+=]+");
std::string str_source = "философия знак новое!территория субъект стих.забота дождь политика доля.";
 
bool b_IsFindForbWord()
{
    auto begin = std::sregex_iterator(str_source.begin(), str_source.end(), words_regex);
    auto end = std::sregex_iterator();
 
    for (auto i = begin; i != end; ++i)
    {
        std::smatch match = *i;
 
        std::string word_from_source = match.str();
 
        //printf("word_from_source = '%s'\n", word_from_source.c_str());
 
        for (const auto &element : forb_words)
        {
            if (word_from_source == element.c_str())
            {
                return true;
            }
        }
    }
 
    return false;
}
 
int main()
{
    setlocale(LC_ALL, "ru");
 
    // Загрузка слов
    LoadingForbiddenWords();
 
    // Вычисления
    unsigned int t1 = GetTickCount();
 
    for (int i = 0; i < 100000; i++)
    {
        a_IsFindForbWord();
    }
 
    unsigned int t2 = GetTickCount();
 
    printf("Время работы программы = %d", t2 - t1);
 
    _getch();
 
    return 0;
}
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
23.09.2021, 10:30
leo7755, глянул мельком результат профилирования под VS2019. Основное время тратится на итерацию по std::sregex_iterator. Думаю, что на вашей задаче не удастся на регулярных выражениях получить результат, сопоставимый с strtok. Внутри std::sregex_iterator постоянно выделяется и освобождается динамическая память, да и других накладных расходов очень много.
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
23.09.2021, 22:39  [ТС]
Цитата Сообщение от nonedark2008 Посмотреть сообщение
Думаю, что на вашей задаче не удастся на регулярных выражениях получить результат, сопоставимый с strtok
Ну вот теперь не знаю, может быть оставить strtok..
Дело в том, что эти функции будут использоваться в игровом серверном моде с некоторым онлайном (~ 50-100 игроков). И там конечно же есть чат. Он фильтруется в некоторых моментах. И можете себе представить если в чат сразу отправят сообщение 20 игроков, т.е. 20 раз нужно будет вызвать функцию.
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
23.09.2021, 23:09
Цитата Сообщение от leo7755 Посмотреть сообщение
И можете себе представить если в чат сразу отправят сообщение 20 игроков, т.е. 20 раз нужно будет вызвать функцию.
Думаю, какой-либо просадки в производительности вы даже не заметите. В качестве вариантов могу предложить следующее:
1. Взять стороннюю библиотеку для регулярных выражений. Очень вероятно, что она окажется существенно быстрее библиотеки из STL;
2. Выкинуть strtok и использовать std::string в связке с std::string::find_first_of. Должно работать несильно хуже strtok.
0
Заблокирован
23.09.2021, 23:39
Я вот иногда захожу сюда, и думаю отчего же автор не использует ассоциативные контейнеры.
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
23.09.2021, 23:58
Цитата Сообщение от SmallEvil Посмотреть сообщение
Я вот иногда захожу сюда, и думаю отчего же автор не использует ассоциативные контейнеры.
Потому что регулярные выражения =)

leo7755, можете еще попробовать следующее. Вместо того, чтобы строить регулярное выражение, которое просто выбирает слова из текста, можно попробовать создать специализированное регулярное выражение, которое сразу находит слова из фильтра. При большом размере фильтра это может работать быстрее, чем strtok и с циклом. Но может работать медленнее, чем strtok с каким-нибудь std::unordered_set.
1
736 / 700 / 110
Регистрация: 29.05.2015
Сообщений: 4,266
24.09.2021, 08:03
Может просто озвучить задачу, которую автор топика затрудняется решить? А то приходится напрягать свои экстрасенсорные навыки. Нужно в тексте найти некоторые ключевые слова из списка? Приблизительный размер текста? Приблизительный размер списка?
0
Заблокирован
24.09.2021, 12:24
alexu_007, чем читаешь ? пятым ухом ?
Словарь около 5к слов, текст - сообщение чата, допустим от 10 до 40 слов.
Как то в одном чате практиковался писать нецензур понятным всем способом, вариантов вагон и маленькая тележка.
В итоге "закрыть" можно только базовые слова и словоформы.
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
28.09.2021, 22:06  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
ассоциативные контейнеры
set, map? ну как бы уже есть vector. хотя он последовательный как мы знаем.
Цитата Сообщение от SmallEvil Посмотреть сообщение
В итоге "закрыть" можно только базовые слова и словоформы.
Из опыта скажу, что некоторые умельцы могут писать даже вот так:
Кликните здесь для просмотра всего текста
урод
ур0д - где 0 это конечно же ноль

Поэтому закрыть придётся много слов, в разных вариантах. И мне не лень будет это сделать)
0
Заблокирован
29.09.2021, 12:09
Цитата Сообщение от leo7755 Посмотреть сообщение
Поэтому закрыть придётся много слов, в разных вариантах. И мне не лень будет это сделать)
Если действительно есть такое желание, простім сравнением не обойтись, придется делать морфологический анализатор, но он судя по твоему подходу, тебе не по силам.
Хотя я могу ошибаться. Но в любом случае никакой вектор тут не применим.
Самій лучший вариант - дерево + морф. анализатор.

Добавлено через 53 секунды
тот же map, и есть примитивное дерево
1
736 / 700 / 110
Регистрация: 29.05.2015
Сообщений: 4,266
29.09.2021, 14:00
Цитата Сообщение от leo7755 Посмотреть сообщение
Поэтому закрыть придётся много слов, в разных вариантах. И мне не лень будет это сделать)
Смотри в горячке не запрети словосочетание "застрахуйте меня" - оно без мата.
0
Заблокирован
29.09.2021, 15:06
Цитата Сообщение от alexu_007 Посмотреть сообщение
Смотри в горячке не запрети словосочетание "застрахуйте меня" - оно без мата.
это цена жесткой цензуры

Добавлено через 1 минуту
как то в одной игре у меня блочило слово вполне нормальное слово с буквосочетанием "бля"
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
29.09.2021, 15:30  [ТС]
Цитата Сообщение от alexu_007 Посмотреть сообщение
"застрахуйте меня"
Цитата Сообщение от SmallEvil Посмотреть сообщение
"бля"
В моём случае ложных срабатываний не будет) там же проверка по разделителям есть. т.е. перед/после 'слова' должен быть разделитель какой-то
C++
1
". :)(;?,!*"'-+="
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.09.2021, 15:30
Помогаю со студенческими работами здесь

Уменьшить время выполнения работы программы, увеличить скорость выполнения
Подскажите, пожалуйста, как можно сократить время при компиляции, нужно не более 1 секунды, при некоторых данных выполняется дольше,...

Написать следующие функции в двух вариантах
char* strstr(char* string1, char* string2) Возвращает указатель на первое вхождение подстроки string2 в строке string1. В случае...

Работа с файлами. Нужно сделать функции сохранения и загрузки данных в двух вариантах: текстовый и бинарный режим
Работа с файлами. Нужно сделать функции сохранения и загрузки данных в двух вариантах: текстовый и бинарный режим. С сохранением вроде...

Скорость выполнения.
Есть консольное приложение, работающее с огромными текстовыми файлами, сравнивает их, читает, записывает и т.д. Судя по диспетчеру...

Скорость выполнения
В цикле строка выполняется примерно 10тыс раз, хотелось бы быстрее. // №1 if (this.toString().length &gt; maxLength) maxLength =...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru