LINUX.ORG.RU

Какое же говнище этот ваш С++

 


11

7

Решил намедни углубить свои знания по плюсам, чувствуя, что скоро нехило так потребуются по работе. Теперь сижу, обмазываюсь тут всякими трупами страусов, Скоттом Майерсом и другими. Г-пди, как же можно на этом писать, особенно после знания божественных лиспов, хаскелей и прочих матанских агд (sic!). Это какая-то пытка, честное слово, мне натурально мерзко и противно читать как люди пытаются вырезать гланды через задний проход да ещё и хвалятся этим, поглядите, мол, как это круто. Такое ощущение, будто плюсисты все поголовно латентные мазохисты.

template <typename T>
class Rational
{
    public:
    ...
    friend const Rational operator*(const Rational& lhs, const Rational& rhs)
    {
        return Rational(lhs.numerator() * rhs.numerator(), // same impl
            lhs.denominator() * rhs.denominator()); // as in Item 24
    }
}

An interesting observation about this technique is that the use of friendship has nothing to do with a need to access non-public parts of the class. In order to make type conversions possible on all arguments, we need a non-member function (Item 24 still applies); and in order to have the proper function automatically instantiated, we need to declare the function inside the class. The only way to declare a non-member function inside a class is to make it a friend. So that's what we do. Unconventional? Yes. Effective? Without a doubt.

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

Перемещено mono из talks

★★★★★

Последнее исправление: mono (всего исправлений: 1)
Ответ на: комментарий от anonymous

Зачем? Достаточно умный компилятор может это сам вывести.

затем, что компилятор, даже умный, не сможет сам решить - надо посчитать это за ошибку или нет

Ах ну да, вы же хинт оптимизатору типа 'virtual' тоже привыкли ручками указывать, у вас же нет 'достаточно умного компилятора'

это не хинт

не может в плюсах, потому что там константность нетранзитивна. Чем и отличается constness/immutability в D.

окей, покажи, что нельзя сделать в С++

wota ★★
()
Ответ на: комментарий от aist1

Проблема в реале не так остра, как подразумевал человек, начавший эту тему.

Программы на яве что пішутся с оптимизмом про JVM стартуют долго, жрут много, работают медленно. Зато с модными лямбадами & динамической типизацией & скриптовыми вставками etc.

+80 байт на плюсовой проге - это RTTI, 1) который выключается 2) который скорее всего и не включается для С++ лямбд (не проверял).

dzidzitop ★★
()
Ответ на: комментарий от r

создай TObject -> наследуй всё от него -> юзай только TObject * -> кодогенерация будет работать как в яве (специализация vector<void *> скорее всего уже есть).

dzidzitop ★★
()
Ответ на: комментарий от r

плюсовая прога грузітся через mmap, а жвм всю эту кашу пережёвывает самостоятельно. Так что некорректно сравнивать в мегабайтах.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

Там речь шла не о самих лямбдах, а о накладных расходах на классы в памяти JVM. На что r стал выяснять, во сколько обходятся шаблоны С++.

Как выяснилось, не так уж и много, как в относительных числах, так и в абсолютных.

5.7MB бинарника даже для смартфона не выглядит много, учитывая, сколько всего в него у меня понапихано. Зато и шашечки, и ехать быстро. А уж батарейка как обрадуется...

Сейчас попробовал у себя отключить RTTI, получил -10% к размеру стрипнутого бинарника в режиме с оптимизациями. Не особо много. В других случаях (бинарники clang?) может быть и заметно больше.

aist1 ★★★
()
Ответ на: комментарий от aist1

Сейчас попробовал у себя отключить RTTI
Не особо много.

Ну если там есть код, то так и будет.

А вот для этого будет очень эффективно: Какое же говнище этот ваш С++ (комментарий)

Хотя компілер мог бы вывесті сам что RTTI для этих типов не используется. Возможно правда, что это медленная операция.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

Ну если там есть код, то так и будет.

Попробую сегодня откомпилировать clang с rtti.

Возможно правда, что это медленная операция.

Вряд ли. С -fno-rrti он выкидывает все метаданные rtti, кроме тех, которые описывают бросаемые исключения. Мог бы еще оставлять и для тех типов, которые берутся по typeid().

aist1 ★★★
()
Ответ на: комментарий от dzidzitop

Проверил сборку clang. RTTI занимает менее 2% от примерно 40MB стрипнутого оптимизированного бинарника clang. Это совсем ничего, я думаю.

