Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915

Вызов виртуальных функций настолько медленный ?

29.08.2023, 11:00. Показов 1819. Ответов 23
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте,


Вызов виртуального метода отличается от прямого вызова метода - примерно в два раза.
Если к примеру добавить в базовый класс еще хотя бы 5 классов - то разница уже будет составлять 14 раз!!

Максимум как можно сократить этот разрыв процентов до 30% разницы - это в метод класса добавить очень "тяжелый" код, то есть тем самым сократив кол-во вызовов методов в условную секунду.

Это что за эффективность такая ?


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
150
151
int global_int = 1;
 
struct test_struct
{
    int int_1;
    int int_2;
    int int_3;
    int int_4;
    int int_5;
};
 
 
 
class BASE_CLASS
{
public:
 
    virtual int func_calculate(test_struct test_struct_) = 0;
    virtual ~BASE_CLASS() {}
};
 
 
class my_class_1: public BASE_CLASS
{
public:
 
    int func_calculate(test_struct test_struct_)
    {
 
        int result = test_struct_.int_1*456435 + 54 + test_struct_.int_2^456 + test_struct_.int_3 * test_struct_.int_4/5344 + test_struct_.int_5 / 8;
 
        for (int i = 0; i < global_int; i++)
        {
            result = result + test_struct_.int_1 * 456435 + 54 + test_struct_.int_2 ^ 456 + test_struct_.int_3 * test_struct_.int_4 / 5344 + test_struct_.int_5 / 8;
        }
 
        return result;
    }
 
};
class my_class_2 : public BASE_CLASS
{
public:
 
