powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / TDictionary или TList<>.BinarySearch с позиции поиска
25 сообщений из 479, страница 9 из 20
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381055
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если говорить об универсальном хеше, то он должен быть байтовый, а не юникодный. Как стандартный Джеткинс

Kazantsev Alexey,

Твой генератор распределений где выложен?
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381075
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUЕсли говорить об универсальном хеше, то он должен быть байтовый, а не юникодный. Как стандартный Джеткинс
Меняем UnicodeString на RawByteString и юникодный Седжвик превращается в байтовый. Меняем RawByteString на UnicodeString и байтовый хеш Шарахова превращается в юникодный. Причём, что в одном, что в другом случае, без потери эффективности.

SOFT FOR YOUТвой генератор распределений где выложен?
Нигде не выложен. Чего там выкладывать-то? Банальное расставление пикселей в соответствии с признаком занятой ячейки таблицы.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381092
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeySOFT FOR YOUТак выложи нормальные тестовые данные, нормальный тестовый проект, с замером времени, генерацией распределения и прочей штукой. А потом будем думать, что с этим делать
Тестовые данные , нормальный тестовый проект . Обгонишь по скорости Седжвика с Дженкинсом, будем рисовать распределение.

Вот что ты за человек такой?
Даже приведённый тобой вариант на x86 выдаёт такой результат:

Код: plaintext
1.
2.
3.
4.
TSedgwicComparer... 827мс
TShaPerfectComparer... 827мс
TFastComparer... 749мс

Press Enter

Я думал, я зайду, скачаю, а там подсчёт коллизий, замер времени, разные тестовые базы, генерация GIF-а распределения
Сейчас адаптирую хеш под UTF-16, выложу
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381097
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUДаже приведённый тобой вариант на x86 выдаёт такой результат:

Код: plaintext
1.
2.
3.
4.
TSedgwicComparer... 827мс
TShaPerfectComparer... 827мс
TFastComparer... 749мс

Press Enter

А какой результат он должен выдавать?

SOFT FOR YOUЯ думал, я зайду, скачаю, а там подсчёт коллизий, замер времени, разные тестовые базы, генерация GIF-а распределения
Ты меня с дедом морозом не путаешь?
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381098
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Просто я искренне не понимаю, зачем эти тонны пространных рассуждений, если можно взять конкретный пример и экспериментировать с ним. Вот по кой фиг нужны были эти изобретения хешей, если на реальном примере мой хеш уже выдаёт лучший результат? Ладно бы вы придумывали что-то что быстрее, или с одинаковой скоростью, но лучшим распределением. Тогда был бы смысл
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381101
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Последние результаты такие

x86:
Код: plaintext
1.
2.
TSedgwicComparer... 936мс
TShaPerfectComparer... 920мс
TFastComparer... 795мс

x64:
Код: plaintext
1.
2.
TSedgwicComparer... 1357мс
TShaPerfectComparer... 1420мс
TFastComparer... 1217мс

Проект (Рядом должен лежать "StringBase.txt")
Код: 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.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
program SpeedTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Winapi.Windows,
  System.Generics.Defaults,
  System.Generics.Collections,
  System.SysUtils,
  System.Classes;

type
  TStringEqualComparer = class(TInterfacedObject)
    function Equals(const Left, Right: string): Boolean; reintroduce;
    // важно! если сделать виртуальный метод - то скорость падает ~3 раза
    // function GetHashCode(const Value: string): Integer; reintroduce; virtual; abstract;
  end;
  TComparerClass = class of TStringEqualComparer;

  TSedgwicComparer = class(TStringEqualComparer, IEqualityComparer<string>)
    function GetHashCode(const Value: string): Integer; reintroduce;
  end;

  TShaPerfectComparer = class(TStringEqualComparer, IEqualityComparer<string>)
    function GetHashCode(const Value: string): Integer; reintroduce;
  end;

  TFastComparer = class(TStringEqualComparer, IEqualityComparer<string>)
    function GetHashCode(const Value: string): Integer; reintroduce;
  end;

{ TStringEqualComparer }

function TStringEqualComparer.Equals(const Left, Right: string): Boolean;
label
  cmp_ptrs;