В моем случае, при активном использовании шаблонов, получилось 10%. Это заметно больше, но всё равно незначительно. В общем, отключать RTTI имеет смысл только если ну совсем жесткие ограничения по размеру бинарника.

aist1 ★★★
()
Ответ на: комментарий от aist1

Ну так RTTI - это label + helper structures. Выгода от его выключенія только когда есть много классов/інстансов шаблонов по тіпу тех что выдал r. C накладнымі расходамі жавы не сравнімо - кто не відал как она валітся с OutOfMemory: no PermGen size когда выставлено PermGen 128MiB.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

Выгода от его выключенія только когда есть много классов/інстансов шаблонов по тіпу тех что выдал r

Даже когда очень много, как у меня, выгода не особо заметна.

C накладнымі расходамі жавы не сравнімо - кто не відал как она валітся с OutOfMemory: no PermGen size когда выставлено PermGen 128MiB.

Это верно. С другой стороны, на фоне многогигабайтных куч пара сотен мегабайт на код сурово не выглядит, да и ничего не решает :)

aist1 ★★★
()
Ответ на: комментарий от dzidzitop

кто не відал как она валітся с OutOfMemory: no PermGen size когда выставлено PermGen 128MiB.

Есть фрейсворки которые используют классогенерацию на лету. Не надо это выдавать за накладные расходы жабы. А то так и new int[2^59] можно выдать за проблемы си++.

r ★★★★★
()
Ответ на: комментарий от qulinxao

В С++ лямбды практически бесплатные. Потому что они большей частью инлайнятся. RTTI, как мы выяснили, много не ест, да еще и отключается.

aist1 ★★★
()
Ответ на: комментарий от qulinxao

ЦэПэПэшачка кажется даёт іх бесплатно (asm listings не смотрел)

dzidzitop ★★
()
Ответ на: комментарий от r

Есть фрейсворки которые используют классогенерацию на лету. Не надо это выдавать за накладные расходы жабы.

А то созданный в рантайме класс как-то отличается от подгруженного с диска?

aist1 ★★★
()
Ответ на: комментарий от aist1

А то созданный в рантайме класс как-то отличается от подгруженного с диска?

Нет просто коллега запускает всякую фигню а выдает ее за проблемы жабы.

r ★★★★★
()
Ответ на: комментарий от r

Не настолько все в жабе тупо как вам кажется.

:))) Ты не поверишь, всё с точностью до наоборот. В Java (JVM) всё очень умно. Это фантастический софт, который по сложности и объему вложенного в него человеческого гения намного опережает всю индустрию. Что бы там о нем не говорили хейтеры.

Но в этом-то и проблема. За всё приходится платить, и возможности, которые навязываются нам со стороны JVM, даются не бесплатно.

Та же динамическая компиляция. Зачем она нам? Зачем она на десктопе, зачем она на сервере? Чтобы у меня Эклипс вместо секунды запускался 20 секунд? Чтобы JBoss вставал 3 минуты вместо 10 секунд, а потом еще несколько часов «прогревался»?

Зачем всё каждый раз перекомпилировать в памяти, находясь в жесточайших ограничениях реалтайма? Чего ради? Где все эти приложения, которым так необходимо метапрограммирование времени выполнения?

Тут недавно мы с tailgunner сошлись во мнении относительно С++, что его система абстракций плохо сбалансирована и внутренне противоречива. Java в этом смысле (как язык и платформа) намного лучше. Но и у неё есть трудноразрешимые проблемы. В свое время (когда я этим еще активно занимался) остро стоял вопрос, почему Swing такой медленный? Были у него очевидные проблемы с произволительностью нативной части. Но главная проблема была в другом. HotSpot не справлялся с оптимизацией Swing-приложений из-за большого количества мелких методов. Гистограмма была слишком плоской. В результате всё интерпретировалось. Как тогда говорили, swing is over-engineered. Перемудрили с ним, короче. Нестыковка абстракций.

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

Т.е. Java — очень сбалансированный язык, и JVM очень умна. А толку-то, если идеальный в теоретическом смысле код напрочь замусоривает оптимизатор?

На счастье Java всем просто пофиг на эти проблемы. Java дает надежность, за что и ценится. За это люди согласны платить перерасходом ресурсов и относительно низкой производительностью. А где не согласны, там пишут на C и C++.

aist1 ★★★
()
Ответ на: комментарий от kamre

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

