Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];

Вниз

Объясните пожалуйста дельфисту, что такое шаблоны в Си?   Найти похожие ветки 

 
Циркуль   (2007-11-01 01:57) [0]

И что надо отвечать на нападки агрессивных сишников?


 
umbra ©   (2007-11-01 01:59) [1]

отвечать надо одним словом - "отстой" :)


 
Германн ©   (2007-11-01 02:08) [2]


> И что надо отвечать на нападки агрессивных сишников?

Отвечать надо "Вас здесь не стояло". Ну или по Паниковскому с Балагановым - "А ты кто такой?" с толчком в грудь :)


 
Ega23 ©   (2007-11-01 09:08) [3]

Изучить Си, понять, в чём он хуже, а в чём лучше того же Delphi, и потом филосовски пожимать плечами и говорить: профессионалу всё равно на чём писать.


 
Думкин ©   (2007-11-01 09:13) [4]

> профессионалу всё равно на чём писать.

Это не так немного. :)


 
wendy parkinson   (2007-11-01 09:21) [5]

>И что надо отвечать на нападки агрессивных сишников?

"О, милостливый государь, я раскаиваюсь в том, что был привержен все эти годы
упадочническому культу Дельфи. Я вижу мощь C++ и, находясь в здравом уме и твердой памяти, признаю, что программист познавший C++ никогда больше не возьмется за Дельфи. Преклоняюсь пред вами и падаю ниц, да хранит вас Господь."


 
Однокамушкин   (2007-11-01 09:32) [6]

Начнём с того, что в С шаблонов вообще нет, они есть в С++

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

Шаблоны считаются устаревшим небезопасным средством, в новых языках вместо них принято делать обобщения (generics), которые по сути то же самое, но менее гибкие и потому более безопасные... В Delphi обобщения тоже давно обещают, по крайней мере, в .NET 2 - версии, потому что там они средой поддерживаются


 
Anatoly Podgoretsky ©   (2007-11-01 09:35) [7]

> Ega23  (01.11.2007 09:08:03)  [3]

> говорить: профессионалу всё равно на чём писать.

А раз все равно, то писать будет на одном языке.


 
guav ©   (2007-11-01 09:36) [8]

http://yosefk.com/c++fqa/templates.html


 
wendy parkinson   (2007-11-01 09:49) [9]

Однокамушкин   (01.11.07 09:32) [6]


> Шаблоны считаются устаревшим небезопасным средством, в новых
> языках вместо них принято делать обобщения (generics), которые
> по сути то же самое, но менее гибкие и потому более безопасные.
> ..


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

http://www.codeproject.com/cpp/crc_meta.asp

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


 
DrPass ©   (2007-11-01 11:18) [10]


> Да, но эти самые устаревшие и небезопасные шаблоны, которые
> по сути являются макросами, позволяют осуществлять метапрограммирование
> посредством себя

А зачем в коде, предназначенном для чтения и дальнейшей поддержки живыми людьми, делать "метапрограммирование посредством шаблонов"?


 
wendy parkinson   (2007-11-01 11:23) [11]

DrPass ©   (01.11.07 11:18) [10]

Статью читали?

A while ago I was working on a program that used a large lookup table to do some computations. The contents of the table depended on a large number of parameters that I had to tweak to get optimal performance from my code. And every time I changed one parameter the whole table had to be recalculated...

I had written a function that dumped the content of the table to standard output. That way I could compile my program with the new parameters set, cut-and-paste the table from screen and into my source code and finally recompile the whole project. I didn"t mind doing that - the first twenty times. After that I figured there had to be a better way. There was. Enter Template Metaprogramming.


 
Игорь Шевченко ©   (2007-11-01 11:26) [12]

А в C нету шаблонов


 
DrPass ©   (2007-11-01 11:35) [13]


> wendy parkinson   (01.11.07 11:23) [11]
> DrPass ©   (01.11.07 11:18) [10]
>
> Статью читали?

Ага. Согласись, что ЭТО
template< int i >
class LOOP{
 public:
   static inline void EXEC(){
     cout << "A-" << i << " ";
           LOOP< i-1 >::EXEC();
      cout << "B-" << i << " ";
   }
};
class LOOP< 0 >{
 public:
   static inline void EXEC(){
     cout << "A-" << i;
     cout << "\n";
      cout << "B-" << i;
   }
};


...не имеет права быть в программе вместо этого
int sum = 0;
for (int i = 1 ; i <= 1000; i++)
    sum += i;


Пусть даже и разворачивается в более быстрый линейный код (хотя неизвестно, что лучше - три ассемблерные инструкции цикла или тысяча линейных инкрементов).


 
wendy parkinson   (2007-11-01 11:48) [14]

DrPass ©   (01.11.07 11:35) [13]

Программы вообще не нужны. А программирование суть зло.


 
DrPass ©   (2007-11-01 12:44) [15]


> wendy parkinson   (01.11.07 11:48) [14]

Да, а С++ные программисты пьют кровь убиенных христианских младенцев


 
clickmaker ©   (2007-11-01 12:49) [16]


> что надо отвечать на нападки агрессивных сишников?

хук в бубен


 
wicked ©   (2007-11-01 12:55) [17]

> DrPass ©   (01.11.07 11:35) [13]
имеет, поскольку развернется не в линейные инструкции, а в одну константу
вообще, суть метапрограммирования с темплатами - порождать необходимый код на стадии компиляции, а также вынести константные вычисления из стадии выполнения в стадию компиляции


 
Mystic ©   (2007-11-01 12:57) [18]

Говорить, что аналог шаблонов есть в Ada ;)


 
DiamondShark ©   (2007-11-01 12:58) [19]


> Объясните пожалуйста дельфисту, что такое шаблоны в Си?

Седло для коровы.


> И что надо отвечать на нападки агрессивных сишников?

Посылать далеко и нецензурно.


 
Alkid ©   (2007-11-01 13:28) [20]


> Шаблоны считаются устаревшим небезопасным средством, в новых
> языках вместо них принято делать обобщения (generics), которые
> по сути то же самое, но менее гибкие и потому более безопасные.
> .. В Delphi обобщения тоже давно обещают, по крайней мере,
>  в .NET 2 - версии, потому что там они средой поддерживаются

Это чем же шалоны небезопасны? Очень интересно, жду ответа.

Вообще же, дженерики - это весьма размытый термин, ибо они есть и в Java и в .NET 2, но имеют разную природу. В Java это чисто compile-time вещь, по сути аналогичная шаблонам в С++, а в .NET 2 это Run-Time механизм, поддержаный в платформе.

Кстати, небольшой нюанс: под .NET 2 можно писать используюя и шаблоны и дженерики. Это можно сделать при помощи MC++ и С++/CLI.

В Дельфи шаблонов сильно не хватает. Там хотя бы дженерики сильно бы пригодились.

Что касается метапрограммирования на шаблонах, то как некий state-of-art программисткого умения и концепт, показывающий безграничность нашей мысли, это очень хорошо, а в промышленной практике - это плохо. По сути это есть попытка нецелевым способом использовать шаблоны для того, что бы моделировать такие стредства, как макросы (не Сишные, а в стиле LISP и Nemerle) и "нормальное" метапрограммирование.

Как и все попытки моделировать на уровне библиотечного кода те вещи, которые должны быть поддержаны на уровне языка или платформы (такие как Reflection, автоматическая сборка мусора, метапрограммирование и т.п.) этот подход имеет кучу минусов: нечитаемый переусложнённый код, в котором легко сделать ошибку, который серъёзно повышает требования к подготовке программиста. Кроме того, код становится более требователен к качеству реализации стандарта компилятором и дольше собирается.

В С++ скорось сборки это вообще проблема. У нас на работе и без особого метапрограммирования один модуль может собираться по 1.5-2 часа. А всё из-за одного перца, который реализовал парочку своих state-of-art идей.

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


 
clickmaker ©   (2007-11-01 13:30) [21]


> Это чем же шалоны небезопасны?

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


 
Alkid ©   (2007-11-01 13:35) [22]


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

Точнее, если хочется впарить что-то, что должно вытеснить соль с рынка :)


 
wendy parkinson   (2007-11-01 13:38) [23]

Alkid ©   (01.11.07 13:28) [20]


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


Но делает C++ однозначно лучше среди языков своего класса.


 
homm ©   (2007-11-01 13:43) [24]

> Объясните пожалуйста дельфисту, что такое шаблоны в Си?

В Си нет шаблонов, afaik.


 
Alkid ©   (2007-11-01 13:46) [25]


> Но делает C++ однозначно лучше среди языков своего класса.

А какие ещё языки входят в этот класс?
Это я к тому, что достоинства языка складываются из многих его свойств, а не только из начилия/отсутствия шаблонов :)


 
DiamondShark ©   (2007-11-01 13:51) [26]


> В Дельфи шаблонов сильно не хватает.

О, да. Дельфист без шаблонов -- всё равно что рыба без велосипеда.


 
Alkid ©   (2007-11-01 13:58) [27]


> О, да. Дельфист без шаблонов -- всё равно что рыба без велосипеда.

Сарказм не по делу. Основное назначение шаблонов - создание типобезопасноых контейнеров.
Сейчас, если у меня есть класс TMyClass, и я хочу сделать для него контейнер, то у меня есть 2 пути:
1. Использовть TObjectList и каждый раз заниматься небезопасными конверсиями типов.
2. Писать самому свой контейнер.

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

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


 
clickmaker ©   (2007-11-01 13:59) [28]


> если хочется впарить что-то, что должно вытеснить соль с
> рынка

да
в умелых руках, как известно, и топор - балалайка
а тому, у кого руки под х.. заточены, тому никакие шаблоны не помогут )


 
vpbar ©   (2007-11-01 14:05) [29]

Alkid ©   (01.11.07 13:58) [27]
Для таких случаев можно симулировать :)
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=744 и ww.delphikingdom.com/asp/viewitem.asp?catalogid=453 есть статья получше. Но ссылку не помню.


 
DiamondShark ©   (2007-11-01 14:07) [30]

Я знал, что мне опять расскажут байку про контейнеры.


 
Alkid ©   (2007-11-01 14:18) [31]


> Я знал, что мне опять расскажут байку про контейнеры.

Я примерно 5 лет программировал на дельфи на прошлой работе. За это время я бессчётное количество раз реализовывал разного рода контейнеры, пока не открыл способ, описанный в [29]. На этом я потерял столько времени и наделал столько ошибок, переписывая в n+1-ый раз методы GetCount, GetItem, Add, Remove и Clear, что могу тебе авторитетно заявить - про контейнеры, это не байки, а суровая правда жизни.


> vpbar ©   (01.11.07 14:05) [29]

Да, я этот медод знаю и использовал. :)


 
Palladin ©   (2007-11-01 14:23) [32]


> Но делает C++ однозначно лучше среди языков своего класса.

а что за класс языков то?


 
wendy parkinson   (2007-11-01 14:31) [33]

Palladin ©   (01.11.07 14:23) [32]

>а что за класс языков то?\

general purpose strongly typed languages


 
DiamondShark ©   (2007-11-01 14:35) [34]


> Alkid ©   (01.11.07 14:18) [31]

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

Зато я прекрасно помню проект на позапрошлой работе, который мне достался в наследство от предыдущего сотрудника -- весьма креативного юноши, у которого ещё не прошёл ребячий восторг от возможности написать vector<CMyObject>. Проект долго переходил из рук в руки, вызывая рак мозгов у всех, пытавшихся разобраться в нагромождении шаблонов юного вундеркинда.

После этого я повесил в красном углу икону преподобного Вирта и возжёг пред ней лампаду.


 
Alkid ©   (2007-11-01 14:44) [35]


> Я примерно 12 лет программировал на дельфи, не помню, сколько
> раз я реализовывал разного рода контейнеры. Наверное, потому
> не помню, что это не было не только сколь-нибудь трудным
> делом, но и сколь-нибудь значимым, по сравнению со всем
> остальным делом.

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

Что касается креативного юноши - я уже сказал, что шаблонами надо уметь пользоваться, и как и любое языковое средство их можно употребить во вред. Неумелое (или же "креативное") пользование указателями и динамическим распределением памяти может превратить работу с программой в ад. Является ли это поводом отказаться от них? Я думаю, что нет.

Принципиальны отказ от шаблонов тут так же излишне категоричен, как и их "креативное" использование в стиле boost.


 
wendy parkinson   (2007-11-01 14:44) [36]

DiamondShark ©   (01.11.07 14:35) [34]

А от такого бы на месте застрелился?

vector<shared_ptr<map<string, stirng> > >


 
Alkid ©   (2007-11-01 14:46) [37]


> general purpose strongly typed languages