var
  i, Count: NativeInt;
  S1, S2: PNativeUInt;
begin
  S1 := Pointer(Left);
  S2 := Pointer(Right);
  if (S1 <> S2) and (S1 <> nil) and (S2 <> nil) then
  begin
    Dec(NativeUInt(S1), SizeOf(Integer));
    Dec(NativeUInt(S2), SizeOf(Integer));
    Count := PInteger(S1)^;
    if (Integer(Count) <> PInteger(S2)^) then goto cmp_ptrs;
    Inc(NativeUInt(S1), SizeOf(Integer));
    Inc(NativeUInt(S2), SizeOf(Integer));

    for i := 1 to Count shr {$if SizeOf(NativeUInt) = 8}2{$else}1{$endif} do
    begin
      if (S1^ <> S2^) then goto cmp_ptrs;
      Inc(S1);
      Inc(S2);
    end;

    {$if SizeOf(NativeUInt) = 8}
    if (Count and 2 <> 0) then
    begin
      if (PCardinal(S1)^ <> PCardinal(S2)^) then goto cmp_ptrs;
      Inc(NativeUInt(S1), SizeOf(Cardinal));
      Inc(NativeUInt(S2), SizeOf(Cardinal));
    end;
    {$endif}

    if (PWord(S1)^ <> PWord(S2)^) then goto cmp_ptrs;
    Result := True;
    Exit;
  end else
  begin
  cmp_ptrs:
    Result := (S1 = S2);
  end;
end;

{ TSedgwicComparer }

function TSedgwicComparer.GetHashCode(const Value: string): Integer;
var
  a, 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;

{ TShaPerfectComparer }

function TShaPerfectComparer.GetHashCode(const Value: string): Integer;
var
  i, j: integer;
begin;
  Result:=0;
  for i:=0 to Length(Value)-1 do begin;
    j:=ord(Value[i+1]);
    Result:=Result * 1041204193 + (j+1507220783);
    end;
  Result:=Result * -1866451833;
end;

{ TFastComparer }

function TFastComparer.GetHashCode(const Value: string): Integer;
var
  i, X, Count: Integer;
  S: PByte;
begin
  S := Pointer(Value);
  Result := 0;
  if (S <> nil) then
  begin
    Count := PInteger(NativeInt(Value) - 4)^;

    Result := Count;
    for i := 1 to (Count shr 1) do
    begin
      X := Result xor PInteger(S)^;
      Result := Result * i;
      Inc(Result, X shr 16);
      Inc(S, SizeOf(Integer));
      Inc(Result, X);
    end;

    Inc(Result, Ord(PChar(S)^));
    Result := Result * -1866451833;
  end;
end;


const
  ITERATIONS_COUNT = 100;
  COMPARERS: array[0..2] of TComparerClass = (TSedgwicComparer, TShaPerfectComparer, TFastComparer);

var
  i, c, k: NativeInt;
  VALUES: TArray<string>;
  List: TStringList;
  Time: Cardinal;
  Comparer: IEqualityComparer<string>;
  Dictionary: TDictionary<string, Integer>;

begin
  try
    // загрузка значений
    List := TStringList.Create;
    try
      List.LoadFromFile('StringBase.txt');
      SetLength(VALUES, List.Count);

      for i := 0 to List.Count - 1 do
      begin
        VALUES[i] := List[i];
      end;
    finally
      List.Free;
    end;

    // цикл по всем компарерам
    for c := Low(COMPARERS) to High(COMPARERS) do
    begin
      // компарер, конструктор
      Write(COMPARERS[c].ClassName, '...');
      case c of
        0: Comparer := TSedgwicComparer.Create;
        1: Comparer := TShaPerfectComparer.Create;
      else
        // 2:
        Comparer := TFastComparer.Create;
       end;
      Dictionary := TDictionary<string, Integer>.Create(Length(VALUES), Comparer);

      try
        // заполняем
        for k := Low(VALUES) to High(VALUES) do
          Dictionary.Add(VALUES[k], 0);

        // тестируем
        Time := GetTickCount;
        for i := 1 to ITERATIONS_COUNT do
        for k := Low(VALUES) to High(VALUES) do
        begin
          Dictionary.Items[VALUES[k]];
        end;
        Time := GetTickCount - Time;
        Writeln(' ', Time, 'мс');

      finally
        Comparer := nil;
        Dictionary.Free;
      end;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

  // нажать Enter
  Writeln;
  Write('Press Enter');
  Readln;
