Производительность управляемого и неуправляемого кода
От: void29091988  
Дата: 29.04.09 07:31
Оценка:
Добрый день, уважаемые участники форума!
Сегодня столкнулся с интересным фактом, который немного меня удивил.

Пишу 2 простейших приложения для записи в файл на управляемом(C#) и неуправляемом(C++) коде

#include <stdio.h>


class PerfCounter
    {
    public:
        LARGE_INTEGER _start;

        PerfCounter()
        {}
        /// <summary>
        /// Начинает подсчет вермени выполнения.
        /// </summary>
        void Start()
        {
            QueryPerformanceCounter(&_start);
        }

        /// <summary>
        /// Завершает полсчет вермени исполнения и возвращает время в секундах.
        /// </summary>
        /// <returns>Время в секундах потраченое на выполнение участка
        /// кода. Десятичная часть отражает доли секунды.</returns>
        float Finish()
        {
            LARGE_INTEGER finish;
            QueryPerformanceCounter(&finish);

            LARGE_INTEGER freq;
            QueryPerformanceFrequency(&freq);
            return (float)((finish.QuadPart - _start.QuadPart) / (float)freq.QuadPart);
        }
    };

int main(int argc, char* argv[])
{
    FILE* out = fopen("C:\\1\\1.txt", "a");
    char* buffer = new char[10000];
    for (int i = 0; i < 10000; i++)
        buffer[i] = 'D';
    PerfCounter pc;
    pc.Start();
    for (int i = 0; i < 10000; i++)
    fprintf(out, "%s", buffer);
    fclose(out);
    float t = pc.Finish();
    printf("%f", t);
    return 1;

}




    class Program
    {
        static void Main(string[] args)
        {
            char[] array = new char[10000];
            for (int i = 0; i < 10000; i++)
            {
                array[i] = 'D';
            }
            PerfCounter pc = new PerfCounter();
            pc.Start();
            using (StreamWriter writer = new StreamWriter(
                new FileStream(@"C:\1\2.txt", FileMode.Append, FileAccess.Write)))
            {
                for (int i = 0; i < 10000; i++)
                {
                    writer.Write(array);
                }
            }
            Console.WriteLine(pc.Finish());
        }
    }

    public class PerfCounter
    {
        Int64 _start;

        /// <summary>
        /// Начинает подсчет вермени выполнения.
        /// </summary>
        public void Start()
        {
            _start = 0;
            QueryPerformanceCounter(ref _start);
        }

        /// <summary>
        /// Завершает полсчет вермени исполнения и возвращает время в секундах.
        /// </summary>
        /// <returns>Время в секундах потраченое на выполнение участка
        /// кода. Десятичная часть отражает доли секунды.</returns>
        public float Finish()
        {
            Int64 finish = 0;
            QueryPerformanceCounter(ref finish);

            Int64 freq = 0;
            QueryPerformanceFrequency(ref freq);
            return (((float)(finish - _start) / (float)freq));
        }

        [DllImport("Kernel32.dll")]
        static extern bool QueryPerformanceCounter(ref Int64 performanceCount);

        [DllImport("Kernel32.dll")]
        static extern bool QueryPerformanceFrequency(ref Int64 frequency);
    }


Компилирую оба в релизе Вижуал Студией

И замеряю производительность, вот результаты 5 тестов(в секундах):


Управляемый код                         Неуправляемый код

2,57                                    3,17
2,86                                    3,57
2,97                                    3,00
3,35                                    3,12
2,66                                    3,09


Тестовые примеры, извлекающие данные из базы данных SqlServer дали еще большую разницу.

Это нормально? Мне казалось, что неуправляемый код должен давать преимущества в производительности...
Или я где то ошибаюсь?
Re: Производительность управляемого и неуправляемого кода
От: TK Лес кывт.рф
Дата: 29.04.09 07:47
Оценка:
Здравствуйте, void29091988, Вы писали:

V>Тестовые примеры, извлекающие данные из базы данных SqlServer дали еще большую разницу.


V>Это нормально? Мне казалось, что неуправляемый код должен давать преимущества в производительности...

V>Или я где то ошибаюсь?

1. Попробуйте для начала писать эквивалентный код.
2. Основные преимущества в производительности дают те или иные архитектурные решения — от "управляемости" это зависит мало.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Производительность управляемого и неуправляемого кода
От: _FRED_ Черногория
Дата: 29.04.09 07:52
Оценка:
Здравствуйте, void29091988, Вы писали:

V>Пишу 2 простейших приложения для записи в файл на управляемом(C#) и неуправляемом(C++) коде


Тесты не одинаковые: в сишной части отчёт времени начинается уже после открытия файлы, а в шарповой — до.

V>Это нормально? Мне казалось, что неуправляемый код должен давать преимущества в производительности...

V>Или я где то ошибаюсь?

Как мерил?
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Производительность управляемого и неуправляемого кода
От: void29091988  
Дата: 29.04.09 08:00
Оценка:
Здравствуйте, TK, Вы писали:

TK>1. Попробуйте для начала писать эквивалентный код.
TK>2. Основные преимущества в производительности дают те или иные архитектурные решения — от "управляемости" это зависит мало.


1. Честно говоря, всеми силами пытался писать правильный и объективный код. Мои познания в С++ ограничиваются семестровым курсом по программированию, потому буду очень признателен если объясните где я совершил ошибки и что можно улучшить.
2. Так или иначе, но контроль типов во время исполнения должен хоть немного замедлять программу. А по результатам теста видим обратное, вот что собственно меня удивило.
Re[2]: Производительность управляемого и неуправляемого кода
От: void29091988  
Дата: 29.04.09 08:05
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Тесты не одинаковые: в сишной части отчёт времени начинается уже после открытия файлы, а в шарповой — до.

_FR>Как мерил?

1. Хорошо, но это значит, что сишная часть будет выполняться еще дольше(плюс время на открытие), а значит производительность еще меньше.
2. То есть? По времени выполнения...
Re[3]: Производительность управляемого и неуправляемого кода
От: _FRED_ Черногория
Дата: 29.04.09 08:11
Оценка:
Здравствуйте, void29091988, Вы писали:

_FR>>Тесты не одинаковые: в сишной части отчёт времени начинается уже после открытия файлы, а в шарповой — до.

_FR>>Как мерил?

V>1. Хорошо, но это значит, что сишная часть будет выполняться еще дольше(плюс время на открытие), а значит производительность еще меньше.


Безполезно гадать

V>2. То есть? По времени выполнения...


В дебаг\релиз? Если релиз, то с какими опциями оптимизации С++? Из под студии запускал или нет? Нужно собрать релиз, подготовить NativeImage (для managed) и запускать "врукопашную".

Во-вторых, кажется, ты здесь меряешь, в основном, скорость IO (fprintf vs. Write) и не скорость выполнения.
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Производительность управляемого и неуправляемого кода
От: void29091988  
Дата: 29.04.09 08:35
Оценка:
Здравствуйте, _FRED_, Вы писали:

V>>2. То есть? По времени выполнения...


_FR>В дебаг\релиз? Если релиз, то с какими опциями оптимизации С++? Из под студии запускал или нет? Нужно собрать релиз, подготовить NativeImage (для managed) и запускать "врукопашную".


_FR>Во-вторых, кажется, ты здесь меряешь, в основном, скорость IO (fprintf vs. Write) и не скорость выполнения.


А, ну конечно компилил в релиз и запускал без студии. Оптимизация С++ — Maximize Speed(/O2);
После вашего сообщения полазил и поставил Favor Fast Code(/Ot) & Enable link-time code generation(/GL) & Enable Fiber-safe Optimization(/GT), что некоторым образом улучшило время выполнения — теперь оно отстает от управляемого кода всего на 7-8%.

Да, именно скорость IO, мне нужно улучшить производительность приложения во время работы с файловой системой(как вариант засчет неуправляемого кода), но что то пока не очень получается
Re[5]: Производительность управляемого и неуправляемого кода
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.04.09 08:58
Оценка: +2
Здравствуйте, void29091988, Вы писали:

V>Да, именно скорость IO, мне нужно улучшить производительность приложения во время работы с файловой системой(как вариант засчет неуправляемого кода), но что то пока не очень получается


Может лучше воспользоваться профайлером, и понять в чем проблема?
В любом случае управляемый код работает с файловой системой через WinAPI.
Re: Производительность управляемого и неуправляемого кода
От: Pavel Dvorkin Россия  
Дата: 29.04.09 09:21
Оценка: +1
Здравствуйте, void29091988, Вы писали:

V>Добрый день, уважаемые участники форума!


V> char* buffer = new char[10000];

V> for (int i = 0; i < 10000; i++)
V> buffer[i] = 'D';

Строка не заканчивается нулем.


V> PerfCounter pc;

V> pc.Start();
V> for (int i = 0; i < 10000; i++)
V> fprintf(out, "%s", buffer);

А поэтому fprintf будет выводить 10000 букв D и неизвестно сколько чего еще, пока не найдет какой-то 0 или не получит AV.

И второе. Форматный ввод/вывод — не самое подходящее место для того, чтобы делать выводы о производительности.
With best regards
Pavel Dvorkin
Re[2]: Производительность управляемого и неуправляемого кода
От: void29091988  
Дата: 29.04.09 09:40
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, void29091988, Вы писали:


V>>Добрый день, уважаемые участники форума!


V>> char* buffer = new char[10000];

V>> for (int i = 0; i < 10000; i++)
V>> buffer[i] = 'D';

PD>Строка не заканчивается нулем.



V>> PerfCounter pc;

V>> pc.Start();
V>> for (int i = 0; i < 10000; i++)
V>> fprintf(out, "%s", buffer);

PD>А поэтому fprintf будет выводить 10000 букв D и неизвестно сколько чего еще, пока не найдет какой-то 0 или не получит AV.


PD>И второе. Форматный ввод/вывод — не самое подходящее место для того, чтобы делать выводы о производительности.


Спасибо за идеи, давно на с++ ничего не писал — забыл уж) правда исправления:

char* buffer = new char[10000];
for (int i = 0; i < 9999; i++)
buffer[i] = 'D';
buffer[9999] = '\0';


и


for (int i = 0; i < 10000; i++)
fprintf(out, buffer);


дают точно такое же время выполнения
Re[3]: Производительность управляемого и неуправляемого кода
От: Pavel Dvorkin Россия  
Дата: 29.04.09 10:15
Оценка:
Здравствуйте, void29091988, Вы писали:

V>дают точно такое же время выполнения


Могу лишь повторить

Форматный ввод/вывод — не самое подходящее место для того, чтобы делать выводы о производительности.

Ты не производительность C++ против C# мерял, а качество реализации fprintf против writer.Write. А это вообще-то, малосущественно.
With best regards
Pavel Dvorkin
Re[3]: Производительность управляемого и неуправляемого кода
От: TK Лес кывт.рф
Дата: 29.04.09 10:20
Оценка:
Здравствуйте, void29091988, Вы писали:

V>2. Так или иначе, но контроль типов во время исполнения должен хоть немного замедлять программу. А по результатам теста видим обратное, вот что собственно меня удивило.


Контроль типов и в том и другом случае происходит на этапе компиляции. В двоичном же коде всегда ясно с каким типом в данный момент времени идет работа.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[5]: Производительность управляемого и неуправляемого кода
От: TK Лес кывт.рф
Дата: 29.04.09 10:24
Оценка: +1
Здравствуйте, void29091988, Вы писали:

V>Да, именно скорость IO, мне нужно улучшить производительность приложения во время работы с файловой системой(как вариант засчет неуправляемого кода), но что то пока не очень получается


Смотрите в сторону буферизации. Если надо считать "именно" ввод/вывод то, после каждой операции надо делать Flush и писать данные фиксированными кусками. В противном случае, меряется эффективность работы внутреннего буфера.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Производительность управляемого и неуправляемого кода
От: Александр Кузнецов Россия  
Дата: 29.04.09 10:55
Оценка: :)
Здравствуйте, void29091988, Вы писали:

