Re[12]: C# generics: Тормоза. Что я не так делаю?
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.01.05 01:41
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Ага, спасибо. Просто из чтения стандарта у меня сложилось ощущение, что даже не гарантируется, что sizeof(int) == sizeof(IntWrapper):


Не, это то работает. Только все способы обойти систему типа не безопасны. Так что если тебе нужно надежное решение, то вот так будет относительно обобщенно и быстро:
private T[] CreateArray(string fileName)
{
    using (BinaryReader reader =
        new BinaryReader(File.Open(fileName, FileMode.Open)))
    {
        long len = reader.BaseStream.Length / 4;
        T[] array = new T[len];

        for (int i = 0; i < len; i++)
            array[i] = CreateElement(reader.ReadInt32());

        return array;
    }
}

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

Ну, а самый быстрый и простой способ будет такой:
// Объявления констант для функции CreateFile
enum DESIRED_ACCESS : ulong
{
    GENERIC_READ = 0x80000000L,
    GENERIC_WRITE = 0x40000000L,
    GENERIC_EXECUTE = 0x20000000L,
    GENERIC_ALL = 0x10000000L,
};
enum SHARE_MODE : ulong
{
    FILE_SHARE_READ = 0x00000001,
    FILE_SHARE_WRITE = 0x00000002,
    FILE_SHARE_DELETE = 0x00000004
};
enum FLAGSANDATTRIBUTES : ulong
{
    FILE_ATTRIBUTE_READONLY = 0x00000001,
    FILE_ATTRIBUTE_HIDDEN = 0x00000002,
    FILE_ATTRIBUTE_SYSTEM = 0x00000004,
    FILE_ATTRIBUTE_DIRECTORY = 0x00000010,
    FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
    FILE_ATTRIBUTE_ENCRYPTED = 0x00000040,
    FILE_ATTRIBUTE_NORMAL = 0x00000080,
    FILE_ATTRIBUTE_TEMPORARY = 0x00000100,
    FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200,
    FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400,
    FILE_ATTRIBUTE_COMPRESSED = 0x00000800,
    FILE_ATTRIBUTE_OFFLINE = 0x00001000,
    FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
};
enum CREATION_DISPOSITION : ulong
{
    CREATE_NEW = 1, CREATE_ALWAYS, OPEN_EXISTING,
    OPEN_ALWAYS, TRUNCATE_EXISTING
};

const int INVALID_HANDLE_VALUE = -1;
const uint INVALID_FILE_SIZE = 0xFFFFFFFF;

// Объявление Win32 API-функции CreateFile
[DllImport("Kernel32.dll")]
private extern static int CreateFile(
    string lpFileName,                            // LPCTSTR - file name
    uint daDesiredAccess,                        // DWORD - access mode
    uint smShareMode,                            // DWORD - share mode
    int lpSecurityAttributes,                    // LPSECURITY_ATTRIBUTES - SD
    CREATION_DISPOSITION dwCreationDisposition,    // DWORD - how to create
    uint dwFlagsAndAttributes,                    // DWORD - file attributes
    int hTemplateFile                            // HANDLE - handle to template file
    );

[DllImport("Kernel32.dll")]
private extern static bool ReadFile(
    int hFile,                        // handle to file
    int[] IntWrapper,                    // data buffer
    uint nNumberOfBytesToRead,        // number of bytes to read
    ref uint lpNumberOfBytesRead,    // number of bytes read
    int lpOverlapped                // overlapped buffer
    );

далее просто:
uint len = (uint)new FileInfo(fileName).Length;
ReadFile(hInputFile, arrayOfIntWrapper, len, ref dwNumberOfBytesRead, 0);
... << RSDN@Home 1.1.4 beta 3 rev. 273>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: C# generics: Тормоза. Что я не так делаю?
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.01.05 01:41
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Честно говоря, больше всего напрягла необходимость дублировать код для каждого из тестов из-за отсутствия С++-подобных шаблонов без ограничений, присущих generics. Думаю, может, переписать тест на C++/CLI? Заодно увидим, может, там оптимизация удачнее


А в чем проблема?

ЗЫ

Вообще-то твой околотестовый код можно раза в два сплющить.
... << RSDN@Home 1.1.4 beta 3 rev. 273>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: C# generics: Тормоза. Что я не так делаю?
От: Павел Кузнецов  
Дата: 12.01.05 04:27
Оценка:
VladD2,

> ПК> Ага, спасибо. Просто из чтения стандарта у меня сложилось ощущение, что даже не гарантируется, что sizeof(int) == sizeof(IntWrapper):


> Не, это то работает. Только все способы обойти систему типа не безопасны.


Я тоже так думаю.

> Так что если тебе нужно надежное решение, то вот так будет относительно обобщенно и быстро:

>
> private T[] CreateArray(string fileName)
> {
>     using (BinaryReader reader =
>         new BinaryReader(File.Open(fileName, FileMode.Open)))
>     {
>         long len = reader.BaseStream.Length / 4;
>         T[] array = new T[len];
>
>         for (int i = 0; i < len; i++)
>             array[i] = CreateElement(reader.ReadInt32());
>
>         return array;
>     }
> }
>


Похоже на то, что и было, но немного "причесанное". В любом случае спасибо, вставлю эту версию.

> хотя начерта нужно обобщения для чтения встроенных типов фиксированного размера?


Читаются не встроенные типы: в одном из случаев читается IntWrapper.

> Ну, а самый быстрый и простой способ будет такой:

> <... простыня кода для импорта и вызова функции Win API пропущена ...>

