Po, laptopi im të vjetër është disa herë më i fuqishëm se serveri juaj i prodhimit.

Katër ankesat e këtij lloji i kam dëgjuar nga zhvilluesit tanë. E veçanta është se kjo doli të ishte e vërtetë, duke çuar në një hetim të gjatë. Bëhet fjalë për serverët SQL që funksionojnë në VMware.

Po, laptopi im të vjetër është disa herë më i fuqishëm se serveri juaj i prodhimit.

Në fakt, është e lehtë të bësh që serveri i prodhimit të mbetet pas laptopit. Ekzekuto (jo në tempdb dhe jo në një bazë me Delayed Durability të aktivizuar) kodin:

set nocount on
create table _t (v varchar(100))
declare @n int=300000
while @n>0 begin 
  insert into _t select 'ÇfarĂ« njĂ« ngadalĂ«sie!'
  delete from _t
  set @n=@n-1
  end
GO
drop table _t

NĂ« desktopin tim ekzekutohet pĂ«r 5 sekonda, ndĂ«rsa nĂ« serverin e prodhimit pĂ«r 28 sekonda. Sepse SQL duhet tĂ« presĂ« pĂ«rfundimin fizik tĂ« shkruarjes nĂ« regjistrin e transaksionit, dhe ne jemi duke bĂ«rĂ« transaksione shumĂ« tĂ« shkurtra. Thjesht, kemi futur njĂ« kamion tĂ« madh dhe tĂ« fuqishĂ«m nĂ« trafikun e qytetit dhe po shohim si e kalojnĂ« lehtĂ«sisht shpĂ«rndarĂ«sit e picave me skuterĂ« — kĂ«tu nuk ka rĂ«ndĂ«si throughput, rĂ«ndĂ«si ka vetĂ«m latency. Dhe asnjĂ« ruajtje nĂ« rrjet, sado tĂ« jetĂ« çmimi i saj, nuk mund tĂ« fitojĂ« nĂ« latency pĂ«rpara njĂ« SSD lokal.

(nĂ« komentet doli se gĂ«njeva — kam pasur delayed durability nĂ« tĂ« dy vendet. Pa delayed durability rezulton:
Desktop — 39 sekonda, 15K tr/sec, 0.065ms/io roundtrip
PROD — 360 sekonda, 1600 tr/sec, 0.6ms
Duhet të kisha kushtuar vëmendje, që gjithçka ishte shumë e shpejtë)

MegjithatĂ«, nĂ« kĂ«tĂ« rast ne po merremi me zerot triviale tĂ« funksionit Riemann me njĂ« shembull trivial. NĂ« atĂ« shembull qĂ« mĂ« sollĂ«n zhvilluesit, kishte diçka tjetĂ«r. UnĂ« u sigurova qĂ« kishin tĂ« drejtĂ« dhe fillova tĂ« pastronja nga shembulli çdo specifikĂ« tĂ« lidhur me logjikĂ«n e biznesit. NĂ« njĂ« moment kuptova se mund tĂ« hodha krejt kodin e tyre dhe tĂ« shkruaja timin — i cili tregon tĂ« njĂ«jtin problem — nĂ« prodhim ai ekzekutohet 3-4 herĂ« mĂ« ngadalĂ«:

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 -- kontrollo çifto deri në 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

NĂ«se gjithçka Ă«shtĂ« nĂ« rregull, kontrolli i thjeshtĂ«sisĂ« sĂ« numrit do tĂ« kryhet pĂ«r 6-7-8 sekonda. KĂ«shtu ka ndodhur nĂ« disa raste serverĂ«ve. Por, nĂ« disa raste kontrollet zgjatnin 25-40 sekonda. E çuditshme, nuk kishte serverĂ« ku ekzekutimi zgjaste, le tĂ« themi, 14 sekonda — kodi punonte ose shumĂ« shpejt, ose krejt ngadalĂ«, qĂ« do tĂ« thotĂ« se problemi ishte, le tĂ« themi, bardhezi.

ÇfarĂ« kam bĂ«rĂ«? Hapa nĂ« metrikat VMware. Atje ishte gjithçka mirĂ« - burimet ishin tĂ« mjaftueshme, koha e gatishmĂ«risĂ« = 0, gjithçka Ă«shtĂ« e mjaftueshme, gjatĂ« testimit dhe nĂ« serverat e shpejtĂ« e tĂ« ngadalshĂ«m CPU=100 nĂ« njĂ« vCPU. Mora njĂ« test pĂ«r llogaritjen e numrit Pi - testi tregonte rezultate tĂ« njĂ«jta nĂ« çdo server. Aroma e magjisĂ« sĂ« zezĂ« po bĂ«hej gjithnjĂ« e mĂ« e fortĂ«.