Очень широкий класс языков получается.
В любом случае, если свободно выбирать из них на чём стартовать новый проект, то у меня выбор будет скорее всего в пользу C#, а не С++, хоть дженерики С# мне нравятся меньше, чем шаблоны в С++. А всё потому, что у С++ есть куча других недостатков, которые не компенсируются наличием шаблонов.


 
clickmaker ©   (2007-11-01 14:46) [38]


> Принципиальны отказ от шаблонов тут так же излишне категоричен,
> как и их "креативное" использование в стиле boost.

короче, любая ветка в стиле "холивор" сводится к тому, что "любой овощ должен быть употреблен в надлежащее время..." или как там говорил незабвенный Козьма Прутков...
:)


 
wendy parkinson   (2007-11-01 14:47) [39]

Alkid ©   (01.11.07 14:46) [37]

Но у C# тоже есть один большой недостаток. 20 мегабайтный :)


 
homm ©   (2007-11-01 14:48) [40]

> [39] wendy parkinson   (01.11.07 14:47)
> Но у C# тоже есть один большой недостаток. 20 мегабайтный :)

В версии 3.0 уже 35 вроде. И все больше и больше…


 
Alkid ©   (2007-11-01 14:50) [41]


> Но у C# тоже есть один большой недостаток. 20 мегабайтный
> :)

