Об эффективности виртуальных функций
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 04.08.24 20:19
Оценка:
Всю жизнь был уверен, что оценки вроде "виртуальные функции сильно снижают быстродействие" идут от неграмотных гуманитариев, которые где-то слышали звон, а потом рожают на его основе заумные тексты, которые потом цитируют технари, совершенно незнакомые с языком. Но почитал описании истории языка от Страуструпа (я читал несколько его книг, но истории раньше почему-то не попадалось), где он пишет, что многим программистам, в том числе системным, "было трудно поверить в то, что виртуальные функции могут быть достаточно быстрыми".

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

Что эти люди, которые переживали (а некоторые и сейчас переживают, судя по дискуссиям) о "стоимости вызова", собирались делать с помощью виртуальных функций? Если вызывать их сотни тысяч раз в секунду и чаще, то и при обычном прямом вызове такие функции будут сильно тормозить. А если вызывать с разумной частотой, то лишь в очень редких случаях можно обнаружить заметную разницу.

Все эти люди старательно избегали любой косвенности, указатели/ссылки использовали лишь в самых крайних случаях?

Кому-нибудь удавалось заметно снизить быстродействие заменой обычных функций на виртуальные? Ну, кроме случаев совсем уж плохого проектирования.
Re: Об эффективности виртуальных функций
От: opfor  
Дата: 04.08.24 20:25
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Кому-нибудь удавалось заметно снизить быстродействие заменой обычных функций на виртуальные? Ну, кроме случаев совсем уж плохого проектирования.


Может на какой-то машине вроде спектрума или realtime микроконтроллеров это возможно, где метод может вызываться много раз за цикл. На современных машинах об этом даже задумываться нет смысла, лучше устранять другие ботлнеки. Более того, большинство ЯП идут по умолчанию с виртуальными ф-циями ON.

Кстати, почему они называются виртуальными? Дурацкое название.
Страуструп придумал?
Re: Об эффективности виртуальных функций
От: Stanislav V. Zudin Россия  
Дата: 04.08.24 20:46
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Всю жизнь был уверен, что оценки вроде "виртуальные функции сильно снижают быстродействие" идут от неграмотных гуманитариев, которые где-то слышали звон, а потом рожают на его основе заумные тексты, которые потом цитируют технари, совершенно незнакомые с языком...


ЕМ>Кому-нибудь удавалось заметно снизить быстродействие заменой обычных функций на виртуальные? Ну, кроме случаев совсем уж плохого проектирования.


На борландовском компиляторе (ещё в ДОСе) обращение к статическим переменным было на порядок быстрее, чем к мемберам класса.
В Ваткомовском компиляторе такой проблемы уже не было.

Предполагаю, что разница между прямым и косвенным вызовом функции происходит с тех времён.

Ну и да, в каких-то задачах косвенный вызов может стоить дополнительных тактов и может дать некоторое замедление — лишние микросекунды. Для сурового риалтайма может быть важным.
Мы в своих задачах таким не заморачивались — все ускорения достигались за счёт алгоритмов.
_____________________
С уважением,
Stanislav V. Zudin
Re[2]: Об эффективности виртуальных функций
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 04.08.24 20:51
Оценка:
Здравствуйте, opfor, Вы писали:

O>Может на какой-то машине вроде спектрума или realtime микроконтроллеров это возможно, где метод может вызываться много раз за цикл.


Так то же самое получится при активном использовании любой косвенности. Теми же ссылками народ обычно пользуется, не глядя, но на косвенные вызовы почему-то сразу настораживается.

O>Кстати, почему они называются виртуальными? Дурацкое название.


Вы в курсе, что virtual — это "действительный", "фактический"?
Re[2]: Об эффективности виртуальных функций
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 04.08.24 20:58
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>На борландовском компиляторе (ещё в ДОСе) обращение к статическим переменным было на порядок быстрее, чем к мемберам класса.


Не помню такого. Может, там где-то одна лишняя команда и затесывалась, но чтоб на порядок — не было.

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

SVZ>В Ваткомовском компиляторе такой проблемы уже не было.


SVZ>в каких-то задачах косвенный вызов может стоить дополнительных тактов и может дать некоторое замедление — лишние микросекунды. Для сурового риалтайма может быть важным.


В те времена, когда одно-два обращения к памяти занимали микросекунды, "суровый реалтайм" даже не помышляли писать даже на C, не говоря уже о C++.

SVZ>Мы в своих задачах таким не заморачивались — все ускорения достигались за счёт алгоритмов.


Дык, о том и речь.
Re[3]: Об эффективности виртуальных функций
От: opfor  
Дата: 04.08.24 21:16
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Вы в курсе, что virtual — это "действительный", "фактический"?


Нет, не в курсе:

Virtual:
Existing in the mind, especially as a product of the imagination
Existing or resulting in essence or effect though not in actual fact, form, or name
Created, simulated, or carried on by means of a computer or computer network