aist1 ★★★
()
Последнее исправление: aist1 (всего исправлений: 1)
Ответ на: комментарий от r

это лучше чем anonymous class, но всё равно код не будет инлайниться + это даже не invokevirtual.

Нужно сравнить inlined code vs anonymous class vs lambda (invoke dynamic).

dzidzitop ★★
()
Ответ на: комментарий от r

а если б сделали нормальные указатели на функции, во сообсче было б хорошо.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

но всё равно код не будет инлайниться

точнее может, для for_each какіх-нібудь, вместе с for_each.

dzidzitop ★★
()
Ответ на: комментарий от aist1

А толку-то, если идеальный в теоретическом смысле код напрочь замусоривает оптимизатор?

Эсть. При всех упомянутых недостатках позволяет писать софт который в противном случае за разумное время бы написан не был. И если взять шутаут - не все там так плохо даже по сравнению с плюсами.

r ★★★★★
()
Ответ на: комментарий от dzidzitop

это лучше чем anonymous class, но всё равно код не будет инлайниться

В жабе код инлайнится JITом а не в байткоде.

r ★★★★★
()
Ответ на: комментарий от r

Я знаю. Только большие статические функции не инлайнятся (конфигурируется). или в большие функции другие функции не инлайнятся.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

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

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

aist1 ★★★
()
Ответ на: комментарий от r

При всех упомянутых недостатках позволяет писать софт который в противном случае за разумное время бы написан не был.

Соврешенно верно. Только не всегда.

Да, прототипирование на платформе Java делается намного быстрее, чем на С++. IDE, отладка, профилирование, кратчайший цикл «модификация-исполнение». Рефакторинг и прочие инструменты. И при этом высокая скорость исполнения кода.

По моим наблюдениям, в устоявшемся режиме производительность программиста на С++ и на Java будет примерно одинакова. Однако, в случае С++ этот устоявшийся режим достигается намного дольше. Для долгоживущих проектов это не особо важно.

И если взять шутаут - не все там так плохо даже по сравнению с плюсами.

На шутауте тесты классические: мало кода, много данных. Но разве это до сих пор не понятно, что код давно уже сам стал данными, а данные становятся кодом? И вот в этом режиме, когда кода много и он структурирован совсем не так, как классические алгоритмы, производительность JVM оказывается под вопросом. Справедливости ради, тут под вопросом будет и производительность современных CPU.

Классический код JVM выполняет очень хорошо. Например, говорили, что она очень уверенно чувствовала себя в секторе численных вычислений. До тех пор, пока он на GPGPU не переехал.

aist1 ★★★
()
Ответ на: комментарий от aist1

Чтобы JBoss вставал 3 минуты вместо 10 секунд

ты сначала расскажи что тебе даст 10 секунд вместо 3 минут в данном случае

shty ★★★★★
()
Ответ на: комментарий от aist1

в устоявшемся режиме производительность программиста на С++ и на Java будет примерно одинакова

практика показывает иное, конечно с точностью до области применения

shty ★★★★★
()
Ответ на: комментарий от aist1

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

не скажу за все версии всех компиляторов C++, но обычно inline трактуется как пожелание для компилятора, то есть факт наличия ключевого слова inline не означает что inline на самом деле состоится

shty ★★★★★
()
Последнее исправление: shty (всего исправлений: 1)
Ответ на: комментарий от shty

ты сначала расскажи что тебе даст 10 секунд вместо 3 минут в данном случае

Ускорение разработки, например. Впрочем, не так существенно, чтобы за него держаться.

Важно другое. Огромные усилия вкладываются в поддержание и развитие функционала виртуальной машины, который прямой практической ценности не имеет. За все 17 лет существования Java метапрограммированию времени выполнения так и нашли эффективного применения. И это, вообще говоря, был бы ожидаемый результат, если знать теорию, которая за ним стоит.

Я не против виртуальной машины как таковой. Я просто очень хотел бы в составе платформы видеть оптимизирующий AOT-компилятор.

aist1 ★★★
()
Ответ на: комментарий от shty

не скажу за все версии всех компиляторов C++, но обычно inline трактуется как пожелание для компилятора, то есть факт наличия ключевого слова inline не означает что inline на самом деле состоится

Совершенно верно. Так стандарт говорит. inline означает лишь высказывание пожелания компилятору, и он будет ему следовать. Но, как оказывается, не всегда. И иногда короткие ф-ии не инлайнятся. Однако, ф-ю можно заинлайнить принудительно с помощью атрибутов компилятора.

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