Видишь ли, это сейчас для всего, кроме embedded систем и мобильный платформ, на которых я ни разу не специализируюсь, уже ОЧЕНЬ МАЛЕНЬКИЙ недостаток. Даже если учесть распухание framework`а, этот недостаток остаётся маленьким.

Зато программировать на С# быстрее и приятнее. :)


 
Alkid ©   (2007-11-01 14:52) [42]


> короче, любая ветка в стиле "холивор" сводится к тому, что
> "любой овощ должен быть употреблен в надлежащее время...
> " или как там говорил незабвенный Козьма Прутков...
> :)

А ты думал я тут буду глотку рвать, в стиле "don"t underestimate power of the Dark Side, son"? :)
Кстати, Ega23 ещё в самом начале ветки высказался в том же духе :)


 
Anatoly Podgoretsky ©   (2007-11-01 14:55) [43]

> Alkid  (01.11.2007 14:44:35)  [35]

> По сравнению с остальным делом - не трудное. Но это примерно как заворачивать винты отвёрткой, когда есть электический шуруповёрт. Можно, но удобнее с шуруповёртом.

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


 
Anatoly Podgoretsky ©   (2007-11-01 14:57) [44]


> general purpose strongly typed languages

Ой не надо к этому с++ приписывать.


 
Alkid ©   (2007-11-01 14:57) [45]


> Руки бы оторвал, кому то приходится и откручивать их, например
> винчестеры и народный инструмент - зубило не применишь.

Значит пользовались шуруповёртами не той системы :)
У нас всё ок - админы с ними ходят, а мы, если что, отвёртками свои компы развиничаем :-)


 
homm ©   (2007-11-01 14:57) [46]

> [41] Alkid ©   (01.11.07 14:50)
> Видишь ли, это сейчас для всего, кроме embedded систем и
> мобильный платформ, на которых я ни разу не специализируюсь,
> уже ОЧЕНЬ МАЛЕНЬКИЙ недостаток.

Ага, уже любой пенсионер на свою пенсию и из любой деревни может выкачать из инета 30 метров. ;)


> [41] Alkid ©   (01.11.07 14:50)
> Зато программировать на С# быстрее и приятнее. :)

Зато программы уродские и тормозные получаются. Парадоксс.


 
Anatoly Podgoretsky ©   (2007-11-01 14:58) [47]

> wendy parkinson  (01.11.2007 14:47:39)  [39]

У тебя проблемы с винчестером, купи побольше.


 
Alkid ©   (2007-11-01 15:00) [48]


> Ага, уже любой пенсионер на свою пенсию и из любой деревни
> может выкачать из инета 30 метров. ;)

А у большинства пенсионеров в деревне вообще компов нет. Что, заря программисты вообще существуют?


> Зато программы уродские и тормозные получаются. Парадоксс.

Это из разряда "мне друг напел"? :)
Грамотно спроектированные решения на C# и выглядят красиво и по скорости исполнения обходят нативный С++ код на вычислительных задачах.


 
homm ©   (2007-11-01 15:04) [49]

> [48] Alkid ©   (01.11.07 15:00)
> и по скорости исполнения обходят нативный С++ код на вычислительных задачах.

Бла-бла-бла.


 
homm ©   (2007-11-01 15:05) [50]

Грамотно спроектированные решения на C# в виде пустой формы стартуют на Селероне500 с 128мб памяти 30 секунд. Куда уж там нативному коду…


 
DrPass ©   (2007-11-01 15:08) [51]


> Грамотно спроектированные решения на C# и выглядят красиво
> и по скорости исполнения обходят нативный С++ код на вычислительных
> задачах

Только следует уточнить - нативный С++ код, написанный дятлом


 
Anatoly Podgoretsky ©   (2007-11-01 15:13) [52]

> Alkid  (01.11.2007 14:57:45)  [45]

Наверно для того и ходят, что бы не развинчивали.


 
Anatoly Podgoretsky ©   (2007-11-01 15:14) [53]

> homm  (01.11.2007 14:57:46)  [46]

Посмотри тесты быстродействия на RSDN и удивись.


 
Alkid ©   (2007-11-01 15:15) [54]


> Бла-бла-бла.

Потрясающий по аргументированности ответ, однако :)
Постараюсь быть более аргументированным:
http://www.grimes.demon.co.uk/dotnet/man_unman.htm


 
Alkid ©   (2007-11-01 15:17) [55]


> Наверно для того и ходят, что бы не развинчивали.

Ну, столь глубоких мотивов выяснить не могу :)


 
Palladin ©   (2007-11-01 15:27) [56]


> wendy parkinson   (01.11.07 14:31) [33]

хм... Наличие виртуальных конструкоторов и VCL делает Delphi однозначно лучше среди языков своего класса


 
Alkid ©   (2007-11-01 15:32) [57]


> хм... Наличие виртуальных конструкоторов и VCL делает Delphi
> однозначно лучше среди языков своего класса

VCL - это библиотека, она к языку не очень относится. А вот виртуальные конструкторы - это 5!


 
homm ©   (2007-11-01 15:35) [58]

> [54] Alkid ©   (01.11.07 15:15)
> Постараюсь быть более аргументированным:
> http://www.grimes.demon.co.uk/dotnet/man_unman.htm

Ну и? Смотрим на столбец Optimized For Speed, и видим что результат в пределах погрешности. Смотрим на количество съеденой опреативы этими процессами, и сразу видим аутсайдера.


 
Palladin ©   (2007-11-01 15:38) [59]


> Alkid ©   (01.11.07 15:32) [57]

это я приплел, что бы MFC"ой не хвастались...


 
Alkid ©   (2007-11-01 15:41) [60]


> Ну и? Смотрим на столбец Optimized For Speed, и видим что
> результат в пределах погрешности. Смотрим на количество
> съеденой опреативы этими процессами, и сразу видим аутсайдера.

Ну, строго говря разница там примерно на прядок больше статистической погрешности :) А про количество съеденной памяти там вообще речи нет, и я про неё не говорил :)

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

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


 
Alkid ©   (2007-11-01 15:43) [61]


> это я приплел, что бы MFC"ой не хвастались...

MFC-ой хватались?! :) Не смеши меня. Такого монстра, как MFC я давно не видел. ИМХО одна из весьма неудачных классовых бибилиотек.

С другой стороны, если "говорим Делфьи, подразумеваем VCL", то в С++ такого нет. Хорошо это или плохо, но для С++ есть куча конкурирующих библиотек разного назначения.


 
homm ©   (2007-11-01 15:45) [62]

> [60] Alkid ©   (01.11.07 15:41)
> Но хочу показать, что утвержденияо "тормознутости" .NET
> как правило голословны.

Ага? [50]


 
homm ©   (2007-11-01 15:46) [63]

> [61] Alkid ©   (01.11.07 15:43)
> С другой стороны, если "говорим Делфьи, подразумеваем VCL",

Кто как.


 
homm ©   (2007-11-01 15:49) [64]

> [60] Alkid ©   (01.11.07 15:41)
> Ну, строго говря разница там примерно на прядок больше статистической
> погрешности :)

Ты меня не заставишь поверить в то, что в виндовс статистическая погрешность может быть меньше хотя-бы 10мс.


 
Alkid ©   (2007-11-01 15:52) [65]


> Ага? [50]

И что из этого следует? Ты сам понимаешь, что этот пример показывает нам, что .NET Run-Time инициализируется медленее, чем Run-Time нативных приложений, но это ничего не говорит о скорости выполенния самих программ.


 
Alkid ©   (2007-11-01 15:57) [66]


> Ты меня не заставишь поверить в то, что в виндовс статистическая
> погрешность может быть меньше хотя-бы 10мс.

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


 
homm ©   (2007-11-01 15:57) [67]

> [65] Alkid ©   (01.11.07 15:52)
> но это ничего не говорит о скорости выполенния самих программ.

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


 
umbra ©   (2007-11-01 15:59) [68]


> это ничего не говорит о скорости выполенния самих программ.

так выполняется же в любом случае нативной код, хоть в .NET, хоть в С++. Поэтому выражение ".NET быстрее нативного кода" бессмысленно.


 
Palladin ©   (2007-11-01 16:01) [69]


>  Такого монстра, как MFC я давно не видел. ИМХО одна из
> весьма неудачных классовых бибилиотек.



> С другой стороны, если "говорим Делфьи, подразумеваем VCL",
>  то в С++ такого нет.


эт точно... но все равно грех VCL не упомянуть... :)


 
Mystic ©   (2007-11-01 16:05) [70]

> Но хочу показать, что утвержденияо "тормознутости" .NET
> как правило голословны.


После такого рода заявлений я решил попробовать C#. Выбрал себе задачу (шахматы, генератор ходов), для которой критична производительность (сила напрямую зависит от количества позиций в секунду). Понеслась.

Итак, как хотелось бы представить себе поле? Поскольку очень хотелось бы, чтобы была допустима запись

using namespace Chess;

Field x = Field.A1;
Bitboard test = x.GetBitboard();

и т. д., то первой мыслью было объявить тип Field не как enum, а как struct, наподобие System.Drawing.Color. Итак


   struct Field
   {
       private int index;

       private Field(int _index)
       {
           index = _index;
       }

       public Field(Field Orig)
       {
           index = Orig.index;
       }

       public static bool operator ==(Field a, Field b)
       {
           return a.index == b.index;
       }

       public static bool operator !=(Field a, Field b)
       {
           return a.index != b.index;
       }

       /* Просят объявить, хотя я его использовать не собираюсь */
       public override bool Equals(object a)
       {
           if (typeof(Field) != a.GetType()) return false;
           return this == (Field)a;
       }

       /* Тоже надо */
       public override int GetHashCode()
       {
           return index.GetHashCode();
       }

       static public Field A1
       {
           /* Оптимизация, потому что return new Field(0) приводит к unboxing */
           get
           {
               Field Data;
               Data.index = 0;
               return Data;
           }
       }

       static public Field B1
       {
           get
           {
               Field Data;
               Data.index = 1;
               return Data;
           }
       }

   }


И использовал его я, как и хотел, так:


       static int Test()
       {
           Chess.Field Test = Chess.Field.A1;
           if (Test == Chess.Field.A1)
               return 0;
           else if (Test == Chess.Field.B1)
               return 1;
           return -1;
       }


Скомпилировал в релизе, опция Optimize Code стоит. Смотрю что вышло:


;        static int Test()
;        {

00000000  sub         rsp,48h  ; Инициализация фрейма стека

00000004  mov         r8d,4    
0000000a  xor         edx,edx
0000000c  lea         rcx,[rsp+20h]
00000011  call        FFFFFFFFFF514BA0 ; Вызов не расшифрован

00000016  nop              
00000017  mov         rax,64280013128h
00000021  mov         eax,dword ptr [rax]
00000023  test        eax,eax
00000025  je          000000000000002C
00000027  call        FFFFFFFFFF78DDC0 ; Вероятно обращение к JIT-компилятору

;            Chess.Field Test = Chess.Field.B1;
0000002c  call        FFFFFFFFFFFFFFD8
00000031  mov         dword ptr [rsp+2Ch],eax
00000035  mov         eax,dword ptr [rsp+2Ch]
00000039  mov         dword ptr [rsp+20h],eax

;            if (Test == Chess.Field.A1)
0000003d  mov         eax,dword ptr [rsp+20h]
00000041  mov         dword ptr [rsp+24h],eax
00000045  call        FFFFFFFFFFFFFFD0
0000004a  mov         dword ptr [rsp+30h],eax
0000004e  mov         edx,dword ptr [rsp+30h]
00000052  mov         ecx,dword ptr [rsp+24h]
00000056  call        FFFFFFFFFFFFFFB0
0000005b  mov         byte ptr [rsp+34h],al
0000005f  movzx       eax,byte ptr [rsp+34h]
00000064  test        eax,eax
00000066  je          000000000000006C

;                return 0;
00000068  xor         eax,eax
0000006a  jmp         00000000000000A5

;            else if (Test == Chess.Field.B1)
0000006c  mov         eax,dword ptr [rsp+20h]
00000070  mov         dword ptr [rsp+28h],eax
00000074  call        FFFFFFFFFFFFFFD8
00000079  mov         dword ptr [rsp+38h],eax
0000007d  mov         edx,dword ptr [rsp+38h]
00000081  mov         ecx,dword ptr [rsp+28h]
00000085  call        FFFFFFFFFFFFFFB0
0000008a  mov         byte ptr [rsp+3Ch],al
0000008e  movzx       eax,byte ptr [rsp+3Ch]
00000093  test        eax,eax
00000095  je          000000000000009E

;                return 1;
00000097  mov         eax,1
0000009c  jmp         00000000000000A5

;            return -1;
0000009e  mov         eax,0FFFFFFFFh
000000a3  jmp         00000000000000A5
000000a5  add         rsp,48h
000000a9  rep ret


Остальное не лучше... Вместо нескольких ассемблерных инструкций переливание из пустого в порожнее...


 
Mystic ©   (2007-11-01 16:06) [71]

Может это я не знаю, как писать? Попробовал скомпилировать такой код:


           System.Drawing.Color Color = System.Drawing.Color.Black;
           if (Color == System.Drawing.Color.Black)
               System.Console.WriteLine("Catastrophic execution");


Результат:


;            System.Drawing.Color Color = System.Drawing.Color.Black;
0000005c  lea         rcx,[rsp+40h]
00000061  call        FFFFFFFFF5A8CBF0
00000066  mov         qword ptr [rsp+000000D0h],rax
0000006e  lea         rcx,[rsp+40h]
00000073  mov         rax,qword ptr [rcx]
00000076  mov         qword ptr [rsp+20h],rax
0000007b  mov         rax,qword ptr [rcx+8]
0000007f  mov         qword ptr [rsp+28h],rax
00000084  mov         rax,qword ptr [rcx+10h]
00000088  mov         qword ptr [rsp+30h],rax

;            if (Color == System.Drawing.Color.Black)
0000008d  lea         rcx,[rsp+20h]
00000092  mov         rax,qword ptr [rcx]
00000095  mov         qword ptr [rsp+58h],rax
0000009a  mov         rax,qword ptr [rcx+8]
0000009e  mov         qword ptr [rsp+60h],rax
000000a3  mov         rax,qword ptr [rcx+10h]
000000a7  mov         qword ptr [rsp+68h],rax
000000ac  lea         rcx,[rsp+70h]
000000b1  call        FFFFFFFFF5A8CBF0
000000b6  mov         qword ptr [rsp+000000D8h],rax
000000be  lea         rcx,[rsp+70h]
000000c3  mov         rax,qword ptr [rcx]
000000c6  mov         qword ptr [rsp+000000B0h],rax
000000ce  mov         rax,qword ptr [rcx+8]
000000d2  mov         qword ptr [rsp+000000B8h],rax
000000da  mov         rax,qword ptr [rcx+10h]
000000de  mov         qword ptr [rsp+000000C0h],rax
000000e6  lea         rcx,[rsp+58h]
000000eb  mov         rax,qword ptr [rcx]
000000ee  mov         qword ptr [rsp+00000090h],rax
000000f6  mov         rax,qword ptr [rcx+8]
000000fa  mov         qword ptr [rsp+00000098h],rax
00000102  mov         rax,qword ptr [rcx+10h]
00000106  mov         qword ptr [rsp+000000A0h],rax
0000010e  lea         rdx,[rsp+000000B0h]
00000116  lea         rcx,[rsp+00000090h]
0000011e  call        FFFFFFFFF5A7DEA0
00000123  mov         byte ptr [rsp+000000E0h],al
0000012a  movzx       eax,byte ptr [rsp+000000E0h]
00000132  test        eax,eax
00000134  je          0000000000000148

;                System.Console.WriteLine("Catastrophic execution");
00000136  mov         rcx,12969090h
00000140  mov         rcx,qword ptr [rcx]
00000143  call        FFFFFFFFF81DFAE0


 
Anatoly Podgoretsky ©   (2007-11-01 16:06) [72]

> Alkid  (01.11.2007 15:57:06)  [66]

И статистика, а не разовое выполнение.


 
Mystic ©   (2007-11-01 16:08) [73]

Примерно в том же ключе. Видимо так писать еще рано. Попробовал другой путь --- просто использовать Enum. Тут я решил сразу писать код, используя напрямую работу с типами int, System.UInt64 и т. д. Итак, общая структура


   enum Field
   {
       A1, B1, C1, D1, E1, F1, G1, H1,
       A2, B2, C2, D2, E2, F2, G2, H2,
       A3, B3, C3, D3, E3, F3, G3, H3,
       A4, B4, C4, D4, E4, F4, G4, H4,
       A5, B5, C5, D5, E5, F5, G5, H5,
       A6, B6, C6, D6, E6, F6, G6, H6,
       A7, B7, C7, D7, E7, F7, G7, H7,
       A8, B8, C8, D8, E8, F8, G8, H8
   }

       public static System.UInt64 MakeBitboard(Field A)
       {
           return (System.UInt64)1 << (System.Byte)A;
       }


Итак, в этот раз код получился лучше:


;        static int Test()
;        {
00000000  sub         rsp,48h
00000004  mov         dword ptr [rsp+20h],0
0000000c  mov         qword ptr [rsp+28h],0
00000015  mov         rax,64280013128h
0000001f  mov         eax,dword ptr [rax]
00000021  test        eax,eax
00000023  je          000000000000002A
00000025  call        FFFFFFFFFF78DE00

;            Chess.Field A = Chess.Field.B1;
0000002a  mov         dword ptr [rsp+20h],1

;            System.UInt64 Test = Chess.Engine.MakeBitboard(A);
00000032  mov         ecx,dword ptr [rsp+20h]
00000036  call        FFFFFFFFFFFFFFE0
0000003b  mov         qword ptr [rsp+30h],rax
00000040  mov         rax,qword ptr [rsp+30h]
00000045  mov         qword ptr [rsp+28h],rax

;            if (Test == 0x01)
0000004a  cmp         qword ptr [rsp+28h],1
00000050  jne         0000000000000056

;                return 0;
00000052  xor         eax,eax
00000054  jmp         000000000000006C

;            else if (Test == 0x02)
00000056  cmp         qword ptr [rsp+28h],2
0000005c  jne         0000000000000065

;                return 1;
0000005e  mov         eax,1
00000063  jmp         000000000000006C

;            return -1;
00000065  mov         eax,0FFFFFFFFh
0000006a  jmp         000000000000006C
0000006c  add         rsp,48h
00000070  rep ret    
;        }


и

;        public static System.UInt64 MakeBitboard(Field A)
;        {
00000000  mov         dword ptr [rsp+8],ecx
00000004  sub         rsp,28h
00000008  nop              
00000009  mov         rax,64280013128h
00000013  mov         eax,dword ptr [rax]
00000015  test        eax,eax
00000017  je          000000000000001E
00000019  call        FFFFFFFFFF78DD50

;            return (System.UInt64)1 << (System.Byte)A;
0000001e  movzx       ecx,byte ptr [rsp+30h]
00000023  and         ecx,3Fh
00000026  mov         eax,1
0000002b  shl         rax,cl
0000002e  jmp         0000000000000030
00000030  add         rsp,28h
00000034  rep ret          
;        }


В этот раз много лучше, но все-таки остаются вопросы:
(а) Разве трудно догадаться сделать вызов функции MakeBitboard inline-ом? Или хотя-бы дать возможность его объявить...
(б) Почему не упростить фрейм функции? Если это вызов JIT-компилятора, то почему не делать обращения к нему до инициализации стека и не затирать впоследствие обращение к нему?
(в) Почему не использовать для хранения локальных переменных регистры, коих в ADM64 дочерта?
(г) В чем смысл jmp 0000000000000030 в функции MakeBitboard?
(д) Зачем использовать передачу параметров через регистры, если потом их копировать в стек?


 
Anatoly Podgoretsky ©   (2007-11-01 16:09) [74]

> homm  (01.11.2007 15:57:07)  [67]

Это расплата за ООП, за managed code, за рантайм вынесеный на уровень системы и прочие прелести.
Дельфи в этом плане находится там же. А если какой ни будь Power Buider / Ява и другие продукты с большим рантаймом.


 
Джо ©   (2007-11-01 16:12) [75]

[71] Mystic ©
Ужас. Честно, ужас.


 
homm ©   (2007-11-01 16:14) [76]

> [70] Mystic ©   (01.11.07 16:05)
> Выбрал себе задачу (шахматы, генератор ходов), для которой
> критична производительность (сила напрямую зависит от количества
> позиций в секунду). Понеслась.

Что вышло то по тестам?


 
Джо ©   (2007-11-01 16:18) [77]

> [76] homm ©   (01.11.07 16:14)
> > [70] Mystic ©   (01.11.07 16:05)
> > Выбрал себе задачу (шахматы, генератор ходов), для которой
>
> > критична производительность (сила напрямую зависит от
> количества
> > позиций в секунду). Понеслась.
>
> Что вышло то по тестам?

А какое там может выйти быстродействие, если даже if (Color == System.Drawing.Color.Black) разворачивается в такой ужас?


 
homm ©   (2007-11-01 16:20) [78]

> [77] Джо ©   (01.11.07 16:18)
> А какое там может выйти быстродействие, если даже if (Color
> == System.Drawing.Color.Black) разворачивается в такой ужас?

Есть мнение что это промежуточный асемблер…
Так все-же?


 
Mystic ©   (2007-11-01 16:28) [79]

> homm ©   (01.11.07 16:14) [76]

До тестов я не дошел. Для меня важнее было не сравнить C# с C++, а сравнить мой генератор ходов с другими. К тому же шахматные программы используют хэш позиций, размер которого задается заранее. Например, я задаю в качестве параметра размер кэша в один гигабайт, и если число информации в кэше подходит к этому значению, то устаревшие/боковые позиции из него удаляются. Хорошей идеи как это реализовать в C# я не нашел. Ну и по совокупности C# был признан языком, не адекватным поставленной задачи :)

Есть чистый генератор + парсер PGN на Pure C, если интересно. Могу выслать для ознакомления при условии неразглашения :)


 
Mystic ©   (2007-11-01 16:37) [80]

> Есть мнение что это промежуточный асемблер…

Это мне показал cordbg.exe. Скомпилировано в релизе.


 
clickmaker ©   (2007-11-01 16:37) [81]


> что это промежуточный асемблер

а что это (сорри за серость)?


 
homm ©   (2007-11-01 16:41) [82]

> [81] clickmaker ©   (01.11.07 16:37)
> а что это (сорри за серость)?

Асемблерные команды, понимаемые jit компилятором. Промежуточное представление кпрограммы, до того, как она оттранслируется во время выполнеия в машинные кода.


 
clickmaker ©   (2007-11-01 16:42) [83]


> Асемблерные команды, понимаемые jit компилятором

видимо jit туповат все-таки... если банальный if ему так надо разжевать :)


 
Mystic ©   (2007-11-01 16:59) [84]

> Асемблерные команды, понимаемые jit компилятором.

Эти ассемблерные команды, пониамемые JIT-компилятором, называются иструкциями CIL. Там есть такие команды, как box, callvirt, castclass, newobj, newarr и т. д. Тут же нативный AMD64 ассемблер. Я не пробовал, как это скомпилируется в 32-битной Windows, может там оптимизатор получше. Но под 64 битами результаты устрашающе угнетающие.

К тому же как можно упростить этот "промежуточный" код? По большому счету никак, он и так оптимизирован на уровне ассемблерных инструкций. Оптимизировать его надо было уровнями выше.


 
clickmaker ©   (2007-11-01 17:01) [85]


> ;            if (Color == System.Drawing.Color.Black)
> 0000008d  lea         rcx,[rsp+20h]

судя по всему, там какая-то предварительная работа... только вот, хрен знает, зачем
ну не может один if в такую простыню развернуться. Хоть на 32-бит, хоть на 64, хоть на Марсе...


 
Mystic ©   (2007-11-01 17:24) [86]

> clickmaker ©   (01.11.07 17:01) [85]

Второй if разворачивается в аналогичную конструкцию (32 бита). Может у кого-то получится это сделать более оптимально?

--- C:\Mu\Labs\cs\test1\Program.cs ---------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;

namespace test1
{
 class Program
 {
   static void Main(string[] args)
   {
     System.Drawing.Color Color = System.Drawing.Color.Black;
00000000  push        ebp  
00000001  mov         ebp,esp
00000003  push        edi  
00000004  push        esi  
00000005  sub         esp,64h
00000008  mov         esi,ecx
0000000a  lea         edi,[ebp-6Ch]
0000000d  mov         ecx,18h
00000012  xor         eax,eax
00000014  rep stos    dword ptr es:[edi]
00000016  mov         ecx,esi
00000018  mov         dword ptr [ebp-0Ch],ecx
0000001b  cmp         dword ptr ds:[0092885Ch],0
00000022  je          00000029
00000024  call        79421156
00000029  lea         ecx,[ebp-2Ch]
0000002c  call        7A191508
00000031  lea         edi,[ebp-1Ch]
00000034  lea         esi,[ebp-2Ch]
00000037  movs        dword ptr es:[edi],dword ptr [esi]
00000038  movs        dword ptr es:[edi],dword ptr [esi]
00000039  movs        dword ptr es:[edi],dword ptr [esi]
0000003a  movs        dword ptr es:[edi],dword ptr [esi]
     if (Color != System.Drawing.Color.Black)
0000003b  lea         edi,[ebp-3Ch]
0000003e  lea         esi,[ebp-1Ch]
00000041  movs        dword ptr es:[edi],dword ptr [esi]
00000042  movs        dword ptr es:[edi],dword ptr [esi]
00000043  movs        dword ptr es:[edi],dword ptr [esi]
00000044  movs        dword ptr es:[edi],dword ptr [esi]
00000045  lea         ecx,[ebp-4Ch]
00000048  call        7A191508
0000004d  lea         eax,[ebp-3Ch]
00000050  push        dword ptr [eax+0Ch]
00000053  push        dword ptr [eax+8]
00000056  push        dword ptr [eax+4]
00000059  push        dword ptr [eax]
0000005b  lea         eax,[ebp-4Ch]
0000005e  push        dword ptr [eax+0Ch]
00000061  push        dword ptr [eax+8]
00000064  push        dword ptr [eax+4]
00000067  push        dword ptr [eax]
00000069  call        7A18C808
0000006e  mov         esi,eax
00000070  test        esi,esi
00000072  je          0000007F
       System.Console.WriteLine("Catastrophic execution");
00000074  mov         ecx,dword ptr ds:[0228307Ch]
0000007a  call        78747F3C
     if (Color == System.Drawing.Color.White)
0000007f  lea         edi,[ebp-5Ch]
00000082  lea         esi,[ebp-1Ch]
00000085  movs        dword ptr es:[edi],dword ptr [esi]
00000086  movs        dword ptr es:[edi],dword ptr [esi]
00000087  movs        dword ptr es:[edi],dword ptr [esi]
00000088  movs        dword ptr es:[edi],dword ptr [esi]
00000089  lea         ecx,[ebp-6Ch]
0000008c  call        7A18A2B4
00000091  lea         eax,[ebp-5Ch]
00000094  push        dword ptr [eax+0Ch]
00000097  push        dword ptr [eax+8]
0000009a  push        dword ptr [eax+4]
0000009d  push        dword ptr [eax]
0000009f  lea         eax,[ebp-6Ch]
000000a2  push        dword ptr [eax+0Ch]
000000a5  push        dword ptr [eax+8]
000000a8  push        dword ptr [eax+4]
000000ab  push        dword ptr [eax]
000000ad  call        7A18A424
000000b2  mov         esi,eax
000000b4  test        esi,esi
000000b6  je          000000C3
       System.Console.WriteLine("Catastrophic execution");
000000b8  mov         ecx,dword ptr ds:[0228307Ch]
000000be  call        78747F3C
   }
000000c3  nop              
000000c4  lea         esp,[ebp-8]
000000c7  pop         esi  
000000c8  pop         edi  
000000c9  pop         ebp  
000000ca  ret              


 
Mystic ©   (2007-11-01 18:02) [87]

Хорошо, протестировал сей момент:

Исходник C#, test1.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace test1
{
 class Program
 {
   static void Main(string[] args)
   {
     System.DateTime begin = System.DateTime.Now;
   
     for (int i=0; i<50000000; ++i)
     {
       System.Drawing.Color Color = System.Drawing.Color.Black;
       if (Color != System.Drawing.Color.Black)
         System.Console.WriteLine("Catastrophic execution");
       if (Color == System.Drawing.Color.White)
         System.Console.WriteLine("Catastrophic execution");
     }

     System.DateTime end = System.DateTime.Now;
     

     Console.WriteLine(end - begin);
   }
 }
}


Исходник C++, test2.cpp

#include <iostream>
#include "windows.h"

namespace System
{
 namespace Drawing
 {
   class Color
   {
     private:
       int value;
       Color(const int _value): value(_value) {}
     public:
       Color(const Color& color): value(color.value) {}
       static const Color White;
       static const Color Black;
       friend bool operator == (const Color& color1, const Color& color2) { return color1.value == color2.value; }
       friend bool operator != (const Color& color1, const Color& color2) { return color1.value != color2.value; }
   };
   
   const Color Color::White(0x00FFFFFF);
   const Color Color::Black(0x00000000);
 }
}

int main()
{
 LARGE_INTEGER begin, end, f;

 QueryPerformanceFrequency(&f);
 double frequency = static_cast<double>(f.QuadPart);
 
 QueryPerformanceCounter(&begin);
 for (int i=0; i<50000000; ++i)
 {
   System::Drawing::Color Color = System::Drawing::Color::Black;
   if (Color != System::Drawing::Color::Black)
     std::cout << "Catastrophic execution" << std::endl;
   if (Color == System::Drawing::Color::White)
     std::cout << "Catastrophic execution" << std::endl;
 }
 QueryPerformanceCounter(&end);
 
 std::cout << (end.QuadPart - begin.QuadPart) / frequency << std::endl;
return 0;
}


Результаты:


C:\Mu\Labs\cs\test1\bin\Release>test1.exe
00:00:05.7343750

C:\Mu\Labs\cs\test2\Release>test2.exe
0.0569969


Итого, разница примерно в 100 раз :)


 
Mystic ©   (2007-11-01 18:03) [88]

Что видно по ассемблерному коду C++:

#include <iostream>

namespace System
{
 namespace Drawing
 {
   class Color
   {
     private:
       int value;
       Color(const int _value): value(_value) {}
     public:
       Color(const Color& color): value(color.value) {}
       static const Color White;
       static const Color Black;
       friend bool operator == (const Color& color1, const Color& color2) { return color1.value == color2.value; }
       friend bool operator != (const Color& color1, const Color& color2) { return color1.value != color2.value; }
   };
   
   const Color Color::White(0x00FFFFFF);
   const Color Color::Black(0x00000000);
 }
}

int main()
{
 System::Drawing::Color Color = System::Drawing::Color::Black;
00401000  mov         eax,dword ptr [System::Drawing::Color::Black (403374h)]
 if (Color != System::Drawing::Color::Black)
   std::cout << "Catastrophic execution" << std::endl;
 if (Color == System::Drawing::Color::White)
00401005  cmp         eax,dword ptr [System::Drawing::Color::White (40301Ch)]
0040100B  jne         main+2Ah (40102Ah)
   std::cout << "Catastrophic execution" << std::endl;
0040100D  mov         eax,dword ptr [__imp_std::endl (402038h)]
00401012  mov         ecx,dword ptr [__imp_std::cout (402054h)]
00401018  push        eax  
00401019  push        ecx  
0040101A  call        std::operator<<<std::char_traits<char> > (401160h)
0040101F  add         esp,4
00401022  mov         ecx,eax
00401024  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402040h)]
 
return 0;
0040102A  xor         eax,eax
}
0040102C  ret  


 
homm ©   (2007-11-01 18:09) [89]

> [87] Mystic ©   (01.11.07 18:02)
> Итого, разница примерно в 100 раз :)

Жесть :)
Где там госпадин Alkid ?


 
Amoeba ©   (2007-11-01 18:21) [90]


> vpbar ©   (01.11.07 14:05) [29]
>
> Alkid ©   (01.11.07 13:58) [27]
> Для таких случаев можно симулировать :)
> http://www.delphikingdom.com/asp/viewitem.asp?catalogid=744
> и ww.delphikingdom.com/asp/viewitem.asp?catalogid=453 есть
> статья получше. Но ссылку не помню.
>

http://www.delphikingdom.com/asp/viewitem.asp?catalogid=891


 
Alkid ©   (2007-11-01 18:23) [91]


> Жесть :)
> Где там госпадин Alkid ?

Я тут. :)
Если заметите, здесь не чисто вычислительная задача, а задача связанная с вводом-выводом :)
А они там действительно могут подтормаживать.


 
Джо ©   (2007-11-01 18:31) [92]

К сожалению, большинство *реальных* программ не занимаются только вычислением. Я готов признать, что для вычисления a := sqrt(b*sin(c)/123) в .Net генерится хороший, грамотный машинный код, врял ли, конечно, он быстрее кода, скомпилированного из C++, но все же он будет *достаточно быстр*.
Но в *реальных* программах, как правило, встречаются сравнения, условные переходы (господин Mystic уже показал, во что они компилятся) и (ужас!) операции ввода-вывода.
Так что, надо признать, что все эти тесты скорости программ под .Net никакого *практического* применения не имеют.


 
Джо ©   (2007-11-01 18:33) [93]

Собственно, это даже не нужно доказывать теоретически, ибо видно и «на глазок» — все программы на Дотнет, которые я видел, тормозили.
То же самое с Джавой. Можно сколько угодно рассуждать о тестах скорости, о быстроте выполнения, но, опять же, «на глазок» — они тормозят и все тут :)


 
Mystic ©   (2007-11-01 18:40) [94]


> Если заметите, здесь не чисто вычислительная задача, а задача
> связанная с вводом-выводом :)


Ввод-вывод не выполняется :) Единственный вывод этих программ вначале и в конце, так что это вычислительная задача :)

Вообще-то примеры тут несколько некорректны, потому что указывают на наэффективность реализации System.Drawing.Color. Если сляпать похожий класс самому, то разница будет примерно в 20 раз:

C:\Mu\Labs\cs\test1\bin\Release>test1.exe
00:00:00.9843750


Нет, если алгоритмический код выполнять в процедурном стиле, все мелкие функции инлайнить ручками, то мы и в C# приблизимся к результату C++. Что и показывают тесты. Скажем, если в этом примере не использовать класс MyColor, а вместо использовать int, медоды заменить статическими вызовами, а самые мелкие из них инлайнить руками... Но для этого надо специально извращаться, код в результате будет негибкий :) А для тестов, чтобы показать могучесть JIT-компилятора---самый раз

Программа:


using System;
using System.Collections.Generic;
using System.Text;

namespace test1
{
 struct MyColor
 {
   private int value;
   
   private MyColor(int _value)
   {
     value = _value;
   }
   
   static public bool operator == (MyColor color1, MyColor color2)
   {
     return color1.value == color2.value;
   }

   static public bool operator !=(MyColor color1, MyColor color2)
   {
     return color1.value != color2.value;
   }
   
   static public MyColor White
   {
     get
     {
       /* avoid boxing/unboxing operations in case of return new MyColor(0x00FFFFFF) */
       MyColor retVal;
       retVal.value = 0x00FFFFFF;
       return retVal;
     }
   }

   static public MyColor Black
   {
     get
     {
       MyColor retVal;
       retVal.value = 0x00000000;
       return retVal;
     }
   }
 }

 class Program
 {
   static void Main(string[] args)
   {
     /* JIT compilation of MyColor"s methods */
     MyColor t1 = MyColor.White;
     MyColor t2 = MyColor.Black;
     if ((t1==t2) == (t1 != t2))
       System.Console.WriteLine("Catastrophic execution");
     
     System.DateTime begin = System.DateTime.Now;
   
     for (int i=0; i<50000000; ++i)
     {
       MyColor Color = MyColor.Black;
       if (Color != MyColor.Black)
         System.Console.WriteLine("Catastrophic execution");
       if (Color == MyColor.White)
         System.Console.WriteLine("Catastrophic execution");
     }

     System.DateTime end = System.DateTime.Now;
     

     Console.WriteLine(end - begin);
   }
 }
}


 
isasa ©   (2007-11-01 19:29) [95]

Джо ©   (01.11.07 18:33) [93]

Собственно, это даже не нужно доказывать теоретически, ибо видно и «на глазок» — все программы на Дотнет, которые я видел, тормозили.
То же самое с Джавой. Можно сколько угодно рассуждать о тестах скорости, о быстроте выполнения, но, опять же, «на глазок» — они тормозят и все тут :)


В основном тормозят из-за криворукости писателей, которые во время "тяжелых" операций пытаются визуализировать ход их выполнения.
Пример, использование TMemo для показа добавления большого числа строк(т.е. TMemo.Add(...) внутри большого цикла).

Про Java молчу, там и без этого (при Resize окна) видно, что графический движок оставляет желать лучшего ...


 
wicked ©   (2007-11-01 21:12) [96]

> Джо ©   (01.11.07 18:33) [93]

> Собственно, это даже не нужно доказывать теоретически, ибо
> видно и «на глазок» — все программы на Дотнет, которые я
> видел, тормозили.
> То же самое с Джавой. Можно сколько угодно рассуждать о
> тестах скорости, о быстроте выполнения, но, опять же, «на
> глазок» — они тормозят и все тут :)

да.... для определения "тормознутости" можно глянуть Paint.NET (дотнет) или Eclipse (джава)...

> isasa ©   (01.11.07 19:29) [95]

>
> Про Java молчу, там и без этого (при Resize окна) видно,
>  что графический движок оставляет желать лучшего ...

там много движков - AWT, Swing, SWT - который из них?


 
Джо ©   (2007-11-01 21:43) [97]

> [96] wicked ©   (01.11.07 21:12)
> да.... для определения "тормознутости" можно глянуть Paint.NET
> (дотнет) или Eclipse (джава)...

Оба продукта тормознутые.


 
@!!ex ©   (2007-11-01 22:17) [98]

У Paint.NET даже установщик тормозит...
Хотя софтина приятная.


 
Джо ©   (2007-11-01 22:44) [99]

Но, видимо, рекордсмен тормозов — это ДжБилдер, не ко сну будь упомянут :)


 
Efir   (2007-11-02 00:34) [100]

Ну почему же, Paint.Net вполне быстро работает. Последние версии неплохо оптимизированы.


 
Mystic ©   (2007-11-05 18:12) [101]

Никто не спорит, что на C# можно писать оптимизированные с учетом производительности программы. Но... отсутствие inline функций заставляет реализовывать inline-ы руками (Copy + Paste). Далее, экземпляры классов (и структур) помещаются не в регистрах, а в памяти (чтобы можно было взять адрес при передаче по ссылке). Ну и необходимо знать не только как писать оптимальные программы, но и ньюансы .NET (что получится в CLI инструкциях, как эти инструкции потом переведутся в ассемблер, boxing/unboxing).


 
oxffff ©   (2007-11-05 19:22) [102]


> Mystic ©   (05.11.07 18:12) [101]


> Далее, экземпляры классов (и структур) помещаются не в регистрах,
>  а в памяти (чтобы можно было взять адрес при передаче по
> ссылке).


А что в других языках структуры в регистрах хранятся?
:)

Теперь что касаемо inline.

Method Implementation Flags
The nonterminal symbol <impl> in the method definition form denotes the implementation flags of the method (the ImplFlags entry of a Method record).
The implementation flags are

..............
noinlining (0x0008). The runtime is not allowed to inline the method—that is, to
replace the method call with explicit insertion of the method’s IL code.


Даже возможно IL Inlining in High-Level Languages с помощью спецсредств.


 
Юрий Зотов ©   (2007-11-05 19:53) [103]

> Alkid ©   (01.11.07 13:58) [27]

Хотите, прямо здесь, за 5 минут напишу на Delphi контейнер, абсолютно универсальный, абсолютно типобезопасный и без всяких шаблонов?


 
Сусл ©   (2007-11-05 19:56) [104]


> Хотите, прямо здесь, за 5 минут напишу на Delphi контейнер,
>  абсолютно универсальный, абсолютно типобезопасный и без
> всяких шаблонов?


я хочу. очень.
только - проверка типов в compile-time, а не в runtime.


 
Юрий Зотов ©   (2007-11-05 20:10) [105]

> Сусл ©   (05.11.07 19:56) [104]

Тоже можно, но уже не за 5 минут, конечно. Эксперт IDE с BeforeCompile способен проверить что угодно.


 
Alkid ©   (2007-11-05 20:26) [106]


> Хотите, прямо здесь, за 5 минут напишу на Delphi контейнер,
>  абсолютно универсальный, абсолютно типобезопасный и без
> всяких шаблонов?

Очень хочу, но именно Compile-time проверку типов :)
Касательно IDE-эксперта - это хотелось поподробнее. Меня терзают смутные сомнения, что это будет тот "шаблонатор", только не в компилятор встроенный, а "сбоку" прикрученный.


 
Mystic ©   (2007-11-05 20:52) [107]

> А что в других языках структуры в регистрах хранятся?
> :)


Если помещаются в регистр---почему нет? Если я объявлю
class A { private: int x; }, то если это возможно, то локальные переменные обычно размещаются в регистрах.

А вот в .NET 64 я не так давно видел такую картину: по стандарту stdcall переменные передаются в регистрах (их там дофига от R8 до R15). Поэтому вызов функции сводился к тому, что значения из памяти копировались в регистры. Потом происходил вызов функции. а затем переменные из памяти копировались в стек, где и положено быть локальным переменным :)

> Теперь что касаемо inline.
И как это легко использовать?

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


А какая, собственно говоря, разница? Чем Вас так не устраивает прикрученность сбоку? LEX + YACC удобная библиотека для лексического и синтаксического анализа, но ее тоже можно назвать прикрученной сбоку, потому как что в C++, что в Delphi она генерируют код. Написать утилиту, которая принимает на вход файл описаний и генерирует нужные контейнеры это дело одного дня.


 
Юрий Зотов ©   (2007-11-05 20:53) [108]

> Alkid ©   (05.11.07 20:26) [106]

ОК, значит будем считать, что все прекрасно понимают, что проверка типа в run-time  - абсолютно не проблема:


type
 TSafeContainer = class(...)
 protected
   class procedure TMyContainer.GetItemClass: TClass; virtual; abstract;
   class procedure CheckItemClass(Item: TObject; Strict: boolean); dynamic;
 public
   procedure Add(Item: TObject);
   procedure Insert(Item: TObject; Index: Integer);
   procedure Append(Item: TObject);
   // и т.п.
 end;

// И вызываем этот метод из Add, Insert, Append и т.п.
class procedure TSafeContainer.CheckItemClass(Item: TObject; Strict: boolean);
begin
 if ... then
   raise ...
end;

class procedure TSafeContainerDescendantExample.GetItemClass: TClass;
begin
 Result := TНужный_класс
end;


Тперь что касается Compile-time: задача, конечно, намного сложнее, но в принципе, решаема. В IDE можно (и даже несложно) вживить собственный эксперт, метод которого будет автоматически вызываться средой перед компиляцией проекта. В этом методе, вообще говоря, можно сделать что угодно, хоть собственный препроцессор наваять.


 
oxffff ©   (2007-11-05 21:09) [109]


> Mystic ©   (05.11.07 20:52) [107]
> > А что в других языках структуры в регистрах хранятся?
> > :)
>
> Если помещаются в регистр---почему нет? Если я объявлю
> class A { private: int x; }, то если это возможно, то локальные
> переменные обычно размещаются в регистрах.
>
> А вот в .NET 64 я не так давно видел такую картину: по стандарту
> stdcall переменные передаются в регистрах (их там дофига
> от R8 до R15). Поэтому вызов функции сводился к тому, что
> значения из памяти копировались в регистры. Потом происходил
> вызов функции. а затем переменные из памяти копировались
> в стек, где и положено быть локальным переменным :)


Что касаемо classA, то его нельзя разместить в регистре по причине того, что экземпляр класса содерживат еще дополнительные служебный поля, кроме поля X. Вы наверное имели ввиду value type.
Которые могут быть размещены в регистре при размере value type в int.

В .NET нет понятия регистров. Но есть понятие evaluation stack, который естественно при компиляции в native код транслируется на набор регистров и слоты стека потока.
:)

Что касаемо передачи stdcall, то все передается через стек.


 
Mystic ©   (2007-11-05 21:33) [110]

> Которые могут быть размещены в регистре при размере value
> type в int.


Может быть и могут, я не видел.

В .NET нет понятия регистров. Но есть понятие evaluation stack, который естественно при компиляции в native код транслируется на набор регистров и слоты стека потока.

Это понятно. Я говорю о том, как JIT в реализации .NET на платформе x86 использует регистры.

Что касаемо передачи stdcall, то все передается через стек.
Это справедливо для 32-х битной среде. В 64-х битной среде STDCALL == FASTCALL.


 
Mystic ©   (2007-11-05 21:38) [111]

Тут описано соглашения вызова функций для AMD64:
http://blogs.msdn.com/oldnewthing/archive/2004/01/14/58579.aspx
Других пока что нет :)


 
Сусл ©   (2007-11-05 21:39) [112]


> Юрий Зотов ©   (05.11.07 20:10) [105]
> Тоже можно, но уже не за 5 минут, конечно. Эксперт IDE с
> BeforeCompile способен проверить что угодно.


Знаешь, Юра, "способен" и "проворачивает" две огромные разницы.
Ты и за месяц это не напиешь. Могу даже объяснить почему. Тебе придется написать нефиговый парсер. Причем повторить те же ошибки, которые есть в парсере самого дельфи :) Это титаническая работа.

К тому же, Юра, позволь заметить следующую вещь. К сожалению в дельфи нет доступа к распарсеному тексту. Ну то есть - либо исх. код, либо готовый бинирник. В java есть возможность обращаться а байт-коду, который, конечно, намного легче для использования, нежели исх. код. Я недавно читал статью про статическое тестирование (напомню, что традиционно под термином понимается выявление ошибок на основе изучения кода без его выполнения). В частности там были обсуждены некоторые приблуды к eclipse, которые позволяют выполнять статическое тестирование программ на java на основе расширяемых шаблонов. Ну так вот. Все инструменты опираются на использование байт-кода. Сам понимаешь, что сделать твой эксперт в таком случае на порядок проще.

Резюм, я бы не говорил, что сделать такой эксперт ТЕБЕ вообще возможно (имеется в виду экономическая целесообразность). Почему я выделил ТЕБЕ? А потому, что ты, хоть и способный программист, но не имеешь доступа к внутреннему дереву компиляции кода на Delphi. Я уверен, что эксперты от самого CodeGear имеет естественно недокументированный доступ к такому дереву. Иначе объяснить относительно качественную работу экспертов рефакторинга объяснить сложно.


 
Mystic ©   (2007-11-05 21:50) [113]

> Знаешь, Юра, "способен" и "проворачивает" две огромные разницы.
> Ты и за месяц это не напиешь.


Думаю, что ты не понял основной идеи :) Смотри, есть некоторый файл, который содержит нечто следующее:


OUTPUT myutils.pas
USES MyUnit1, MyUnit2, MyUnit2
LIST TMyObj1 ITEM IS CLASS TMyClass1
DICTIONARY TMyObj2 KEY IS Integer VALUE IS RECORD TRecord1


Эту же информацию можно задать и в GUI эксперта. На основании этой информации генерируется исходник

uses myutils;
interface
uses MyUnit1, MyUnit2, MyUnit2;
type
 TMyObj1 = class
 private
...................
 public
   constructor Create;
   destructor Destroy; override;
   procedure Add(Value: TMyObj1);
   property Items[I: Integer]: TMyObj1 read GetItem write SetItem default;
 end;

...............

implementation

......................

end.


Этот исходник включается в проект, автоматически обновляется и используется :)


 
Черный Шаман   (2007-11-05 21:58) [114]


> Alkid ©   (01.11.07 13:58) [27]


Там есть ClassName и Published свойства которые можно достать в рантайм. Все отлично и без шаблонов можно сделать с использованием особенностей RTTI, причем все отлично читается и понимается потом.


 
Черный Шаман   (2007-11-05 22:14) [115]


> homm ©   (01.11.07 14:57) [46]
>
> > [41] Alkid ©   (01.11.07 14:50)
> > Видишь ли, это сейчас для всего, кроме embedded систем
> и
> > мобильный платформ, на которых я ни разу не специализируюсь,
>
> > уже ОЧЕНЬ МАЛЕНЬКИЙ недостаток.
>
> Ага, уже любой пенсионер на свою пенсию и из любой деревни
> может выкачать из инета 30 метров. ;)


На компакте со всеми программами использующими .NET всегда лежит сама среда. А 700 МБ или 4.7 Гб(DVD) для всех хватит. DVD-RW(хороший Asus/Nec) стоит 37$, вполне бюджетно для пенсионера.


 
Alkid ©   (2007-11-05 22:20) [116]


> А какая, собственно говоря, разница? Чем Вас так не устраивает
> прикрученность сбоку? LEX + YACC удобная библиотека для
> лексического и синтаксического анализа, но ее тоже можно
> назвать прикрученной сбоку, потому как что в C++, что в
> Delphi она генерируют код. Написать утилиту, которая принимает
> на вход файл описаний и генерирует нужные контейнеры это
> дело одного дня.

Да я и не спорю, просто тогда это и получаются те самые "шаблоны в Дельфи", о ненужности которых постоянно твердят некоторые участники форума.


 
Alkid ©   (2007-11-05 22:21) [117]


> ОК, значит будем считать, что все прекрасно понимают, что
> проверка типа в run-time  - абсолютно не проблема:

Гм. А где метод Get? Он-то в данном случае наиболее интересен. Точнее тип его возвращаемого значения. И еще точнее - надо ли каждый раз при взятии элемента из контейнера делать приведение типов от более общего к частному?


 
Alkid ©   (2007-11-05 22:24) [118]


> Там есть ClassName и Published свойства которые можно достать
> в рантайм. Все отлично и без шаблонов можно сделать с использованием
> особенностей RTTI, причем все отлично читается и понимается
> потом.

Тем, что
1. Этот контейнер не ловит во время компиляции попыток положить в него объект не того класса. Он их ловит только во время исполнения.
2. Использование RTTI снижает производительность операции добавления элемента в контейнер.
3. Взятие элемента из контейнера будет требовать явно прописанного в коде приведения типов, что будет замусоривать исходники.

Это не фатальные недостатки, в конце концов люди жили раньше с одним TObjectList`ом и выкручивались (равно как и с ArrayList в .NET до появления дженериков).


 
Юрий Зотов ©   (2007-11-05 22:43) [119]

