Bai, nire ordenagailu eramangarri zaharra zure ekoizpen zerbitzaria baino hainbat aldiz indartsuagoa da

Hauek dira, hain zuzen, gure garatzaileengandik entzun nituen kexak. Interesgarriena hau egia izan zela da, ikerketa luze bati hasiera emanez. VMware-n exekutatzen diren SQL zerbitzariei buruz hitz egingo dugu.

Bai, nire ordenagailu eramangarri zaharra zure ekoizpen zerbitzaria baino hainbat aldiz indartsuagoa da

Egia esan, erraza da ekoizpen zerbitzaria ordenagailu eramangarriaren atzean dagoela ziurtatzea. Exekutatu (ez tempdb-n eta ez Iraunkortasun atzeratua gaituta duen datu-base batean) kodea:

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

Nire mahaigainean 5 segundo behar ditu eta ekoizpen zerbitzarian 28 segundo. SQL-k transakzioen erregistroaren amaiera fisikoaren amaierara itxaron behar duelako, eta transakzio oso laburrak egiten ari gara hemen. Gutxi gorabehera, kamioi handi eta indartsu bat gidatu genuen hiriko trafikoan, eta motorretan pizza banatzen zutenek izugarri aurreratzen zutela ikusi genuen. Hemen errendimendua ez da garrantzitsua, latentzia baino ez da garrantzitsua. Eta ez dago sareko biltegiratzerik, bere prezioan zenbat zero dauden ere, tokiko SSDa gainditu dezake latentziari dagokionez.

(Iruzkinetan gezurra esan dudala geratu da - bi lekuetan iraunkortasuna atzeratua izan dut. Iraunkortasun atzeratu gabe geratzen da:
Mahaigaina - 39 segundo, 15K tr/seg, 0.065 ms/io joan-etorria
PROD - 360 segundo, 1600 tr/s, 0.6 ms
Azkarregia zela konturatu beharko nuke)

Hala ere, kasu honetan Riemann zeta funtzioaren zero hutsalez ari gara adibide hutsal batekin. Garatzaileek ekarri didaten adibidean, ezberdina zen. Arrazoia zutela sinetsita nengoen, eta adibidetik negozio-logikari lotutako zehaztasun guztiak kentzen hasi nintzen. Noizbait konturatu nintzen haien kodea guztiz bota nezakeela eta nirea idatzi - eta horrek arazo bera erakusten du - ekoizpenean 3-4 aldiz motelagoa da:

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

Dena ondo badago, zenbaki baten lehentasuna egiaztatzeak 6-7-8 segundo beharko ditu. Hau zerbitzari batzuetan gertatu da. Baina batzuetan, egiaztapenak 25-40 segundo behar zituen. Interesgarria da, ez zegoen zerbitzaririk exekuzioak, esate baterako, 14 segundo iraungo zuen - kodeak oso azkar edo oso poliki funtzionatzen zuen, hau da, arazoa, demagun, zuri-beltzean zegoen.

Zer egin dut? Erabilitako VMware neurketak. Dena ondo zegoen han - baliabide ugari zegoen, Prest denbora = 0, denetarik nahikoa zegoen, proban zehar zerbitzari azkar zein moteletan CPU = 100 vCPU batean. Pi zenbakia kalkulatzeko proba bat egin nuen; probak emaitza berdinak erakutsi zituen edozein zerbitzaritan. Magia beltzaren usaina gero eta indartsuagoa zen.

Behin DEV baserrira iritsi nintzenean, zerbitzariekin jolasten hasi nintzen. Agertu zen vMotion-ek ostalari batetik bestera zerbitzari bat "sendatu" dezakeela, baina zerbitzari "bizkorra" bat "motel" bihur dezakeela ere. Badirudi hauxe dela - ostalari batzuek arazo bat dute... baina... ez. Makina birtual batzuk motelak ziren ostalarian, demagun A, baina azkar funtzionatu zuen B ostalarian. Eta beste makina birtual batek, aitzitik, azkar funtzionatu zuen A-n eta moteldu zen B-n! Makina "bizkorra" eta "motela" askotan biraka ari ziren ostalariaren gainean!

Une horretatik aurrera, sufre usain nabarmena zegoen airean. Azken finean, arazoa ezin zitzaion makina birtualeri egotzi (Windows adabakiak, adibidez) - azken finean, "azkar" bihurtu zen vMotion-ekin. Baina arazoa ere ezin zaio ostalariari egotzi; azken finean, makina "azkarrak" eta "motelak" izan ditzake. Gainera, hau ez zegoen kargarekin zerikusirik - ostalariaren makina "motel" bat lortzea lortu nuen, horrez gain ezer ez zegoen.

Etsipenaz, Process Explorer abiarazi nuen Sysinternals-etik eta SQL pila begiratu nuen. Makina moteletan lerroak berehala harrapatu zuen nire begia:

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
... saltatu
sqldk.dll!SystemThread::MakeMiniSOSThread+0xa54
KERNEL32.DLL!BaseThreadInitThunk+0x14
ntdll.dll! RtlUserThreadStart + 0x21