Duke dalë në fermën DEV, fillova të luaja me serverat. Doli që vMotion nga hosti në host mund të "shërojë" serverin, por gjithashtu mund ta kthejë një server "të shpejtë" në "të ngadalshëm". Duket se këtu është - disa hote kanë probleme... por... jo. Një makinë virtuale po ngadalësohej në hostin, le të themi, A, por punonte shpejt në hostin B. Ndërsa një makinë tjetër virtuale, përkundrazi, punonte shpejt në A dhe ngadalësohej në B! Në hostin shpesh rrotulloheshin si makinat "e shpejta" ashtu edhe "të ngadalshmet"!

Nga ky moment, erdhi qartĂ« njĂ« erĂ« e sulfurit. Problemi nuk mund tĂ« ishte i atribuar as virtuelit (si pĂ«r shembull, patch-et e Windows) — sepse ajo po shndĂ«rrohej nĂ« 'tĂ« shpejtĂ«' gjatĂ« vMotion. Por problemi gjithashtu nuk mund tĂ« ishte i atribuar hostit — sepse aty mund tĂ« kishte si makina 'tĂ« shpejta', ashtu edhe 'tĂ« ngadalta'. Gjithashtu, kjo nuk kishte tĂ« bĂ«nte me ngarkesĂ«n — arrita tĂ« merrja njĂ« makinĂ« 'tĂ« ngadaltĂ«' nĂ« hostin ku pĂ«rveç saj nuk kishte asgjĂ« tjetĂ«r.

Nga dëshpërimi, fillova Process Explorer nga Sysinternals dhe kontrollova stekën SQL. Në makinat e ngadalta, më ra menjëherë në sy rreshti:

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

 skipped
sqldk.dll!SystemThread::MakeMiniSOSThread+0xa54
KERNEL32.DLL!BaseThreadInitThunk+0x14
ntdll.dll!RtlUserThreadStart+0x21

Kjo tashmë ishte diçka. Ishte shkruar një program:

    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  0)
                {
                    Console.WriteLine("{0}", counter);
                }
            }
        }
    }

Ky program tregoi njĂ« ngadalĂ«sim edhe mĂ« tĂ« dukshĂ«m — nĂ« "makinat" e shpejta tregon 16-18 milion cikle nĂ« sekondĂ«, ndĂ«rsa nĂ« ato tĂ« ngadalta — njĂ« milion e pesĂ«qind, madje edhe 700 mijĂ«. Pra, diferenca Ă«shtĂ« 10-20 herĂ« (!!!). Kjo ishte tashmĂ« njĂ« fitore e vogĂ«l: nĂ« çdo rast, nuk kishte kĂ«rcĂ«nim pĂ«r tĂ« ngecur midis mbĂ«shtetjes sĂ« Microsoft dhe VMware duke e transferuar topin te njĂ«ri-tjetri.

MĂ« pas, progresi u ndal — pushime, punĂ« tĂ« rĂ«ndĂ«sishme, hysteria virusale dhe njĂ« rritje drastike e ngarkesĂ«s. Shpesh e kam pĂ«rmendur problemin magjik te kolegĂ«t, por herĂ« pas here mĂ« dukej se ata nuk mĂ« besonin gjithmonĂ« — ishte e tepĂ«rt pĂ«r tĂ« qenĂ« e vĂ«rtetĂ« qĂ« VMware ngadalĂ«son kodin me 10-20 herĂ«.

Provova tĂ« gjej vetĂ« se çfarĂ« e ndalon. HerĂ« pas here mĂ« dukej se e gjeta zgjidhjen — ndezja dhe fikja e Hot plugs, ndryshimi i sasisĂ« sĂ« memories ose i numrit tĂ« procesorĂ«ve shpesh prodhonte njĂ« makinĂ« "tĂ« shpejtĂ«". Por jo pĂ«r gjithmonĂ«. Ajo qĂ« doli e vĂ«rtetĂ« ishte se mjafton tĂ« dalĂ«sh dhe tĂ« godasĂ«sh rrotĂ«n — do tĂ« thotĂ« tĂ« ndryshosh çdo kush parametrin e virtualkes

Më në fund, kolegët e mi amerikanë papritur gjetën shkakun kryesor.