> Сусл ©   (05.11.07 21:39) [112]

Дима, я не то что за месяц, я и за 3 месяца вряд ли это напишу. И никто не говорил, что это простая задача. Но решаемая.

Эксперту для проверки валидности класса Item"ов нужен доступ:

а). К классам уже загруженных пакетов (причем эти классы ему заранее известны - это класс абстрактного контейнера и его потомки). Такой доступ у эксперта есть, поскольку он сам - часть среды.

б). К исходникам проекта. Такой доступ у него тоже есть (через интерфейсы BorlandIDEServices).

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

И при чем тут какая-то там экономическая целесообразность? Зачем притягивать за уши аргументы, не имеющие к сабжу никакого отношения?

Уж не говоря о способе [113], когда исходник юнита генерится "на лету".


 
oxffff ©   (2007-11-05 23:30) [120]


> Юрий Зотов ©   (05.11.07 22:43) [119]
> > Сусл ©   (05.11.07 21:39) [112]
>
> Дима, я не то что за месяц, я и за 3 месяца вряд ли это
> напишу. И никто не говорил, что это простая задача. Но решаемая.
>


Есть готовые реализации парсера Delphi. Причем с исходниками.

DGrok?


 
oxffff ©   (2007-11-05 23:32) [121]


> Mystic ©   (05.11.07 21:33) [110]
> > Которые могут быть размещены в регистре при размере value
>
> > type в int.
>
> Может быть и могут, я не видел.
>
> В .NET нет понятия регистров. Но есть понятие evaluation
> stack, который естественно при компиляции в native код транслируется
> на набор регистров и слоты стека потока.
>
> Это понятно. Я говорю о том, как JIT в реализации .NET на
> платформе x86 использует регистры.
>
> Что касаемо передачи stdcall, то все передается через стек.
>
> Это справедливо для 32-х битной среде. В 64-х битной среде
> STDCALL == FASTCALL.


