Форум: "Прочее";
Текущий архив: 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.052 c