TieÅ”i Å”Ädas sÅ«dzÄ«bas es dzirdÄju no mÅ«su izstrÄdÄtÄjiem. InteresantÄkais ir tas, ka tÄ izrÄdÄ«jÄs patiesÄ«ba, kas izraisÄ«ja ilgu izmeklÄÅ”anu. MÄs runÄsim par SQL serveriem, kas darbojas VMware.
PatiesÄ«bÄ ir viegli nodroÅ”inÄt, ka ražoÅ”anas serveris bezcerÄ«gi atrodas aiz klÄpjdatora. Izpildiet kodu (nevis tempdb un datu bÄzÄ, kurÄ ir iespÄjota kavÄtÄ izturÄ«ba) kodu:
set nocount on
create table _t (v varchar(100))
declare @n int=300000
while @n>0 begin
insert into _t select 'What a slowpoke!'
delete from _t
set @n=@n-1
end
GO
drop table _t
ManÄ darbvirsmÄ tas aizÅem 5 sekundes, bet ražoÅ”anas serverÄ« - 28 sekundes. TÄ kÄ SQL ir jÄgaida darÄ«jumu žurnÄla ieraksta fiziskÄ beigas, un mÄs Å”eit veicam ļoti Ä«sus darÄ«jumus. Aptuveni sakot, mÄs iebraucÄm pilsÄtas satiksmÄ ar lielu, jaudÄ«gu kravas automaŔīnu un skatÄ«jÄmies, kÄ to braÅ”i apdzina picu piegÄdÄtÄji ar motorolleriem - caurlaidspÄja Å”eit nav svarÄ«ga, svarÄ«gs ir tikai latentums. Un neviena tÄ«kla krÄtuve, neatkarÄ«gi no tÄ, cik nulles ir tÄs cenÄ, nevar pÄrspÄt vietÄjo SSD latentuma ziÅÄ.
(komentÄros izrÄdÄ«jÄs, ka meloju - abÄs vietÄs man bija aizkavÄjusies izturÄ«ba. Bez aizkavÄtÄs izturÄ«bas izrÄdÄs:
Galddators ā 39 sekundes, 15 0.065 tr/s, XNUMX ms/io turp un atpakaļ
PROD ā 360 sekundes, 1600 tr/s, 0.6 ms
Man vajadzÄja ievÄrot, ka tas bija pÄrÄk Ätri)
TomÄr Å”ajÄ gadÄ«jumÄ mums ir darÄ«Å”ana ar triviÄlÄm RÄ«maÅa zeta funkcijas nullÄm ar triviÄlu piemÄru. PiemÄrÄ, ko man atnesa izstrÄdÄtÄji, tas bija savÄdÄk. Es biju pÄrliecinÄts, ka viÅiem ir taisnÄ«ba, un sÄku izÅemt no piemÄra visu viÅu specifiku, kas saistÄ«ta ar biznesa loÄ£iku. KÄdÄ brÄ«dÄ« es sapratu, ka varu pilnÄ«bÄ izmest viÅu kodu un uzrakstÄ«t savu - kas parÄda to paÅ”u problÄmu - ražoÅ”anÄ tas darbojas 3-4 reizes lÄnÄk:
create function dbo.isPrime (@n bigint)
returns int
as
begin
if @n = 1 return 0
if @n = 2 return 1
if @n = 3 return 1
if @n % 2 = 0 return 0
declare @sq int
set @sq = sqrt(@n)+1 -- check odds up to sqrt
declare @dv int = 1
while @dv < @sq
begin
set @dv=@dv+2
if @n % @dv = 0 return 0
end
return 1
end
GO
declare @dt datetime set @dt=getdate()
select dbo.isPrime(1000000000000037)
select datediff(ms,@dt,getdate()) as ms
GO
Ja viss ir kÄrtÄ«bÄ, skaitļa pirmatnÄ«bas pÄrbaude prasÄ«s 6-7-8 sekundes. Tas notika vairÄkos serveros. Bet dažiem pÄrbaude aizÅÄma 25ā40 sekundes. Interesanti, ka nebija serveru, kur izpilde aizÅemtu, teiksim, 14 sekundes ā kods darbojÄs vai nu ļoti Ätri, vai ļoti lÄni, proti, problÄma bija, teiksim, melnbalta.
Ko es esmu izdarÄ«jis? IzmantotÄ VMware metrika. Tur viss bija kÄrtÄ«bÄ - bija resursu pÄrbagÄtÄ«ba, Ready time = 0, visa kÄ pietika, testa laikÄ gan uz Ätrajiem, gan lÄnajiem serveriem CPU = 100 uz viena vCPU. Es veicu testu, lai aprÄÄ·inÄtu skaitli Pi - tests parÄdÄ«ja tÄdus paÅ”us rezultÄtus jebkurÄ serverÄ«. MelnÄs maÄ£ijas smarža kļuva arvien spÄcÄ«gÄka.
Kad nokļuvu DEV fermÄ, sÄku spÄlÄt ar serveriem. IzrÄdÄ«jÄs, ka vMotion no resursdatora uz resursdatoru var āizÄrstÄtā serveri, bet tas var arÄ« pÄrvÄrst āÄtroā serveri par ālÄnuā. Å Ä·iet, ka tÄ ir - dažiem saimniekiem ir problÄma... bet... nÄ. Dažas virtuÄlÄs maŔīnas darbojÄs lÄni resursdatorÄ, piemÄram, A, bet darbojÄs Ätri resursdatorÄ B. Un cita virtuÄlÄ maŔīna, gluži pretÄji, Ätri darbojÄs uz A un palÄninÄja B! Uz saimnieka bieži griezÄs gan āÄtrÄsā, gan ālÄnÄsā maŔīnas!
KopÅ” tÄ brīža gaisÄ bija jÅ«tama izteikta sÄra smaka. Galu galÄ problÄmu nevarÄja saistÄ«t ar virtuÄlo maŔīnu (piemÄram, Windows ielÄpus) - galu galÄ tÄ kļuva par āÄtruā, izmantojot vMotion. Bet problÄmu arÄ« nevarÄja saistÄ«t ar saimniekdatoru - galu galÄ tam varÄtu bÅ«t gan āÄtrasā, gan ālÄnasā maŔīnas. ArÄ« tas nebija saistÄ«ts ar slodzi - man izdevÄs uz resursdatora dabÅ«t ālÄnuā maŔīnu, kurÄ bez tÄ nebija nekÄ.
Aiz izmisuma es palaižu Process Explorer no Sysinternals un paskatÄ«jos uz SQL steku. LÄnÄs maŔīnÄs lÄ«nija uzreiz iekrita acÄ«s:
ntoskrnl.exe!KeSynchronizeExecution+0x5bf6
ntoskrnl.exe!KeWaitForMultipleObjects+0x109d
ntoskrnl.exe!KeWaitForMultipleObjects+0xb3f
ntoskrnl.exe!KeWaitForSingleObject+0x377
ntoskrnl.exe!KeQuerySystemTimePrecise+0x881 < ā !!!
ntoskrnl.exe!ObDereferenceObjectDeferDelete+0x28a
ntoskrnl.exe!KeSynchronizeExecution+0x2de2
sqllang.dll!CDiagThreadSafe::PxlvlReplace+0x1a20
... izlaists
sqldk.dll!SystemThread::MakeMiniSOSThread+0xa54
KERNEL32.DLL!BaseThreadInitThunk+0x14
ntdll.dll! RtlUserThreadStart + 0x21
Tas jau bija kaut kas. Programma tika uzrakstīta:
class Program
{
[DllImport("kernel32.dll")]
static extern void GetSystemTimePreciseAsFileTime(out FILE_TIME lpSystemTimeAsFileTime);
[StructLayout(LayoutKind.Sequential)]
struct FILE_TIME
{
public int ftTimeLow;
public int ftTimeHigh;
}
static void Main(string[] args)
{
for (int i = 0; i < 16; i++)
{
int counter = 0;
var stopwatch = Stopwatch.StartNew();
while (stopwatch.ElapsedMilliseconds < 1000)
{
GetSystemTimePreciseAsFileTime(out var fileTime);
counter++;
}
if (i > 0)
{
Console.WriteLine("{0}", counter);
}
}
}
}
Å Ä« programma demonstrÄja vÄl izteiktÄku palÄninÄjumu - uz āÄtrÄmā maŔīnÄm tÄ rÄda 16-18 miljonus ciklu sekundÄ, savukÄrt uz lÄnÄm maŔīnÄm uzrÄda pusotru miljonu vai pat 700 tÅ«kstoÅ”us. Tas ir, atŔķirÄ«ba ir 10-20 reizes (!!!). Å Ä« jau bija maza uzvara: jebkurÄ gadÄ«jumÄ nebija nekÄdu draudu iesprÅ«st starp Microsoft un VMware atbalstu, lai tie grieztu viens pret otru bultas.
Tad progress apstÄjÄs ā atvaļinÄjumi, svarÄ«gas lietas, vÄ«rusu histÄrija un straujÅ” darba slodzes pieaugums. Bieži pieminÄju maÄ£isko problÄmu saviem kolÄÄ£iem, taÄu brīžiem Ŕķita, ka viÅi pat ne vienmÄr man tic - apgalvojums, ka VMware palÄnina kodu 10-20 reizes, bija pÄrÄk zvÄrÄ«gs.
Es mÄÄ£inÄju pats izrakt to, kas mani bremzÄ. Brīžiem Ŕķita, ka esmu atradis risinÄjumu - Hot plugs ieslÄgÅ”ana un izslÄgÅ”ana, atmiÅas apjoma vai procesoru skaita maiÅa bieži vien padarÄ«ja maŔīnu par āÄtroā. Bet ne uz visiem laikiem. TaÄu patiesÄ«ba izrÄdÄ«jÄs, ka pietiek iziet ÄrÄ un pieklauvÄt pie stÅ«res ā tas ir, pÄrÄ£Ärbties jebkurÅ” virtuÄlÄs maŔīnas parametrs
Visbeidzot, mani amerikÄÅu kolÄÄ£i pÄkÅ”Åi atrada galveno cÄloni.
Saimnieki atŔķīrÄs pÄc biežuma!
- KÄ likums, tas nav nekas liels. Bet: pÄrejot no āvietÄjÄā resursdatora uz resursdatoru ar āatŔķirÄ«guā frekvenci, VMware ir jÄpielÄgo GetTimePrecise rezultÄts.
- Parasti tÄ nav problÄma, ja vien nav lietojumprogrammas, kas pieprasa precÄ«zu laiku miljoniem reižu sekundÄ, piemÄram, SQL serveris.
- Bet tas nav biedÄjoÅ”i, jo SQL serveris ne vienmÄr to dara (skatiet SecinÄjumu)
Bet ir gadÄ«jumi, kad Å”is grÄbeklis sit smagi. Un tomÄr, jÄ, pieskaroties ritenim (kaut ko mainot VM iestatÄ«jumos), es piespiedu VMware āpÄrrÄÄ·inÄtā konfigurÄciju, un paÅ”reizÄjÄ resursdatora frekvence kļuva par maŔīnas ādzimtoā frekvenci.
Å Ä·Ä«dums
AtspÄjojot TSC virtualizÄciju, nolasot TSC no virtuÄlÄs maŔīnas, tiek atgriezta fiziskÄs maŔīnas TSC vÄrtÄ«ba, un TSC rakstÄ«Å”anai no virtuÄlÄs maŔīnas nav nekÄdas ietekmes. MigrÄjot virtuÄlo maŔīnu uz citu resursdatoru, atsÄkot to no apturÄta stÄvokļa vai atgriežoties uz momentuzÅÄmumu, TSC pÄrlec nepÄrtraukti. DažÄm viesu operÄtÄjsistÄmÄm neizdodas sÄknÄties vai rodas citas hronometrÄžas problÄmas, kad TSC virtualizÄcija ir atspÄjota. AgrÄk Ŕī funkcija dažkÄrt tika ieteikta, lai uzlabotu to lietojumprogrammu veiktspÄju, kuras bieži lasa TSC, taÄu paÅ”reizÄjos produktos virtuÄlÄ TSC veiktspÄja ir bÅ«tiski uzlabota. Funkciju ieteicams izmantot arÄ«, veicot mÄrÄ«jumus, kuriem nepiecieÅ”ams precÄ«zs reÄllaika avots virtuÄlajÄ maŔīnÄ.
ÄŖsÄk sakot, jums jÄpievieno parametrs
monitor_control.virtual_rdtsc = FALSE
SecinÄjums
Jums droÅ”i vien ir jautÄjums: kÄpÄc SQL tik bieži izsauc GetTimePrecise?
Man nav SQL servera pirmkoda, bet loÄ£ika to saka. SQL ir gandrÄ«z operÄtÄjsistÄma ar kooperatÄ«vu vienlaicÄ«gumu, kur katram pavedienam ik pa laikam ir ājÄpiekÄpjasā. Kur ir vislabÄkÄ vieta, kur to izdarÄ«t? Kur ir dabiska gaidÄ«Å”ana - slÄdzene vai IO. Labi, bet ja mÄs griežam skaitļoÅ”anas cilpas? Tad acÄ«mredzamÄ un gandrÄ«z vienÄ«gÄ vieta ir tulkÄ (tas Ä«sti nav tulks), pÄc nÄkamÄ paziÅojuma izpildÄ«Å”anas.
Parasti SQL serveri neizmanto tÄ«rai skaitļoÅ”anas naglÄm, un tÄ nav problÄma. Bet cilpas, kas strÄdÄ ar visÄdÄm pagaidu tabulÄm (kas tiek nekavÄjoties saglabÄtas keÅ”atmiÅÄ), pÄrvÄrÅ” kodu ļoti Ätri izpildÄmu paziÅojumu secÄ«bÄ.
Starp citu, ja funkciju iesaiÅo NATIVELY COMPILED, tad tÄ pÄrstÄj prasÄ«t laiku, un tÄs Ätrums palielinÄs 10 reizes.. KÄ ar kooperatÄ«vo daudzuzdevumu veikÅ”anu? Bet sÄkotnÄji kompilÄta koda gadÄ«jumÄ mums bija jÄveic PREEMPTIVE MULTITASKING SQL.
Avots: www.habr.com