end.

...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381105
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOU,

Гы:

TSedgwicComparer... 1750мс
TShaPerfectComparer... 1750мс
TFastComparer... 1937мс

Press Enter

:)
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381107
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, еще надо сделать так:
Код: pascal
1.
List.LoadFromFile('StringBase.txt',TEncoding.UTF8);



TSedgwicComparer... 1312мс
TShaPerfectComparer... 1328мс
TFastComparer... 1422мс

Press Enter
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381110
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUПросто я искренне не понимаю, зачем эти тонны пространных рассуждений, если можно взять конкретный пример и экспериментировать с ним. Вот по кой фиг нужны были эти изобретения хешей, если на реальном примере мой хеш уже выдаёт лучший результат?
Точно! Давайте возьмём конкретный пример и... загрузим в него словарь Лопатина . Но тестировать будем только с одной итерацией, во избежание.
Результат...Default... 32мс
TSedgwicComparer... 15мс
TSimpleComparer... 46203мс
TShiftComparer... 42922мс
TFastComparer... 1391мс

Press Enter
Вот этим и отличается "решение под задачу" от универсального хеша.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381121
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Шарахов использует строки, а не произвольные байты, ты вообще настаиваешь на Unicode
Где тут универсальность?
На лицо "решение под задачу"

Собственно, словарь Лопатина - тоже весьма специфичная штука. Множество коротких похожих слов

В универсале Седжвик неплох, на мой взгляд лучше Дженкинса
Но для простых задач, типа сериализации или идентификации лексем, лучше конечно упрощать функции
Если нет возможности кодогенерить
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381125
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
немного переделал ваш тест
Код: 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.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
program HashTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Winapi.Windows,
  System.SysUtils,
  System.Classes,
  System.Generics.Collections,
  System.Generics.Defaults;

type
  TStringEqualComparer = class(TInterfacedObject)
    function Equals(const Left, Right: string): Boolean; reintroduce;
    // важно! если сделать виртуальный метод - то скорость падает ~3 раза
    // function GetHashCode(const Value: string): Integer; reintroduce; virtual; abstract;
  end;

  TSedgwicComparer = class(TStringEqualComparer, IEqualityComparer<string>)
    function GetHashCode(const Value: string): Integer; reintroduce;
  end;

  TSimpleComparer = class(TStringEqualComparer, IEqualityComparer<string>)
    function GetHashCode(const Value: string): Integer; reintroduce;
  end;

  TShiftComparer = class(TStringEqualComparer, IEqualityComparer<string>)
    function GetHashCode(const Value: string): Integer; reintroduce;
  end;

  TFastComparer = class(TStringEqualComparer, IEqualityComparer<string>)
    function GetHashCode(const Value: string): Integer; reintroduce;
  end;

  TMurmur3Comparer = class(TStringEqualComparer, IEqualityComparer<string>)
    function GetHashCode(const Value: string): Integer; reintroduce;
  end;

{ TStringEqualComparer }

function TStringEqualComparer.Equals(const Left, Right: string): Boolean;
label
  cmp_ptrs;
var
  i, Count: NativeInt;
  S1, S2: PNativeUInt;
