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)

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

Да я же не спорю :)

Но я тебе скажу, что по сравнению с остальными накладными расходами, диктуемыми моделью памяти Java, эти анонимные классы — капля в море.

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

122 Remove the Permanent Generation

Remove the permanent generation from the Hotspot JVM and thus the need to tune the size of the permanent generation.

Ты думаешь, что если они уберут PermGen как отдельно управляемую кучу, что-то изменится с накладными расходами на представление классов?

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

главная проблема этого на 64бітах - даже не memory overhead, а bootstrap time. Потому что каждый файл нужно найти в jars, достать, верифицировать, залинковать.

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

Кстаті, лямбды на говняном C++ - тру. Потому что бесплатные.

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

главная проблема этого на 64бітах - даже не memory overhead, а bootstrap time

кстати да. собирать всё из мелких кусочков - не подарок.

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

Ты думаешь, что если они уберут PermGen как отдельно управляемую кучу, что-то изменится с накладными расходами на представление классов?

Во всех других прочих языках классы представляются как-то по другому? Если на то пошло c++ обложенный бустами и stlами вообще генерирует такие семейства что мама не горюй.

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

Совершенно верно! У меня процесс компилятора на моем проекте иногда распухает до 2ГБ. Только в рантайм это всё не пойдет. В рантайме останутся считанные мегабайты бинарника.

JVM для каждого класса хранит много метаданных + статистика HotSpot. Но даже всё это не особо много, если весь код статический и метапрограммированием не увлекаться. А вот если увлекаться, то может подкрасться ой. Без PermGen он будет красться просто немного дольше.

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

В рантайме останутся считанные мегабайты бинарника.

template<typename W>
class R {
        W w;
    public:
        R(W _w): w(_w){}
};

int main() {
    R<int> ri(1);
    R<float> rf(1.1);

    return 0;
}

Каждая новая строчка +80 байт.

JVM для каждого класса хранит много метаданных

Сколько - много?

А вот если увлекаться, то может подкрасться ой.

С чего это он будет крастся? Оно никуда не растет. Его должно быть достаточно.

Без PermGen он будет красться просто немного дольше.

Без permgen оно будет GCшица.

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

Каждая новая строчка +80 байт.

Не мог бы ты объяснить, как ты это число получил?

Сколько - много?

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

С чего это он будет крастся? Оно никуда не растет. Его должно быть достаточно.

Она растет быстрее, чем кажется, если BCI субоптимален.

Без permgen оно будет GCшица.

А в PermGen выгрузки классов разве не было? Не уверен на 100%, но вроде бы эта опция проблему решает -XX:+CMSClassUnloadingEnabled при условии использования CMS.

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

Не мог бы ты объяснить, как ты это число получил?

Добавлял строчку и компилял.

                 w _Jv_RegisterClasses
00000000004005b8 W _ZN1RIPcEC1ES0_
00000000004005b8 W _ZN1RIPcEC2ES0_
00000000004005a0 W _ZN1RIfEC1Ef
00000000004005a0 W _ZN1RIfEC2Ef
000000000040058a W _ZN1RIiEC1Ei
000000000040058a W _ZN1RIiEC2Ei

На каждую декларацию по паре символов.

Че генерит вот это - можешь себе представить.

#include<vector>

int main() {
    std::vector<int> v1;
    std::vector<float> v2;

        return 0;
}

Разница между одной строчкой и двумя - 5.5k.

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

На каждую декларацию по паре символов.
Че генерит вот это - можешь себе представить.

Щас разберусь, псб.

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

Не уверен на 100%, но вроде бы эта опция проблему решает

Это вообще интересно только для динамической конструкции классов на лету. Я пока знаю всего 2 «проги» которым не хватало стандартного permgen - его увеличивали в IDEA и для всей скальной либы.

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

Это вообще интересно только для динамической конструкции классов на лету.

А кто её сейчас не использует? Куда ни кинь, везде AOP. Интерцепторы, понимаешь.

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

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

А кто её сейчас не использует?

Статические языки:))

Куда ни кинь, везде AOP.

Это половые проблемы всяких спрингов. Они нам не интересны.

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

Они нам не интересны.

Да, помню. Хибернейт вы не используете, серверами приложений не пользуетесь :)

Короче, другим эти проблемы интересны :)

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

Хибернейт вы не используете

«Я про него слишком много знаю» (C)...

В свое время писал один коннектор к экзотическому SQL хранилищу.

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

Да посто вот сюда достаточно глянуть (это для одной строки) чтобы видеть где собака порылась.

                 w _Jv_RegisterClasses
                 U _Unwind_Resume@@GCC_3.0
