powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / TDictionary или TList<>.BinarySearch с позиции поиска
25 сообщений из 479, страница 5 из 20
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369348
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyА подумать? Идентификаторы сессий/объектов/дачегоугодновообще на сервере.
Integer?
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369349
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asviridenkovСейчас проверил на своем примере, с при подстановке компаратора с Седжвиком, поиск стал медленнее в 1.5 раза
Ничего удивительного. Дефолтный Дженкинс тоже очень хороший хеш. Кстати, в твоём примере словарь слишком маленький, выгоднее было бы захардкодить.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369353
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня простейший словарь: таблица + цепочки. Использую простые числа для размерности таблицыю Юзается Elf. Прикол в правильном подборе размера таблицы. Рядом стоящие простые числа могут давать (на моих данных) от 0 до нескольких тысяч коллизий. Мурмуры, дженкинсы, crc, дотнетовские варианты более устойчивы к размеру таблицы
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369357
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUInteger?
Слишком маленький диапазон значений. Большая вероятность коллизий при генерации на разных машинах.

А вообще, рандомные ключи удобны для твоего хеша - на них коллизий мало (в последнем варианте).
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369361
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_niggerУ меня простейший словарь: таблица + цепочки.
У меня первая версия тоже с цепочками была. Но тут есть одна проблема - невозможно гарантировать отсутствие реаллокаций после задания вместимости (capacity) таблицы. В таблице с прямой адресацией такая возможность есть + есть возможность делать перестроение таблицы тоже без реаллокаций.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369365
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Aleksandr SharahovА ведь кто-то может утащить в копилку алгоритм с ошибой )
Вот тут правильный Седжвик :)
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369369
asviridenkov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeyasviridenkovСейчас проверил на своем примере, с при подстановке компаратора с Седжвиком, поиск стал медленнее в 1.5 раза
Ничего удивительного. Дефолтный Дженкинс тоже очень хороший хеш. Кстати, в твоём примере словарь слишком маленький, выгоднее было бы захардкодить.

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

Код: 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.
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;

  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;

{ 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 := 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;


const
  ITERATIONS_COUNT = 1000000;
  COMPARERS: array[0..4] of TComparerClass = (nil, TSedgwicComparer, TSimpleComparer, TShiftComparer, TFastComparer);

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

begin
  VALUES := [
    'div',
    'span',
    'table',
    'td',
    'tr',
    'th',
    'li',
    'meta',
    'script',
    'style',
    'ol',
    'ul',
    'h1',
    'h2',
    'h3',
    'h4',
    'h5',
    'thead',
    'tbody',
    'html',
    'body',
    'blockquote',
    'address',
    'frame',
    'frameset',
    'pre',
    'button',
    'textarea',
    'strike',
    'del',
    'menu',
    'small',
    'sub',
    'sup',
    'img',
    'fieldset',
    'legend'
  ];

  try
    // цикл по всем компарерам
    for c := Low(COMPARERS) to High(COMPARERS) do
    begin
      // конструктор, инфо
      if (COMPARERS[c] = nil) then
      begin
        Write('Default', '...');
        Dictionary := TDictionary<string, Integer>.Create;
      end else
      begin
        Write(COMPARERS[c].ClassName, '...');
        case c of
          1: Dictionary := TDictionary<string, Integer>.Create(TSedgwicComparer.Create);
          2: Dictionary := TDictionary<string, Integer>.Create(TSimpleComparer.Create);
          3: Dictionary := TDictionary<string, Integer>.Create(TShiftComparer.Create);
        else
          // 4:
          Dictionary := TDictionary<string, Integer>.Create(TFastComparer.Create);
        end;
      end;

      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
        Dictionary.Free;
      end;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

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



Код: plaintext
1.
2.
3.
4.
Default... 1794мс
TSedgwicComparer... 624мс
TSimpleComparer... 624мс
TShiftComparer... 827мс
TFastComparer... 577мс
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369377
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
x64:

Код: plaintext
1.
2.
3.
4.
Default... 1779мс
TSedgwicComparer... 639мс
TSimpleComparer... 577мс
TShiftComparer... 702мс
TFastComparer... 562мс
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369387
Kazantsev Alexey
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUКак-то так :)
Седжвик неправильный.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369393
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeySOFT FOR YOUКак-то так :)
Седжвик неправильный.
Чего в нем не так?
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369395
rgreat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Компа род рукой нет, чтобы проверить.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369396
Aleksandr Sharahov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rgreatKazantsev Alexeyпропущено...

