Dneska mi dorazil takovýhle zajímavý dotaz:
"Aplikacia pri urcitom evente zavola nespecifikovany PowerShell script ktory nasledne danu informaciu zapise do suboru (par bajtov) (resp. uvazuje sa aj o DB). A tu prichadza problem, je mozne taketo nieco paralene zavolat cca 500-600x za sekundu (tj. jeden script by musel zbehnut do cca 2ms?) Pocitame samozrejme s tym ze zapis do identickeho suboru je vyluceny takze v pripade takejto poziadavky prichadza do uvahy iba externa DB. Je to extremny pripad ktory v realnej situacii s velkou pravdepodobnostou nenastane – no poziadavka je otestovat to z ich aplikacie."
A protože mě to taky zajímalo, tak jsem si rovnou naprogramoval malinký skriptík, který zapisuje nějaká malinká data do souboru. Aby ten skriptík mohl běžet ve více instancích, musel jsem do něho přidat synchronizaci pomocí mutexu, což je mimochodem zajímavý příklad.
$mutex = New-Object System.Threading.Mutex($false, "someDataIntoFile")
[void] $mutex.WaitOne()
$logFile = "$env:Temp\someDataInfoFile.txt"
$logFileOriginalSize = (Get-Item $logFile -EA SilentlyContinue).Length
('{0}' -f (Get-Date)) | Out-File $logFile -Append
$logFileOriginalSize | Out-File $logFile -Append
$args[0] | Out-File $logFile -Append
'---------------' | Out-File $logFile -Append
[void] $mutex.ReleaseMutex()
Tenhle skript by měl být snad jasný. Na začátku si počkám, než dostanu mutex, abych mohl zapsat do souboru výhradně a tudíž konzistentně.
Skrip si uložte do nějakého PS1 souboru.
Jenže já tenhle skript potřebuju spustit současně 600x. Na to jsem si udělal malinký BAT soubor, který to prostě spustít tak rychle jak to jen jde právě šetset krát. Neříkám, že za sekundu, ale to není podstatné. Spustí to všechno co nejrychleji to jde. Rychleji to tedy nejde. Jestli to spouštění nebude trvat sekundu (to nebude :-)) tak aspoň víme, že to nejde.
Ale to neva. Necháme je spustit. Všechny poběží, počkají až se dostanou na řadu a zapíšou do souboru svoji vysněnou hodnotu. Zapisuji tam i čas, takže nakonec, až všech šet set PowerShelláčků skončí, tak v souboru bude vidět první a poslední datum zápisu a z toho půjde krásně zjistit, jak dlouho to trvalo.
BAT soubor následuje. Jediné co musíte, je umístit ho do stejného adresáře jako ten původní PS1 soubor a hlavně ho pojmenovat stejně, jako ten PS1 soubor.
FOR /L %%i IN (1,1,600) DO (START powershell -ExecutionPolicy Bypass -File %~d0%~p0%~n0.ps1 "Testovaci vstupni data")
A jak to všechno dopadlo na mém notebooku?
Akce se rozjela. A počítač vytuhnul. Chvilku byl vytuhnutý. A potom se restartoval :-)
Po novém startu jsem zkontroloval onen soubor. Během celé akce se podařilo zapisovat jen 1 minutu a 8 sekund. Potom to zřejmě vytuhlo. Během této doby dokončilo svoji práci cca 40 PowerShell procesů.
Takže to v provozu nezkoušejte :-)