Re[3]: Об эффективности виртуальных функций
От: Stanislav V. Zudin Россия  
Дата: 04.08.24 21:22
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

SVZ>>На борландовском компиляторе (ещё в ДОСе) обращение к статическим переменным было на порядок быстрее, чем к мемберам класса.


ЕМ>Не помню такого. Может, там где-то одна лишняя команда и затесывалась, но чтоб на порядок — не было.


Подробностей уже не помню, кажется, компилятор делал вычисление адреса мембера класса в рантайме в лоб — с несколькими уровнями косвенности, а со статическими переменными обращался напрямую по адресу.

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


Версию компилятора уже не помню. Не исключено, что в последующих версиях этот косяк был поправлен, но, код уже написан, я пришел в тот проект в 97г, в 98 мы портировали его на винду. И, кажется, он до сих пор используется в неизменном виде. 💪

SVZ>>в каких-то задачах косвенный вызов может стоить дополнительных тактов и может дать некоторое замедление — лишние микросекунды. Для сурового риалтайма может быть важным.


ЕМ>В те времена, когда одно-два обращения к памяти занимали микросекунды, "суровый реалтайм" даже не помышляли писать даже на C, не говоря уже о C++.


Я уже говорю про сейчас — какой-нибудь HFT, передача по сети и т.п.
_____________________
С уважением,
Stanislav V. Zudin
Re[4]: Об эффективности виртуальных функций
От: · Великобритания  
Дата: 04.08.24 21:41
Оценка: +1
Здравствуйте, opfor, Вы писали:

o> ЕМ>Вы в курсе, что virtual — это "действительный", "фактический"?

o> Нет, не в курсе:
Синоним "почти", например в рекламе часто попадается virtually indestructible.

virtual: almost a particular thing or quality

She suffered a virtual breakdown when her marriage broke up.

https://dictionary.cambridge.org/dictionary/english/virtual
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Об эффективности виртуальных функций
От: vsb Казахстан  
Дата: 05.08.24 02:49
Оценка: +4
Сотни тысяч раз можно и функцию на питоне вызывать. Наверное те, кто переживает за виртуальные функции, собираются их вызывать хотя бы миллиард раз в секунду.
Re[3]: Об эффективности виртуальных функций
От: σ  
Дата: 05.08.24 03:46
Оценка: +3
O>>Кстати, почему они называются виртуальными? Дурацкое название.

ЕМ>Вы в курсе, что virtual — это "действительный", "фактический"?


Почти действительный
Re: Об эффективности виртуальных функций
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 05.08.24 04:04
Оценка: +2
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Все эти люди старательно избегали любой косвенности, указатели/ссылки использовали лишь в самых крайних случаях?


Беседовал когда-то с челом из HFT, так его беспокоили не сами вызовы виртуальных функций, а наличие таблицы виртуальных функций, которая увеличивала размер класса. Ну и массовое создание/удаление множества мелких объектов без виртуальности происходило заметно быстрее. Сериализация — вот это всё.
Я в детали не вдавался, это было на какой-то конференции по С++, поэтому на дополнительные вопросы ответить не смогу.
Re: Об эффективности виртуальных функций
От: karbofos42 Россия  
Дата: 05.08.24 05:15
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Откуда вообще могло взяться такое опасение в профессиональной-то среде?


Можно у разработчиков STL спросить почему они не сделали абстракции в виде Collection/ICollection как в библиотеках той же Java или C#.
Удобно ведь было бы в метод принимать просто коллекцию, получать какой-то абстрактный итератор для перебора или через виртуальный метод add добавить пару элементов.
Вместо этого приходится писать методы конкретно под std::vector и никакой std::set не передашь.
Re[2]: Об эффективности виртуальных функций
От: so5team https://stiffstream.com
Дата: 05.08.24 06:31
Оценка:
Здравствуйте, karbofos42, Вы писали:

K>Можно у разработчиков STL спросить почему они не сделали абстракции в виде Collection/ICollection как в библиотеках той же Java или C#.


Вроде бы об этом Страуструп в своей книге "Дизайн и эволюция" писал. Как и об отсутствии единого базового класса Object, как в во многих ООЯП.

K>Вместо этого приходится писать методы конкретно под std::vector и никакой std::set не передашь.


Это какой-то странный код, если ему фиолетово, используется ли std::vector или std::set.
Re[4]: Об эффективности виртуальных функций
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 05.08.24 08:52
Оценка:
Здравствуйте, Stanislav V. Zudin, Вы писали:

SVZ>кажется, компилятор делал вычисление адреса мембера класса в рантайме в лоб — с несколькими уровнями косвенности


class If {

  public:

  virtual void f1 () = 0;
  virtual void f2 () = 0;

};

void f (If & i) {

  i.f1 ();
  i.f2 ();

}


