Здравствуйте, karbofos42, Вы писали:
S>>Вот так выглядит пример, который вы хотели видеть, в рамках C++20 с концептами: https://wandbox.org/permlink/Plv2rFZlwbFFgQ1i
K>Немного поправил создание объектов: K>
K>Успешно выполнилось, просто результат несколько изменился. Пожалуй, это не то, чего я хотел от типизированного языка с проверкой compile-time
За это нужно говорить спасибо совместимости с Си. Без которой, следует признать, востребованность C++ даже в наши дни была бы ниже (полагаю в разы, если не на порядок).
Когда это является проблемой можно использовать strong typedef-ы (хоть в виде готовых библиотек, хоть слепленные на коленке). Благо все это будет с нулевыми накладными расходами в run-time. Хотя ТС может и прифигеть от использования возможностей современного C++ в этих самых strong typedef-ах.
Здравствуйте, karbofos42, Вы писали:
S>>Кто это пишет? Я здесь пока не увидел ни одного бенчмарка.
K>Так меня все убеждают
Поосторожнее с категориями всеобщности. Я, например, вас ни в чем подобном не утверждал.
K>что виртуальные методы в коллекциях сделают их медленными и такое не нужно, а то миллионы записей перелопачиваться перестанут.
Вынужден повторить: тут нет пока бенчмарков, поэтому, по сути, и предмета разговора нет.
У меня было желание набросать такой, что-то вроде перемножения матриц, реализованных разными способами. Но нет времени чтобы этим заняться.
Здравствуйте, so5team, Вы писали:
S>Поосторожнее с категориями всеобщности. Я, например, вас ни в чем подобном не утверждал.
ОК.
S>Вынужден повторить: тут нет пока бенчмарков, поэтому, по сути, и предмета разговора нет. S>У меня было желание набросать такой, что-то вроде перемножения матриц, реализованных разными способами. Но нет времени чтобы этим заняться.
Для виртуальных методов бенчмарки сложно придумать и сделать.
Я набросил на вентилятор относительно простой в реализации вариант с коллекциями, но как-то не оценили в большинстве своём и смысла в таком бенчмарке не будет.
Сложность в том, что отказ от виртуальных функций влечёт за собой изменения в архитектуре.
Где-то наследование на композицию заменится, где-то через шаблонную обёртку решится и т.д.
По сути уже будет сравнение двух подходов и там начнутся споры, что примеры неправильные и не то показывают.
Вот чел написал тесты сравнения просто вызовов виртуальных функций: https://stackoverflow.com/a/77983092
Сами по себе виртуальные вызовы сильно медленнее и вроде ужасно.
Но вот что будет суммарно с кодом, когда в нём появятся всякие обёртки для "эмуляции" виртуальности — вопрос.
Может оптимизатор всё съест, заинлайнит и получится в итоге со всех сторон без виртуальных функций лучше, а может разница не такая большая в итоге будет и можно не загоняться.
Здравствуйте, Евгений Музыченко, Вы писали:
N>>Восемь лишних байт на класс в каждом экземпляре. ЕМ>Если объектов единицы-десятки миллионов, и в каждом до десятков байт, то можно обойтись и 32-разрядными адресами,
Не можно. Надо же не объекты считать, а где загрузчик разместит виртуальную таблицу в памяти. Где гарантия в 64 битной системе, что она будет находиться в пределах 32 битного адреса?
Здравствуйте, Евгений Музыченко, Вы писали:
P>>Не знаю как сейчас, но еще в 00х разница между прямым вызовом и виртуальным была значительная — в разы.
ЕМ>В разы могла быть разница только у самих команд вызова (прямой call по сравнению с загрузкой в регистр адреса vtbl, с последующим косвенным call). Если же сравнивать полную стоимость вызова (загрузку параметров, собственно вызов, создание стекового кадра, сохранение/восстановление регистров, возврат результата), то разница очень сильно уменьшается. Не следует забывать, что все стековые операции — косвенные.
Я в то время занимался замерами этой хрени для оптимизации и сравнивал вызовы, а не команды. Во сколько именно раз было медленнее, не скажу, но точно в разы.
ЕМ>Корректировка this выполняется при любом приведении указателя к производному типу. Сам вызов, что прямой, что виртуальный, выполняется на this конкретного объекта. Ну и множественное наследование — таки частный случай, а не общий.
не совсем понятно, что там корректировать при отсутствии множественного наследования? this по идее один и тот же, т.к. vtbl ровно одна штука. Может я забыл чего, последний раз году в 15м это смотрел.
ЕМ>Про "тысячи" стартер писал в отношении всяких чисто системных косвенных вызовов, без привязки к C++. В отношении виртуальных функций стартер писал о "сотнях тысяч".
Сотни тысяч это всё равно не тот масштаб
P>>Сейчас модно все вычисления выталкивать в компилятор
ЕМ>И как компилятор вычисляет то, что ему во время компиляции неизвестно?
Здравствуйте, karbofos42, Вы писали:
K>Или всё же чаще хардкодится конкретный условный std::vector и методы все его принимают, т.к. нафиг надо шаблоны городить?
Во-первых, мегауниверсальный метод нужен редко, и тогда принимают пару итераторов.
Во-вторых, в реальном методе реального проекта ты знаешь с каким классом работаешь.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, karbofos42, Вы писали:
K>Единообразно может быть только при условии наличия этого в стандартных библиотеках. В плюсах этого нет, поэтому куча велосипедов.
Почему непременно в библиотеках? Нужные средства могут быть и в ядре языка. В плюсах, как в свое время и с C, выбрали в целом правильный подход, ограничив ядро до минимума, и вынеся все остальное в библиотеку, чтобы сделать их "ортогональными". Но если в C ядро в целом достаточно функционально, и библиотека естественным образом расширяет его возможности, то в плюсовом ядре долгое время не было критически необходимых средств, да и сейчас есть не все, из-за чего библиотека вынуждена не только расширять возможности языка, но и преодолевать недостатки его ядра. Той самой "ортогональности" в плюсах нет, и еще долго не будет. Отсюда и большинство велосипедов.
K>Так тут в итоге все пишут, что виртуальные функции медленные
Вам пишут вовсе не это. Медленны не сами по себе виртуальные функции, а решения, к которым Вы эти функции предлагаете прибить гвоздями. Если предложите решения, в которых виртуальные функции используются только при необходимости, а без нее обходятся дешевыми средствами, то будет смысл обсуждать. С идеей строить на них любой контейнер я тоже не согласен категорически, хотя сам знаю, что ничего особо тяжелого в них нет. Но мне регулярно требуются решения, в которых нет ничего лишнего, а Ваш подход предполагает лишить меня такой возможности, дав взамен лишь сомнительное преимущество в синтаксисе.
Здравствуйте, so5team, Вы писали:
S>Т.е. вы сперва утверждаете, что кодирование в виде "длина+текст" буквально "в итоге сделали в C++11 для string"
Да, сделали — компилятор передает конструктору длину строки в готовом виде, а не заставляет вычислять ее во время выполнения или ожидать, что это сделает оптимизатор.
S>следом, говорите, что "задачу создания таблиц строк вида "длина+текст" это все равно не решает"
Именно так — не решает. Один костыль поменяли на другой, как обычно.
Здравствуйте, cserg, Вы писали:
C>Надо же не объекты считать, а где загрузчик разместит виртуальную таблицу в памяти. Где гарантия в 64 битной системе, что она будет находиться в пределах 32 битного адреса?
Здравствуйте, Евгений Музыченко, Вы писали:
S>>Т.е. вы сперва утверждаете, что кодирование в виде "длина+текст" буквально "в итоге сделали в C++11 для string"
ЕМ>Да, сделали — компилятор передает конструктору длину строки в готовом виде, а не заставляет вычислять ее во время выполнения или ожидать, что это сделает оптимизатор.
К кодированию строки в виде "длина+текст" это не имеет отношения.
Для тех, кто хотел иметь такую же оптимизацию в C++98 можно было использовать что-то вроде:
Здравствуйте, T4r4sB, Вы писали:
TB>Во-первых, мегауниверсальный метод нужен редко, и тогда принимают пару итераторов.
Никогда не бывает такого, что ошиблись с выбором контейнера или объём/характер данных несколько изменился, что требуется вектор заменить на хэш-таблицу с быстрым поиском?
У меня вот периодически встречаются задачи, когда кто-то когда-то написал на аналоге вектора, т.к. и данных мало и вызывалась функция редко. Спустя годы в коллекцию и информации куда больше попадает и уже чуть ли не на hit test мыши привязывается, что нужно оптимизировать, уходить от полного перебора коллекции для поиска элементов и т.п.
Сидеть менять везде std::vector на std::unordered_set, а в итоге окажется, что вроде по скорости нормально выходит, но по памяти фигня, стоит попробовать что-то ещё. И опять сидеть всякие хелперы править, которым по сути плевать на тип коллекции?
Вопрос не в написании кода, а в его поддержке и развитии.
TB>Во-вторых, в реальном методе реального проекта ты знаешь с каким классом работаешь.
В реальном методе реального проекта я работаю с тем, что дали.
Если мне нужно найти элемент в коллекции и эта коллекция — вектор, то придётся искать перебором.
Не буду же я ради одной побочной функции лезть и переписывать половину программы, просаживая другие более важные функции.
В C# я буду использовать виртуальный метод коллекции Contains, который скажет есть ли нужный объект в коллекции.
Для List(аналог вектора) он будет работать через перебор, для хэш-множества — с быстрым поиском по хэшу.
Если я заменю тип коллекции с List на HashSet, то у меня автоматически этот самый вызов Contains станет работать быстрее с использованием плюшек множества.
В C++ я так понимаю будет вот такая ситуация: https://stackoverflow.com/a/71063103
Сначала напишешь для вектора через std::find, а потом при переходе на множество упустишь момент и в нём всё продолжит искаться перебором, без использования плюшек нового контейнера.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Ниасилил. Можно расшифровать подробнее?
Объект содержит указатель на таблицу виртуальных функций. Таблица в памяти находится там, где ее разместил загрузчик исполняемого файла/разделяемой библиотеки. Загрузчик в 64 битной системе не обязан размещать ее в пределах 32 битного адреса, т.е. не хватит 32 бит для такого указателя.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Вам пишут вовсе не это. Медленны не сами по себе виртуальные функции, а решения, к которым Вы эти функции предлагаете прибить гвоздями. Если предложите решения, в которых виртуальные функции используются только при необходимости, а без нее обходятся дешевыми средствами, то будет смысл обсуждать. С идеей строить на них любой контейнер я тоже не согласен категорически, хотя сам знаю, что ничего особо тяжелого в них нет. Но мне регулярно требуются решения, в которых нет ничего лишнего, а Ваш подход предполагает лишить меня такой возможности, дав взамен лишь сомнительное преимущество в синтаксисе.
Я пишу о том, что в других языках с другими приоритетами в стандартных библиотеках коллекций используются виртуальные методы и люди не жужжат.
Кому нужно что-то супер-мега оптимизированное и без лишнего — всегда можно взять или сделать стороннюю библиотеку и не прикручивать виртуализацию.
Вариант коллекций из C#/Java мне видится более удобный и безопасный в повседневном использовании, где никто байты не считает и миллионами записей не орудует.
Зато стандартность таких коллекций и их интерфейсов приводит к простоте написания кода рядовыми разработчиками и сложнее им выстрелить себе в ногу.
Против STL ничего не имею, но ведь варианты на всех этих шаблонах в итоге дают простые способы выстрелить себе в ногу.
Вроде язык с контролем типов и максимально проверки вынесены в compile-time, а вроде в коллекцию bool легко int запишет с неявным преобразованием и лови баг сиди.
Ну, а раз в языке так принято и народу так нравится, значит тут так принято и те же виртуальные методы для плюсовиков действительно достаточно дороги для использования и целесообразно на них экономить
Здравствуйте, пффф, Вы писали:
П>те, кто под них пишет — конченные люди, их уже только могила исправит. И пишут они лютое говно.
Вот прям все, без исключения? А почему, собственно? Что, по-Вашему, делает их такими?
П>Я знавал одного сишника/асмщика с PIC — на его код без слез смотреть было нельзя. Под MSC-51 сам писал. И много читал сишного кода. Тоже тоже очень хотелось плакать. Всё это было написано людьми, явно далекими от программирования, и ни о какой эффективности там говорить не приходилось.
А я видел немало кода, написанного вроде бы профессиональными программистами, но тоже хотелось плакать. Какой вывод-то?
П>Ни о каком промышленном серьёзном применении этого говна речи идти не может.
"Промышленное серьезное применение" — это не только сложные станки, выпускаемые сотнями-тысячами штук. Это любая индустрия с достаточно большими капиталовложениями и объемами производства.
П>Это уродцы, которые обычно выступают в роли вспомогательных чипов на больших чипах, для их настройки, и предназначено это для электронщиков, которые чутка освоили сишечку, и могут наговнякать управляющую программу для чипа, который они вкорячили в свою схему.
Или для серийно выпускаемых устройств, которым достаточно минимального интеллекта, чтобы не городить его прямиком на топологии.
П>Ну и код у всего этого именно такого качества.
Именно из-за устройства МК? Какие параметры МК обрекают любой код для него на говнистость?
П>Это нельзя называть серьёзным промышленным применением, ничего сложного там и не делается.
А если этого выпускается тонны, и продается на миллиарды?
П>лучше бы, чтобы все уже выкинули это древнее говнецо на помоечку, и вкорячивали бы STMку какую, туда бы прошивали Lua, и для кастомизации нанимали бы студента-хипстера
Да, и в каждые настольные часы вкорячить линукс. А кто за все это заплатит? STM-ки вроде как не бесплатные.
П>Другое применение этих уродцев — это контроллеры стиральных машин
Которые выпускаются штучно, отчего встречаются очень редко.
П>где оно решает мега сложные задачи по измерению температуры воды и её нагреву (там аж ПИД-регулятор надо делать, это да), да по смене режимов работы, включения мотора барабана и насосов на двухчасовом цикле стирки. Да, тут 5 Мгц частоты точно мало, тут 160 надо.
Про оценку распределения масс в барабане по соотношению токов в обмотках двигателя Вы явно не в курсе.
П>Ещё применение — выполнять какую-то примитивнейшую функцию, потребляя как можно меньше энергии. Не спорю, полезно иногда
Вот прям иногда? Если каждые часы, термометр, датчик дыма и прочая мелочь вокруг Вас станет разряжать свой источник не за год-два, а за две недели, Вы ничуть не расстроитесь?
П>но квалификации тут не нужно никакой от слова вообще.
Изначально речь шла не о квалификации, а о возможности применения для всего этого более удобного и надежного языка, нежели ассемблер или C. Глядишь, и говнокода стало бы поменьше.
П>прошивки к этим устройствам пишут не какие-то супер-эффективные сишники-программисты, прошивки к ним пишут инженеры-электронщики
Возможно, Вы не в курсе, но многие сильные программисты вышли из технарей, изучая программирование самостоятельно. А вот изначально подготовленные на профильных факультетах далеко не всегда демонстрируют хороший уровень.
П>Петров, у вас же в институте язык C давали? — Давали, один семестр. — Отлично, Петров, вот ты прошивку и напишешь".
И что, если бы Петрову давали не C, а C++ или Pascal, он написал бы хуже?
П>А вы много вообще сишников знаете, и ещё и пишущих под контроллеры? Нету таких сишников, как класса.
Когда мне попадаются исходники прошивок для устройств, которые я использую, многие производят неплохое впечатление.
П>У плюсового компилятора гораздо больше информации, которую можно использовать для оптимизации. И плюсовый компилятор умеет многое делать на этапе компиляции, на сишечке это всё будет в рантайме.
Каким образом все эти качества могут концентрироваться в плюсовом компиляторе, но избегать попадания в сишный? Если в компиляторе есть соответствующая логика — он будет оптимизировать до упора, если ее нет — будет делать код, как придется. Стандарты C++ не устанавливают конкретных требований к оптимизации, за исключением некоторых явно оговоренных. А многие компиляторы изначально умеют и C, и C++. Функционально эквивалентные исходники они чаще всего компилируют в один и тот же код.
ЕМ>>Просто писать будет удобнее, код будет более читаемым, ошибки делать сложнее, а вылавливать — легче.
П>Это вы про сишечку?
Это я про плюсики по сравнению с сишечкой.
П>Вы сами на сишечке много писали?
Не очень. Я много писал на ассемблерах, на сишечке успел пописать всего года три-четыре, потом перелез на плюсы.
П>Я, как минимум, написал один HTTP-сервер на сишечке
Это считается сложным проектом для C? Не знал, честно. Вот, например, Simple HTTP Server — цельных 25 килобайт исходник. Или Ваш был сильно круче?
П>что написали на сишечке вы?
Успел написать пару драйверов средней сложности, несколько приложений для работы со звуком, кучку разных мелких утилит. Делал оконную подсистему и музыкальный секвенсор, но бросил.
Можем помериться приборами по ассемблерам. Я на одном ассемблере когда-то написал многопользовательскую интерактивную систему составления программ для графопостроителя и управления заданиями для него (это когда в школе учился), а на другом — программу составления и печати спецификаций оборудования для газодобывающей промышленности, по набору заданных шаблонов (эту спихнул в качестве дипломной работы в институте, чтоб отдельной темы не брать). А в машинных кодах (ибо на той машине ассемблера не было) я написал дизассемблер (чтоб удобнее было возиться с кодами) и визуальный текстовый редактор с форматированием и печатью в несколько столбцов. И не скажу, что это были сложные задачи — вполне себе ординарные.
П>Что это должно доказать? Что сырой плюсовый компилятор 40 лет назад выдавал код хуже вылизанного сишного?
Только то, что я сам был одержим предубеждениями, но они хотя бы имели какое-то основание.
П>А другие крмпиляторы пробовали? Например, Watcom?
Пробовал — он давал хороший код, но работал гораздо медленнее. А меня медленная работа раздражает, как и стояние в пробке. Потому и писал долгое время на ассемблерах — "лучше медленно ехать, чем долго стоять".
П>Я могу примерно прикинуть мою производительность на масме, и на плюсиках. Субъективно разница где-то от 1000 до 10000 раз
Как-то слишком разительно. Ну, или для Вас ассемблеры просто сильно непривычны.
П>Код среднего плюсовика всегда выиграет у кода среднего сишечника по скорости.
Да не выиграет он всегда. Если и тот, и другой делают код согласно устоявшимся правилам и рекомендациям, то где-то будет быстрее на C за счет простоты, где-то — на плюсах за счет выразительности. А если как попало, то и там, и там будет медленно.
Здравствуйте, so5team, Вы писали:
S>Для тех, кто хотел иметь такую же оптимизацию в C++98 можно было использовать что-то вроде:
Осталось найти способ сложить строки в таблицу, о чем я с самого начала и говорил. Когда нужно просто вывести конкретную строку, уже не особо важно, известна ее длина заранее, или нет.
Здравствуйте, cserg, Вы писали:
C>Объект содержит указатель на таблицу виртуальных функций. Таблица в памяти находится там, где ее разместил загрузчик исполняемого файла/разделяемой библиотеки. Загрузчик в 64 битной системе не обязан размещать ее в пределах 32 битного адреса, т.е. не хватит 32 бит для такого указателя.
Я имел в виду 32-разрядное приложение, а не ограничение адреса в 64-разрядной системе.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Осталось найти способ сложить строки в таблицу, о чем я с самого начала и говорил.
Евгений, здесь все ходы записаны, так что не не сложно тыкнуть вас фейсом в ваше же говно:
В сам язык имело смысл изначально завезти кодирование строковых литералов в виде "длина+текст", наравне со стандартным нулем в конце, что в итоге сделали в C++11 для string.
Никакого кодирования "длина+текст" в C++11 не сделали. Ни для строк, ни для чего-либо еще.
Ладно вы не можете в конкретику (из-за чего дискуссии с вами теряют смысл т.к. вы не даете себе труда подтвердить ваши же слова хоть чем либо). Гуманитарии они такие. Поймем и (не) простим.
Но когда вы не можете перечитать что сами написали пару ответов назад, это уже совсем уже клиникой попахивает.
Остается только лишний раз показывать где вы снова жидко обделались.
Здравствуйте, karbofos42, Вы писали:
K>Я пишу о том, что в других языках с другими приоритетами в стандартных библиотеках коллекций используются виртуальные методы и люди не жужжат.
С чего б им жужжать, коли они на этих языках попросту не решают задач, для которых принято привлекать C/C++? Я сам езжу на машине с клиренсом в 16 см по асфальту, и тоже не жужжу.
K>Кому нужно что-то супер-мега оптимизированное и без лишнего — всегда можно взять или сделать стороннюю библиотеку и не прикручивать виртуализацию.
Если есть подходящий инструмент для разных задач, всегда удобнее обойтись им, чем сочетать разные.
K>Вариант коллекций из C#/Java мне видится более удобный и безопасный в повседневном использовании, где никто байты не считает и миллионами записей не орудует.
Так те, кому не надо считать/орудовать, и пишут на C#/Java.
K>Против STL ничего не имею
А я имею. Но, что выросло — то выросло.
K>Вроде язык с контролем типов и максимально проверки вынесены в compile-time, а вроде в коллекцию bool легко int запишет с неявным преобразованием
Да, это косяк, растущий из совместимости с C, "умолчательность" которой давно пора ликвидировать, но далеко не все с этим согласны. Многим почему-то позарез надо эту совместимость искаропки, чтоб ни одного лишнего движения не требовалось для успешной компиляции куска сишного кода, вставленного в плюсовый.
K>и лови баг сиди.
Или повысь уровень предупреждений, и компилятор сам поймает.
K>те же виртуальные методы для плюсовиков действительно достаточно дороги для использования и целесообразно на них экономить
Вы так и не поняли нюансов, которые Вам упорно пытаются объяснить.