begin
  S1 := Pointer(Left);
  S2 := Pointer(Right);
  if (S1 <> S2) and (S1 <> nil) and (S2 <> nil) then
  begin
    Dec(NativeUInt(S1), SizeOf(Integer));
    Dec(NativeUInt(S2), SizeOf(Integer));
    Count := PInteger(S1)^;
    if (Integer(Count) <> PInteger(S2)^) then goto cmp_ptrs;
    Inc(NativeUInt(S1), SizeOf(Integer));
    Inc(NativeUInt(S2), SizeOf(Integer));

    for i := 1 to Count shr {$ifdef CPUX64}2{$else}1{$endif} do
    begin
      if (S1^ <> S2^) then goto cmp_ptrs;
      Inc(S1);
      Inc(S2);
    end;

    {$ifdef CPUX64}
    if (Count and 2 <> 0) then
    begin
      if (PCardinal(S1)^ <> PCardinal(S2)^) then goto cmp_ptrs;
      Inc(NativeUInt(S1), SizeOf(Cardinal));
      Inc(NativeUInt(S2), SizeOf(Cardinal));
    end;
    {$endif}

    if (PWord(S1)^ <> PWord(S2)^) then goto cmp_ptrs;
    Result := True;
    Exit;
  end else
  begin
  cmp_ptrs:
    Result := (S1 = S2);
  end;
end;

{ TSedgwicComparer }

function TSedgwicComparer.GetHashCode(const Value: string): Integer;
var
  a, i: Integer;
begin
  Result := 0;
  a := 63689;
  for i := 1 to Length(Value) - 1 do
  begin
    Result := Result * a + PWordArray(Value)[i];
    a := a * 378551;
  end;
end;

{ TSimpleComparer }

function TSimpleComparer.GetHashCode(const Value: string): Integer;
var
  i: NativeInt;
  S: PChar;
begin
  S := Pointer(Value);
  Result := 0;
  if (S <> nil) then
  begin
    Result := PInteger(NativeInt(Value) - 4)^;

    for i := 0 to NativeInt(Result) - 1 do
    begin
      Result := Result + Ord(S[i]);
    end;
  end;
end;

{ TShiftComparer }

function TShiftComparer.GetHashCode(const Value: string): Integer;
var
  i: NativeInt;
  S: PChar;
begin
  S := Pointer(Value);
  Result := 0;
  if (S <> nil) then
  begin
    Result := PInteger(NativeInt(Value) - 4)^;

    for i := 0 to NativeInt(Result) - 1 do
    begin
      Result := Result xor (Result shr (i and 7 + 1)) + Ord(S[i]);
    end;
  end;
end;

{ TFastComparer }

function TFastComparer.GetHashCode(const Value: string): Integer;
var
  i, X, Count: Integer;
  S: PByte;
begin
  S := Pointer(Value);
  Result := 0;
  if (S <> nil) then
  begin
    Count := PInteger(NativeInt(Value) - 4)^;

    Result := Count;
    for i := 1 to (Count shr (SizeOf(Char) xor 3)) do
    begin
      X := Result xor PInteger(S)^;
      Result := Result * i;
      Inc(Result, X shr 19);
      Inc(S, SizeOf(Integer));
      Inc(Result, X);
    end;

    for i := 1 to (Count and ((SizeOf(Char) xor 2) or 1)) do
    begin
      Result := Result * i;
      Inc(Result, Ord(PChar(S)^));
      Inc(S, SizeOf(Char));
    end;
  end;
end;

{ TMurmur3Comparer }

type
  uint32_t = cardinal;
{$IFNDEF fpc}
function RolDWord(x:uint32_t;r:integer):uint32_t;
{$IF Defined(CPUX86)}
asm
  MOV  CL, DL
  ROL  EAX, CL
end;
{$ELSEIF Defined(CPUX64)}
asm
  MOV  EAX, ECX
  MOV  CL, DL
  ROL  EAX, CL
end;
{$ELSE}
begin
  Result:=(x shl r) or (x shr (32 - r));
end;
{$IFEND}
{$ENDIF}

function MurmurHash3_x86_32 ( const Akey; len:uint32_t): cardinal;
type
  Puint32_t=^uint32_t;

var data:Puint32_t;
  nblocks,tail_len,i:uint32_t;
  h1,k1:uint32_t;
const
   c1:uint32_t = $cc9e2d51;
   c2:uint32_t = $1b873593;
type
 TTailRec=packed record
  case Integer of
   1:(b:byte);
   2:(w:word);
   3:(uint24_d:uint32_t);
 end;
var
 tail:^TTailRec;