Не, спасибо, я лучше по-простому
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[2]: C# generics: Тормоза. Что я не так делаю?
От: Павел Кузнецов  
Дата: 12.01.05 06:22
Оценка: :)
VladD2,

> ПК>(*) Правда, оказалось, что то ли сортировка там не вполне сортирует, то ли поиск не вполне ищет, то ли

>
> Прогаммисты хреновые...

Возможно. Код взят из твоего сообщения
Автор: VladD2
Дата: 25.10.04
. Функция сравнения осталась такой же, какой она была у тебя. Кста, данный казус лишний раз демонстрирует, что ни язык, ни среда исполнения не могут в достаточной степени ловить проявления небрежности

Мне было более-менее без разницы, что именно делает тест, абы это что-то было одним и тем же, как для C#, так и для C++. Это условие, имхо, выполнялось.

Твое наблюдение о переполнении верно. Интересно только, почему для IntWrapper и int была такая разница в быстродействии при том, что по идее работа делалась та же самая...

> В общем, нужно или делать проверку полноценной:

>
> return _value > r._value ? 1 : _value == r._value ? 0 : -1;
>


Ок, сделаем проверку "полноценной".

> ПК> в любом случае, алгоритмы и в C#, и в C++ одни и те же, так что на время, что нас и интересует, это влиять не должно.


> Ага. И главное полная гарантия, что переполнение обрабатывается одинаково и никаких проблем нет.


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



Единственное, просто поправить не получилось: увлекся обобщением и упрощением, пытаясь и в C# уменьшить дублирование кода Разница немного упала, 3-кратного преимущества C++, вроде, не наблюдается, теперь разрыв "всего лишь" в 2 раза. Но и тесты, в общем-то несколько изменились... Также можно заметить, что теперь в C# и int тормозит почти так же, как IntWrapper. Ниже привожу новые результаты и код, по просьбам телезрителей включая C++

D:\Users\Pavel\test\C#\sort\sort\bin\Release>sort.exe AdbeRdr60_enu_full.exe
Delegate...       Sort: 2218     (index: 2096905)
                         2296     (index: 2096905)
                         2296     (index: 2096905)
                         2437     (index: 2096905)
                         2296     (index: 2096905)
Comparer...       Sort: 1390     (index: 2096905)
                         1390     (index: 2096905)
                         1375     (index: 2096905)
                         1375     (index: 2096905)
                         1375     (index: 2096905)
Delegate (int)... Sort: 1968     (index: 2096905)
                         1968     (index: 2096905)
                         1953     (index: 2096905)
                         1968     (index: 2096905)
                         1984     (index: 2096905)
Comparer (int)... Sort: 1203     (index: 2096905)
                         1187     (index: 2096905)
                         1203     (index: 2096905)
                         1203     (index: 2096905)
                         1203     (index: 2096905)


D:\Users\Pavel\test\C++\sort\Release>sort.exe AdbeRdr60_enu_full.exe
Delegate...       Sort: 1157    (index: 2096905)
                         1188    (index: 2096905)
                         1141    (index: 2096905)
                         1125    (index: 2096905)
                         1125    (index: 2096905)
Comparer...       Sort: 657     (index: 2096905)
                         656     (index: 2096905)
                         656     (index: 2096905)
                         656     (index: 2096905)
                         657     (index: 2096905)
Delegate (int)... Sort: 1234    (index: 2096905)
                         1234    (index: 2096905)
                         1219    (index: 2096905)
                         1203    (index: 2096905)
                         1219    (index: 2096905)
Comparer (int)... Sort: 671     (index: 2096905)
                         657     (index: 2096905)
                         672     (index: 2096905)
                         656     (index: 2096905)
                         656     (index: 2096905)




using System;

struct IntWrapper : IComparable<IntWrapper>
{
     public IntWrapper(int value)
     {
         value_ = value;
     }

     public static bool operator <(IntWrapper l, IntWrapper r)
     {
         return l.value_ < r.value_;
     }

     public static bool operator >(IntWrapper l, IntWrapper r)
     {
         return l.value_ > r.value_;
     }

     public static bool operator ==(IntWrapper l, IntWrapper r)
     {
         return l.value_ == r.value_;
     }

     public int CompareTo(IntWrapper r)
     {
         return this > r ? 1 : this == r ? 0 : -1;
     }

     // Following are here just to keep the compiler silent.
     public static bool operator !=(IntWrapper l, IntWrapper r) { return l.value_ != r.value_; }
     public bool Equals(IntWrapper r) { return this == r; }
     public override bool Equals(Object r) { return this == (IntWrapper)r; }
     public override int GetHashCode() { return value_; }

     // private
     int value_;
};


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

interface IFactory<T>
{
     T Create(int value);
};