Po, laptopi im të vjetër është disa herë më i fuqishëm se serveri juaj i prodhimit.

Hostet ndryshonin frekuencën!

  • Si rregull, kjo nuk Ă«shtĂ« e frikshme. Por: kur kalon nga hosti ‘i origjinĂ«s’ nĂ« njĂ« host me ‘frekuencĂ« tjetĂ«r’, VMware duhet tĂ« korrigjojĂ« rezultatin GetTimePrecise.
  • Si rregull, kjo nuk Ă«shtĂ« e frikshme, pĂ«rveç nĂ«se ka aplikacione qĂ« kĂ«rkojnĂ« kohĂ«n e saktĂ« miliona herĂ« nĂ« sekondĂ«, si SQL server.
  • Por as kjo nuk Ă«shtĂ« e frikshme, pasi SQL server e bĂ«n kĂ«tĂ« jo gjithmonĂ« (shih pĂ«rfundimin).

Por ka raste kur kĂ«to gĂ«rshĂ«rĂ« e godasin keq. Dhe po, duke trokitur nĂ« rrotĂ« (duke ndryshuar diçka nĂ« konfigurimet e VM) e detyrova VMware ta ‘ri-luajë’ konfigurimin, dhe frekuenca e hostit aktual bĂ«hej frekuenca ‘origjinale’ e makinĂ«s.

Zgjidhja

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

Kur e çaktivizoni virtualizimin e TSC, leximi i TSC nga brenda makinës virtuale kthen vlerën TSC të makinës fizike, dhe shkrimi i TSC nga brenda makinës virtuale nuk ka efekt. Migrimi i makinës virtuale në një host tjetër, rikthimi i saj nga gjendja e pezullimit, ose kthimi në një snapshot shkakton që TSC të skadojë në mënyrë të ndërprerë. Disa sisteme operative mysafir dështojnë të boot-ojnë ose tregojnë probleme të tjera me mbajtjen e kohës, kur virtualizimi i TSC është i çaktivizuar. Në të kaluarën, kjo veçori është rekomanduar ndonjëherë për të përmirësuar performancën e aplikacioneve që lexojnë shpesh TSC., por performanca e TSC virtual është përmirësuar ndjeshëm në produktet aktuale. Kjo veçori është rekomanduar gjithashtu për përdorim kur kryhen matje që kërkojnë një burim të saktë të kohës reale në makinën virtuale.

Shkurtimisht, duhet të shtoni parametrin

monitor_control.virtual_rdtsc = FALSE

Përfundimi

Sigurisht që ka një pyetje: pse SQL thërret GetTimePrecise kaq shpesh?

Nuk kam burime tĂ« SQL server, por logjika thotĂ« kĂ«shtu. SQL Ă«shtĂ« pothuajse njĂ« sistem operativ me konkurrencĂ« bashkĂ«punuese, ku çdo thread duhet herĂ« pas here "tĂ« heqĂ« dorĂ«". E ku e bĂ«n kĂ«tĂ« mĂ« mirĂ«? Atje ku ka njĂ« pritje natyrale — lock ose IO. MirĂ«, dhe çfarĂ« ndodh nĂ«se ne lĂ«vizim ciklet e llogaritjeve? AtĂ«herĂ« vendi i dukshĂ«m dhe pothuajse i vetĂ«m Ă«shtĂ« nĂ« interpretues (nuk Ă«shtĂ« krejtĂ«sisht njĂ« interpretues), pas ekzekutimit tĂ« çdo urdhĂ«ri.

Në përgjithësi, SQL server nuk përdoret për të goditur tela për llogaritje të pastra dhe kjo nuk është një problem. Por ciklet me punë me tabela përkohshme (të cilat menjëherë cache-ohen) e shndërrojnë kodin në një radhë të urdhërave që ekzekutohen shumë shpejt.

Për më tepër, nëse funksioni është i mbështjellë në NATIVELY COMPILED, atëherë ai ndalon të kërkojë kohë, dhe shpejtësia e tij rritet 10 herë. E si qëndron me multitasking-un bashkëpunues? Në këtë rast, për kodin natively compiled, u desh të bëhej në SQL PREEMPTIVE MULTITASKING.

Burimi: habr.com

Bli njĂ« hosting tĂ« besueshĂ«m pĂ«r faqet me mbrojtje DDoS, VPS VDS serverĂ« đŸ”„ Bli njĂ« hosting tĂ« besueshĂ«m pĂ«r faqet me mbrojtje DDoS, VPS VDS serverĂ« | ProHoster