V>Это нормально? Мне казалось, что неуправляемый код должен давать преимущества в производительности...

V>Или я где то ошибаюсь?

Подумай вот в каком направлении:
Когда ты компилиш программу в неуправляемый код, под какой процессор/версию ОС это компилится? Под тот, на котором прога будет выполняться, или под минимальную конфигурацию, для совместимости?
А если речь заходит об управляемом коде, то CLR делает из IL маш. код, заточенный под конкретное сочетание проца/ОС.

Т.е., если не отказываться от обратной совместимости, то на новых машинах управляемый код МОЖЕТ выполняться быстрее, чем неуправляемый.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
Re: Производительность управляемого и неуправляемого кода
От: Adriano  
Дата: 29.04.09 11:25
Оценка:
Здравствуйте, void29091988, Вы писали:

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

int main(int argc, char* argv[])
{
    FILE* out = fopen("C:\\1\\1.txt", "a");
    char* buffer = new char[10000];
    for (int i = 0; i < 10000; i++)
        buffer[i] = 'D';
    PerfCounter pc;
    pc.Start();
    for (int i = 0; i < 10000; i++)
        fwrite(buffer, 10000, 1, out);
    fclose(out);
    float t = pc.Finish();
    printf("%f", t);
    return 1;
Re[2]: Производительность управляемого и неуправляемого кода
От: void29091988  
Дата: 29.04.09 12:22
Оценка:
Здравствуйте, Александр Кузнецов, Вы писали:

АК>Здравствуйте, void29091988, Вы писали:


АК>Подумай вот в каком направлении:

АК>Когда ты компилиш программу в неуправляемый код, под какой процессор/версию ОС это компилится? Под тот, на котором прога будет выполняться, или под минимальную конфигурацию, для совместимости?
АК>А если речь заходит об управляемом коде, то CLR делает из IL маш. код, заточенный под конкретное сочетание проца/ОС.

АК>Т.е., если не отказываться от обратной совместимости, то на новых машинах управляемый код МОЖЕТ выполняться быстрее, чем неуправляемый.


блин, а ведь все правильно
Re[2]: Производительность управляемого и неуправляемого кода
От: void29091988  
Дата: 29.04.09 12:37
Оценка:
Здравствуйте, Adriano, Вы писали:

A>Здравствуйте, void29091988, Вы писали:


A>что бы тесты были одинаковыми попробуй заменить на fwrite, т.к. fprintf, сам понимаешь, парсит формат и ищет в буфере признак конца строки


A>
A>int main(int argc, char* argv[])
A>{
A>    FILE* out = fopen("C:\\1\\1.txt", "a");
A>    char* buffer = new char[10000];
A>    for (int i = 0; i < 10000; i++)
A>        buffer[i] = 'D';
A>    PerfCounter pc;
A>    pc.Start();
A>    for (int i = 0; i < 10000; i++)
A>        fwrite(buffer, 10000, 1, out);
A>    fclose(out);
A>    float t = pc.Finish();
A>    printf("%f", t);
A>    return 1;

A>


такой вариант работает дольше

вот нашел вариант низкоуровневой реализации:

    // открываем файл
    int fh = _open("file.dat",_O_RDWR | _O_BINARY);
    if (fh == -1)
    {
        // или при необходимости создаём новый
        fh = _creat("file.dat",_S_IREAD | _S_IWRITE);
        if (fh == -1)
            return 1;
    }

    // позиционируемся в конец файла
    _lseek(fh,0,SEEK_END);

    for (int i = 0; i < 10000; i++)
    // добавляем новую структуру
    _write(fh,&buffer,10000);


он работает быстрее первоначального варианта на с++ на 15-18% и быстрее варианта на управляемом коде на 4-5%
Re[4]: Производительность управляемого и неуправляемого кода
От: void29091988  
Дата: 29.04.09 12:37
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, void29091988, Вы писали:


V>>дают точно такое же время выполнения


PD>Могу лишь повторить


PD>Форматный ввод/вывод — не самое подходящее место для того, чтобы делать выводы о производительности.


PD>Ты не производительность C++ против C# мерял, а качество реализации fprintf против writer.Write. А это вообще-то, малосущественно.


спасибо, буду рыть ниже
Re[3]: Производительность управляемого и неуправляемого кода
От: hattab  
Дата: 29.04.09 14:26
Оценка: +3
Здравствуйте, void29091988, Вы писали:

АК>>Подумай вот в каком направлении:

АК>>Когда ты компилиш программу в неуправляемый код, под какой процессор/версию ОС это компилится? Под тот, на котором прога будет выполняться, или под минимальную конфигурацию, для совместимости?
АК>>А если речь заходит об управляемом коде, то CLR делает из IL маш. код, заточенный под конкретное сочетание проца/ОС.

АК>>Т.е., если не отказываться от обратной совместимости, то на новых машинах управляемый код МОЖЕТ выполняться быстрее, чем неуправляемый.


V>блин, а ведь все правильно


В теории.
Re[4]: Производительность управляемого и неуправляемого кода
От: Александр Кузнецов Россия  
Дата: 30.04.09 06:38
Оценка:
Здравствуйте, hattab, Вы писали:

H>Здравствуйте, void29091988, Вы писали:


АК>>>Подумай вот в каком направлении:

АК>>>Когда ты компилиш программу в неуправляемый код, под какой процессор/версию ОС это компилится? Под тот, на котором прога будет выполняться, или под минимальную конфигурацию, для совместимости?
АК>>>А если речь заходит об управляемом коде, то CLR делает из IL маш. код, заточенный под конкретное сочетание проца/ОС.

АК>>>Т.е., если не отказываться от обратной совместимости, то на новых машинах управляемый код МОЖЕТ выполняться быстрее, чем неуправляемый.


V>>блин, а ведь все правильно


H>В теории.


Я, поэтому, и выделил "МОЖЕТ"
Ежику понятно, что при прочих равных неуправляемый код быстрее. Хотя все, как обычно, зависит от кривизны ручек и настроек компилятора.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.