Hau jada zerbait zen. Programa idatzi zen:

    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);
                }
            }
        }
    }

Programa honek are moteltze nabarmenagoa erakutsi zuen: makina "azkar"etan 16-18 milioi ziklo erakusten ditu segundoko, eta makina moteletan milioi bat eta erdi edo 700 mila erakusten ditu. Hau da, aldea 10-20 aldiz (!!!). Garaipen txikia zen jada: edonola ere, ez zegoen Microsoft eta VMware euskarriaren artean trabatuta geziak elkarri buelta emateko mehatxurik.

Ondoren, aurrerapena gelditu zen: oporrak, gai garrantzitsuak, histeria birikoa eta lan-karga handitu zen. Askotan aipatu nien magia-arazoa nire lankideei, baina batzuetan zirudien ez zidatela beti sinisten ere - VMware-k kodea 10-20 aldiz moteltzen duela esatea izugarriegia zen.

Moteltzen ninduena neure burua ateratzen saiatu nintzen. Batzuetan konponbide bat aurkitu nuela iruditu zitzaidan - Hot plug-ak piztu eta itzaltzeak, memoria-kopurua edo prozesadore-kopurua aldatzeak sarritan makina "azkar" bihurtzen zuen. Baina ez betirako. Baina egia izan zena da nahikoa dela kalera atera eta gurpila jotzea, hau da, aldatzea. Edozein makina birtualaren parametroa

Azkenik, nire lankide amerikarrek bat-batean aurkitu zuten arrazoia.

Bai, nire ordenagailu eramangarri zaharra zure ekoizpen zerbitzaria baino hainbat aldiz indartsuagoa da

Ostalariak maiztasunean desberdinak ziren!

  • Oro har, hau ez da gauza handia. Baina: "jatorrizko" ostalari batetik maiztasun "ezberdina" duen ostalari batera pasatzen denean, VMware-k GetTimePrecise emaitza egokitu behar du.
  • Orokorrean, hau ez da arazoa, segundoko milioika aldiz ordu zehatza eskatzen duen aplikaziorik ez badago, SQL zerbitzaria bezala.
  • Baina hau ez da beldurgarria, SQL zerbitzariak ez baitu beti hau egiten (ikusi Ondorioa)

Baina badaude kasuak arraste honek gogor jotzen duenean. Eta, hala ere, bai, gurpila sakatuz (VM ezarpenetan zerbait aldatuz) VMware behartu nuen konfigurazioa 'berriro kalkulatzera', eta uneko ostalariaren maiztasuna makinaren maiztasun 'berezko' bihurtu zen.

Erabaki

www.vmware.com/files/pdf/techpaper/Timekeeping-In-VirtualMachines.pdf

TSC birtualizazioa desgaitzen duzunean, TSC makina birtualetik irakurtzeak makina fisikoaren TSC balioa itzultzen du, eta TSC makina birtualetik idazteak ez du eraginik. Makina birtuala beste ostalari batera migratzeak, eseki egoeratik berregiteak edo argazki batera itzultzeak TSC-a etengabe jauzi egiten du. Gonbidatuen sistema eragile batzuek ez dute abiarazten edo beste arazo batzuk erakusten dituzte TSC birtualizazioa desgaituta dagoenean. Iraganean, eginbide hau batzuetan TSC maiz irakurtzen duten aplikazioen errendimendua hobetzeko gomendatzen zen, baina TSC birtualaren errendimendua nabarmen hobetu da egungo produktuetan. Ezaugarri hau makina birtualean denbora errealeko iturri zehatza behar duten neurketak egiteko ere gomendatu da.

Laburbilduz, parametroa gehitu behar duzu

monitor_control.virtual_rdtsc = GEZURRA

Ondorioa

Seguruenik galdera bat duzu: zergatik deitzen dio SQL-k GetTimePrecise hain maiz?

Ez dut SQL zerbitzariaren iturburu kodea, baina logikak hau dio. SQL aldiberekotasun kooperatiboa duen ia sistema eragile bat da, non hari bakoitzak noizean behin "eman" behar duen. Non dago hau egiteko lekurik onena? Itxaron naturala dagoen tokian - blokeoa edo IO. Ados, baina zer gertatzen da begizta konputazionalak birakatzen ari bagara? Orduan, leku agerikoa eta ia bakarra interpretatzailean dago (hau ez da benetan interpretea), hurrengo adierazpena exekutatu ondoren.

Orokorrean, SQL zerbitzaria ez da informatika hutsezko iltzerako erabiltzen eta hau ez da arazo bat. Baina aldi baterako taula mota guztiekin lan egiten duten begiztak (berehala cachean gordetzen direnak) kodea oso azkar exekutatutako instrukzioen sekuentzia bihurtzen dute.

Bide batez, funtzioa NATIVELY COMPILED-en biltzen baduzu, orduan denbora eskatzeari utziko dio, eta bere abiadura 10 aldiz handitzen da.Zer gertatzen da multiataza kooperatiboa? Baina natiboki konpilatutako kodearentzat PREEMPTIVE MULTATASKING egin behar genuen SQLn.

Iturria: www.habr.com

Gehitu iruzkin berria