Я тогда не понял. В чем притензия к JIT Compiler"у?
Насколько я понял stdcall использовалось для вызова Native кода.


 
Сусл ©   (2007-11-05 23:37) [122]


> Юрий Зотов ©   (05.11.07 22:43) [119]


Юра, скоро мы все войдем в век шаблнов в Дельфи. Вот тогда и поговорим :р


 
oxffff ©   (2007-11-05 23:38) [123]


> Сусл ©   (05.11.07 23:37) [122]


Дмитрий, согласись это же не плохо?


 
Сусл ©   (2007-11-05 23:42) [124]


> oxffff ©   (05.11.07 23:38) [123]
> > Сусл ©   (05.11.07 23:37) [122]
> Дмитрий, согласись это же не плохо?


Сергей, знаешь какой бардак начнется?
:)


 
oxffff ©   (2007-11-05 23:49) [125]


> Сусл ©   (05.11.07 23:42) [124]


Тогда добавят специально раздел "Шаблоны".
:)

Меня больше другое волнует.
Сообщество Delphi программистов, всегда ставили стороникам С++ в укор их наличие.
Сейчас для нас это вопрос времени.
Хотя я не знаю и думаю, на что будут похоже compile time их реализация в win32 на template или generics.

Что нам говорить теперь им.