0000000000400916 W _ZN9__gnu_cxx13new_allocatorIiE10deallocateEPim
0000000000400946 W _ZN9__gnu_cxx13new_allocatorIiEC1Ev
0000000000400946 W _ZN9__gnu_cxx13new_allocatorIiEC2Ev
000000000040090c W _ZN9__gnu_cxx13new_allocatorIiED1Ev
000000000040090c W _ZN9__gnu_cxx13new_allocatorIiED2Ev
00000000004008f2 W _ZNSaIiEC1Ev
00000000004008f2 W _ZNSaIiEC2Ev
000000000040087e W _ZNSaIiED1Ev
000000000040087e W _ZNSaIiED2Ev
0000000000400938 W _ZNSt12_Destroy_auxILb1EE9__destroyIPiEEvT_S3_
0000000000400840 W _ZNSt12_Vector_baseIiSaIiEE12_Vector_implC1Ev
0000000000400840 W _ZNSt12_Vector_baseIiSaIiEE12_Vector_implC2Ev
0000000000400762 W _ZNSt12_Vector_baseIiSaIiEE12_Vector_implD1Ev
0000000000400762 W _ZNSt12_Vector_baseIiSaIiEE12_Vector_implD2Ev
0000000000400898 W _ZNSt12_Vector_baseIiSaIiEE13_M_deallocateEPim
0000000000400808 W _ZNSt12_Vector_baseIiSaIiEE19_M_get_Tp_allocatorEv
000000000040077c W _ZNSt12_Vector_baseIiSaIiEEC1Ev
000000000040077c W _ZNSt12_Vector_baseIiSaIiEEC2Ev
0000000000400796 W _ZNSt12_Vector_baseIiSaIiEED1Ev
0000000000400796 W _ZNSt12_Vector_baseIiSaIiEED2Ev
00000000004006e4 W _ZNSt6vectorIiSaIiEEC1Ev
00000000004006e4 W _ZNSt6vectorIiSaIiEEC2Ev
00000000004006fe W _ZNSt6vectorIiSaIiEED1Ev
00000000004006fe W _ZNSt6vectorIiSaIiEED2Ev
00000000004008cc W _ZSt8_DestroyIPiEvT_S1_
0000000000400816 W _ZSt8_DestroyIPiiEvT_S1_RSaIT0_E
                 U _ZdlPv@@GLIBCXX_3.4

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

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

Далее, если ты будешь компилировать с -O2, то у тебя большая часть кода будет выоптимизирована и останется совсем ничего.

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

«Я про него слишком много знаю» (C)...

Да я ж не в претензии. :)

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

стрип не спасает - он только элиминейтит символы. Как я уже написал стрип разицу между двумя строчками и одной сводит с 5k до 4k.

-O2 генерирует файлы которые отличаются так же.

ll v*O2.out

12845 Sep 24 23:06 v1O2.out
17117 Sep 24 23:06 v2O2.out

С символами просто удобно смотреть «почему».

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

Не всё так просто :) FC 19, gcc 4.8.1

g++ дефолт

14369 vec1
15904 vec2

strip vec1 vec2

10432 vec1
10432 vec2

числа близкие к твоим.

-O2 в данном крохотном примере должен всё выоптимизировать нафиг. Не наглядно.

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

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

-O2 в данном крохотном примере должен всё выоптимизировать нафиг.

:) естественно:)

#include<vector>
#include<iostream>

int main() {
    std::vector<int> v1;
    v1[0] = 1;
    std::vector<float> v2;
    v2[0] = 1.1;
    std::cout << v1[0] << std::endl;
    std::cout << v2[0] << std::endl;
        return 0;
}

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

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

Так вопрос то в том сколько шаблоны порождают кода. Как ты это покажешь на несинтетическом проекте?

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

Так вопрос то в том сколько шаблоны порождают кода. Как ты это покажешь на несинтетическом проекте?

Важно то, сколько оптимизатор реально уберет. Это лучше всего смотреть на несинтетическом проекте :)

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

Что значит сколько? Сколько надо столько и порождают. Сравнивать наверно надо шаблонную и нешаблонную реализацию, а не 2 инстанса шаблона.

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

Важно то, сколько оптимизатор реально уберет. Это лучше всего смотреть на несинтетическом проекте :)

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

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

Сравнивать наверно надо шаблонную и нешаблонную реализацию, а не 2 инстанса шаблона.

Нет. Мы говорили о синтетике - вроде анонимных классов для ламбд в жабе. Вот в жабе на генерики ничего не порождается. А в плюсах порождается синтетика не хуже жабских лямбд на шаблоны. «Особенности реализации» (TM)

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

Какое это имеет значение?

Большое. Очень много кода оптимизатором просто инлайнится, не создавая никаких символов.

Вот пример результата компиляции моих тестов структур данных. Без оптимизации и с оптимизацией.

clang++ -g

36636953 tests
13516024 tests-strip

clang++ -g -O3

36576352 tests
 5794904 tests-strip

Там под сотню тяжелых тестов. Многие структуры данных по сложности сопоставимы с raiserfs, а их таких несколько инстансов. Это тебе не легковесный std::vector<>. Там полноценное мультиарное сбалансированное дерево, создаваемое системой метапрограммирования.

В итоге всего 5.5 мегабайт стрипнутого оптимизированного кода. Не ахти сколько. Символы занимают 30 мегабайт. Внезапно, в режиме без оптимизаций символы занимают немного больше: 36-13 = 23 MB. Т.е. с оптимизациями символов получилось больше. Код после оптимизации меньше примерно в 2.5 раза. С gcc ситуация аналогичная. Не надо смотреть на отладочные символы, они в память не грузятся.

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