class Test<T, Comparer, Factory>
     where Comparer : IComparer<T>, new()
     where Factory : IFactory<T>, new()
{
     public Test(string name)
     {
         name_ = name;
         comparer_ = new Comparer();
     }

     public void Run(string fileName)
     {
         string prefix = name_ + "Sort: ";

         for (int i = 0; i < 5; ++i)
         {
             T[] array = CreateArray(fileName);
             T value = array[0];

             Console.Write(prefix + (int)Measure(delegate() { Sort(array); }));

             int index = Search(array, value);
             Console.WriteLine("\t (index: " + index + ")");

             if (i == 0)
                 prefix = new string(' ', prefix.Length);
         }
     }

     // private

     void Sort(T[] array)
     {
         Sort(array, 0, array.Length - 1);
     }

     void Sort(T[] array, int left, int right)
     {
         int i = left;
         int j = right;
         T center = array[(left + right) / 2];

         while (i <= j)
         {
             while (comparer_.Compare(array[i], center) < 0)
                 i++;

             while (comparer_.Compare(array[j], center) > 0)
                 j--;

             if (i <= j)
             {
                 T x = array[i];
                 array[i] = array[j];
                 array[j] = x;
                 i++;
                 j--;
             }
         }

         if (left < j)
             Sort(array, left, j);

         if (right > i)
             Sort(array, i, right);
     }

     int Search(T[] array, T value)
     {
         return BinarySearch(array, 0, array.Length, value);
     }

     int BinarySearch(T[] array, int lo, int hi, T value)
     {
         while (lo <= hi)
         {
             int i = (lo + hi) / 2;
             int cmpResult = comparer_.Compare(array[i], value);

             if (cmpResult == 0)
                 return i;
             else if (cmpResult < 0)
                 lo = i + 1;
             else
                 hi = i - 1;
         }

         return ~lo;
     }

     T[] CreateArray(string fileName)
     {
         Factory factory = new Factory();

         using (BinaryReader reader =
             new BinaryReader(File.Open(fileName, FileMode.Open)))
         {
             long len = reader.BaseStream.Length / 4;
             T[] array = new T[len];

             for (int i = 0; i < len; i++)
                 array[i] = factory.Create(reader.ReadInt32());

             return array;
         }
     }

     delegate void Action();
     double Measure(Action action)
     {
         DateTime start = DateTime.Now;
         action();
         DateTime end = DateTime.Now;
         return (end - start).TotalMilliseconds;
     }

     string name_;
     Comparer comparer_;
};


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

struct DirectComparer<T> : IComparer<T>
     where T : IComparable<T>
{
     public int Compare(T l, T r) { return l.CompareTo(r); }
     public bool Equals(T l, T r) { return l.CompareTo(r) == 0; }
     public int GetHashCode(T obj){ return obj.GetHashCode(); }
}

struct DelegateComparer<T> : IComparer<T>
     where T : IComparable<T>
{
     public int Compare(T l, T r) { return compare_element_(l, r); }
     public bool Equals(T l, T r) { return compare_element_(l, r) == 0; }
     public int GetHashCode(T obj){ return obj.GetHashCode(); }

     // private
     delegate int CompareElement(T x, T y);
     static CompareElement compare_element_ = delegate(T x, T y) { return x.CompareTo(y); };
}

struct IntWrapperFactory : IFactory<IntWrapper>
{
     public IntWrapper Create(int value) { return new IntWrapper(value); }
}

struct IntFactory : IFactory<int>
{
     public int Create(int value) { return value; }
}

class Program
{
     static void Main(string[] args)
     {
         RunTest<IntWrapper, DelegateComparer<IntWrapper>, IntWrapperFactory>(
             args[0], "Delegate...       ");

         // RunTest<IntWrapper, ???, IntWrapperFactory>(args[0], "CompareTo...");

         RunTest<IntWrapper, DirectComparer<IntWrapper>, IntWrapperFactory>(
             args[0], "Comparer...       ");

         RunTest<int, DelegateComparer<int>, IntFactory>(
             args[0], "Delegate (int)... ");

         // RunTest<int, ???, IntFactory>(args[0], "CompareTo (int)...");

         RunTest<int, DirectComparer<int>, IntFactory>(
             args[0], "Comparer (int)... ");
     }

     private static void RunTest<T, Comparer, Factory>(string fname, string test_name)
         where T : IComparable<T>
         where Comparer : IComparer<T>, new()
         where Factory : IFactory<T>, new()
     {
         Test<T, Comparer, Factory> test = new Test<T, Comparer, Factory>(test_name);
         test.Run(fname);
     }
}




IntWrapper.h
#pragma once

struct IntWrapper
{
public:
     IntWrapper(int value)
     : value_ (value)
     {
     }

     friend bool operator <(IntWrapper l, IntWrapper r)
     {
         return l.value_ < r.value_;
     }

     friend bool operator >(IntWrapper l, IntWrapper r)
     {
         return l.value_ > r.value_;
     }

     friend bool operator ==(IntWrapper l, IntWrapper r)
     {
         return l.value_ == r.value_;
     }

private:
     int value_;
};

template< class T >
int CompareTo( T l, T r )
{
     return l > r ? 1 : l == r ? 0 : -1;
}

Sort.h
#pragma once

#include <vector>

template< class T, template<class> class Comparer >
void Sort(std::vector<T>& v, std::size_t left, std::size_t right)
{
     std::size_t i = left;
     std::size_t j = right;
     T center = v[(left + right) / 2];

     while (i <= j)
     {
         while (Comparer<T>::compare(v[i], center) < 0)
             i++;

         while (Comparer<T>::compare(v[j], center) > 0)
             j--;

         if (i <= j)
         {
             T x = v[i];
             v[i] = v[j];
             v[j] = x;
             i++;
             j--;
         }
     }

     if (left < j)
         Sort<T, Comparer>(v, left, j);

     if (right > i)
         Sort<T, Comparer>(v, i, right);
}

template< class T, template<class> class Comparer >
void Sort(std::vector<T>& v)
{
     if (!v.empty())
         Sort<T, Comparer>(v, 0, v.size() - 1);
}

Search.h
#pragma once

#include <vector>

template< class T, template<class> class Comparer >
std::size_t
BinarySearch(std::vector<T> const& v, std::size_t lo, std::size_t hi, T value)
{
     while (lo <= hi)
     {
         std::size_t i = (lo + hi) / 2;
         int cmpResult = Comparer<T>::compare(v[i], value);

         if (cmpResult == 0)
             return i;
         else if (cmpResult < 0)
             lo = i + 1;
         else
             hi = i - 1;
     }

     return ~lo;
}

template< class T, template<class> class Comparer >
std::size_t
Search(std::vector<T> const& v, T value)
{
     return BinarySearch<T, Comparer>(v, 0, v.size(), value);
}

Test.h
#pragma once

#include <string>
#include <vector>
#include <fstream>

#include "Timer.h"
#include "Sort.h"
#include "Search.h"

template< class T >
void CreateArray(std::vector<T>& v, std::string const& fname)
{
     v.clear();

     std::filebuf reader;
     if (reader.open(fname.c_str(), std::ios::in | std::ios::binary))
     {
         int value;
         while (reader.sgetn(reinterpret_cast<char*>(&value), 4) == 4)
         v.push_back(T(value));
     }
}

template< class T, template<class> class Comparer >
void Test(std::string const& fname, std::string const& test_name)
{
     std::string prefix = test_name + "Sort: ";

     for (int i = 0; i < 5; ++i)
     {
         std::vector<T> v;
         CreateArray(v, fname);

         if ( !v.empty() )
         {
             T value = v[0];

             std::cout << prefix;

             Timer timer;
             Sort<T, Comparer>(v);
             std::cout << timer.time();

             std::cout
                 << "\t(index: "
                 << (unsigned)Search<T, Comparer>(v, value)
                 << ')'
                 << std::endl;

             if (i == 0)
                 prefix.assign(prefix.size(), ' ');
         }
     }
}

Timer.h
#pragma once

#include <ctime>

class Timer
{
public:
     Timer() { reset(); }

     void reset() { start_ = std::clock(); }

     std::clock_t time() const { return (std::clock() - start_) / ( CLOCKS_PER_SEC / 1000 ); }

private:
     std::clock_t start_;
};

Program.cpp
#include <boost/function/function2.hpp>

#include "Test.h"
#include "IntWrapper.h"

template< class T >
struct DirectComparer
{
     static int compare( T l, T r ) { return CompareTo(l, r); }
};

template< class T >
struct DelegateComparer
{
     static int compare(T l, T r) { return delegate(l, r); }
     static boost::function2<int, T, T> delegate;
};

template< class T >
struct Functor
{
     int operator()(T l, T r) const { return CompareTo(l, r); }
};

template< class T >
boost::function2<int, T, T>
DelegateComparer<T>::delegate = Functor<T>();

int main(int argc, char** argv)
{
     if ( argc <= 1 )
     {
         std::cout << "usage: <program> <filename>" << std::endl;
     }
     else
     {
        Test<IntWrapper, DelegateComparer>(argv[1], "Delegate...       ");
        Test<IntWrapper, DirectComparer>(argv[1],   "Comparer...       ");
        Test<int, DelegateComparer>(argv[1],        "Delegate (int)... ");
        Test<int, DirectComparer>(argv[1],          "Comparer (int)... ");
     }
}
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: C# generics: Тормоза. Что я не так делаю?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.01.05 10:36
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>struct DirectComparer<T> : IComparer<T>

ПК> where T : IComparable<T>
ПК>{
ПК> public int Compare(T l, T r) { return l.CompareTo(r); }
ПК> public bool Equals(T l, T r) { return l.CompareTo(r) == 0; }
ПК> public int GetHashCode(T obj){ return obj.GetHashCode(); }
ПК>}

В данном коде никакого инлайна не будет (веренее теле инлайна будет вызов l.CompareTo(r) вместо реальног сравнения) . Опять наступаешь на теже грабли.
Заметь для инта у тебя сразу скорость упала


ПК>struct DelegateComparer<T> : IComparer<T>

ПК> where T : IComparable<T>
ПК>{
ПК> public int Compare(T l, T r) { return compare_element_(l, r); }
ПК> public bool Equals(T l, T r) { return compare_element_(l, r) == 0; }
ПК> public int GetHashCode(T obj){ return obj.GetHashCode(); }

ПК> // private

ПК> delegate int CompareElement(T x, T y);
ПК> static CompareElement compare_element_ = delegate(T x, T y) { return x.CompareTo(y); };
ПК>}

Вот любители перегрузок. Вызов виртуальных (не инлайновых) компараторов не смущает. Или долго сделать специализацию компараторов конкретного типа, исключая виртуальность и используя инлайн????
Перегрузку операторов тебе не лень писать. Зачем такие сложности
и солнце б утром не вставало, когда бы не было меня
Re[8]: C# generics: Тормоза. Что я не так делаю?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.01.05 11:43
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Serginio1,


>> считывать в буффер byte[] , из которого через BlockCopy копировать в массив.


ПК>А можно ли через BlockCopy копировать побайтно в массив IntWrapper[]? Что-то я не нашел гарантий работоспособности этого способа в стандарте C#. По первому впечатлению попахивает использованием для аналогичных целей memcpy в C++ со всеми вытекающими.


По умолчанию для структур применяется LayoutKind.Sequential Поля структуру располагаются в памяти последовательно в том порядке, в котором они были описаны.
Что легко проверить через Marshal.SizeOf или вычислить размер массива в байтах через метод Buffer.
и солнце б утром не вставало, когда бы не было меня
Re[14]: C# generics: Тормоза. Что я не так делаю?
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.01.05 15:00
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Похоже на то, что и было, но немного "причесанное". В любом случае спасибо, вставлю эту версию.


Это и есть причесанное. Я взял твой код и выкинул не разумные моменты: убрал ArrayList, так как он приводит к боксингу (да и вообще зачем память дублировать?), вместо исключений сделал нормальную обработку конца файла, заменил неуклюжий try на using.

Могу предложить более экстровагантный способ на итераторах. Правда он будет процентов на 20% медленее. За-то красиво.

ПК>Читаются не встроенные типы: в одном из случаев читается IntWrapper.


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

ПК>Не, спасибо, я лучше по-простому


Кстати, это очень даже по простому и довольно надежно. Описывать АПИ-шные методы нужно ровно один раз. К тому же уже имеется описание. Маршалинг выделяет для промежуточного буфера защищенный участок памяти, так что если ты напортачишь, то будет максимум безобидное исключение (в отличии от IJW в МС++ где все на твоей совести). Ну, и скорость... наверное чуть выше будет.
... << RSDN@Home 1.1.4 beta 3 rev. 273>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: C# generics: Тормоза. Что я не так делаю?
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.01.05 15:00
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

>> Прогаммисты хреновые...


ПК>Возможно. Код взят из твоего сообщения
Автор: VladD2
Дата: 25.10.04
. Функция сравнения осталась такой же, какой она была у тебя.


А ты не обратил внимание, на то что все числа в тесте целые и меленькие?

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


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

А что касается защиты среды... Дык включив контроль переполнения и будет тебе счатье. Кстати, в VC есть такая опция? Я что-то с ходу не нашел.

ПК>Мне было более-менее без разницы, что именно делает тест, абы это что-то было одним и тем же, как для C#, так и для C++. Это условие, имхо, выполнялось.


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

ПК>Твое наблюдение о переполнении верно. Интересно только, почему для IntWrapper и int была такая разница в быстродействии при том, что по идее работа делалась та же самая...


Думаю, происки сырого оптимизатора. Все же VC уже более 10 лет, а оптимизатору дотнета 2 года, причем с дженириками он пока что вообще не встречался.

ПК>Ок, сделаем проверку "полноценной".


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

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

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


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

ПК>

ПК>Единственное, просто поправить не получилось: увлекся обобщением и упрощением, пытаясь и в C# уменьшить дублирование кода

Гы. Я изучение твоего кода сразу начал с вырезания лишнего жира. Если охота могу прислать солющен. Я там еще пару вариантов компареров забубенил.

ПК> Разница немного упала, 3-кратного преимущества C++, вроде, не наблюдается, теперь разрыв "всего лишь" в 2 раза.


Ты С++-ный проект выложил бы в файлы. Да и Шарповый тоже.

ПК> Но и тесты, в общем-то несколько изменились... Также можно заметить, что теперь в C# и int тормозит почти так же, как IntWrapper. Ниже привожу новые результаты и код, по просьбам телезрителей включая C++


Ты кстати, мерил бы вот этим: Точное измерение производительности в дотнете
Автор: VladD2
Дата: 23.04.03
.

Вот результаты твоего подтюнегого кода (в секундах, Load это скорость загрузки, корректность проверяется ассертами):
C:\MyProjects\Tests\PerfPK\PerfPK\bin\Release>PerfPK.exe
Framework version: 2.0.40607.16

Start DelegateTest`1 test  ...
        Load time: 0.265829
        Unsorted array check sum: 192090977768567
        value: 67324752
                                                Sort duration:    0.83459
        Index: 1320102
        array[index]: 67324752
        Sorted array check sum: 192090977768567

Start ComparableTest`1 test  ...
        Load time: 0.2612564
        Unsorted array check sum: 192090977768567
        value: 67324752
                                                Sort duration:    0.59322
        Index: 1320102
        array[index]: 67324752
        Sorted array check sum: 192090977768567

Start AbstractClassComparerTest`1 test  ...
        Load time: 0.2588181
        Unsorted array check sum: 192090977768567
        value: 67324752
                                                Sort duration:    0.71454
        Index: 1320102
        array[index]: 67324752
        Sorted array check sum: 192090977768567

Start InterfaceComparerTest`1 test with IntWrapperItfOnClassComparer ...
        Load time: 0.2576783
        Unsorted array check sum: 192090977768567
        value: 67324752
                                                Sort duration:    0.70451
        Index: 1320102
        array[index]: 67324752
        Sorted array check sum: 192090977768567