:)

P.S. Зато искренне и откровенно. IMHO

:)


 
Черный Шаман   (2007-11-06 00:07) [126]


> Alkid ©   (05.11.07 22:24) [118]
>
>
> > Там есть ClassName и Published свойства которые можно
> достать
> > в рантайм. Все отлично и без шаблонов можно сделать с
> использованием
> > особенностей RTTI, причем все отлично читается и понимается
> > потом.
>
> Тем, что
> 1. Этот контейнер не ловит во время компиляции попыток положить
> в него объект не того класса. Он их ловит только во время
> исполнения.


А чем плохо? Лично у меня в одном из проектов все данные по по конкретному элементу брались из xml и на лету создавались динамические объекты с перегрузкой методов выполнения по их символьным значениям(с наследованием и прочим). Этакая объектная база данных вышла для проектирования визуального интерфейса.

Это удобнее тем, что программу можно создавать на основе общего ядра, надстроечных xml файлов и скриптов(где все ресурсоемкие функции вынесены в ядро системы).

На современных системах(Celeron2000+, 256Мб+) тормозов не видно, а гибкость и простота налицо.

Кроме того S.T.A.L.K.E.R. полностью написан на XML + общее ядро.


 
Alkid ©   (2007-11-06 10:33) [127]


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

Наличие типизированного контейнера их шаблона такую возможность ничуть не приуменьшает :) То же самое прекрасно делается и на шаблонах, только при этом у тебя меньше накладных расходов во время выполнения и принципиально ликвидируется вероятность запихивания в контейнер "левого" объекта.

В твоей же схеме либо проверять всё в run-time при помощи RTTI, либо вся система становится уязвима для неправильно написанных XML-скриптов с конфигурацией. А что бы этого не было, придётся делать свою систему проверки валидности этих скриптов.


 
Юрий Зотов ©   (2007-11-06 10:41) [128]

> Сусл ©   (05.11.07 23:42) [124]

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

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


 
Mystic ©   (2007-11-06 12:59) [129]

> Да я и не спорю, просто тогда это и получаются те самые
> "шаблоны в Дельфи", о ненужности которых постоянно твердят
> некоторые участники форума.


Сделать это несложно, но это никто не сделал. Значит не очень то и хотелось :)

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

Одно из различий Delphi и C++ состоит в том, что Delphi имело определенный вектор развития, основанный в первую очередь на практических потребностях. Когда становился вопрос шаблоны vs поддержку COM, расширение возможностей компонент и т. д., то шаблоны были в проигрыше. Потому как вещь приятная, но не настолько необходимая. Текущие средства покрывают 95% всех задач, а в случае 5% нетрудно сделать Copy + Paste и т. д.

Фичи в C++ добавлялись комитетом. Насколько я понимаю этот процесс, шел он примерно так: возникал вопрос: "а не добавить ли нам такую-то возможность?" Потом шло обсуждение. Принималась резолюция:  "Да, это круто". Добавляли в стандарт. Потом она реализовывалась в компиляторах. Потом иногда находились грабли, приходилось делать заплатки (так появился, например, explicit). Как сейчас помню, когда читал первое издание Страуструпа (зеленое такое), увлекся обработкой исключительных ситуаций (как это здорово!). Поставил новый Borland C++ 3.1, а он этих слов и не понимает :( Но выбор компиляторов C++ тогда был: Semantec, Watcom, ... BTW, Потом я узнал, что исключительные ситуации давно уже были реализованы в Ada :)

Вообще, например, по ознакомительным статьям мне более импонирует язык D, потому как C++ очень уж завязан на недостатки C. Ну и Ada :)


 
Mystic ©   (2007-11-06 13:17) [130]

> Я тогда не понял. В чем притензия к JIT Compiler"у?
> Насколько я понял stdcall использовалось для вызова Native
> кода.


Нет, не native кода, я обычного кода

Претензия в том, что
1. По стандарту вызова метода, параметры передаются в регистрах.
2. JIT компилятор упорно размещает переменные типа class в стеке (может это надо для сборки мусора или еще чего, не знаю).
Поэтому, при вызове метода происходило следующее
1. Аргументы копировались в регистры
2. Вызов функции
3. Инициализация cтека внутри функции
4. Копирование аргументов из регистров в стек
5. Выполнение кода функции
Согласись, это неэффективно?

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

> Меня больше другое волнует.
> Сообщество Delphi программистов, всегда ставили стороникам
> С++ в укор их [шаблонов] наличие.


Для меня не наличие шаблонов, а их реализация :) Сейчас то сообщения об ошибках более-менее грамотные стали. А так как по мне, компилятор слишком много работы делает, которую тяжело проконтроллировать, сам что-то там себе выводит, хотя мне несложно было бы и подсказать. Да и спокойнее :)


 
Mystic ©   (2007-11-06 14:30) [131]

Кстати, еще одна попытка сравнить C++ и C# по скорости:
http://rsdn.ru/forum/Message.aspx?mid=2720100&only=1
Код C++ быстрее в 10 раз :)


 
oxffff ©   (2007-11-06 14:49) [132]


> Mystic ©   (06.11.07 13:17) [130]


Method calls
Instructions emitted by the CIL code generator contain sufficient information for different implementations of the CLI to use different native calling conventions.

Получается, что способ приема/передачи параметров оставлен на усмотрение JIT.
И детерминированно мы можем (точнее должны) указать способ вызова
только для вызова native кода.

Что касаемо конкретного случая.
То я не склонен думать, что это неэффективно.
И вот почему

Поскольку область стековой машины, параметров, локальных переменных может произвольным (точнее выбранным по определныым критериям) отображаться на подмножество регистров и стек потока, то чисто технически я допускаю возможность их переотображения на другие варианты в течение работы метода. Также я допускаю, возможно они анализирует IL код на количество обращений и в соответствии с этим ранжируют отображения,  жертвуя в начале, но выигрывая в конце.

:)


 
oxffff ©   (2007-11-06 15:00) [133]


> 2. JIT компилятор упорно размещает переменные типа class
> в стеке (может это надо для сборки мусора или еще чего,
> не знаю).


А как вы к managed объекту обратитись без ссылки на него. :)
Если есть переменная типа O - объектная ссылка в терминах VES.
То она является корнем, которая анализируется при последующем анализе при сборке мусора.
Но сам объект размещен в управляемой куче.


 
oxffff ©   (2007-11-06 15:08) [134]


> Тем более на каждый вызов функции :) Ну и по тому коду,
> что я видел, .NET Framework абсолютно не понимал, зачем
> нужны регистры процессора, большая часть их которых просто
> не использовалась, разве что для передачи параметров :)


Я безусловно допускаю и такой вариант.
А нельзя ли этот код IL код и соответствующий x86 код  посмотреть?
И какая версия JIT?


 
Mystic ©   (2007-11-06 15:20) [135]

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

Хорошо, давая я просто приведу пример, а ты объяснишь, почему код, который сгенерировал JIT компилятор, эффективен?


   enum Field
   {
       A1, B1, C1, D1, E1, F1, G1, H1,
       A2, B2, C2, D2, E2, F2, G2, H2,
       A3, B3, C3, D3, E3, F3, G3, H3,
       A4, B4, C4, D4, E4, F4, G4, H4,
       A5, B5, C5, D5, E5, F5, G5, H5,
       A6, B6, C6, D6, E6, F6, G6, H6,
       A7, B7, C7, D7, E7, F7, G7, H7,
       A8, B8, C8, D8, E8, F8, G8, H8
   }

   public static System.UInt64 MakeBitboard(Field A)
   {
      return (System.UInt64)1 << (System.Byte)A;
   }


Получаем следующий нативный код:

