По информации автора менеджер памяти FastMM производительность приложений, использующих FastMM 5-й версии выше, чем у использующих FastMM версии 4.992 в однопоточных тестах на 15%, а в многопоточных тестах на 30%. Так ли это? Давайте проверим и сравним скорость работы FastMM 4, который используется в Delphi 10.3, и FastMM 5.0.
Сразу хочу предупредить – я понятия не имею, как тестировать менеджеры памяти. Поэтому мой тест – это первое, что пришло мне в голову. Большое количество итераций должно хоть немного сглаживать погрешности. Тест состоит из четырех частей:
1. распределяем 10 участков памяти по 10-100 байт, затем увеличиваем их размер до 20-200 байт и высвобождаем память;
2. распределяем 10 участков памяти по 10-100 килобайт, затем увеличиваем их размер до 20-200 килобайт и высвобождаем память;
3. распределяем 10 участков памяти по 10-100 мегабайт и высвобождаем память;
4. проводим конкатенацию строк различного размера.
Результаты работы 32-х битного приложения
Результаты работы 64-х битного приложения
Итак, что мы видим? Для однопоточных приложений, если исключить тест со строками, результаты тестов не в пользу 5-й версии. А вот многопоточные версии тестов реально впечатляют. Значит вполне можно подождать несколько недель или месяц, что бы побольше приложений испытали на себе FastMM 5, и включать его в свои проекты. Особенно в многопоточные и те, в которых ведется интенсивная работа со строками.
Сразу хочу предупредить – я понятия не имею, как тестировать менеджеры памяти. Поэтому мой тест – это первое, что пришло мне в голову. Большое количество итераций должно хоть немного сглаживать погрешности. Тест состоит из четырех частей:
1. распределяем 10 участков памяти по 10-100 байт, затем увеличиваем их размер до 20-200 байт и высвобождаем память;
2. распределяем 10 участков памяти по 10-100 килобайт, затем увеличиваем их размер до 20-200 килобайт и высвобождаем память;
3. распределяем 10 участков памяти по 10-100 мегабайт и высвобождаем память;
4. проводим конкатенацию строк различного размера.
program MMtest;
{$APPTYPE CONSOLE}
uses
  FastMM5,
  System.Classes,
  System.SysUtils,
  System.Threading,
  System.Diagnostics;
procedure MemoryTest(const iCoeff: Integer);
var
  i, j: Integer;
  p: Array[1..10] of Pointer;
begin
  for i := 1 to 100000 do
    begin
      for j := 1 to 10 do
        p[j] := GetMemory(j * 10 * iCoeff);
      for j := 1 to 10 do
        p[j] := ReallocMemory(p[j], j * 20 * iCoeff);
      for j := 1 to 10 do
        FreeMemory(p[j]);
    end;
end;
procedure MemoryTest2;
var
  i, j: Integer;
  p: Array[1..10] of Pointer;
begin
  for i := 1 to 10000 do
    begin
      for j := 1 to 10 do
        p[j] := GetMemory(j * 10485760);
      for j := 1 to 10 do
        FreeMemory(p[j]);
    end;
end;
function StringTest: String;
var
  i: Integer;
  sTemp: String;
begin
  Result := '';
  sTemp  := '';
  for i := 32 to 132 do
    sTemp := sTemp + Chr(i);
  for i := 1 to 1000 do
    Result := Result + sTemp;
  for i := 1 to 1000 do
    Result := sTemp + Result + sTemp;
end;
var
  sw: TStopwatch;
begin
  FastMM_SetOptimizationStrategy(mmosOptimizeForSpeed);
  // Test #1
  sw := TStopwatch.StartNew;
  MemoryTest(1);
  sw.Stop;
  WriteLn(sw.ElapsedMilliseconds);
  sw := TStopwatch.StartNew;
  TParallel.For(1, 10, procedure (i: integer) begin MemoryTest(1) end);
  sw.Stop;
  WriteLn(sw.ElapsedMilliseconds);
  // Test #2
  sw := TStopwatch.StartNew;
  MemoryTest(1024);
  sw.Stop;
  WriteLn(sw.ElapsedMilliseconds);
  sw := TStopwatch.StartNew;
  TParallel.For(1, 10, procedure (i: integer) begin MemoryTest(1024) end);
  sw.Stop;
  WriteLn(sw.ElapsedMilliseconds);
  // Test #3
  sw := TStopwatch.StartNew;
  MemoryTest2;
  sw.Stop;
  WriteLn(sw.ElapsedMilliseconds);
  sw := TStopwatch.StartNew;
  TParallel.For(1, 10, procedure (i: integer) begin MemoryTest2 end);
  sw.Stop;
  WriteLn(sw.ElapsedMilliseconds);
  // Test #4
  sw := TStopwatch.StartNew;
  StringTest;
  sw.Stop;
  WriteLn(sw.ElapsedMilliseconds);
  sw := TStopwatch.StartNew;
  TParallel.For(1, 10, procedure (i: integer) begin StringTest end);
  sw.Stop;
  WriteLn(sw.ElapsedMilliseconds);