TC++ 1.0:

@f$qr2If    proc    near
    push    bp
    mov    bp,sp
    push    si
    mov    si,word ptr [bp+4]
   ;    
   ;    
   ;      i.f1 ();
   ;    
    push    si
    mov    bx,word ptr [si]
    call    word ptr [bx]
    pop    cx
   ;    
   ;      i.f2 ();
   ;    
    push    si
    mov    bx,word ptr [si]
    call    word ptr [bx+2]
    pop    cx
   ;    
   ;    
   ;    }
   ;    
    pop    si
    pop    bp
    ret    
@f$qr2If    endp


Я тут вижу только лишние push/pop, но получить из-за них сколько-нибудь ощутимое снижение быстродействия нужно очень-очень постараться.

ЕМ>>В те времена, когда одно-два обращения к памяти занимали микросекунды, "суровый реалтайм" даже не помышляли писать даже на C, не говоря уже о C++.


SVZ>Я уже говорю про сейчас — какой-нибудь HFT, передача по сети и т.п.


А сейчас — тем более, десяток-другой лишних обращений к памяти — ничто по сравнению с затратами на основную обработку данных и временем ожидания ответа устройств.
Re[2]: Об эффективности виртуальных функций
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 05.08.24 09:01
Оценка:
Здравствуйте, Nuzhny, Вы писали:

N>Беседовал когда-то с челом из HFT, так его беспокоили не сами вызовы виртуальных функций, а наличие таблицы виртуальных функций, которая увеличивала размер класса.


Они использовали хотя бы миллионы разных классов? Таблица-то общая на весь класс, а в каждом объекте добавляется только ее адрес. Чтобы получить заметное (в нынешних масштабах) увеличение расходов, они должны создавать хотя бы миллионы объектов очень маленького размера (десяток-другой байт), иначе этот прирост теряется на фоне размера самого объекта.

N>Ну и массовое создание/удаление множества мелких объектов без виртуальности происходило заметно быстрее. Сериализация — вот это всё.


Тоже странно. Такое ощущение, что было как-то неправильно спроектировано.
Re[2]: Об эффективности виртуальных функций
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 05.08.24 09:04
Оценка: 10 (1) +1
Здравствуйте, karbofos42, Вы писали:

K>Вместо этого приходится писать методы конкретно под std::vector и никакой std::set не передашь.


Насколько я понимаю, они делали простые контейнеры вроде vector/list так, чтобы после оптимизации получался предельно эффективный код, не уступающий коду со встроенными массивами и ручными списками. В принципе, это правильно, иначе нареканий на STL было бы гораздо больше.
Re[3]: Об эффективности виртуальных функций
От: so5team https://stiffstream.com
Дата: 05.08.24 09:16
Оценка: :)
Здравствуйте, Евгений Музыченко, Вы писали:

N>>Ну и массовое создание/удаление множества мелких объектов без виртуальности происходило заметно быстрее. Сериализация — вот это всё.


ЕМ>Тоже странно. Такое ощущение, что было как-то неправильно спроектировано.


Ну так в HFT же криворукие идиоты работают, половину которых набрали по объявлению, а вторую половину -- по блату.
Re[3]: Об эффективности виртуальных функций
От: · Великобритания  
Дата: 05.08.24 09:18
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ> N>Беседовал когда-то с челом из HFT, так его беспокоили не сами вызовы виртуальных функций, а наличие таблицы виртуальных функций, которая увеличивала размер класса.

ЕМ> Они использовали хотя бы миллионы разных классов? Таблица-то общая на весь класс, а в каждом объекте добавляется только ее адрес. Чтобы получить заметное (в нынешних масштабах) увеличение расходов, они должны создавать хотя бы миллионы объектов очень маленького размера (десяток-другой байт), иначе этот прирост теряется на фоне размера самого объекта.
Так примерно оно и есть. Какой-нибудь там Order будет i64 цена, i64 количество, i16 currency pair, и неск байт всяких атрибутов. И в памяти лежат миллионы таких.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[4]: Об эффективности виртуальных функций
От: · Великобритания  
Дата: 05.08.24 09:20
Оценка: :)
Здравствуйте, so5team, Вы писали:

s> Ну так в HFT же криворукие идиоты работают, половину которых набрали по объявлению, а вторую половину -- по блату.

Иди туда, спроектируй всё по правильному — заработаешь миллионы и получишь мировую известность.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: Об эффективности виртуальных функций
От: so5team https://stiffstream.com
Дата: 05.08.24 09:27
Оценка: +1 :)
Здравствуйте, ·, Вы писали:

s>> Ну так в HFT же криворукие идиоты работают, половину которых набрали по объявлению, а вторую половину -- по блату.

·>Иди туда, спроектируй всё по правильному — заработаешь миллионы и получишь мировую известность.

Не-не-не, у меня с сарказмом все нормально, в отличии от.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.