Ya, laptop lawasku kaping pirang-pirang luwih kuat tinimbang server produksi sampeyan

Iki persis keluhan sing dakrungu saka pangembang. Sing paling menarik yaiku yen iki bener, nyebabake penyelidikan sing dawa. Kita bakal ngomong babagan server SQL sing mlaku ing VMware.

Ya, laptop lawasku kaping pirang-pirang luwih kuat tinimbang server produksi sampeyan

Bener, gampang kanggo mesthekake yen server produksi ora ngarep-arep ing mburi laptop. Eksekusi (ora ing tempdb lan ora ing basis data kanthi Ketahanan Tundha aktif) kode kasebut:

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

Ing desktopku butuh 5 detik, lan ing server produksi butuh 28 detik. Amarga SQL kudu ngenteni mburi fisik entri log transaksi, lan kita nindakake transaksi cendhak banget kene. Kira-kira, kita ndamel truk gedhe lan kuat menyang lalu lintas kutha, lan mirsani amarga dicekel dening wong pangiriman pizza ing skuter - throughput ora penting ing kene, mung latensi sing penting. Lan ora panyimpenan jaringan, ora ketompo carane akeh nul ana ing rega, bisa ngalahake SSD lokal ing latensi.

(ing komentar ternyata aku ngapusi - aku wis tundha kekiatan ing loro panggonan. Tanpa kekiatan telat ternyata:
Desktop - 39 detik, 15K tr/detik, 0.065ms/io bolak-balik
PROD - 360 detik, 1600 tr/detik, 0.6ms
Aku kudune weruh yen cepet banget)

Nanging, ing kasus iki kita dealing karo nol trivial saka fungsi Riemann zeta karo conto ora pati penting. Ing conto sing digawa dening pangembang, beda. Aku iki nggawe percoyo sing padha bener, lan wiwit mbusak saka conto kabeh spesifik related kanggo logika bisnis. Ing sawetara titik aku nyadari yen aku bisa mbuwang kode kasebut lan nulis dhewe - sing nuduhake masalah sing padha - ing produksi mlaku 3-4 kaping luwih alon:

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

Yen kabeh iku nggoleki, mriksa primality nomer bakal njupuk 6-7-8 detik. Iki kedadeyan ing sawetara server. Nanging ing sawetara, mriksa njupuk 25-40 detik. Apike, ora ana server ing ngendi eksekusi bakal ditindakake, ujare, 14 detik - kode kasebut bisa digunakake kanthi cepet utawa alon banget, yaiku, masalah kasebut, umpamane, ireng lan putih.

Apa aku wis rampung? Metrik VMware sing digunakake. Kabeh iku nggoleki ana - ana turah mbrawah saka sumber daya, Siap wektu = 0, ana cukup kabeh, sak test ing loro cepet lan alon server CPU = 100 ing siji vCPU. Aku njupuk test kanggo ngetung nomer Pi - test nuduhake asil padha ing server sembarang. Ambune mambu ireng dadi saya kuwat.

Sawise aku menyang farm DEV, Aku miwiti muter karo server. Ternyata vMotion saka host menyang host bisa "ngobati" server, nanging uga bisa ngowahi server "cepet" dadi "alon". Iku misale jek kaya iki - sawetara sarwa dumadi duwe masalah ... nanging ... ora. Sawetara mesin virtual alon ing inang, ngandika A, nanging makarya cepet ing inang B. Lan mesin virtual liyane, ing nalisir, makarya cepet ing A lan kalem ing B! Loro-lorone "cepet" lan "alon" mesin asring muter ing inang!

Wiwit wektu iku, ana ambune belerang ing udhara. Sawise kabeh, masalah kasebut ora bisa disebabake karo mesin virtual (patch Windows, contone) - sawise kabeh, dadi "cepet" karo vMotion. Nanging masalah uga ora bisa lantaran kanggo inang - sawise kabeh, iku bisa duwe loro mesin "cepet" lan "alon". Uga, iki ora ana hubungane karo beban - aku bisa entuk mesin "alon" ing host, sing ora ana apa-apa liyane.

Saka desperation, Aku dibukak Proses Explorer saka Sysinternals lan katon ing tumpukan SQL. Ing mesin alon, garis kasebut langsung narik kawigatenku:

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

Iki wis soko. Program kasebut ditulis:

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

