Проанализировав ошибки, допущенные нашими предшественниками, мы пришли к выводу, что нужен не один интегральный тест, а несколько маленьких независимых тестов. Каждый из них должен (по возможности) представлять собой узкую, но часто встречающуюся задачу. Главной задачей тестирования было определение скорости выполнения одного и того же алгоритма, скомпилированного разными компиляторами. Сначала пример реализовывался на C++, после чего переписывался на другие языки. При этом стояла задача переписать как можно ближе к эталону.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Может быть еще test1 := CTest1.Create(); в теле цикла напишем????????
Хотя в таком виде при c_iCount = 1000000000 это test1 := CTest1.Create();
особо не влияет на результат.
Код в VC6
CTest1 test1;
m_spIUtility->TimerStart();
for(int i = 0; i < c_iCount; i++) { test1.Inc(); }
m_spIUtility->TimerEnd(/*sbsInfo*/);
И код в Delphi
Utility1.TimerStart();
test1 := CTest1.Create(); ==================>>>> Это уже предвзятость!!!!!!!
for i := 0 To c_iCount do begin test1.Inc_m_i(); end;
Utility1.TimerEnd();
И ещё
Опираясь на свой опыт инлайн не всегда увеличиван\ет произвадительность. Когда достаточно много локальных переменных, они не могут все размещатся в РОН(регистрах общего назначения, их же всего 7, не считая ESP), компилятору приходится использовать стек! Пример: писал один алгоритм, разбил его на две функции, не-инлайн, произфодительность выросла на 10%!.
Хочу добавить от себя
Совершенно очевидный промах во floating point тесте:
Вместо
for(int i = 0; i < iInitVal; i++)
{
f0 = (f1 / (double)i/*деление на ноль!*/) f2 + (f3 * (double)i);
}
нужно бы написать
for(int i = 1 i < iInitVal; i++)
{
f0 +=/*накапливать результат, чтобы использовалась f0!!!*/ (f1 /(double)i/*нет деления на ноль!*/) — f2 + (f3 * (double)i);
}
чтобы компилятор не отбрасывал результат f0!
При таком виде картина резко меняется и компилятор Intel оказывается на 2 месте!(77.8-VC6, 78.3-IntelC++5.0.1 на машине Celeron800)
Скачал тесты, и ожидаемо (из результатов тестов) нашел некоторые некорректности в реализации тестов:
1. Удивило преимущество Делфи в скорости доступа к данным класса, смотрим в реализацию и видим, в С++
переменная класса объявлена статически, тогда как в Делфи это указатель, меняем в С++ на
динамическое создание и получаем абсолютно идентичные показатели, что и не удивительно учитывая код.
Объясняется тем, что в случае указателя (Self, this) хранится в регистре, а в случае статической
переменной перед каждым вызовом его (this) надо достать из стека.
2. А заявление о блокировках в библиотеке выделения памяти при компиляции Release версии в VC смехотворны,
без них нельзя, причем НУ НИКАК НЕЛЬЗЯ в многопоточных приложениях. Хотел бы я посмотреть как вы сделаете
многопоточное приложение на Делфи без установки глобальной переменной IsMultiThreaded в True. А эта
Есть еще несколько мелких замечаний (описывать лень :))
И самое главное замечание: тесты реализовывались везде похожим способом, НО сравнивалась производительность
конечных приложений, поэтому нужно было реализовывать оптимальным способом в каждом из языков, с
использованием всех их возможностей, а так получалось что избранный вариант реализации подходил больше под
какой-то один или два языка, а для остальных можно было бы добиться лучших результатов пойдя другим путем
(возможно :))
переменная как раз и отвечает за применение блокировок при выделении памяти. Справка: создание потоков
через Делфийский BeginThread и класс TThread автоматом проставляет эту переменную, а тех кто случайно
создал потоки через WinAPI и не установил перем., того ждут очень веселые сюрпризы особенно на
многопроцессорных машинах.
3. Также весело выглядит Float-test. Неужели нельзя было взять РЕАЛЬНУЮ задачу, у меня есть алгоритм
нахождения точки пересечения двух отрезков, который реально применяется в решении реальных задач, причем
количество обращений к нему в процессе работы программы достаточно велико. Он был реализован на
VC6, Delphi5, VB6: так вот Delphi оказалась самой медленной, более того она проиграла VC в ТРИ раза.
Да. Здесь все верно. Это промах. Интересно, что только bcc 5.5 выдал сообщение об ошибке. Остальные молча съели этот вариант и даже показали одинаковые результаты. При этом время выполнения теста Intel C++ compiler-ом изменилось. В третьей статье этого цикла приведен исправленный тест и корректировка выводов.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Во-первых это уже давно исправлено (см. код к третей версии статьи). Во-вторых, ты соизмеряешь скорость создания одного объекта и скорость выполнения теста? Это примерно 0.00001 процента.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
В скором времени на этом сайте появится продолжение данной статьи. В нем будут освещены: BCC 5.5, GCC и VC7. BCB нами не рассматривался, но можно предположить, что его результаты будет такими же как у BCC 5.5 (по крайней мере лучше они быть не должны). Пока продолжение доступно здесь: http://www.optim.ru/cs/2001/4/test2/test2.asp
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
> ...без них нельзя, причем НУ НИКАК НЕЛЬЗЯ в > многопоточных приложениях...
Блин, а никто не знал! Проблема не в 10% (которые могут дать бокировки), а в том, что стандартный хип начинает дико тормозить (в разы) на втором (и далее) проходе теста.
Кстати, о IsMultiThreaded я не знал. Что же попробовал с ней... Действительно скорость выполнения Delphi-йской замедлилась приблизившись к скорости показанной VC, но! Но VC-шный тест-то, был как раз скомпилирован в single-thread-версии. Так что он все равно проиграл, а сравнение было совершенно корректным. Более того. Сегодняшнее тестирование доказало, что реализация хипа в Delphi превосходит реализацию хипа в W2k, так как Delphi-ёвый тест проходит, в multi-thread-версии повторные тесты без задержек.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
> ...переменная класса объявлена статически, тогда > как в Делфи это указатель, меняем в С++ на > динамическое создание и получаем абсолютно > идентичные показатели
VC действительно зачем то лезет в стек, но это его личные проблемы (вернее разработчиков и продавцов). К тому же заявление "и получаем абсолютно идентичные показатели", мягко говоря не соответствует действительности. Я переделал тест и прогнал оба варианта по очереди несколько раз (на той же машине — AMD1400). Так вот скорость выполнения теста не изменилась! Так что наезд бессмысленный.
К тому же в inline-режиме VC стал бесспорным лидером, а в обычном победил не Дельфи, а C#. Просто сейчас на этом сайте есть ошибка. Думаю завтра исправят.
VC7 создал в точности такой же код вызова, но при этом, был быстрее (4.36 и в inline и не- режиме). Полностью его результаты мы опубликуем позже. Кстати, на одном из тестов (и не синтетическим как доступ к членам) он оказался значительно быстрее. Но всему свое время.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.