Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81

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

26.08.2021, 23:27. Показов 4526. Ответов 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
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
29.09.2021, 15:50
Студворк — интернет-сервис помощи студентам
ну_ты_ххх_ххх_красавец, ваших разделителей здесь нет, разделить похабщину можно любым символом.
Вы слишком самоуверены, видимо ваша игра детская и хватит и прямого фильтра

Добавлено через 1 минуту
leo7755, кстати цитировать нецензур было не обязательно!
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
29.09.2021, 16:40  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
ну_ты_ххх_ххх_красавец, ваших разделителей здесь нет
ну добавлю, и тильды нет)))
Игра детская, SA-MP по сети (GTA SA), поэтому мне хватит того, что есть)
А вот по поводу map интересно. я занёс в vector слова - разве это не правильно?
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
29.09.2021, 16:46
Лучший ответ Сообщение было отмечено leo7755 как решение

Решение

Цитата Сообщение от leo7755 Посмотреть сообщение
А вот по поводу map интересно. я занёс в vector слова - разве это не правильно?
тут не стоит вопрос в правильности. Слова в векторе вполне "правильно" лежат. )
Вопрос стоит в быстродействии. А значит способ хранения слов (в std::vector) выбран неправильный (не эффективный).
Доступ к слову по ключу map или set (в данном случае предпочтительно использовать set), намного быстрей , чем проходить весь вектор(дин. массив).

Почитайте про хеш функции и деревья, возможно это прояснит ситуацию.
1
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
29.09.2021, 17:03  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
Вопрос стоит в быстродействии. А значит способ хранения слов (в std::vector) выбран неправильный (не эффективный).
Доступ к слову по ключу map или set (в данном случае предпочтительно использовать set), намного быстрей , чем проходить весь вектор(дин. массив).
я попробую поработать с set. переделаю функцию и замерю скорость
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
01.10.2021, 02:43  [ТС]
SmallEvil,
Дело обстоит так, что вместо vector применил контейнер set, а вместо регулярных - boost::split

Кликните здесь для просмотра всего текста
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#define _CRT_SECURE_NO_WARNINGS
 
 
 
#include <conio.h>
#include <iostream>
#include <fstream>
//#include <iterator>
//#include <string>
#include <regex>
//#include <fstream>
#include <windows.h>
#include <vector>
#include <set>
//#include <map>
//#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
 
 
 
static std::set<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_5000.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.insert(sub);
        }
    }
    handle.close();
}
 
/************************************************************************/
/* strtok                                                               */
/************************************************************************/
 
static char ch_source[] = "философия знак новое!территория субъект стих.забота дождь политика доля.";
 
bool a_IsFindForbWord()
{
    char *piece = strtok(ch_source, ". :)(;?,!*\"'-+=");
 
    while (piece != nullptr)
    {
        for (const auto &element : forb_words)
        {
            if (strcmp(piece, element.c_str()) == 0)
            {
                return true;
            }
        }
 
        piece = strtok(0, ". :)(;?,!*\"'-+=");
    }
 
    return false;
}
 
/************************************************************************/
/* boost::split                                                         */
/************************************************************************/
 
static std::string str_source   =   "философия знак новое!территория субъект стих.забота дождь политика доля.";
static std::vector<std::string>     words_split;
 
bool b_IsFindForbWord()
{
    boost::split(words_split, str_source, boost::is_any_of(". :)(;?,!*\"'-+="));
 
    for (auto it = words_split.cbegin(), end = words_split.cend(); end != it; ++it)
    {
        const std::string word = *it;
 
        for (const auto &element : forb_words)
        {
            if (strcmp(word.c_str(), element.c_str()) == 0)
            {
                return true;
            }
        }
    }
 
    return false;
}
 
int main()
{
    setlocale(LC_ALL, "ru");
 
 
 
    LoadingForbiddenWords();
 
    //if (b_IsFindForbWord())
    //{
    //  printf("найдено слово");
    //}
    //else
    //{
    //  printf("НЕ найдено слов");
    //}
 
    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;
}

Результат теста обрадовал. Ну явно побыстрее, чем было (~ на 20 сек.):

a_IsFindForbWord(): 6365 (6 секунд)
b_IsFindForbWord(): 48937 (48 секунд)

Имеются ли недочёты в b_IsFindForbWord()?
0
1394 / 1023 / 325
Регистрация: 28.07.2012
Сообщений: 2,813
01.10.2021, 08:39
Лучший ответ Сообщение было отмечено leo7755 как решение

Решение

Цитата Сообщение от leo7755 Посмотреть сообщение
Имеются ли недочёты в b_IsFindForbWord()?
Ты не пользуешься преимуществами std::set. Вместо всего внутреннего цикла можно бы было просто написать:
C++
1
2
if (forb_words.count(word))
    return true;
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
02.10.2021, 02:21  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static std::string str_source =     "философия знак новое!территория субъект стих.забота дождь политика доля.";
static std::vector<std::string>     words_split;
 