;        public static System.UInt64 MakeBitboard(Field A)
;        {
00000000  mov         dword ptr [rsp+8],ecx
00000004  sub         rsp,28h
00000008  nop              
00000009  mov         rax,64280013128h
00000013  mov         eax,dword ptr [rax]
00000015  test        eax,eax
00000017  je          000000000000001E
00000019  call        FFFFFFFFFF78DD50

;            return (System.UInt64)1 << (System.Byte)A;
0000001e  movzx       ecx,byte ptr [rsp+30h]
00000023  and         ecx,3Fh
00000026  mov         eax,1
0000002b  shl         rax,cl
0000002e  jmp         0000000000000030
00000030  add         rsp,28h
00000034  rep ret          
;        }


Итак, параметр передается в ecx. Далее я так восстановил смысл проивходящего:
Строка 0000 запихивает его в стек
Строка 0004 делает стековый фрейм функции (-28h)
Строка 0008 это пресловутый nop, чтобы пользователь покупал новый процессор
Строки 0009-0019 см. строку 0008. Расшифровать не удалось
Строка 001e копируем параметр из стека в регистр ecx (+8р -28р = 30р)
Строка 0023 контрольное изнасилование в голову
Строка 0026 это наша единица (а почему не rax)?
Строка 002b сдвиг!
Строка 002e чтобы не тормозило
Строка 0030 восстанавливаем стек
Строка 0034 покидаем функцию

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


mov rax, 1
shl rax, cl
ret


?


 
Mystic ©   (2007-11-06 15:24) [136]

Еще примеры на пятой странице:
http://delphimaster.net/view/15-1193871434/


 
homm ©   (2007-11-06 15:27) [137]

> [135] Mystic ©   (06.11.07 15:20)
> Строка 0008 это пресловутый nop, чтобы пользователь покупал
> новый процессор

+1 :)


 
homm ©   (2007-11-06 15:32) [138]

Сори за оффтоп, но стало интересно, в х86 регистры rXX — это раширенные регистры eXX, или же осабнячком? т.е. младшее двойное слово rax, например, является eax ?


 
Mystic ©   (2007-11-06 15:34) [139]

Да, rax это 64-битный регистр, младшее двойное слово это eax. Есть еще дополнительные 64-битные регистры r8, r9, r10, r11, r12, r13, r14, r15


 
homm ©   (2007-11-06 15:44) [140]

> Есть еще дополнительные 64-битные регистры r8, r9, r10,
> r11, r12, r13, r14, r15

Я только недавно оправился от шока, что у меня есть 8 128-и битных регистров xmm ,и вот опять новый шок %)


 
Mystic ©   (2007-11-06 15:52) [141]

Расслабся, они не используются ;)
Хотя когда знакомый перешел в 32-битного Gentoo на 64-битный, то на глазок разница по скорости была примерно в полтора-два раза :) Но там можно все перекомпилировать, а под Windows большинство программа все равно *32. Хотя рыбка и заппа молотят варианты пошустрее :)


 
oxffff ©   (2007-11-06 15:58) [142]


> Хорошо, давая я просто приведу пример, а ты объяснишь, почему
> код, который сгенерировал JIT компилятор, эффективен?


Здесь я могу только констатировать обратное.
Хотя release версия дает чуть лучший код, но это совершенно не меняет суть.
Над JIT (x86) еще  нужно работать.


 
Alkid ©   (2007-11-06 16:17) [143]


> Сделать это несложно, но это никто не сделал. Значит не
> очень то и хотелось :)

Ну "никто не сделал" - это Вы погорячились :) Тут летали ссылки на разного рода реализации шаблонов в Дельфи, от наколеночных, до более серьёзных.


> Фичи в C++ добавлялись комитетом. Насколько я понимаю этот
> процесс, шел он примерно так: возникал вопрос: "а не добавить
> ли нам такую-то возможность?" Потом шло обсуждение. Принималась
> резолюция:  "Да, это круто". Добавляли в стандарт. Потом
> она реализовывалась в компиляторах. Потом иногда находились
> грабли, приходилось делать заплатки (так появился, например,
>  explicit). Как сейчас помню, когда читал первое издание
> Страуструпа (зеленое такое), увлекся обработкой исключительных
> ситуаций (как это здорово!). Поставил новый Borland C++
> 3.1, а он этих слов и не понимает :( Но выбор компиляторов
> C++ тогда был: Semantec, Watcom, ... BTW, Потом я узнал,
>  что исключительные ситуации давно уже были реализованы
> в Ada :)

Ну, на самом деле не всё так однозначно. Предшественник С++  - C with classes возник из весьма практической задачи, которую Страуструп решал в своё время. И С++ вначале тоже делался без этой бюрократической волокиты.
Так что С++ тоже имел свой вектор в развитии.

Другое дело, что язык, развиваемый разношёрстным комитетом всегда будет развиваться медленнее, чем проприетарный язык, развиваемый какой-нибудь энергичной корпорацией или даже Open-Source сообществом. Это мы сейчас можем наблюдать на примере будущего стандарта С++0х, принятие которого анонсировано аж на 2009-ый год (а, значит, реальная поддержка в инструментальных средствах появится не раньше 2010-2011-годов).

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

Лично "для себя" (т.е. для программирования "для души") я пока выбрал С# 2.0 и хочу пощупать С# 3.0


> Вообще, например, по ознакомительным статьям мне более импонирует
> язык D, потому как C++ очень уж завязан на недостатки C.
>  Ну и Ada :)

ИМХО, D ещё сыроват. :)


 
oxffff ©   (2007-11-06 16:44) [144]

to Mystic ©  
Хотя чисто технически задача решается.
Поскольку используется peephole.
Тогда добавить peephole  шаблон + увеличить глубину peephole.


 
Mystic ©   (2007-11-06 16:54) [145]

И что это за зверь peephole?


 
oldman ©   (2007-11-06 16:57) [146]


> Объясните пожалуйста дельфисту, что такое шаблоны в Си?

> И что надо отвечать на нападки агрессивных сишников?


На нападки отвечать надо.
Но знать, что такое шаблоны, не надо.
Что, кирпичи отменили? Или ПМы? Или АКМы?

ЗЫ: А по поводу шаблонов - литературу почитать лень?


 
oxffff ©   (2007-11-06 17:08) [147]


> Mystic ©   (06.11.07 16:54) [145]
> И что это за зверь peephole?


http://en.wikipedia.org/wiki/Peephole_optimization


 
Mystic ©   (2007-11-06 17:14) [148]

Ну... с учетом того, что CLI instruction set по сути сокращенная форма исходников, то улучшить оптимизацию JIT можно. Но пока... маємо те що маємо.


 
celades ©   (2007-11-06 18:11) [149]

>на примере будущего стандарта С++0х, принятие которого анонсировано аж на 2009-ый год >(а, значит, реальная поддержка в инструментальных средствах появится не раньше >2010-2011-годов).
многие его нововведения уже реализованы в современных компиляторах.


 
Alkid ©   (2007-11-06 18:22) [150]


> многие его нововведения уже реализованы в современных компиляторах.

Верю. И что? :) Пока это ещё не стандарт цена этим нововведениям не столь уж высока - всё равно ими мало будут пользоваться. Вот у нас код должен компилироваться минимум тремя компиляторами под несколько платформ. Т.е. все использованные в этом коде возможности должны одинаково хорошо быть поддержаны всеми этими компиляторами. Когда это случится?


 
celades ©   (2007-11-06 20:15) [151]


> Верю. И что? :)

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


 
Alkid ©   (2007-11-06 22:40) [152]


> Поэтому процесс внедрения будет вполне безболезненный и
> достаточно быстрый.

Не, ну я только за, если оно действительно все так хорошо.
Кстати, они там reflection так и не включили в стандарт?


 
Фрейм   (2007-11-07 01:43) [153]


> Alkid ©   (01.11.07 14:18) [31]
>
>
> > Я знал, что мне опять расскажут байку про контейнеры.
>
> Я примерно 5 лет программировал на дельфи на прошлой работе.
>  За это время я бессчётное количество раз реализовывал разного
> рода контейнеры, пока не открыл способ, описанный в [29].
>  На этом я потерял столько времени и наделал столько ошибок,
>  переписывая в n+1-ый раз методы GetCount, GetItem, Add,
>  Remove и Clear, что могу тебе авторитетно заявить - про
> контейнеры, это не байки, а суровая правда жизни.


Можно с этого места по подробнее? Что именно приходилось переписывать?
Может вы просто чего-то не знали о Дельфи? Использование фреймов, например?


 
Джо ©   (2007-11-07 03:12) [154]

> [153] Фрейм   (07.11.07 01:43)
> Может вы просто чего-то не знали о Дельфи? Использование
> фреймов, например?

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


 
Фрейм   (2007-11-07 04:07) [155]

Удалено модератором
Примечание: Ты еще совочком швырнись, да.


 
KilkennyCat ©   (2007-11-07 05:33) [156]

Читал ветку. Много думал. Понял, что я тварь дражжащая и пошел вешаться: я любил бейсик...


 
boa_kaa ©   (2007-11-07 08:50) [157]

Код, приведенный в ссылке [130] ужасен. Причем как С#, так и C++. Я уж не говорю, что на моем ноуте в release версии C# обставил C++. Даже, пардон, не в 10 раз.


 
homm ©   (2007-11-07 09:55) [158]

> Я уж не говорю, что на моем ноуте в release версии C# обставил
> C++.

Ты что-то напутал. Возможно ты хотел сказать в debug версии.


 
Alkid ©   (2007-11-07 10:20) [159]


> Можно с этого места по подробнее? Что именно приходилось
> переписывать?
> Может вы просто чего-то не знали о Дельфи? Использование
> фреймов, например?

Не, ну я конечно каких-то тонкостей Дельфи и VCL не знаю, но не надо меня полным ослом считать :) Фреймы я знаю и активно их использовал.
Вот только не прикину, как фреймы относятся к теме данного топика.
Можешь поясните?


 
Alkid ©   (2007-11-07 10:23) [160]


> Код, приведенный в ссылке [130] ужасен. Причем как С#, так
> и C++. Я уж не говорю, что на моем ноуте в release версии
> C# обставил C++. Даже, пардон, не в 10 раз.

Что конкретно там тестировалось? Код из [130]?
А методику можешь рассказать?
Просто разные исследования авторитетно заявляют разные вещи, от превосходства кода С# над С++ на порядок по скорости выполнения до наоборот.


 
Юрий Зотов ©   (2007-11-07 10:37) [161]

> Alkid ©   (07.11.07 10:20) [159]

Ошибся человек. Посчитал, что речь идет о визуальных контейнерах.
:о)


 
Alkid ©   (2007-11-07 10:43) [162]


> Ошибся человек. Посчитал, что речь идет о визуальных контейнерах.

А может не ошибся. Может он стандартно для хранения списка строк в своём проекте использует TListView или TMemo :)


 
Юрий Зотов ©   (2007-11-07 10:57) [163]

> Alkid ©   (07.11.07 10:43) [162]

А че? Отличные контейнеры.
:о)

============

И кто скажет, что это девочка, пусть первым бросит в меня камень.
(с) Ося Б.


 
boa_kaa ©   (2007-11-07 12:03) [164]


> homm ©   (07.11.07 09:55) [158]

Я сказал релиз - значит релиз.

> Alkid ©   (07.11.07 10:23) [160]

Просто откомпилировал и запустил то, что дано по ссылке. Кстати, сейчас проверил на работе. То же самое:
Результаты:
C++: 2046 ms
C#: 0,002sec. = 2 ms
Могу скриншоты показать.

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

Если будет сегодня время, тоже померяю их этими... ;)


 
Ega23 ©   (2007-11-07 12:10) [165]


> Юрий Зотов ©   (07.11.07 10:57) [163]
>
> > Alkid ©   (07.11.07 10:43) [162]
>
> А че? Отличные контейнеры.
> :о)


Шутки-шутками, но
http://delphimaster.net/view/15-1193871434/


 
homm ©   (2007-11-07 12:20) [166]

> [164] boa_kaa ©   (07.11.07 12:03)
> Просто откомпилировал и запустил то, что дано по ссылке.

Начнем с того, что в [130] нет ссылок ;) Если ты имел ввимду ссылку из [131], то я ее тоже тестировал, у меня получилась разница в 8 раз не в пользу СиДиез в релизе, и раз в 10 медленее в дебаге.


 
boa_kaa ©   (2007-11-07 12:50) [167]


> homm ©   (07.11.07 12:20) [166]
> Начнем с того, что в [130] нет ссылок ;)

Промахнулся :)

> у меня получилась разница в 8 раз не в пользу СиДиез в релизе,
>  и раз в 10 медленее в дебаге

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