Program iki nuduhake kalem sing luwih cetha - ing mesin "cepet" nuduhake 16-18 yuta siklus per detik, nalika ing mesin alon nuduhake siji lan setengah yuta, utawa malah 700 ewu. Tegese bedane ping 10-20 (!!!). Iki wis dadi kamenangan cilik: ing kasus apa wae, ora ana ancaman kanggo macet ing antarane dhukungan Microsoft lan VMware supaya bisa saling panah.

Banjur kemajuan mandheg - preian, prakara penting, histeria virus lan beban kerja mundhak. Aku kerep nyebataken masalah sihir marang kanca-kancaku, nanging kadhangkala dheweke ora percaya karo aku - pratelan manawa VMware nyuda kode kasebut kaping 10-20 banget.

Aku nyoba kanggo dig metu dhewe apa sing slowing kula mudhun. Kadhangkala, aku wis nemokake solusi - nguripake lan mateni plug Hot, ngganti jumlah memori utawa jumlah prosesor asring ngowahi mesin dadi "cepet". Nanging ora langgeng. Nanging apa sing dadi bener iku cukup kanggo metu lan ngalahake setir - yaiku, ngganti apa wae parameter mesin virtual

Pungkasan, kanca-kanca Amerikaku dumadakan nemokake sababe.

Ya, laptop lawasku kaping pirang-pirang luwih kuat tinimbang server produksi sampeyan

Tuan rumah beda frekuensi!

  • Minangka aturan, iki ora masalah gedhe. Nanging: nalika pindhah saka host 'native' menyang host kanthi frekuensi 'beda', VMware kudu nyetel asil GetTimePrecise.
  • Minangka aturan, iki ora masalah, kajaba ana aplikasi sing njaluk wektu pas yuta kaping per detik, kaya SQL server.
  • Nanging iki ora medeni, amarga server SQL ora tansah nindakake iki (pirsani Kesimpulan)

Nanging ana kasus nalika rake iki hard. Nanging, ya, kanthi nutul ing setir (kanthi ngganti soko ing setelan VM) Aku meksa VMware kanggo 'recalculate' konfigurasi, lan frekuensi saka host saiki dadi frekuensi 'native' saka mesin.

kaputusan

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

Nalika sampeyan mateni virtualisasi TSC, maca TSC saka mesin virtual ngasilake nilai TSC mesin fisik, lan nulis TSC saka mesin virtual ora ana pengaruhe. Migrasi mesin virtual menyang host liyane, nerusake saka negara sing ditanggepi, utawa bali menyang snapshot nyebabake TSC mlumpat kanthi ora terus-terusan. Sawetara sistem operasi tamu gagal boot, utawa nuduhake masalah timekeeping liyane, nalika virtualisasi TSC dipateni. Sadurunge, fitur iki kadhangkala disaranake kanggo nambah kinerja aplikasi sing kerep maca TSC, nanging kinerja saka TSC virtual wis apik mesti ing produk saiki. Fitur kasebut uga disaranake digunakake nalika nindakake pangukuran sing mbutuhake sumber wektu nyata sing tepat ing mesin virtual.

Ing cendhak, sampeyan kudu nambah parameter

monitor_control.virtual_rdtsc = PALSU

kesimpulan

Sampeyan bisa uga duwe pitakon: kenapa SQL nelpon GetTimePrecise asring?

Aku ora duwe kode sumber SQL server, nanging logika ngandika iki. SQL meh sistem operasi karo concurrency koperasi, ngendi saben thread kudu "menehi" saka wektu kanggo wektu. Ing endi panggonan sing paling apik kanggo nindakake iki? Ing ngendi ana tunggu alam - kunci utawa IO. Oke, nanging kepiye yen kita muter loop komputasi? Banjur panggonan sing jelas lan meh mung ana ing juru basa (iki dudu juru basa), sawise nglakokake pernyataan sabanjure.

Umume, server SQL ora digunakake kanggo nailing komputasi murni lan iki ora dadi masalah. Nanging puteran sing bisa digunakake karo kabeh jinis tabel sementara (sing langsung di-cache) ngowahi kode kasebut dadi urutan pernyataan sing dieksekusi kanthi cepet.

Miturut cara, yen sampeyan mbungkus fungsi ing NATIVELY COMPILED, banjur mandheg takon wektu, lan kacepetan mundhak kaping 10. Kepiye babagan multitasking koperasi? Nanging kanggo kode kompilasi asli, kita kudu nindakake PREEMPTIVE MULTITASKING ing SQL.

Source: www.habr.com

Add a comment