aist1 ★★★
()
Ответ на: комментарий от aist1

Ускорение разработки, например.

ну так jboss - это не developer support tool, jboss - это сервер который умет работать, долго, долго, долго

я вообще в jboss вставлял всё в последний момент

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

вот это, конечно, сильное заявление

За все 17 лет существования Java метапрограммированию времени выполнения так и нашли эффективного применения.

так, и что это значит?

Я просто очень хотел бы в составе платформы видеть оптимизирующий AOT-компилятор.

1) статическая компиляция вполне себе возможна на jvm, так что - напиши, сорцы jvm открыты, или просто подожди - может и запилят
2) вот ты жалуешься чуть выше на startup time, а ведь AOT-компиляция может здорово его увеличивать
3) как мне сделать dynamic optimization profile используя AOT-компиляцию?

и у JIT и у AOT - у каждой есть свои сильные и слабые стороны, и не надо видеть всё хорошее в чём-то одном, а всё плохое в чём-то другом, на самом деле интересно было бы совмещение пруфитов JIT и AOT

shty ★★★★★
()
Ответ на: комментарий от aist1

практика показывает иное

Поделись опытом :)

ускорение работы на порядок (+-), либо подбор менее квалифицированной команды при сохранении производительности

shty ★★★★★
()
Ответ на: комментарий от aist1

За все 17 лет существования Java метапрограммированию времени выполнения так и нашли эффективного применения.

O_O

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

Раскрой тему.

tailgunner ★★★★★
()
Ответ на: комментарий от aist1

Однако, ф-ю можно заинлайнить принудительно с помощью атрибутов компилятора.

понял, ок

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

1) во-первых это просто мелочь, в более или менее крупном проекте скорее всего этот getter вообще не будет видно
2) во-вторых вот, кстати, вопрос - может лучше проанализировать почему так часто getter тягается или проинспектировать getter на предмет - а вдруг там «жыр»? это может дать лучший результат

shty ★★★★★
()
Последнее исправление: shty (всего исправлений: 1)
Ответ на: комментарий от shty

я вообще в jboss вставлял всё в последний момент

hot deployment?

вот это, конечно, сильное заявление

А то! Вызывающее :) Апплеты благополучно забыты, JWS благополучно забыт. Где еще нужен верифицируемый в рантайме байт-код? В барузерах прочно обосновался JavaScript. Вот тут он нужен, безусловно.

так, и что это значит?

Это значит, что на поддержание состояния этой возможности, согласованного с другими возможностями платформы, тратятся значительные усилия. А в итоге мы имеем медленное развитие платформы.

1) статическая компиляция вполне себе возможна на jvm, так что - напиши, сорцы jvm открыты, или просто подожди - может и запилят

Офигенный аргумент. Тебе нужно — пиши сам. Ты не поверишь, но я именно так и делаю. Только не AOT-компилятор для Java. Они, кстати, есть. Это GCJ и Excelsior JET. Либо реализации неудачные, либо сама идея AOT-компиляции для Java себя технически не оправдывает. Т.е. особо ничего не дает, только добавляет сложности.

2) вот ты жалуешься чуть выше на startup time, а ведь AOT-компиляция может здорово его увеличивать

Что ты имеешь в виду? Удлиняется change->compilation->deploy?

как мне сделать dynamic optimization profile используя AOT-компиляцию?

Ну а как она делается в том же gcc? Компилируешь с поддержкой профилирования, выполняешь профилировочные бенчмарки, перекомпилируешь обратно. Вуаля! +40% производительности (у меня).

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

на самом деле интересно было бы совмещение пруфитов JIT и AOT

Совершенно верно! Только в каких пропорциях? Я думаю, 1 к 9 JIT к AOT.

aist1 ★★★
()
Ответ на: комментарий от tailgunner

O_O

Суровая реальность, да. Что из того, что сейчас делается в рантайме, не могло бы делаться на этапе компиляции исходников?

Раскрой тему.

Пожалуйста. Речь идет о теории алгоритмической информации. Она, в частности, изучает вопросы поиска кратчайших программ. Так вот, процедура эта очень дорогостоящая, и хороших алгоритмов для неё нет. А когда они появятся, можно считать, что сильный ИИ сделан. Если хочешь погрузиться в подробности, смотри, например, проблематику генетического программирования.