Я реализовывал один и тот же алгоритм триангуляции Делоне на Delphi, C# и C++. Разница была, но незначительная (примерно 20% отклонения, C++ впереди). Я отношу ее на тот факт, что добиться полного соответствия в коде невозможно. К примеру, на C++ можно создать класс без new, а в C# и Delphi приходится использовать для этого структуры, что часто просто неудобно. Зато процесс разработки на C# несравнимо легче, чем даже в Delphi.


 
homm ©   (2007-11-07 12:53) [168]

> [167] boa_kaa ©   (07.11.07 12:50)
> Я реализовывал один и тот же алгоритм триангуляции Делоне
> на Delphi, C# и C++.

А можно выложить куданить? Мне бы дома было бы интересно помотреть. Или на мыло в анкете.


 
Alkid ©   (2007-11-07 13:02) [169]


> Шутки-шутками, но
> http://delphimaster.net/view/15-1193871434/

Да я это внутренне и поминал, когда писал :)
А для студенческих поделок это вообще - классика.


 
boa_kaa ©   (2007-11-07 13:37) [170]


> А можно выложить куданить? Мне бы дома было бы интересно
> помотреть. Или на мыло в анкете.

Можно. Но уже не сегодня. 2 кода нашел (Delphi и C#). Не могу найти от C++ (все в старых архивах).
Протестровал еще раз:
C#: 0.7 сек. для 1000 точек.
Delphi: 0.5 сек. для тех же 1000 точек.

Алгоритм там тоже старый, инкрементный сложности O(n2).
Как найду остальное - вышлю


 
Lamer@fools.ua ©   (2007-11-07 13:42) [171]

>>Mystic ©   (01.11.07 16:37) [80]

>Это мне показал cordbg.exe. Скомпилировано в релизе.

1.
Если не студией, а "csc.exe", то главное "/optimize+".

2.
(cordbg) m JitOptimizations 1
?

3.
FYI,
System.Runtime.InteropServices.Marshal.SizeOf(typeof(System.Drawing.Color)) = 24


 
Lamer@fools.ua ©   (2007-11-07 13:50) [172]

>>Lamer@fools.ua ©   (07.11.07 13:42) [171]

P.S.
Если же смотреть дизассемблер в VS, то стОит иметь в виду опции:
* Debugging | Suppress JIT optimization on module load (Managed Only)
* Debugging | Enable Just My Code


 
Lamer@fools.ua ©   (2007-11-07 13:53) [173]

Прочитал http://rsdn.ru/forum/Message.aspx?mid=2544936
Похоже, всё сложнее :-)


 
pasha_golub ©   (2007-11-07 14:15) [174]


> vpbar ©   (01.11.07 14:05) [29]
>
> Alkid ©   (01.11.07 13:58) [27]
> Для таких случаев можно симулировать :)
> http://www.delphikingdom.com/asp/viewitem.asp?catalogid=744
> и ww.delphikingdom.com/asp/viewitem.asp?catalogid=453 есть
> статья получше. Но ссылку не помню.
>

Ребяты. А там пусто. Не могу я скачать Tems_Pub.zip

Други, киньте мне на мыло шоли pasha_golub (at) yahoo.com  - попробовать хоцца. А то действительно запаривает контейнеры рисовать :)


 
Фрейм   (2007-11-08 02:33) [175]


> Alkid ©   (07.11.07 10:20) [159]
> Не, ну я конечно каких-то тонкостей Дельфи и VCL не знаю,
>  но не надо меня полным ослом считать :) Фреймы я знаю и
> активно их использовал.
> Вот только не прикину, как фреймы относятся к теме данного
> топика.
> Можешь поясните?


Я хочу просто понять в чём проблема с написанием этих контейнеров, и поискать её решение без использования шаблонов.

Можно хотя бы пример того кода который вы по многу раз писали?


 
Джо ©   (2007-11-08 04:41) [176]

> [175] Фрейм   (08.11.07 02:33)
>
> > Alkid ©   (07.11.07 10:20) [159]
> > Не, ну я конечно каких-то тонкостей Дельфи и VCL не знаю,
>
> >  но не надо меня полным ослом считать :) Фреймы я знаю
> и
> > активно их использовал.
> > Вот только не прикину, как фреймы относятся к теме данного
>
> > топика.
> > Можешь поясните?
>
>
> Я хочу просто понять в чём проблема с написанием этих контейнеров,
> и поискать её решение без использования шаблонов.
>
> Можно хотя бы пример того кода который вы по многу раз писали?

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


 
Alkid ©   (2007-11-08 12:26) [177]


> Я хочу просто понять в чём проблема с написанием этих контейнеров,
>  и поискать её решение без использования шаблонов.
>
> Можно хотя бы пример того кода который вы по многу раз писали?

Очень просто : есть свои классы, надо под них забацать контейнеры.
Например, есть некий TMyClass. Можно его коллекции хранить тремя способами:
1. Использовать TObjectList. Проблема в том, что этот подход не типобезопасен, т.е. в контейнер по ошибке может быть положено нечто левое. Да и при взятии элемента приходится каждый раз писать:
myClassRef := TMyClass(Container[index]);
либо:
myClassRef := Container[index] as TMyClass;

При том, что и так жить можно, меня это в целом не устраивает.

2. Содзать один универсальный контейнер (TSafeTypedObjectList), в котором проверка типов производится в Run-Time с использованием RTTI.
Уже лучше, чем первый вариант, но:
 1. Низкая производительность операции добавления эелмента.
 2. Обшибуки ловятся в Run-Time.
 3. Явное приведение типов при взятии элемента остаётся

3. Создавать специализированные контейнеры (TMyClassList), в которых самому определять все методы (Add, Remove, Get, и проч.) с использованием своего типа. Тут всё замечательно: статическая проверка типов на этапе компиляции, нет ненужных накладных расходов и нет приведений типов. Но приходится писать однобразный и на 90% повторяющийся код, различающийся только именами типов. Вот тут шаблоны и нужны - они позволяют делать статически типизированные контейнеры для заданных классов (т.е. получить все их преимущества) без необходимости прерписывать кучу почти одинакового кода вручную (т.е. устраняя главный их недостаток).

И при чём тут фреймы?


 
Фрейм   (2007-11-09 02:06) [178]


> Alkid ©   (08.11.07 12:26) [177]
> Но приходится писать однобразный и на 90% повторяющийся
> код, различающийся только именами типов.


А просто скопировать код и автозамену сделать нельзя? И если можно, то разве это долго?


 
celades ©   (2007-11-09 09:25) [179]


> А просто скопировать код и автозамену сделать нельзя? И
> если можно, то разве это долго?
>

это не долго, это глупо.


 
Alkid ©   (2007-11-09 10:26) [180]


> А просто скопировать код и автозамену сделать нельзя? И
> если можно, то разве это долго?

Можно но если всякое дублирование кода есть зло, то дублирование кода путём Copy/Paste есть зло в квадрате. Вообще-то, это азы правильного проектирования программ.


 
Mystic ©   (2007-11-09 12:44) [181]

> Alkid ©   (09.11.07 10:26) [180]

Слишком категорично. Какие проблемы возникают при Copy/Paste? (a) копирование ошибок (b) сложности с последующим внесением изменений. Соответственно, когда код отлажен или тривиален, а также самодостаточен (изменения в него не планируются), то Copy/Paste вполне допустимое решение. Например,


function Iif(Condition: boolean; TrueValue, FalseValue: Integer): Integer;
begin
 if Condition then Result := TrueValue else Result := FalseValue
end;


Ну и далее по мере необходимости

function Iif(Condition: boolean; TrueValue, FalseValue: string): string;
function Iif(Condition: boolean; TrueValue, FalseValue: TMyObject): TMyObject;
function Iif(Condition: boolean; TrueValue, FalseValue: WideString): WideString;

В данном случае от Copy/Paste опасности нет, разве только некоторым педантам будет действовать на нервы.

С другой стороны, человек, твердо уверовавший в то, что Copy/Paste зло, и пытающийся всеми силами от него избавится, имхо, иногда приносит даже больший вред, чем человек, делающий Copy/Paste. Иногда код только выглядит похожим образом, хотя алгоритмы разные. И когда человек пытается их объединить, то... потом в этом коде сам черт ногу сломит: метод обрастает флагами, в особо тяжких случаях используется полиморфизм, внесение изменений (которое обычно вносится только в один вариант) приводит к еще большему разбуханию кода, ...

Например, если если библиотека для игр, я все-таки предпочту, чтобы для каждой фигуры был отдельный не связанный с другими фигурами класс. Когда конь я китайских шахматах будет наследоваться от коня в обычных шахматах, пушка будет наследоваться от ладьи, лалья от пики в сеги... Один класс для короля, золотого и серебрянного генералов... Это надо пресекать на корню!


 
_Слоник   (2007-11-09 13:00) [182]

про производительность шарпа и оптимизацию (ссылка на исходную статью + обсуждение (особенно интересны последние комменты))
http://forum.vingrad.ru/forum/topic-180722/view-all.html


 
Alkid ©   (2007-11-09 14:28) [183]


> Mystic ©   (09.11.07 12:44) [181]

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

Конечно, если код тривиален, отлажен и не будет меняться, то его можно и тиражировать. Вот только 100% уверенности в этом быть не может. Мы не знаем будущего. А занимаясь копипастом мы на будущее себе подкладываем мину, если всё-таки окажется, что в коде есть ошибка или возникнет необходимость его модифицировать. Т.е. сужаем возможную свободу действий.

Касаемо вреда от особых умников, пытающихся избавиться от дублирующего кода флагами и полиморфизмом: конечно всё можно сделать через задницу. А можно и по-нормальному.

По поводу описанной библиотеки игр - это вообще бредовая ситуация, не имеющая ничего общего с удалением дублирующегося кода, а лишь иллюстрирующая, что гипотетический проектировщик просто ничерта не смыслит в ОО-проектировании.


 
Джо ©   (2007-11-09 14:30) [184]

Вот как-раз на днях избавился от кучи «лишнего» кода (на 70% дублирующегося по разным юнитам) с помощью полиморфизма.
Теперь вот сижу и гадаю — через Ж это было или не через Ж.
:)


 
Alkid ©   (2007-11-09 14:33) [185]


> Вот как-раз на днях избавился от кучи «лишнего» кода (на
> 70% дублирующегося по разным юнитам) с помощью полиморфизма.
>
> Теперь вот сижу и гадаю — через Ж это было или не через
> Ж.
> :)

:), ну, если у тебя остался "code smell" значит через Ж.  :)


 
Джо ©   (2007-11-09 14:48) [186]

> [185] Alkid ©   (09.11.07 14:33)
>
> > Вот как-раз на днях избавился от кучи «лишнего» кода (на
>
> > 70% дублирующегося по разным юнитам) с помощью полиморфизма.
> >
> > Теперь вот сижу и гадаю — через Ж это было или не через
>
> > Ж.
> > :)
>
> :), ну, если у тебя остался "code smell" значит через Ж.
> :)

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


 
Alkid ©   (2007-11-09 16:00) [187]


> Вроде уже два дня как не пахнет. :) Сегодня уже даже на
> дальнейшую работу пошло, до рефакторинга это было немыслимо.

Мда, а мне щас приходится с таким кодом, что от его "code smell" надо зажимать нос, рот, глаза и уши. Собственно по-этому я сейчас готов пришибить чем-нибудь тяжёлым любого, кто будет меня убеждать, что "дублирование кода, это вообщем-то и неплохо" :)


 
umbra ©   (2007-11-10 02:16) [188]

копипаст по ученому называется "editor inheritance" :)


 
Джо ©   (2007-11-10 02:28) [189]

> [188] umbra ©   (10.11.07 02:16)
> копипаст по ученому называется "editor inheritance" :)

Вот буржуи! До чего додумались :-D



Страницы: 1 2 3 4 5 вся ветка

Форум: "Прочее";
Текущий архив: 2007.12.09;
Скачать: [xml.tar.bz2];

Наверх





Память: 1.31 MB
Время: 0.047 c
2-1195133837
unnamed
2007-11-15 16:37
2007.12.09
TIdUDPServer и TIdUDPClient: проблема!(не знаю как её обозвать)


15-1194338110
Costy
2007-11-06 11:35
2007.12.09
Вопрос по литературе


1-1190366442
nali
2007-09-21 13:20
2007.12.09
Ошибка при динамическом создании компонента.


2-1195132279
outlaw
2007-11-15 16:11
2007.12.09
Форматный вывод в StringGrid


2-1194838802
d@nger
2007-11-12 06:40
2007.12.09
Jpeg и дата съемки





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский