Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.11.09;
Скачать: CL | DM;

Вниз

Новые языковые возможности. Первые попытки...   Найти похожие ветки 

 
MBo ©   (2008-09-15 16:03) [0]

Пробую дженерики.
На примере линейного поиска в массиве. Глобальную параметризованную функцию создать компилятор не дает, так что делаю метод формы (можно сделать фиктивный объект с классовым методом, чтобы его не создавать)
Сравниваю по скорости сермяжный поиск, поиск с использованием функции сравнения, дефолтный интерфейс сравнения дженериков, и анонимную функцию сравнения.

uses
 ... Generics.Defaults

type
 TEqualFunc<T> = reference to function(X, Y: T): Boolean;
 TEqual = function(X, Y: Integer): Boolean;

 TForm3 = class(TForm)...
   function FindFirstValueSimple(const A: array of Integer; const Value: Integer): Integer;
   function FindFirstValueCompareFunc(const A: array of Integer; const Value: Integer; Equal: TEqual): Integer;
   function FindFirstValueComparer<T>(const A: array of T; const Value: T): Integer;
   function FindFirstValueAnonFunc<T>(const A: array of T; const Value: T; const Equal: TEqualFunc<T>): Integer;
 end;

var
 Form3: TForm3;

implementation

{$R *.dfm}

function UserTime: Int64;
var
 CreationT,ExitT,KernelT, UserT : _FILETIME;
begin
 GetProcessTimes(GetCurrentProcess, CreationT, ExitT,KernelT, UserT);
 Result := Int64(UserT) div 10000;
end;

function TForm3.FindFirstValueAnonFunc<T>(const A: array of T; const Value: T;
 const Equal: TEqualFunc<T>): Integer;
var
 i: Integer;
begin
 Result := -1;
 for i:= 0 to High(A) do
   if Equal(A[i], Value) then
     Exit(i);
end;

function TForm3.FindFirstValueCompareFunc(const A: array of Integer;
 const Value: Integer; Equal: TEqual): Integer;
var
 i: Integer;
begin
 Result := -1;
 for i:= 0 to High(A) do
   if Equal(A[i], Value) then
     Exit(i);
end;

function TForm3.FindFirstValueComparer<T>(const A: array of T; const Value: T): Integer;
var
 i: Integer;
begin
 Result := -1;
 for i:= 0 to High(A) do
   if TComparer<T>.Default.Compare(A[i], Value) = 0 then
     Exit(i);
end;

function TForm3.FindFirstValueSimple(const A: array of Integer;
 const Value: Integer): Integer;
var
 i: Integer;
begin
 Result := -1;
 for i:= 0 to High(A) do
   if A[i] = Value then
     Exit(i);
end;

function IntEqual(X, Y: Integer): Boolean;
begin
 Result := X = Y
end;

procedure TForm3.Button1Click(Sender: TObject);
var
 i, k, N: Integer;
 A: array of Integer;
 t0, t1, t2, t3, t4: Int64;
begin
 Randomize;
 N := 100000000;
 SetLength(A, N);
 for i := 0 to N - 1 do
   A[i] := Random(N);
 t0 := UserTime;
 k := FindFirstValueSimple(A, 1000);
 t1 := UserTime;
 k := FindFirstValueCompareFunc(A, 1000, IntEqual);
 t2 := UserTime;
 k := FindFirstValueComparer<Integer>(A, 1000);
 t3 := UserTime;
 k := FindFirstValueAnonFunc<Integer>(A, 1000, function(X, Y: Integer): Boolean begin Result := X = Y end);
 t4 := UserTime;
 Memo1.Lines.Add(Format("Indx: %d  Simple: %d  CompFunc: %d  GenComparer: %d  GenAnonFunc: %d",[k, t1-t0, t2-t1, t3-t2, t4 - t3]));
end;

end.


Indx: -1  // элемент не найден, макс. количество сравнений
Simple: 250
CompFunc: 500
GenComparer: 5109
GenAnonFunc: 625


 
MBo ©   (2008-09-15 16:07) [1]

При использовании анонимной функции - скорость вполне сравнима с работой процедуры с обычной глобальной функцией сравнения. В данном случае, когда почти ничего не делается, кроме этих самых сравнений, накладные расходы на вызов функций сравнения, конечно, велики.
Однако TComparer<T>.Default.Compare - ну ооочень медленно работает...


 
Tricky_   (2008-09-15 16:32) [2]

Кто нибудь бы знающий написал бы статью. Про нововведения. Его бы очень и очень много людей благодарило!
Особено про различие delphi 7 и 2009 - т.к. скоро много людей будет переходить с (5, 6) 7 на 2009.
2005-2007 многие не юзали, судя по форумам статьям, исходникам, - хватало и семерки.


 
Riply ©   (2008-09-15 16:42) [3]

Правда, у меня еще нет Delphi 2009 (эт временно),
но я присоединяюсь к пожеланию [2] Tricky_


 
Sapersky   (2008-09-15 16:53) [4]

Однако TComparer<T>.Default.Compare - ну ооочень медленно работает...

Здесь уже обсуждали:
http://delphimaster.net/view/15-1219512329/

Самое смешное, что сравнение на базе TypeInfo можно реализовать в Delphi... ну когда TypeInfo появилось - думаю, в D2. Хотя и без "гламурных" <T>, конечно.


 
KilkennyCat ©   (2008-09-15 17:15) [5]

А вот я наоборот, с 2007 ушел обратно на 7.
Но все равно, интересно...


 
pasha_golub ©   (2008-09-16 10:13) [6]

Так эта... если я буду использовать TList<T> , то метод IndexOf будет работать в 10 раз медленней, чем он работал в TList.IndexOf? Все верно?


 
MBo ©   (2008-09-16 10:33) [7]

>pasha_golub
для TList<Integer> у меня IndexOf получилось в 5 раз медленнее.
Заполнение  списка - незначительно медленнее.


 
_REA_   (2008-09-16 15:38) [8]

А почему? Разница то вроде только в синтаксисе...


 
pasha_golub ©   (2008-09-16 17:11) [9]


> MBo ©   (16.09.08 10:33) [7]


> для TList<Integer> у меня IndexOf получилось в 5 раз медленнее.

Однако, это очень и очень удручает.


 
MBo ©   (2008-09-16 17:28) [10]

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


 
jack128_   (2008-09-16 18:17) [11]


> Эх, не шаблоны это, совсем не шаблоны...

а это и не шаблоны. Это дженерики.


 
Sapersky   (2008-09-16 18:32) [12]

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

На глаз, по выложенному Generics.Defaults, для integer:
TComparer<T>.Default -> _LookupVtableInfo -> Comparer_Selector_Binary -> Compare_U4 (как TComparer.Default.Compare). Плюс ещё, вероятно, компилятор добавляет некоторое кол-во Addref/Release для всех интерфейсов, даже если там просто заглушки, как в случае Comparer"ов.

Чего я не понял - так это делается ли для обход вложенных типов, т.е. будут ли корректно сравниваться длинные строки в записях и т.п. Пока никакого обхода не вижу, вроде бы для tkRecord в _LookupVtableInfo просто вызывается Comparer_Selector_Binary и потом (для общего случая) Compare_Binary -> BinaryCompare.

Если не сложно - проверьте, сравните что-нибудь такое:
TMyRec = record
 Name : String;
 Value : Integer;
end;
Var v1, v2 : TMyRec;
v1.Name := "aaa";
v2.Name := "aa"; v2.Name := v2.Name + "a";
// указатели v1.Name и v2.Name разные, но строка одинаковая
// т.е. простой CompareMem даст неверный результат



Страницы: 1 вся ветка

Текущий архив: 2008.11.09;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.012 c
2-1222926225
tytus
2008-10-02 09:43
2008.11.09
idFTP докачка файла + чтение из файла


15-1221423082
Дмитрий С
2008-09-15 00:11
2008.11.09
еТикет


2-1222866483
Savek
2008-10-01 17:08
2008.11.09
Delphi 7 destruction


15-1221480224
MBo
2008-09-15 16:03
2008.11.09
Новые языковые возможности. Первые попытки...


3-1208872530
TADOCommand
2008-04-22 17:55
2008.11.09
выполнить и получить RowsAffected