Седжвик неправильный.
Чего в нем не так?

Верхний индекс.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369397
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kazantsev AlexeySOFT FOR YOUКак-то так :)
Седжвик неправильный.

Точно. С нуля же надо начать

x86:
Код: plaintext
1.
2.
3.
4.
Default... 1778мс
TSedgwicComparer... 687мс
TSimpleComparer... 624мс
TShiftComparer... 795мс
TFastComparer... 593мс

x64:
Код: plaintext
1.
2.
3.
4.
Default... 1778мс
TSedgwicComparer... 609мс
TSimpleComparer... 577мс
TShiftComparer... 702мс
TFastComparer... 562мс
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369402
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
asviridenkov,

Я тут для тебе кодогенерил
Мне удалось объяснить, почему кодогенерация лучше хеша?
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369406
asviridenkov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUasviridenkov,

Я тут для тебе кодогенерил
Мне удалось объяснить, почему кодогенерация лучше хеша?

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

Ну у тебя константный набор тегов. В HTML вроде
А для расширения - можно совмещать подходы. Вернула StrToHtmlTag значение tagUnknown - значит мутить что-то дальше
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369426
asviridenkov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUasviridenkov,

Ну у тебя константный набор тегов. В HTML вроде
А для расширения - можно совмещать подходы. Вернула StrToHtmlTag значение tagUnknown - значит мутить что-то дальше

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

Смысла как минимум в 10 раз
Но правда я не знаю, насколько это актуально у тебя
Ты же сам начал говорить про скорость хеша )
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369440
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хардкодинг при всей своей производительности хорош пока не вылез за пределы своей песочницы. В компаниях/промышленности он на фиг не упирался. Там другие критерии. Главное универсальность, расширяемость и главное стоимость сопровождения.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369448
asviridenkov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUasviridenkov,

Смысла как минимум в 10 раз
Но правда я не знаю, насколько это актуально у тебя
Ты же сам начал говорить про скорость хеша )

Про скорость хеша это я применительно к другим вещам говорил, иногда критична скорость добавления (не здесь).
А в данном случае, ускорение в 10 раз даст не более 5 процентов во времени парсинга.
Которое на порядок меньше времени расчета стилей, которое в свою очередь еще в разы меньше чем расчет layout-а.
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369449
SOFT FOR YOU
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
white_nigger,

Главное, использовать инструменты согласно задачам
Микроскоп - для одного. Молоток - для другого.
Ты же рассуждаешь о молотке как о лучшем инструменте для всех задач класса сферического коня в вакууме
Сериализирующая кодогенерация нужна для максимально быстрой идентификации заранее известного набора строк. И со своей задачей оно справляется на отличненько, да так, что даже самый лучший хеш нервно курит в сторонке
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369453
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUы же рассуждаешь о молотке как о лучшем инструменте для всех задач класса сферического коня в вакуумеТы не понял меня. Перечитай ещё раз. А также подумай почему майкрософт, эмбаркадеро, и все столпы программирования предлагают эту парадигму, а не хардкодинг, который, повторю ещё раз, может встречаться глубоко внутри и ни разу наружу
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369454
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SOFT FOR YOUы же рассуждаешь о молотке как о лучшем инструменте для всех задач класса сферического коня в вакуумеТы не понял меня. Перечитай ещё раз. А также подумай почему майкрософт, эмбаркадеро, и все столпы программирования предлагают эту парадигму, а не хардкодинг, который, повторю ещё раз, может встречаться глубоко внутри и ни разу наружу
...
Рейтинг: 0 / 0
TDictionary или TList<>.BinarySearch с позиции поиска
    #39369455
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
интересно почему пост продублировался?
...
Рейтинг: 0 / 0
25 сообщений из 479, страница 5 из 20
Форумы / Delphi [игнор отключен] [закрыт для гостей] / TDictionary или TList<>.BinarySearch с позиции поиска
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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