FastMM, UseReleaseStack a další

vložil Radek Červinka 29. května 2016 03:39

Před nedávnem Primoz Gabrijelcic přidal do nejnovější verze FastMM další option, který by měl vylepšit chování FastMM při mnoha vláknech. Od té doby se ozvalo několik lidí, že to s úspěchem používají na velmi zatížených serverech (např. Eric Grange na beginend.net se 180 vlákny). Původní oznámení je na googleplus - velmi zajímavé.

Pozadí: při uvolňování, resp. alokaci používá FastMM zámek, kterým chrání své struktury. Čím více je vláken, tím větší je šance, že na sebe narazí a budou soupeřit (resp. čekat na uvolnění). Primoz přišel s myšlenkou, že nejméně při uvolňování pokud se nepodaří uvolnění k vůli zámku, tak se takový blok odloží a zkusí se uvolnit při dalším volání, nebo ho uvolní nové čistící vláknou na pozadí.

Celkem mne to zaujalo a vytvořil jsem malou aplikaci s hodně vlákny, která trpí realokacemi. Bylo to první co mne napadlo jak to otestovat a je to orientační.

type
  TTestThread = class (TThread)
  public
    procedure Execute; override;
  end;
implementation

{$R *.dfm}

procedure TfDemo.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i := 1 to 50 do
  begin
    TTestThread.Create(False).FreeOnTerminate := True;
  end;

end;

{ TTestThread }

procedure TTestThread.Execute;
var
  s: string;
  I: Integer;
begin
  for I := 1 to 1000000 do
    s := s + IntToStr(i);
end;

V podstatě program vytvoří 50 vláken a v každém je spousta realokací řetězce (tj. hodně možností na kolizi). Test je to velmi orientační, ale hodně práce s řetězci simuluje web server. Všechno bylo testováno na Delphi XE a šlo mi spíše o charakteristiku průběhu.

Zkusil jsem otestovat FastMM z instalace (Delphi XE jako taková klasika), aktuální verzi FastMM ve třech módech, vanilla Delphi 5 a nahrazení správce paměti za volání Windows API.

Delphi 5

Delphi 5 (nebo i 7) používá původní správce paměti, který exceloval kolem Windows 95 pro normální aplikace. Dnes ho snad už nikdo nepoužívá, protože nejméně při delším používání (služby, server) trpí fraqmentací.

Delphi 5

Po minutě mne to přestalo bavit a proces jsem zabil. Paměť konstantní, vytížení všech jader tak na půl.

Windows

Před FastMM bylo pro služby doporučováno nahradit správce paměti za přímé volání Windows API, protože od cca Windows 2000 se správce velmi zlepšil a i dnes to někdo doporučuje. Použil jsem gebyho memory manager.

Windows

Po minutě mne to přestalo bavit a proces jsem zabil. Paměť konstantní, vytížení jader mnohem lepší a s jinou charakteristikou. Celkem ale tedy zklamání (Windows 7 64bit), buďto si to nesedlo s mým testem, nebo nevím.

Výchozí správce z XE

Poslední verze před podporou 64bit.

XE

Not bad. Hlavně to během pár sekund doběhlo, což je plus. Vytížení procesoru nic moc a hrbolek s pamětí ukazuje malé zvýšení.

FastMM ve výchozí konfiguraci měl stejnou charakteristiku, jen byl efektivnější. Jinak předpokládám, že pro novější Delphi je to čím dál lepší, protože přejímají novější verzi FastMM. Takže se vyplatí použít nejméně aktuální verzi FastMM.

NeverSleepOnThreadContention

Jedna z možností jak FastMM poladit je nastavit NeverSleepOnThreadContention, ale to má zlepšit výkon u menšího počtu vláken, protože to při nalezení zámku nepřejde do Sleep, ale aktivně čeká. Tohle mohlo výrazně vylepšit výkon, nebo taky ne.

NeverSleepOnThreadContention

A protože je vláken moc, tak to dopadlo špatně. Všechno vytočené na max, ale trvá to (to je to aktivní čekání).

UseSwitchToThread

Vylepšení předchozího: místo aktivního čekání zavolá SwitchToThread a doufá, že konkurent brzo skončí se zámkem. Vhodné pro mnoho jader nebo mnoho vláken.

UseSwitchToThread

Lepší předchozí. SwitchToThread evidentně zabral (pozn. Windows 2000+).

UseReleaseStack

To je to oč mi vlastně šlo, princip jsem popsal dříve.

{$define UseReleaseStack}

UseReleaseStack

Výsledek není vůbec špatný a shoduje se s ukázkami jiných.

Nechtěl jsem měřit přesné časy, protože je to ošemetné. Ale charakteristiky jsou celkem vypovídající.

Tagy:

Praxe

Komentáře

30.5.2016 21:11:14 #

geby

Jen pro poradek priznavam, ze ten windows memory manager neni muj, ale kdysi jsem ho vystrachal nekde na internetu. Pravda, je tak trivialni, ze se prave autorstvi snad ani resit nemusi.

geby

1.6.2016 23:51:20 #

oxo

Zajímavé - zkus nahradit string za AnsiString. To dostalo moje Seattle naprosto do kolen:

procedure TTestThread.Execute;
var
  s: ansistring;
  I: Integer;
begin
  for I := 1 to 1000000 do
    s := s + IntToStr(i);
end;

oxo

2.6.2016 0:39:36 #

radekc

Mne to zas tak zajímavé nepřijde, jelikož všechny IntToStr varianty vrací string, a žádná ansistring nebo rawbytestring. Tudíž za každé volání IntToStr vloží konverzi z Unicode na Ansi, což je časově náročné.

Nebo jsi myslel něco jiného?

radekc

2.6.2016 6:59:02 #

oxo

Máš pravdu, sakra takhle pozdě večer už nesmím nic nikam psát :)

oxo

5.6.2016 21:41:56 #

geby

Nejak se mi na tech grafech nedari najit, cim ma byt ten UseReleaseStack vyhodnejsi nez vychozi mm v XE? Me to pripada prakticky stejne.

geby

6.6.2016 12:21:54 #

radekc

geby, užší, ale hlavně využije celý procesor. Ten výchozí prakticky díky čekání mu to trvá déle, a nedokáže využít potenciál. UseReleaseStack odbaví více. Resp. za kratší dobu, a čím máš rychlejší proc. tím to bude výraznější.

radekc

Komentování ukončeno

Naše nabídka

MVP
Ing. Radek Červinka - Embarcadero MVP
profil na linkedin, Twitter:@delphicz

Nabízím placené poradenství a konzultace v oblasti programování a vývoje SW.
Dále nabízíme i vývoj speciálního software na zakázku.

Neváhejte nás kontaktovat (i ohledně reklamy).

love Delphi

O Delphi.cz

Delphi je moderní RAD nástroj podporující tvorbu nativních aplikací pro platformu Win32, Win64, Mac OSX, Linux a na iPhone a Android.

Delphi.cz je nezávislý portál pro uživatele Delphi. Portál není koncipován pro úplné začátečníky, i když i ti se zde nebudou nudit, ale spíše na programátory, kteří již něco znají a chtějí své znalosti dále rozvíjet a sledovat novinky.

Poslední komentáře

Comment RSS

Dle měsíců