Форум: "Прочее";
Текущий архив: 2008.11.09;
Скачать: [xml.tar.bz2];
ВнизНовые языковые возможности. Первые попытки... Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.007 c