begin
  data := @Akey;
  nblocks := len div 4;

  h1 := 0;
  //----------
  // body
  for i:=1 to nblocks do begin
    k1 := data^;

    k1 := k1 * c1;
    k1 := RolDWord(k1,15);
    k1 := k1*c2;

    h1 := h1 xor k1;
    h1 := RolDWord(h1,13);
    h1 := h1*5+$e6546b64;

    inc(data);
  end;

  //----------
  // tail

  tail :=pointer(data);

  k1 := 0;
  tail_len:=len and 3;
  if tail_len>0 then begin
    case tail_len of
    3: k1 :=k1 xor (tail^.uint24_d and $FFFFFF);
    2: k1 :=k1 xor tail^.w;
    1: k1 :=k1 xor tail^.b;
    end;

    k1 :=k1* c1;
    k1 := RolDWord(k1,15);
    k1 :=k1 * c2;
    h1 :=h1 xor k1;
  end;
  //----------
  // finalization

  h1 :=h1 xor len;

  //h1 := fmix32(h1);  Result := h1;

  h1 :=h1 xor (h1 shr 16);
  h1 :=h1* $85ebca6b;
  h1 :=h1 xor (h1 shr 13);
  h1 :=h1 * $c2b2ae35;

  Result:=h1 xor (h1 shr 16);
end;
function TMurmur3Comparer.GetHashCode(const Value: string): Integer;
begin
  Result := Integer(MurmurHash3_x86_32(PChar(Value)^, Length(Value) * SizeOf(Char)));
end;



procedure TestDict(Title: string; L: TStringList; C: IEqualityComparer<string> = nil);
var
  t1, t2: Cardinal;
  D: TDictionary<string, Integer>;
  i: Integer;
begin
  Write(Title);
  //
  D := TDictionary<string, Integer>.Create(L.Count, C);
  try
   t1 := GetTickCount();
    for i := L.Count - 1 downto 0 do
      D.AddOrSetValue(L[i], i);

    t2 := GetTickCount();
    Writeln(t2 - t1);
  finally
    D.Free;
  end;
  //
end;

function GenStr(): string;
var
  l: Integer;
begin
  l := Random(1024);
  SetLength(Result, l);
  for l := l downto 1 do
  begin
    Result[l] := Char(Random(256));
  end;
end;

procedure GenList(L: TStringList);
var
  i: Integer;
begin
  RandSeed := 0;
  for i := 1 to 1000000 do
    L.Add(GenStr)
end;

var
  L: TStringList;

begin
  try
    L:= TStringList.Create;
    try
      GenList(L);
      TestDict( 'std: ', L);

      TestDict( 'TSedgwicComparer: ', L, TSedgwicComparer.Create);
      TestDict( 'TMurmur3Comparer: ', L, TMurmur3Comparer.Create);
      TestDict( 'TFastComparer: ', L, TFastComparer.Create);
      TestDict( 'TShiftComparer: ', L, TShiftComparer.Create);
      TestDict( 'TSimpleComparer: ', L, TSimpleComparer.Create);
    finally
      L.Free;
    end;
    { TODO -oUser -cConsole Main : Insert code here }
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.


[quote автор]
Delphi XE2, intel i7 4710hq
Код: plaintext
1.
2.
3.
4.
5.
G:\Binaries>HashTest.exe
std: 4031
TSedgwicComparer: 984
TMurmur3Comparer: 1062
TFastComparer: 750
последних двух я не дождался
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381136
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUШарахов использует строки, а не произвольные байты, ты вообще настаиваешь на Unicode
Где тут универсальность?
Чудак-человек... Универсальность в алгоритме, а не в принимаемом параметре. Я же тебе говорил, что замена байтовой строки на юникод строку не влияет на эффективность этих хешей. И чем байтовая строка отличается от произвольных байтов? Думаешь распределение хуже будет? Не будет. Я тут для прикола засовывал сырые гиды в 8-символьные юникодовые строки без преобразования - всё прекрасно работает. Так что тут подвоха не ищи.

SOFT FOR YOUСобственно, словарь Лопатина - тоже весьма специфичная штука. Множество коротких похожих слов
Ну вот, опять гранаты не той системы... А я тебе говорил, что слабо меняющиеся ключи (последовательные, как частный случай) это одна из проблем для хешей. Кстати, словарь Лопатина это ещё что, ты на словаре Российских фамилий проверь...