    int func_calculate(test_struct test_struct_)
    {
        int result = test_struct_.int_1 * 456435 + 54 + test_struct_.int_2 ^ 456 + test_struct_.int_3 * test_struct_.int_4 / 5344 + test_struct_.int_5 / 8;
 
 
        for (int i = 0; i < global_int; i++)
        {
            result = result + test_struct_.int_1 * 456435 + 54 + test_struct_.int_2 ^ 456 + test_struct_.int_3 * test_struct_.int_4 / 5344 + test_struct_.int_5 / 8;
        }
 
        return result;
    }
 
private:
 
};
 
 
int main()
{
 
 
  
    test_struct test_struct_;
    test_struct_.int_1 = 12;
    test_struct_.int_2 = 34;
    test_struct_.int_3 = 5645;
    test_struct_.int_4 = 876;
    test_struct_.int_5 = test_struct_.int_3 + test_struct_.int_1;
 
 
    //------------------------------------
    size_t numm_ = 9999999;
    std::chrono::time_point<std::chrono::steady_clock> start_;
    std::chrono::time_point<std::chrono::steady_clock> end_;
    size_t result_ms_;
    //------------------------------------
 
 
 
    //------------------------------------
    size_t size_1=0;
    start_ = std::chrono::steady_clock::now();
 
    my_class_1 my_class_1_;
    my_class_2 my_class_2_;
    my_class_3 my_class_3_;
    my_class_4 my_class_4_;
    my_class_5 my_class_5_;
    my_class_6 my_class_6_;
 
 
    for (size_t i=0; i< numm_; i++)
    {
        size_1 = size_1 + my_class_1_.func_calculate(test_struct_);
 
        size_1 = size_1 + my_class_2_.func_calculate(test_struct_);
        size_1 = size_1 + my_class_3_.func_calculate(test_struct_);
        size_1 = size_1 + my_class_4_.func_calculate(test_struct_);
        size_1 = size_1 + my_class_5_.func_calculate(test_struct_);
        size_1 = size_1 + my_class_6_.func_calculate(test_struct_);   
    }
 
    end_ = std::chrono::steady_clock::now();
    result_ms_ = std::chrono::duration_cast<std::chrono::milliseconds>(end_ - start_).count();              //результат в мили секундах
    std::cout << "func_1:" << result_ms_ << std::endl;
    std::cout << size_1 << std::endl;
    //------------------------------------
 
 
 
    //------------------------------------
    std::vector<BASE_CLASS*>vec;
 
    BASE_CLASS* my_class_1_b = new my_class_1;
    BASE_CLASS* my_class_2_b = new my_class_2;
    BASE_CLASS* my_class_3_b = new my_class_3;
    BASE_CLASS* my_class_4_b = new my_class_4;
    BASE_CLASS* my_class_5_b = new my_class_5;
    BASE_CLASS* my_class_6_b = new my_class_6;
 
 
 
    size_t size_2 = 0;
    start_ = std::chrono::steady_clock::now();
 
 
    for (size_t i = 0; i < numm_; i++)
    {
        size_2 = size_2 + my_class_1_b->func_calculate(test_struct_);
 
        
        size_2 = size_2 + my_class_2_b->func_calculate(test_struct_);
        size_2 = size_2 + my_class_3_b->func_calculate(test_struct_);
        size_2 = size_2 + my_class_4_b->func_calculate(test_struct_);
        size_2 = size_2 + my_class_5_b->func_calculate(test_struct_);
        size_2 = size_2 + my_class_6_b->func_calculate(test_struct_);
        
    }
 
    end_ = std::chrono::steady_clock::now();
    result_ms_ = std::chrono::duration_cast<std::chrono::milliseconds>(end_ - start_).count();              //результат в мили секундах
    std::cout << "func_2:" << result_ms_ << std::endl;
    std::cout << size_2 << std::endl;
    //------------------------------------
 
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.08.2023, 11:00
Ответы с готовыми решениями:

Вызов виртуальных функций
Доброго времени суток, форумчане! Стоит такая задача: Есть класс, который содержит три чисто виртуальные функции, назовём его IClass. ...

Вызов виртуальных функций
Привет всем.Помогите пожлауйста.Как можно вывести на экран данные из этого кода.Я использовал виртуальные функции,поэтому создать объект...

Вызов виртуальных методов внутри paintEvent
Добрый вечер уважаемые форумчане. Немного балуюсь с созданием Color Picker. Ниже представлен абстрактный класс т.н. канвы цветовых...

23
267 / 199 / 30
Регистрация: 26.11.2022
Сообщений: 862
29.08.2023, 11:28
можете и более детальный разбор производительности посмотреть
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
29.08.2023, 12:12
Цитата Сообщение от Optimus11 Посмотреть сообщение
Если к примеру добавить в базовый класс еще хотя бы 5 классов - то разница уже будет составлять 14 раз!!
По сравнению с чем? С отсутствием вызова?
Если вам нужны виртуальные функции, то очевидно, что без них задачу не решить. А если без них не решить, то и сравнивать не с чем.
2
Заблокирован
29.08.2023, 12:45
Optimus11, думаете с dynamic_cast и теми же N классов привести, будет лучше ?
Какой
Цитата Сообщение от Optimus11 Посмотреть сообщение
очень "тяжелый" код
вы рассматривали ?

Не по теме:

Aledveu, последний раз показываю
[YOUTUBE=https://www.youtube.com/watch?v=skl6N3zGv-s]skl6N3zGv-s[/YOUTUBE]

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

0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
29.08.2023, 13:08
Optimus11, вы структуры по значению передаёте чтобы утяжелить код?
Кстати, у вас нет динамиеского связывания в коде. То есть инициализация указателей базового класса не зависит от логики в рантайме и будет компилироваться в невиртуальные вызовы даже если бы вы создали виртуальные методы (на более менее актуальных компиляторах).
Вот работа с динамической памятью (если бы методы использовали поля класса) при больших размерах вектора и случайностью его заполнения (не подряд То есть, после заполнения, - какя-то жизнь - сортировка например), могла бы привести к тормозам из-за повышения частоты промахов мимо кэша. Но тут их нет.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
29.08.2023, 13:17
Цитата Сообщение от DrOffset Посмотреть сообщение
С отсутствием вызова?
Объясню для тех, кто не заметил сразу: все его "разы" возникают из-за того, что предполагаемо невиртуальных вызовов вообще нет. Они (вызовы) все встроились. И даже вероятнее всего результат посчитался на этапе компиляции.
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
29.08.2023, 13:20  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
Optimus11, вы структуры по значению передаёте чтобы утяжелить код?
Кстати, у вас нет динамиеского связывания в коде. То есть инициализация указателей базового класса не зависит от логики в рантайме и будет компилироваться в невиртуальные вызовы даже если бы вы создали виртуальные методы (на более менее актуальных компиляторах).
Вот работа с динамической памятью (если бы методы использовали поля класса) при больших размерах вектора и случайностью его заполнения (не подряд То есть, после заполнения, - какя-то жизнь - сортировка например), могла бы привести к тормозам из-за повышения частоты промахов мимо кэша. Но тут их нет.

Тогда почему такая разница во времени выполнения, если компилятор заранее знает какие методы он будет вызывать ?


Цитата Сообщение от IGPIGP Посмотреть сообщение
Optimus11, вы структуры по значению передаёте чтобы утяжелить код?
Нет, просто структура легкая, передавать ее по указателю будет даже в данном конкретном случае медленнее за счет разыменования. Но не суть.

Добавлено через 53 секунды
Цитата Сообщение от DrOffset Посмотреть сообщение
Объясню для тех, кто не заметил сразу: все его "разы" возникают из-за того, что предполагаемо невиртуальных вызовов вообще нет. Они (вызовы) все встроились. И даже вероятнее всего результат посчитался на этапе компиляции.
Если бы вызовы встроились - то не было бы такой разницы ведь ?
0
631 / 526 / 104
Регистрация: 05.08.2022
Сообщений: 2,810
29.08.2023, 13:40
Цитата Сообщение от Optimus11 Посмотреть сообщение
Если бы вызовы встроились
Есть нюанс:
Цитата Сообщение от DrOffset Посмотреть сообщение
что предполагаемо невиртуальных вызовов вообще нет.
Встроились или нет - это я не знаю, про это утверждать/оспаривать не стану. Обращаю лишь внимание на важный момент в сообщении DrOffset
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
29.08.2023, 15:19
Цитата Сообщение от Optimus11 Посмотреть сообщение
Тогда почему такая разница во времени выполнения, если компилятор заранее знает какие методы он будет вызывать ?
У вас они ведь невиртуалные. Тут сказанное мною не применимо. А время - как тестируете так и получаете.
Цитата Сообщение от Optimus11 Посмотреть сообщение
Нет, просто структура легкая, передавать ее по указателю будет даже в данном конкретном случае медленнее за счет разыменования. Но не суть.
Суть. Она тяжелее указателя.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
29.08.2023, 17:42
Цитата Сообщение от Optimus11 Посмотреть сообщение
Вызов виртуального метода отличается от прямого вызова метода - примерно в два раза.
В вашем примере прямые вызовы могли быть встроены. Если это произошло, то сравнение не имеет никакого отношения к сравнению с прямым вызовом.

Цитата Сообщение от Optimus11 Посмотреть сообщение
Если к примеру добавить в базовый класс еще хотя бы 5 классов - то разница уже будет составлять 14 раз!!
Это как это? Что значит "добавить в базовый класс еще хотя бы 5 классов"?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
29.08.2023, 19:18
Цитата Сообщение от Optimus11 Посмотреть сообщение
Если бы вызовы встроились - то не было бы такой разницы ведь ?
Вам нужно несколько раз повторить, да?
Ну вот:
Цитата Сообщение от DrOffset Посмотреть сообщение
предполагаемо невиртуальных вызовов вообще нет. Они (вызовы) все встроились.
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
В вашем примере прямые вызовы могли быть встроены.
-----------------
Цитата Сообщение от KSergey9 Посмотреть сообщение
Встроились или нет - это я не знаю, про это утверждать/оспаривать не стану.
Не смотря на то, что совершенно очевидно и так, что они тут встроились, я, тем не менее, это проверил на godbolt.org прежде чем здесь писать.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
29.08.2023, 19:31
Цитата Сообщение от KSergey9 Посмотреть сообщение
Встроились или нет - это я не знаю, про это утверждать/оспаривать не стану
В данном случае это гарантируется стандартом.

Вот из драфта С++17
12.2.1 Member functions
A member function may be defined (11.4) in its class definition, in which case it is an inline member function
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9005 / 4706 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
29.08.2023, 21:34
Undisputed, и inline как всегда, это пожелание.
1
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
29.08.2023, 22:10
Undisputed, немного не так. В этом пункте гарантируется, что функции определенные в class scope будут inline, а не что они именно встроятся при вызове.
2
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
29.08.2023, 22:33
IGPIGP,
DrOffset,
Ага, благодарю за уместное замечание.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
29.08.2023, 23:25
Цитата Сообщение от Undisputed Посмотреть сообщение
В данном случае это гарантируется стандартом.
Вот из драфта С++17
В этом месте стандарта идет речь об "инлайновости" самой функции, а не о встраивании ее вызовов. А в теме здесь мы говорим именно о встраивании вызовов. Это совершенно разные вещи.

Инлайновость самой функции не имеет никакого отношения к встраиванию ее вызовов. Инлайновость самой функции влияет лишь на то, как эта функция трактуется ODR. А именно: множественные определения инлайновой функции не приводят к ошибке линковки. Вот и все.

Что касается встраивания вызовов этой функции, то тут правила совсем другие и тоже весьма простые: если компилятору в точке вызова видно/доступно тело функции (т.е. ее определение), то вызов такой функции может быть встроен, если компилятор захочет выполнить это встраивание. Больше ничего не имеет значения.
1
Заблокирован
29.08.2023, 23:41
TheCalligrapher, почему нет механизмов для встраивания функций и/или методов ?
Ведь во многих случаях программисту виднее чем компилятору.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12923 / 6790 / 1818
Регистрация: 18.10.2014
Сообщений: 17,179
30.08.2023, 00:11
Цитата Сообщение от SmallEvil Посмотреть сообщение
почему нет механизмов для встраивания функций и/или методов ?
Язык такими вопросами пока не заморачивается, а в конкретных реализациях как раз таки все это есть в виде __forceinlineи __attribyte__((always_inline)). Указываются на уровне функции, а не на уровне отдельных вызовов.

Цитата Сообщение от SmallEvil Посмотреть сообщение
Ведь во многих случаях программисту виднее чем компилятору.
Да? Мне кажется как раз таки наоборот.
0
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
30.08.2023, 01:41
Цитата Сообщение от Optimus11 Посмотреть сообщение
Вызов виртуального метода отличается от прямого вызова метода - примерно в два раза.
Если к примеру добавить в базовый класс еще хотя бы 5 классов - то разница уже будет составлять 14 раз!!
Вы прослушали сказку о сломавшемся механизме предсказания переходов. Кратко говоря, внутри процессора происходит особое колдунство по оптимизации машинного кода. Для работы колдунства нужно чтобы процессор знал, какой код будет выполнен в дальнейшем. Но в случае ветвлений и переходов по указателям (те самые виртуальные вызовы), процессор затрудняется сказать, в какую сторону код поедет. Поэтому, в него встроен специальный хрустальный шар для предсказаний. Но работает он, ну... как хрустальный шар. Так что, если предсказания вдруг не сбылись, процессор выкидывает уже выполненные вычисления в форточку и начинает все с начала. Вот отсюда и тормоза.
1
631 / 526 / 104
Регистрация: 05.08.2022
Сообщений: 2,810
30.08.2023, 07:56
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Инлайновость самой функции не имеет никакого отношения к встраиванию ее вызовов. Инлайновость самой функции влияет лишь на то, как эта функция трактуется ODR. А именно: множественные определения инлайновой функции не приводят к ошибке линковки. Вот и все.
Просто это весьма простое и базовое понятие inline в С++ какого-то хрена перепилили в одном из стандартов.
Зачем, почему - мне решительно не понять. Так что вам хорошо бы уточнять по какой стандарт вы говорите в разрезе такого поведения inline.

Из-за вот этого совершенно идиотского изменения смысла слова inline, я думаю, и возникают тут недопонимания из-за "старых воспоминаний" по классическим книжкам.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.08.2023, 07:56
Помогаю со студенческими работами здесь

Почему Windows настолько популярен, а линукс настолько обделен?
Откуда такая популярность у windows? Многие мои знакомые даже не догадываются про существование Linux... Почему все виндузятские ламеры...

Вызов виртуальных методов
Добрый день! Не могу разобраться с примером из спецификации, объясните, пожалуйста, почему пример, приведенный ниже, выводит то, что...

Таблица виртуальных функций
объясните плиз кто разбирается.. есть абстрактный класс с двумя виртуальными функциями, от него наследуются два класса реализующие эти...

Механизм виртуальных функций
Всем привет! Имею базовый абстрактный класс: class Interface { public: //функция детектирования устройства true - если команда...

Реализация виртуальных функций
Создать класс Fraction для работы с дробными десятичными числами. Количество чисел в дробной части должно задаваться в отдельном поле и...


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

Или воспользуйтесь поиском по форуму:
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