powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Производительность TDictionary
25 сообщений из 60, страница 1 из 3
Производительность TDictionary
    #39805114
Swv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте.

навострячил тут LRU простенький как часть более крупной задачи.
HashMap и список. HashMap на TDictionary<integer,TMyClass>

в задаче понатыкано счетчиков производительности. заместо AQtime )
И получилось, что очень большую часть времени отъедает LRU.
Начала смотреть и все уперлось в TDictionary

А точнее в map.ContainsKey(key) и в node:=map[key];

статистика по LRU примерно такая. Время в секундах

lru.get только hashmap 0,648279488394491 (map.ContainsKey(key) и node:=map[key])
lru.get только все остальное 0,408678524370626
lru.put 0,00645377100622397
get counter 3315095
put counter 7185

Собственно вопрос. А можно как то ускорить?) или это предел для TDictionary и вообще для hashmap?
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39805116
Swv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вернее даже так

lru.get только hashmap 0,961819743242614
lru.get только все остальное 0,159336854435245
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39805122
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Замени TEqualityComparer на свой.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
type

  TIntComp = class(TInterfacedObject, IEqualityComparer<integer>)
    function Equals(const Left, Right: integer): Boolean;
    function GetHashCode(const Value: integer): Integer;
  end;

  TStringComp = class(TInterfacedObject, IEqualityComparer<string>)
    function Equals(const Left, Right: string): Boolean;
    function GetHashCode(const Value: string): Integer;
  end;

{ TIntComp }

function TIntComp.Equals(const Left, Right: integer): Boolean;
begin
  Result:=Left=Right;
end;

function TIntComp.GetHashCode(const Value: integer): Integer;
begin
  Result:=Value;
end;

{ TStringComp }

function TStringComp.Equals(const Left, Right: string): Boolean;
begin
  Result:=Left=Right;
end;

{$OverFlowChecks OFF}
function TStringComp.GetHashCode(const Value: string): Integer;
var
  a : Integer;
  i : Integer;
begin
  Result:=0;
  a:=63689;
  for i:=0 To Length(Value)-1 do begin
    Result:=Result*a+PWordArray(Value)[i];
    a:=a*378551;
  end;
end;
{$OverFlowChecks On}



Далее:
Код: pascal
1.
2.
  IntDict:=TDictionary<integer,TMyClass>.Create(TIntComp.Create);
  StringDict:=TDictionary<string,TMyClass>.Create(TStringComp.Create);



Разница:

default1. Benchmark TDictionary<Integer,Integer>
Add 10.000.000 integers. 1907 msec.
Add 10.000 integers in 10.000.000 iterations. 500 msec.
Locate 10.000 integers in 10.000.000 iterations. 422 msec.

2. Benchmark TDictionary<string,Integer>
Add 1.000.000 GUIDs. 515 msec.
Add 150844 strings in 10.000.000 iterations. 2016 msec.
Locate 150844 strings in 10.000.000 iterations. 1875 msec.

custom1. Benchmark TDictionary<Integer,Integer>
Add 10.000.000 integers. 468 msec.
Add 10.000 integers in 10.000.000 iterations. 156 msec.
Locate 10.000 integers in 10.000.000 iterations. 94 msec.

2. Benchmark TDictionary<string,Integer>
Add 1.000.000 GUIDs. 375 msec.
Add 150844 strings in 10.000.000 iterations. 1656 msec.
Locate 150844 strings in 10.000.000 iterations. 1547 msec.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39805124
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
procedure TDictionaryTestInteger;
type
  TDict = Generics.Collections.TDictionary<integer,integer>;
var
  A : TDict;
  i : Integer;
  T : Cardinal;
const
  SearchVal = 5;
begin
  WriteHeader('Benchmark '+PTypeInfo(TypeInfo(TDict)).Name);
  RandSeed:=Seed;

  A:=TDict.Create(TIntComp.Create);
  try
    Write('Add 10.000.000 integers. ');
    T:=GetTickCount;

    for i:=0 to 9999999 do begin
      A.Add(i,0);
    end;
    T:=GetTickCount-T;
    WriteLn(IntToStr(T)+' msec.');

    A.Clear;
    Write('Add 10.000 integers in 10.000.000 iterations. ');
    T:=GetTickCount;
    for i:=0 to 9999999 do begin
      A.AddOrSetValue(Random(10000),0);
    end;
    T:=GetTickCount-T;
    WriteLn(IntToStr(T)+' msec.');

    Write('Locate 10.000 integers in 10.000.000 iterations. ');
    T:=GetTickCount;
    for i:=0 to 9999999 do begin
      A.ContainsKey(Random(10000));
    end;
    T:=GetTickCount-T;
    WriteLn(IntToStr(T)+' msec.');

  finally
    A.Free;
  end;
end;

procedure TDictionaryTestString;
type
  TDict = Generics.Collections.TDictionary<String,integer>;
var
  A : TDict;
  i : Integer;
  T : Cardinal;
const
  SearchVal = 5;
begin
  WriteHeader('Benchmark '+PTypeInfo(TypeInfo(TDict)).Name);
  RandSeed:=Seed;

  A:=TDict.Create(TStringComp.Create);
  try
    Write('Add 1.000.000 GUIDs. ');
    T:=GetTickCount;
    for i:=0 to 999999 do begin
      A.Add(List1[i],i);
    end;
    T:=GetTickCount-T;
    WriteLn(IntToStr(T)+' msec.');

    A.Clear;
    Write('Add '+IntToStr(List2.Count)+' strings in 10.000.000 iterations. ');
    T:=GetTickCount;
    for i:=0 to 9999999 do begin
      A.AddOrSetValue(List2[Random(List2.Count)],0);
    end;
    T:=GetTickCount-T;
    WriteLn(IntToStr(T)+' msec.');

    Write('Locate '+IntToStr(List2.Count)+' strings in 10.000.000 iterations. ');
    T:=GetTickCount;
    for i:=0 to 9999999 do begin
      A.ContainsKey(List2[Random(List2.Count)]);
    end;
    T:=GetTickCount-T;
    WriteLn(IntToStr(T)+' msec.');
  finally
    A.Free;
  end;
end;
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39805235
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat, а какова частота коллизий твоего хэша?
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39805323
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да мне пофигу. Меня результат тестов устраивает.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39805378
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrbrgreat, а какова частота коллизий твоего хэша?
Это хеш Седжвика (RSHASH). Тут есть данные о коллизиях .
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39805582
Фотография Gator
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вангую, что RS HASH это Robert Sedgewick. Но на дельфях он не писал ведь...
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39805893
rashid.abzalov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806227
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rashid.abzalov,

с тех пор TDictionary afaik стал лучше
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806251
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaonс тех пор TDictionary afaik стал лучше
Да нифига. Хотя, конкретно эта проблема, решается на текущей реализации словаря, буквально, несколькими строчками.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806253
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...ну, то есть, чуть лучше, конечно стал, но в целом, всё по-прежнему.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806377
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey, меняя хэш-функцию?
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806408
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrbKazantsev Alexey, меняя хэш-функцию?
Нет, достаточно добавить случайный seed в компарер. Это поможет даже если будет использоваться очень простая хеш-функция. А у используемого Дженкинса можно указать initial value.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806748
cptngrb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey, а где здесь используется Seed?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
{$OverFlowChecks OFF}
function TStringComp.GetHashCode(const Value: string): Integer;
var
  a : Integer;
  i : Integer;
begin
  Result:=0;
  a:=63689;
  for i:=0 To Length(Value)-1 do begin
    Result:=Result*a+PWordArray(Value)[i];
    a:=a*378551;
  end;
end;
{$OverFlowChecks On}




если только a:=Seed;
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806800
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cptngrb,

Седжвика можно модифицировать так: Result := Seed; Только seed должен быть результатом предыдущего хеширования этой-же функцией. То есть, выглядеть это может примерно так:
Код: pascal
1.
2.
3.
4.
5.
6.
function RSHash(Const AData; ASize : Integer; ASeed : Integer = 0) : Integer;
begin
 Result := ASeed;
...

end;


В констркторе компарера:
Код: pascal
1.
FSeed := RSHash(RandomData, RandomDataSize);


В GetHashCode компарера:
Код: pascal
1.
 Result := RSHash(Pointer(AString)^, Length(AString) * SizeOf(Char), FSeed);


Этот вариант решит проблему обозначенную в статье, но, от атаки hash-flooding не защитит. Аналогичные манипуляции для Дженкинса избавят и от hash-flooding.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806805
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если уж важна защита от флуда менять надо a:=a*378551;
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806809
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat,

Рандомно менять эти коэффициенты чревато ростом коллизий.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806932
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Меняйте через формулу, из простых чисел большого размера.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806937
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat,

Нужен-то рандом, иначе смысла никакого.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806939
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Сделать функцию генеряющую простое число от рандома - это проблема?
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806941
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat,

Сколько таких простых чисел будет в результате?
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806983
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Достаточно.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806985
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
~5% от maxint - вполне достаточно.
...
Рейтинг: 0 / 0
Производительность TDictionary
    #39806996
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreat,

Сомневаюсь, что этого будет достаточно. Значительно более сложный murmur3, изначально сделаный с поддержкой seed, и тот не устоял.
...
Рейтинг: 0 / 0
25 сообщений из 60, страница 1 из 3
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Производительность TDictionary
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]