SOFT FOR YOUВ универсале Седжвик неплох, на мой взгляд лучше Дженкинса
Но для простых задач, типа сериализации или идентификации лексем, лучше конечно упрощать функции
Если нет возможности кодогенерить
Давно известно, что под задачу можно родить самый быстрый хеш. Поэтому таблицы и имеют возможность заменить хеш-функцию.

Кстати, я проверил очередную мутацию твоего хеша . На словаре Лопатина небольшое отставание от Седжвика. На словаре Российских фамилий уже двукратное отставание. На последовательных ключах полный провал - отставание на порядок. Прикладываю распределение на фамилиях.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381150
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyЯ же тебе говорил, что замена байтовой строки на юникод строку не влияет на эффективность этих хешей.

Байтовая универсальная функция отличается от юникодовой тем, что выполняется в 2 раза медленнее

Kazantsev AlexeyИ чем байтовая строка отличается от произвольных байтов? Думаешь распределение хуже будет? Не будет.

Ты прикалываешься?
В русском алфавите 33 буквы. А ходовых вообще штук 10-15

Kazantsev AlexeyКстати, я проверил очередную мутацию твоего хеша. На словаре Лопатина небольшое отставание от Седжвика.

А ты на какой хеш-таблице тестировал?
Собственного приготовления?

Kazantsev AlexeyА я тебе говорил, что слабо меняющиеся ключи (последовательные, как частный случай) это одна из проблем для хешей.

Мы же вроде уже решили, что для универсального случая Седжвик заруливает
Однако универсальных случаев почти нет. И для обычных случаев, как например список HTML-тегов, имеет смысл существенно упростить функцию

P.S. Судя по всему, здесь ещё сильно зависит от реализации хеш-таблицы.
Дубликация хеша - это по сути 1-2 лишних сравнения, несколько тактов, которые должны быть сэкономлены на простых хеш-функциях
Надо так же сказать, что в моей давнишней реализации (x86), сохранялось и предварительно сравнивалось значение функции (не обрезанное), а структуры менеджелись специальными пулами
Это я к тому, что можно померяться ещё реализациями хеш-таблиц )
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381152
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUТы прикалываешься?
В русском алфавите 33 буквы. А ходовых вообще штук 10-15Да-да. Именно для этого случая Седжвик и тюнил свой алгоритм. Тебе же Казанцев написал, что и на сырых бинарных, даёт нормальное распределение. В этом и есть универсальность при отличном быстродействии. В отличии от твоего
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381154
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUБайтовая универсальная функция отличается от юникодовой тем, что выполняется в 2 раза медленнее
Зависит от реализации. Но для сравнения скорости использовались функции с одинаковым типом параметра, или я отдельно указывал что тип ключа отличается (кроме случая с мурмур3, там на вход подавались байты юникодовой строки). Но о скорости хеша нужно беспокоиться только тогда, когда будет получено хорошее распределение, иначе весь пар уйдёт в свисток компарера.

SOFT FOR YOUТы прикалываешься?
В русском алфавите 33 буквы. А ходовых вообще штук 10-15
А в английском ещё меньше, и что? Функции с хорошим лавинным эффектом это не мешает.

SOFT FOR YOUА ты на какой хеш-таблице тестировал?
Собственного приготовления?
Разумеется. Хотя, ты можешь сам проверить на своём примере с TDictionary.