bool b_IsFindForbWord()
{
    boost::split(words_split, str_source, boost::is_any_of(". :)(;?,!*\"'-+="));
 
    for (auto it = words_split.cbegin(), end = words_split.cend(); end != it; ++it)
    {
        if (forb_words.count(std::string(*it)))
        {
            return true;
        }
    }
 
    return false;
}
100 тысяч итераций:
a_IsFindForbWord() : 62 млс.
b_IsFindForbWord() : 843 млс.

1 млн. итераций:
a_IsFindForbWord() : 390 млс.
b_IsFindForbWord() : 8096 млс.

nonedark2008, не поверишь - не зря использовал метод count. Дополнительно поменял set на unordered_set. С ним даже быстрее вышло. Данные в отсортированном виде мне не нужны. Но осталось пару вопросов:

1) std::vector<std::string> words_split обязательно выносить на функцию?
2) можно ли оставить условие в таком виде?
C++
1
2
3
4
5
if (forb_words.count(std::string(*it)))
 
//или так?
const std::string word = *it;
if (forb_words.count(word))
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
02.10.2021, 03:15
C++
1
if (forb_words.count(*it))
вот так, по итератору уже строка находится.

Цитата Сообщение от leo7755 Посмотреть сообщение
std::vector<std::string> words_split обязательно выносить на функцию?
Тут я не совсем понял.
Разделяются слова сообщения, сообщение каждый раз разное, значит и набор слов тоже.
Значит это данные функции и желательно что б они были внутри по всей логике.
А почему words_split объявлена как static ?
И саму строку(сообщение) передавай в функцию по ссылке, много не потеряешь.

Добавлено через 6 минут
Странно но я не вижу твое отфильтрованное сообщение

Добавлено через 4 минуты
Или решил всЁ сообщение блочить ? ))

Добавлено через 13 секунд
Или решил всЁ сообщение блочить ? ))
1
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
02.10.2021, 03:15
Или решил всЁ сообщение блочить ? ))
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
02.10.2021, 05:25  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
А почему words_split объявлена как static ?
Она же глобальной будет, если затереть static. А так только в этом файле доступна.

Цитата Сообщение от SmallEvil Посмотреть сообщение
в функцию по ссылке
да?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
bool b_IsFindForbWord(const std::string &source)
{
    boost::split(words_split, source, boost::...));
}
 
if (b_IsFindForbWord(str_source))
{
    printf("найдено слово");
}
else
{
    printf("НЕ найдено слов");
}
Цитата Сообщение от SmallEvil Посмотреть сообщение
Странно но я не вижу твое отфильтрованное сообщение
Или решил всЁ сообщение блочить ? ))
Я тоже не понял о чём ты)))
Принцип работы функции такой. Игрок пишет сообщение в чат. Это сообщение проверяется через IsFindForbWord. Строка разделяется на слова*. Далее производится поиск первого встречающегося запрещённого слова из словаря forb_words. И если слово найдено, то можно например блокировать вывод такого сообщения.

* словом считается набор символов (Aa-Zz, Аа-Яя), которые с одной или с двух сторон разделяются некоторыми символами-разделителями
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
03.10.2021, 16:49  [ТС]
Цитата Сообщение от leo7755 Посмотреть сообщение
глобальной
вернее она останится глобальной, но в пределах данного файла
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
03.10.2021, 16:59
Жесткий фильтр, одно слово не то и бан всему сообщению )
И можно не понять почему, если произойдет ложное срабатывание.

Цитата Сообщение от leo7755 Посмотреть сообщение
вернее она останится глобальной, но в пределах данного файла
Да я понимаю, но зачем она глобальная (words_split)?
Ради прироста пары милисекунд ?
Она же все равно очищается (дожна) и заполняется заново при каждом вызове функции.

Добавлено через 2 минуты
Она часть этой функции, объявить ее static внутри функции еще понятно.

Добавлено через 36 секунд
И то сомнительно.
0
 Аватар для leo7755
3 / 3 / 1
Регистрация: 12.02.2017
Сообщений: 81
03.10.2021, 17:23  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
Жесткий фильтр, одно слово не то и бан всему сообщению )
Ну можно закрыть звёздочками (само запрещённое слово, т.е. 'ты п*****c') или впускать сообщение, но при этом выдавать автоматически заглушку на n-минут (чтобы игрок не мог пользоваться чатом несколько минут). Такое практикуется же, я видел в разных играх).
Цитата Сообщение от SmallEvil Посмотреть сообщение
Она же все равно очищается (дожна) и заполняется заново при каждом вызове функции.
вот это мне и нужно понять, как её оставить локально или глобально. значит локально
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
03.10.2021, 18:31
Цитата Сообщение от leo7755 Посмотреть сообщение
Ну можно закрыть звёздочками (само запрещённое слово, т.е. 'ты п*****c') или впускать сообщение, но при этом выдавать автоматически заглушку на n-минут (чтобы игрок не мог пользоваться чатом несколько минут). Такое практикуется же, я видел в разных играх).
Тогда подход совсем другой будет, но зато практика уже есть, так что все дело во времени/необходимости.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
03.10.2021, 18:31

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

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

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

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

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


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

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

Новые блоги и статьи
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru