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

навострячил тут 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
23.04.2019, 00:46
    #39805116
Swv
Swv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
вернее даже так

lru.get только hashmap 0,961819743242614
lru.get только все остальное 0,159336854435245
...
Рейтинг: 0 / 0
23.04.2019, 01:16
    #39805122
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
Замени 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
23.04.2019, 01:18
    #39805124
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
Код: 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
23.04.2019, 10:46
    #39805235
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
rgreat, а какова частота коллизий твоего хэша?
...
Рейтинг: 0 / 0
23.04.2019, 12:44
    #39805323
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
Да мне пофигу. Меня результат тестов устраивает.
...
Рейтинг: 0 / 0
23.04.2019, 14:08
    #39805378
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
cptngrbrgreat, а какова частота коллизий твоего хэша?
Это хеш Седжвика (RSHASH). Тут есть данные о коллизиях .
...
Рейтинг: 0 / 0
24.04.2019, 00:36
    #39805582
Gator
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
Вангую, что RS HASH это Robert Sedgewick. Но на дельфях он не писал ведь...
...
Рейтинг: 0 / 0
24.04.2019, 18:39
    #39805893
rashid.abzalov
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
...
Рейтинг: 0 / 0
25.04.2019, 13:15
    #39806227
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
rashid.abzalov,

с тех пор TDictionary afaik стал лучше
...
Рейтинг: 0 / 0
25.04.2019, 13:32
    #39806251
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
makhaonс тех пор TDictionary afaik стал лучше
Да нифига. Хотя, конкретно эта проблема, решается на текущей реализации словаря, буквально, несколькими строчками.
...
Рейтинг: 0 / 0
25.04.2019, 13:41
    #39806253
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
...ну, то есть, чуть лучше, конечно стал, но в целом, всё по-прежнему.
...
Рейтинг: 0 / 0
25.04.2019, 16:13
    #39806377
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
Kazantsev Alexey, меняя хэш-функцию?
...
Рейтинг: 0 / 0
25.04.2019, 17:03
    #39806408
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
cptngrbKazantsev Alexey, меняя хэш-функцию?
Нет, достаточно добавить случайный seed в компарер. Это поможет даже если будет использоваться очень простая хеш-функция. А у используемого Дженкинса можно указать initial value.
...
Рейтинг: 0 / 0
26.04.2019, 13:02
    #39806748
cptngrb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
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
26.04.2019, 13:53
    #39806800
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
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
26.04.2019, 13:55
    #39806805
rgreat
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
Если уж важна защита от флуда менять надо a:=a*378551;
...
Рейтинг: 0 / 0
26.04.2019, 13:59
    #39806809
Kazantsev Alexey
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Производительность TDictionary
rgreat,

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

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

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

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

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

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

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


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