Нет. Мы говорили о синтетике - вроде анонимных классов для ламбд в жабе. Вот в жабе на генерики ничего не порождается. А в плюсах порождается синтетика не хуже жабских лямбд на шаблоны. «Особенности реализации» (TM)

Не-не-не :) Мы говорили о том, что именно порождается в джаве на анонимные классы. Довольно много информации (код + метаданные + статистика), которая вся висит в рантайме до тех пор, пока класс не выгрузят.

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

Могу тебе привести данные по размеру символов llvm/clang. Ты офигеешь. А там классический С++ и шаблонов совсем по минимуму. И ничего, в продакшне все живы, все довольны.

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

В итоге всего 5.5 мегабайт стрипнутого оптимизированного кода

Вся либа скалы 7мб нестрипнутая и неоптимизирвоанная:)

Символы занимают 30 мегабайт.

Я ж сравниваю не сколько символы весят. А разницу. Разница между стрипнутым кодом для вектора с одной строкой и с двумя - 4кб.

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

Но только машинного кода. Занимающего, как оказывается, не так уж много места.

Одна строка добавила 4кб стрипнутого кода:)

И ничего, в продакшне все живы, все довольны.

На скале с ее кучей анонимов пишут приложения под андроид. Тоже нормально.

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

Вся либа скалы 7мб нестрипнутая и неоптимизирвоанная:)

машинного кода?)

Разница между стрипнутым кодом для вектора с одной строкой и с двумя - 4кб.

Если уж ты так хочешь сравнить вектор, то сравнивай на уровне ассемблерных листингов. Заметил, что в моем случае разницы в стрипнутом коде между бинарниками не было?

На таком крохотном примере надо еще смотреть, что там линковшик вставил.

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

Это не делает его говном с рождения?

Говном для чего?

php-то? для всего - для веба в том числе.

Для клепания вебстраничек малограмотныеми кодерами - идеально

Нет, идеально это нормальные веб-фреймворки на высокоуровневых языках, а не php-шаблонизатор.

Вон некоторые фейсбук наклепали

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

На жабе пишут охрененно сложные системы весьма квалифицированные люди

Кто спорит?

Покажи мне замену - на чем их писать для этих людей (в те времена - ~2000-2005)?

При определенных требованиях - ящитаю джава где-то с конца 90х по ~2005 как раз была не особо заменима чем-либо. Это не означает, что на ее месте не мог оказаться какой-то сильно более вменяемый язык еще в середине 90х.

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

< 1. Почему твой фрешмит не занялся ++?

Очевидно, потому что уже дофига всего написано на джаве и джава это платформа с развитой инфраструктурой.

На PHP кроме одних самоубийц больших систем не разрабатывают

Ну, ты ж фейсбук сам в пример привел.

Но таки да - пыхпых выполняет вполне успешно задачу в своей области

У него нет никакой области после появления например RoR, т.е. вообще никакой. Только легаси-cms для бложиков строителей в пхп4-безооп-стайл. Ты же в курсе что в пыхе и ооп-то не было долгое время? :)

Что рождал в это время микроссофт - унылый MFC? DCOM? Борланд родил VCL и все? Qt до сих пор архитектурно слабое подобие свинга?

Мы вообще говорили не о том, что вокруг был один треш, а о том что конкретно джава как язык это кал.

Сравни свою студию например JBuilder+RefactorIt или Together Control Center. До жавосвских IDE никому и в голову такое слово как рефакторинг (содранный из смолтолковских) aka автоматические преобразования кода в голову не приходило. Что там студия умела - унылый сенс? Все?

Ну, интелисенс унылым там не был, рефакторинг да - всегда решался каким-то сторонними средствами (и до сих пор вроде так).

Относительно остального - это какая-то демагогия пошла на тему того, что джава лучше плюсов для интерпрайза в огромно большом количестве случаев (как-будто с этим кто-то спорил). Мое утверждение - что джава как язык был овном с рождения, а не то что надо было назад в пещеры и в С++.

Если скалу сбалансируют нормально по фичам - возможно это будет новая, правильная джава. На что я очень надеюсь.

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

А в плюсах порождается синтетика не хуже жабских лямбд на шаблоны

зато в плюсах можно отсортировать массив int'ов в обратном порядке с помощью шаблона ;)

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

Map<Class<?>, Map<String, List<String>>> compressDependencies(
Map<Class<?>, Map<String, List<String>>> dependencies


У меня одного ощущение, что с дизайном то ли сигнатуры, толи генериков что-то явно не того и что лучше пихать в Object, чем глазами парсить это?

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

У тебя одного:)

Типо который дизайнил это апи наверное пришел из перла.

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

зато в плюсах можно отсортировать массив int'ов в обратном порядке с помощью шаблона ;)

Зато это никому не нужно.

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

Это никому не нужно на стадии компиляции.

а причем тут стадия компиляции? людям надо в рантайме - Java не может

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

где ты взял 4к? у меня с дефолтом без стрипа 900 байт. 4.4 64 бита.

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