end.Результаты работы 32-х битного приложения
| Тест | Потоков | FMM4 | FMM5 | Дельта | % | 
| 1 | 1 | 33 | 36 | -3 | -9.09 | 
| 10 | 3331 | 1551 | 1780 | 53.44 | |
| 2 | 1 | 450 | 659 | -209 | -46.44 | 
| 10 | 30865 | 9985 | 20880 | 67.65 | |
| 3 | 1 | 1114 | 1910 | -796 | -71.45 | 
| 10 | 14364 | 9347 | 5017 | 34.93 | |
| 4 | 1 | 99 | 37 | 62 | 62.63 | 
| 10 | 1024 | 151 | 873 | 85.25 | 
Результаты работы 64-х битного приложения
| Тест | Потоков | FMM4 | FMM5 | Дельта | % | 
| 1 | 1 | 21 | 39 | -18 | -85.71 | 
| 10 | 1751 | 1585 | 166 | 9.48 | |
| 2 | 1 | 344 | 725 | -381 | -110.76 | 
| 10 | 17787 | 10240 | 7547 | 42.43 | |
| 3 | 1 | 1734 | 1867 | -133 | -7.67 | 
| 10 | 18406 | 15183 | 3223 | 17.51 | |
| 4 | 1 | 129 | 40 | 89 | 68.99 | 
| 10 | 1221 | 152 | 1069 | 87.55 | 
Итак, что мы видим? Для однопоточных приложений, если исключить тест со строками, результаты тестов не в пользу 5-й версии. А вот многопоточные версии тестов реально впечатляют. Значит вполне можно подождать несколько недель или месяц, что бы побольше приложений испытали на себе FastMM 5, и включать его в свои проекты. Особенно в многопоточные и те, в которых ведется интенсивная работа со строками.
 
Стоило бы сравнить ещё с форком FastMM4-AVX - также заявляется преимущество для многопоточных приложений.
ОтветитьУдалитьА может я и сам сравню на днях. Конечно менеджер памяти это не то, что стоит менять, если всё работает... Но интересно было бы посмотреть )
Погонял тесты. Получил совсем другие данные для теста 2 в 10 потоков. Что в 32, что в 64 бит - для FastMM5 получается больше, чем у FastMM4...
ОтветитьУдалитьМогу скинуть свою табличку в гуглдоксе...
Может код как-то менялся?
1. Я проводил сравнения с точки зрения человека, который ранее не подключал к проекту FastMM и сравнивал с «FastMM 4, который используется в Delphi 10.3», а это скорее всего не FastMM 4.992 и тем более не ответвление FastMM4-AVX (которое с выходом FastMM 5 потеряло смысл).
ОтветитьУдалить2. Результат возможно, зависит и от версии Delphi (я тестировал на Delphi 10.3.2). Попробуйте поменять количество потоков на 8 или 4.
Я провёл сравнение на 10.3.3 и 10.0 - результаты в этих версиях схожи.
ОтветитьУдалитьКод я взял полностью ваш. И у меня на Ryzen 3600 и Ryzen 3700x получаются в целом схожие результаты.
И самое странное, что во 2м тесте с 10 потоками у меня получается, что FastMM5 не имеет преимущества перед FastMM4. Более того - в 64 битном варианте FastMM4 у меня показал преимущество перед FastMM5.
Я запускал на Core i7-8700 с 32-мя ГБ ОЗУ. Может это дает разницу? Ваши Ryzen будут помощнее.
ОтветитьУдалитьПроверьте, вы может не релиз, а дебаг собирали?
А если убрать FastMM_SetOptimizationStrategy(mmosOptimizeForSpeed), что бы по умолчанию было mmosBalanced? или поставить mmosOptimizeForLowMemoryUsage ?
"Я провёл сравнение на 10.3.3 и 10.0 - результаты в этих версиях схожи." - возможно разработчики Delphi как взяли FastMM 4, так его и не обновляли (если он вообще обновлялся).
Памяти у меня так же по 32 ГБ. Впрочем, учитывая, что в 32 битном режиме вся эта роскошь недоступна...
ОтветитьУдалитьЯ проверял именно релиз. И, кстати, разницы с дебагом для этих тестов почти не было.
Я проверял с оптимизацией по скорости. Но также и в сбалансированном режиме - разницы почти не было.
А теперь по поводу процессора. К сожалению, настольного интела у меня под рукой нет, но есть мобильный 8265u.
И вот на мобильном интеле FastMM5 выиграл у стандартного (FastMM4) менеджера памяти в многопоточной версии теста номер 2. При этом в том же тесте, но уже на райзене стандартный менеджер памяти выигрывает почти 3х кратно...
Интересно будет попробовать на райзене 2600x. Если доберусь до него в ближайшее время...