Start InterfaceComparerTest`1 test with IntWrapperItfOnStructComparer ...
        Load time: 0.2605197
        Unsorted array check sum: 192090977768567
        value: 67324752
                                                Sort duration:    1.07454
        Index: 1320102
        array[index]: 67324752
        Sorted array check sum: 192090977768567

С++-ного проекта небыло, так чта...

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

Кстати, ради хохмы скомпилируй тест на компиляторах отличных от VC. Думаю некоторые могут значительно слить. Особенно разные Борланды.
... << RSDN@Home 1.1.4 beta 3 rev. 273>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: C# generics: Тормоза. Что я не так делаю?
От: VladD2 Российская Империя www.nemerle.org
Дата: 12.01.05 15:40
Оценка: :)))
Здравствуйте, Serginio1, Вы писали:

S> В данном коде никакого инлайна не будет (веренее теле инлайна будет вызов l.CompareTo(r) вместо реальног сравнения) . Опять наступаешь на теже грабли.

S> Заметь для инта у тебя сразу скорость упала

+1

S>Вот любители перегрузок. Вызов виртуальных (не инлайновых) компараторов не смущает. Или долго сделать специализацию компараторов конкретного типа, исключая виртуальность и используя инлайн????

S> Перегрузку операторов тебе не лень писать. Зачем такие сложности

Гы. Думаю что он ради этого эти тесты и писал. Хотел убедиться, что пока у С++ кое-какие приемущества по оптимизации остались. Возможно даже малость в душе покоробило, что разница не ужасно большая.
... << RSDN@Home 1.1.4 beta 3 rev. 273>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: C# generics: Тормоза. Что я не так делаю?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.01.05 15:57
Оценка: 21 (1)
Здравствуйте, VladD2, Вы писали:


VD> Гы. Думаю что он ради этого эти тесты и писал. Хотел убедиться, что пока у С++ кое-какие приемущества по оптимизации остались. Возможно даже малость в душе покоробило, что разница не ужасно большая.


Вообщето не совсем корректно сравнивать бэтту с отлаженным механизмом. А вот тенденции развития и совершенствования дженериков и оптимизации на лицо. А все остальное наживное. Москва не сразу строилась ... траля — ля (почему то нет смайлика пЕвца (одни пИвцы ))
и солнце б утром не вставало, когда бы не было меня
Re[15]: C# generics: Тормоза. Что я не так делаю?
От: Павел Кузнецов  
Дата: 12.01.05 20:43
Оценка:
VladD2,

> ПК> Читаются не встроенные типы: в одном из случаев читается IntWrapper.


> Ну не будет подобного кода в реальных приложениях.


Мне достаточно того, что по меньшей мере в данном тестовом приложении он мне понадобился. Писать два раза одно и то же для int и для IntWrapper, если этого возможно относительно легко избежать, я не собираюсь даже в тесте, тем более, если это не относится к тестируемым аспектам.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[4]: C# generics: Тормоза. Что я не так делаю?
От: Павел Кузнецов  
Дата: 12.01.05 21:08
Оценка: 1 (1)
VladD2,

> ПК>Ок, сделаем проверку "полноценной".


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

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

Мне охота посмотреть возможно ли на Шарпе эффективно писать generic код, работающий с value-типами, и если возможно, насколько легко это дается. Пока, кажется, что нелегко.

> ты меряешь на грани разумного. Здесь любая мелочь может дать разницу в два-три раза.


Для C++ это не так: обычно abstraction penalty колеблется в пределах десятка процентов, если вообще присутствует.

> Это уже не архитектурная разница, а борьба команд оптимизаторов.


Для меня больше вопрос не в абсолютных цифрах C# vs. C++, а в относительных: насколько падает быстродействие C# для арифметики и около того при использовании мало-мальской абстракции над встроенными типами и попытках повторного использования кода. Пока результаты не радуют.

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


Да, конечно, было бы интересно.

> Ты С++-ный проект выложил бы в файлы. Да и Шарповый тоже.


Я выложил полные листинги всех файлов, которые использовал.

> ПК> Но и тесты, в общем-то несколько изменились... Также можно заметить, что теперь в C# и int тормозит почти так же, как IntWrapper. Ниже привожу новые результаты и код, по просьбам телезрителей включая C++

>
> Ты кстати, мерил бы вот этим: Точное измерение производительности в дотнете
Автор: VladD2
Дата: 23.04.03
.


Для этих тестов мне вполне достаточно используемой точности.

> Вот результаты твоего подтюнегого кода (в секундах, Load это скорость загрузки, корректность проверяется ассертами): <...> С++-ного проекта небыло, так чта...


Гм... В том же сообщении полный код на C++

> А вот сам проект.


Ok, посмотрю.

> Кстати, ради хохмы скомпилируй тест на компиляторах отличных от VC. Думаю некоторые могут значительно слить. Особенно разные Борланды.


С удовольствием, если руки дойдут.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: C# generics: Тормоза. Что я не так делаю?
От: TK Лес кывт.рф
Дата: 12.01.05 21:45
Оценка: 21 (1) +1 :)
Hello, "Павел Кузнецов"

> Для меня больше вопрос не в абсолютных цифрах C# vs. C++, а в относительных: насколько падает быстродействие C# для арифметики и около того при использовании мало-мальской абстракции над встроенными типами и попытках повторного использования кода. Пока результаты не радуют.

>

Два раза это так плохо? Если зависимость линейная и проект на год/полтора, то можно все на intel списать
Плюс, обычно оптимизировать нужно не все приложение, а лишь небольшую его часть — эту часть вполне можно сделать на управляемой версии C++
Posted via RSDN NNTP Server 1.9
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[4]: C# generics: Тормоза. Что я не так делаю?
От: Павел Кузнецов  
Дата: 13.01.05 02:13
Оценка: :)
Serginio1,

> ПК>struct DirectComparer<T> : IComparer<T>

> ПК> where T : IComparable<T>
> ПК>{
> ПК> public int Compare(T l, T r) { return l.CompareTo(r); }
>
> В данном коде никакого инлайна не будет (веренее теле инлайна будет вызов l.CompareTo(r) <...>

Ох, точно, "опять об Гоголя" Ща попробуем по-другому

> ПК> static CompareElement compare_element_ = delegate(T x, T y) { return x.CompareTo(y); };


> Вот любители перегрузок. Вызов виртуальных (не инлайновых) компараторов не смущает. Или долго сделать специализацию компараторов конкретного типа, исключая виртуальность и используя инлайн????


Кажется, я начинаю понимать. Чтобы писать относительно эффективный обобщенный код на C#, его в определенных местах нужно разбавлять копипастой

> Перегрузку операторов тебе не лень писать. Зачем такие сложности


Что значит "сложности"? Я хочу повторно использовать один раз написанные функции, а не плодить вместо них "ускорители" В голове в качестве "жизненного" примера я держу шаблоны классов, встречавшихся в реальных проектах: "маленькие" вектора:Vector2<T>, Vector3<T>, Vector4<T> (можно еще обобщить, сделав Vector<dimension,T>); соответствующие им "маленькие" матрицы: Matrix2x2<T> и т.п. Как только начинаются сколько-нибудь существенные вычисления, там очень быстро устаешь размножать копипастой всевозможные операции с векторами и матрицами; да еще и ошибки надоедает вылавливать. Естественно, хочется все это дело один раз написать, и везде использовать. То, что видно в тестовом коде только обозначает характерные моменты.

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

Ладно, на что не пойдешь в целях эксперимента... Ща, для сравнения, наколбасим "ручных" специализаций.

P.S. Кста, в плюсовом коде, что выложен в прошлом сообщении, потенциальная ошибка: там напрасно сделана замена int -> std::size_t в Search.h. Похоже, если это дело дальше развивать, нужно взять какую-нибудь реализацию сортировки и т.п., устойчивой к подобным изменениям...
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[6]: C# generics: Тормоза. Что я не так делаю?
От: Павел Кузнецов  
Дата: 13.01.05 04:33
Оценка: 3 (2) -1
TK,

> Два раза это так плохо?


В основном — не очень. Иногда — плохо. Легко можно представить, что может означать уменьшение FPS в два раза для какого-нибудь видеоплеера. (*)

> Если зависимость линейная и проект на год/полтора, то можно все на intel списать Плюс, обычно оптимизировать нужно не все приложение, а лишь небольшую его часть — эту часть вполне можно сделать на управляемой версии C++


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

Мне как раз и интересно, какая там зависимость "штрафов" от повышения уровня абстракции и повторного использования кода (**), и насколько легко оптимизировать тормозящие части. Далеко не всегда можно легко переписать часть приложения на другом языке: из этих оптимизируемых частей запросто может потребоваться вызывать остальные части, что легко может повлечь дублирование ощутимых кусков, т.к., например, пересечение границы managed/unmanaged, насколько я понимаю, тоже далеко не бесплатно.

Кроме того, мне интересны последствия решений, принятых относительно дизайна generics. Например, одно из далеко не всегда приятных последствий — необходимость в модификации generics, которые используют другие generics, при добавлении новых ограничений на аргументы последних. Это в некотором роде можно рассматривать как нарушение инкапсуляции, т.к. все generic пользователи generic сущностей вынужденно "знают" о потребностях последних.

Соответственно, пока что мне интересны варианты обхода тормозов и проблем с повторным использованием кода именно в рамках C#.



(*) Disclaimer для особо горячих товарищей: это не означает, что generics/.Net/C#/whatever будут автоматически замедлять все в два раза, а только лишь является суждением о том, плохо ли само по себе замедление в 2 раза

(**) Прошу не смешивать с повторным использованием компонентов.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[5]: C# generics: Тормоза. Что я не так делаю?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.01.05 10:42
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:


>> Вот любители перегрузок. Вызов виртуальных (не инлайновых) компараторов не смущает. Или долго сделать специализацию компараторов конкретного типа, исключая виртуальность и используя инлайн????


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


>> Перегрузку операторов тебе не лень писать. Зачем такие сложности


ПК>Что значит "сложности"? Я хочу повторно использовать один раз написанные функции, а не плодить вместо них "ускорители" В голове в качестве "жизненного" примера я держу шаблоны классов, встречавшихся в реальных проектах: "маленькие" вектора:Vector2<T>, Vector3<T>, Vector4<T> (можно еще обобщить, сделав Vector<dimension,T>); соответствующие им "маленькие" матрицы: Matrix2x2<T> и т.п. Как только начинаются сколько-нибудь существенные вычисления, там очень быстро устаешь размножать копипастой всевозможные операции с векторами и матрицами; да еще и ошибки надоедает вылавливать. Естественно, хочется все это дело один раз написать, и везде использовать. То, что видно в тестовом коде только обозначает характерные моменты.


Вообще под Net техника программирования несколько другая, чем в нативе, то что для натива хорошо то для манагед плохо. В данном случае непонятно зачем городить DirectComparer<T> , вместо специализации структуры для конечного типа struct ComparerInt : IComparer<int>
.
Техника перегрузки операторов решается через интерфейс с методами Great,Less,Equals,GreatOrEquals итд.
(при QuicSort оператора на равенство не нужно, а значит и лишние тики выигрываются). И при соответсвующей оптимизации они будут инлайнится так же как и при перегрузке операторов в шаблонах.
Ну и на худой конец еще существует и кодогенерация например R#

В любом случае интересно будет посмотреть на эти тесты после выхода релиза.
и солнце б утром не вставало, когда бы не было меня
Re: C# generics: Тормоза. Что я не так делаю?
От: Tom Россия http://www.RSDN.ru
Дата: 13.01.05 17:08
Оценка: :))
Ээээ. Паш а ты теперь будешь там на C#-пе писать? С плюсы как же? Не покидай нас!
Народная мудрось
всем все никому ничего(с).
Re[2]: C# generics: Тормоза. Что я не так делаю?
От: Павел Кузнецов  
Дата: 13.01.05 17:36
Оценка:
Tom,

> Ээээ. Паш а ты теперь будешь там на C#-пе писать? С плюсы как же? Не покидай нас!


Пока планов писать что-нибудь кроме тестов на C# у меня нет (разве что, если в web какой-нить занесет). (По крайней мере пока) к C# у меня интерес исключительно академический. Интересно смотреть на все (новые) языки. Просто, наконец, получилось немного с C# generics поиграться, а не только в черновиках стандарта читать. Соответственно, и вопросы появились практического характера.
Posted via RSDN NNTP Server 1.9
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[16]: C# generics: Тормоза. Что я не так делаю?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.01.05 23:53
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

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


Бога ради, только не нужн делать далеко идущие выводы.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: C# generics: Тормоза. Что я не так делаю?
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.01.05 23:53
Оценка: 15 (1) :)
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>В основном — не очень. Иногда — плохо. Легко можно представить, что может означать уменьшение FPS в два раза для какого-нибудь видеоплеера. (*)


Да откуда ты взял понижение FPS в два раза? На основании того что листья желтые сделал предположение о скором конце света? Выбрал редковстречающийся и самый сложный для оптимизации сценарий и сделал на его базе выводы об общей производительности. В 99% разницы не вооруженным взглядом ты не заметишь. Например, воспользуйся в своем С++-ном тесте С-шной функций qsort и погляди на результат. Что на базе их можно сделать, что С нельзя использовать для высокопроизводительных программ?

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


Блин, зависимость такая. 2 раза можно получить при самх наихудших условиях. Ну, если конечно не воспользоваться готовым тормозным кодом. Обычно проигрыш колеблится в раене от 5-20 процентов. А это вообще не заметно на гляз. Более того я тебе уже приводил случаи когда при портировании 3D-движка с С++ на C# он стал быстрее. Так что кончай заниматься самовнушением.

ПК>Мне как раз и интересно, какая там зависимость "штрафов" от повышения уровня абстракции и повторного использования кода (**),


Зависит от абстракции. Ты измеряешь скорость косвенного вызова по отношению к скорости прямого или вообще заинлайненного. Тут как никрути разница будет всегда нехилой. Особенно с VC который и устранять виртуальность умеет, и инлайнинг делает на раз. А ты вот с Борландом сравни. У него с этим тоже не здорово.

ПК> и насколько легко оптимизировать тормозящие части.


Блин, ну, напиши версию без компареров (специализированную) и увидишь, что разницы почти нет. Если тебе нужен именно сортировка, то можешь создать МС++-проект и на рем реализовать нужный шаблон, а потом обернуть его специализации в менеджед-обертку. Прокт просто подключить к проекту на Шарпе и использовать как библиотеку.

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


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

Кстатит, по хорошему чтобы понять что происходит нужно получить ассемблерные листинги и сравнить их.

ПК>Кроме того, мне интересны последствия решений, принятых относительно дизайна generics. Например, одно из далеко не всегда приятных последствий — необходимость в модификации generics, которые используют другие generics, при добавлении новых ограничений на аргументы последних.


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

ПК> Это в некотором роде можно рассматривать как нарушение инкапсуляции, т.к. все generic пользователи generic сущностей вынужденно "знают" о потребностях последних.


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

ПК>Соответственно, пока что мне интересны варианты обхода тормозов и проблем с повторным использованием кода именно в рамках C#.


Да не надо обходить то чего нет. Менеджед код компилируется в нэйтив код. Есть пара набор операций который более дорог нежели в анменеджед мире. Но есть и более дешевый. Из дорогого:
1. Вызов делегатов в 2-3 дороже виртуального вызова (ранее было в 20-40 раз).
2. Модификация ссылочных полей медленее примерно в два-три раза за счет writw-барьера (специального кода отслеживающего ссылки из старых поколений и ускоряющего ЖЦ). Во втором фрэймворке встроены нехилые оптимизации удаляющие райт барьер для массивов и нвых объектов (пока что только внутри функции).
3. Вызво методов интерфейсов в 1.5 раза медленее обычного виртуального вызвоа. Это следствие довольно дурацкой реализации вызва метода интерфейса (с тройной косвинностью).
4. Приведение типов дороже чем стати-касты в С++. Их цена где-то сравнима с динамик-кастом (чуть быстрее чем динамик-каст).
5. Работа с финализируемыми объектами.
6. Есть неявнеы проверки выхода за границу массива. Но это фигня, так как подобные вещи выносятся из циклов и очень быстры.

Из того что быстрее:
1. Динамическое выделение памяти.
2. Приведение к интерфейсом (его по сути нет).
3. Освобождение памяти (его тоже нет). Вместо него живые объекты копируется в более старое поколение.


Все остальное приблизительно сравнимо с мнменеджед-кодом и является вопросом качества оптимизатора.

ПК>

ПК>(*) Disclaimer для особо горячих товарищей: это не означает, что generics/.Net/C#/whatever будут автоматически замедлять все в два раза, а только лишь является суждением о том, плохо ли само по себе замедление в 2 раза

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

Ну, и оптять же понятно, что все это вопрос качества оптимизации. О том, что над оптимизатором работы ведутся, ты знаешь и сам. Так что попрос не стоит даже обсуждения. Нужно дождаться релиза, а то и выхода Феникса.

ПК>(**) Прошу не смешивать с повторным использованием компонентов.


Ну, то-есть повторное использование бывает только на макросоподобной основе? А если я пользуюсь ООП, то это уже не кошерно и очень медленно?
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.