SOFT FOR YOUОднако универсальных случаев почти нет. И для обычных случаев, как например список HTML-тегов, имеет смысл существенно упростить функцию
Ну вот Свириденков писал , что у него набор тегов может расширяться в процессе парсинга. А теги в XML, они и на русском могут быть (кстати, какая-то из наших гос.контор такие XML'ки использует), вот уже и требуется универсальное решение.

SOFT FOR YOU P.S. Судя по всему, здесь ещё сильно зависит от реализации хеш-таблицы.
Таблицы которые здесь сравнивали, все являются классическими таблицами с открытой адресацией и линейным пробированием. Реализации отличаются, разумеется, но генеральный алгоритм один.

SOFT FOR YOUДубликация хеша - это по сути 1-2 лишних сравнения, несколько тактов, которые должны быть сэкономлены на простых хеш-функциях
Нет, коллизия хеша это гарантированный поход к компареру за сравнением ключа.

SOFT FOR YOUНадо так же сказать, что в моей давнишней реализации (x86), сохранялось и предварительно сравнивалось значение функции (не обрезанное), а структуры менеджелись специальными пулами
Это я к тому, что можно померяться ещё реализациями хеш-таблиц )
Ну... Вэлкам!
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381168
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Седжвик. Распределение на строковых GUID:
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381169
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Седжвик. Распределение на "сырых" GUID:
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381210
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

я не совсем понял, в TFastComparerPure.GetHashCode ошибка?
или так задумано, что она берёт хеш только от половины строки?
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381216
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
пардон, не разобрал с наскоку
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381238
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Байтовые хеши медленнне в 2 раза уникодных потому, что обрабатывают в 2 раза меньше байт за итерацию. Посмотри стандартный хеш строк. Длина умножается на 2, что вроде как естественно и лежит на поверхности )

Хватит приставать со своими коллизиями. И распределениями.
Дженкинс даёт отличное распределение, но из-за сложности функции, он даёт проседание производительности
Важны 4 составляющие: и реализация таблицы, и коллизии, и скорость функции, и скорость компаратора. А не только распределение

Что касается меряние таблицами - жду твой код в общем примере. Ибо мне свою выдирать из библиотеки долго, а количество твоего кода в ветке удручающе маленькое. 0 если не ошибаюсь
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381303
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUБайтовые хеши медленнне в 2 раза уникодных потому, что обрабатывают в 2 раза меньше байт за итерацию. Посмотри стандартный хеш строк. Длина умножается на 2, что вроде как естественно и лежит на поверхности )
Это и так ясно, только не о том ты думаешь.

SOFT FOR YOUХватит приставать со своими коллизиями. И распределениями.
Коллизии не мои, они у твоего хеша. А чем больше коллизий, тем медленне работает таблица.

SOFT FOR YOUДженкинс даёт отличное распределение, но из-за сложности функции, он даёт проседание производительности
Важны 4 составляющие: и реализация таблицы, и коллизии, и скорость функции, и скорость компаратора. А не только распределение
Всё верно. Только медленный Дженкинс уделывает твой быстрый хеш.

SOFT FOR YOUЧто касается меряние таблицами - жду твой код в общем примере. Ибо мне свою выдирать из библиотеки долго, а количество твоего кода в ветке удручающе маленькое. 0 если не ошибаюсь
Есть встречное предложение, бери TDictionary.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381349
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Я подбираю решение под задачу. На тегах мои хеши уделывают Седжвика. А стандартный компаратор (с Дженкинсом) - уделывает в разы.

Об чем спор то вообще? Что Седжвик в принципе хорош? Так с этим никто не спорит. Но как показала практика, простые хеши вполне могут давать ощутимый прирост. Особенно на длинных и/или разнородных строках.

Я думал, тебя академическая сторона вопроса интересует. Итоговая производительность, приемлемое распределение.
А ты споришь только ради спора. Заняться нечем что ли?
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381369
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUЯ подбираю решение под задачу.
Это ты правильно сейчас говоришь, а раньше утверждал, что твой хеш быстр и удобен вообще для всего .
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381383
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Таки может потому, что в обычной жизни людям не приходит в голову тестировать словарь Лопатина или последовательные числа?

В обычной жизни люди делают сериализацию или поиск токенов. И в таких случаях как раз умельцы наворачивают что-то типа Дженкинса. Только потому, что на Лопатине он даёт меньше коллизий )
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39381385
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev Alexey,

Ты же тоже прочитал про размер таблицы простым числом. А как предложили замерить производительность - ты сразу "не, давайте без меня"
...
Рейтинг: 0 / 0
25 сообщений из 479, страница 9 из 20
Форумы / Delphi [игнор отключен] [закрыт для гостей] / TDictionary или TList<>.BinarySearch с позиции поиска
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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