Иными словами, мы можем генерировать тексты программ по шаблонам. Это просто. Но мы не можем, имея табличное задание функции, получить её короткую программу. Кроме самых простейших случаев. Грубо говоря, мы не можем синтезировать ни пузырьковую сортировку, ни, уж тем более, быструю. Даже ф-я типа strcmp() оказывается нетривиальной задачей.

Вот именно поэтому у нас метапрограммирование шаблонное. Как во время компиляции, так и во время выполнения. Об этом еще говорят так, что метапрограммирование пока что практически не масштабируется за пределы шаблонного.

aist1 ★★★
()
Ответ на: комментарий от shty

ускорение работы на порядок (+-),

Ты в какой системе счисления сейчас находишься? :) (Выделение моё)

aist1 ★★★
()
Последнее исправление: aist1 (всего исправлений: 1)
Ответ на: комментарий от aist1

За все 17 лет существования Java метапрограммированию времени выполнения так и нашли эффективного применения.

O_O

Суровая реальность, да. Что из того, что сейчас делается в рантайме, не могло бы делаться на этапе компиляции исходников?

Суровая реальность в том, что ты путаешь понятия «не используется» и «может быть сделано другим способом».

Речь идет о теории алгоритмической информации [...]

Какие-то наукоподобные умствования.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

ты путаешь понятия «не используется» и «может быть сделано другим способом».

Ничего я не путаю. Я прекрасно знаю возможности динамического кодогенератора и статистического оптимизатора. Их уникальные возможности практически не используются. Делая же шаблонную кодогенерацию в рантайме, мы просто вносим лишнюю избыточность. Зато круто, да. Эзотерично, я бы даже сказал.

Какие-то наукоподобные умствования.

Если не понял, то попроси разъяснить :)

aist1 ★★★
()
Ответ на: комментарий от shty

1) во-первых это просто мелочь, в более или менее крупном проекте скорее всего этот getter вообще не будет видно

Не всегда. Вот была у меня ф-я на С++, возвращающая битовую подстроку заданной длины. Всё над int32/int64. На глаз, очень короткая. При профилировании оказалось, что она не инлайнилась. Я так понял, что из-за контекста. Оптимизатор решил, что не хочет раздувать ф-и, которые её вызывают. Её принудительный инлайнинг сразу дал +50% к производительности.

2) во-вторых вот, кстати, вопрос - может лучше проанализировать почему так часто getter тягается или проинспектировать getter на предмет - а вдруг там «жыр»? это может дать лучший результат

Ну, это всё подразумевается.

Кстати, здесь

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

Только в этом случае повлиять на ситуацию уже нельзя.

я могу оказаться неправ. Точно знаю, что можно отключить JIT для некоторых методов (или даже классов?). Это полезно, если JIT роняет JVM. Может быть, можно таким же образом задать принудительные оптимизации. В любом случае, от сферического программиста все эти вещи скрывают.

aist1 ★★★
()
Ответ на: комментарий от aist1

ты путаешь понятия «не используется» и «может быть сделано другим способом».

Ничего я не путаю.

Значит, специально подтасовываешь.

Я прекрасно знаю возможности динамического кодогенератора и статистического оптимизатора.

Ага, ага. А еще ты знаешь, что динамический кодогенератор не нашел эффективного применения. Хотя... оговорка «эффективного» позволяет тебе отсеять любое применение, которое ты захочешь отсеять.

Какие-то наукоподобные умствования.

Если не понял

Я понял, что описываемая тобой «теория» (если она и в самом деле существует) - это всего лишь одно из применений метапрограммирования. Поэтому не важно, соответствует метапрограммирование в Java этой этой теории или нет.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Хотя... оговорка «эффективного» позволяет тебе отсеять любое применение, которое ты захочешь отсеять.

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

Давай посмотрим, для чего используется динамическая кодогенерация:

1. ORM

2. AOP

3. (что еще?)

В обоих случаях, это всего лишь склейка существующего статического кода. В существующей ситуации, когда виртуальная машина у нас уже есть, делать такую склейку может быть даже и лучше «на горячую». Это всё же несколько упрощает систему. Но городить динамический профилирующий компилятор только ради этого?

Я понял, что описываемая тобой «теория» (если она и в самом деле существует)...

Еще как существует :).

... - это всего лишь одно из применений метапрограммирования

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

aist1 ★★★
()
Ответ на: комментарий от mix_mix

дибилам вроде тебя до сих пор не понятно, что C++ это лучшее что сейчас есть, просто по тому, что у вас нет мозга

golodranez ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.