Тийм ээ, миний хуучин зөөврийн компьютер таны үйлдвэрлэлийн серверээс хэд дахин илүү хүчтэй

Эдгээр нь яг манай хөгжүүлэгчидээс сонссон гомдол юм. Хамгийн сонирхолтой нь энэ нь үнэн болж, урт удаан мөрдөн байцаалтад хүргэв. Бид VMware дээр ажилладаг SQL серверүүдийн талаар ярих болно.

Тийм ээ, миний хуучин зөөврийн компьютер таны үйлдвэрлэлийн серверээс хэд дахин илүү хүчтэй

Үнэн хэрэгтээ үйлдвэрлэлийн сервер зөөврийн компьютерын ард найдваргүй байхыг баталгаажуулахад хялбар байдаг. Дараах кодыг гүйцэтгэнэ (temdb дээр биш, удаан эдэлгээтэй өгөгдлийн сан дээр биш):

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

Миний ширээний компьютер дээр 5 секунд, үйлдвэрлэлийн сервер дээр 28 секунд зарцуулдаг. Учир нь SQL нь гүйлгээний бүртгэлийн бичилтийн физик төгсгөлийг хүлээх ёстой бөгөөд бид энд маш богино гүйлгээ хийж байна. Товчоор хэлбэл, бид том, хүчирхэг ачааны машиныг хотын замын хөдөлгөөнд оруулаад, пицца хүргэгчид скутерээр түрүүлэхийг харлаа - энд дамжуулах чадвар чухал биш, зөвхөн хоцрогдол чухал. Ямар ч сүлжээний хадгалалт үнэ нь хэдэн тэгтэй байсан ч хоцрогдлын хувьд орон нутгийн SSD-г гүйцэж чадахгүй.

(сэтгэгдэл дээр би худал хэлсэн нь тогтоогдсон - Би хоёр газар удаан эдэлгээтэй байсан. Удаан эдэлгээгүй бол:
Ширээний компьютер - 39 секунд, 15K tr/s, 0.065ms /io хоёр талын аялал
PROD - 360 секунд, 1600 тр/сек, 0.6 мс
Энэ нь хэтэрхий хурдан байсныг би анзаарсан байх ёстой)

Гэсэн хэдий ч, энэ тохиолдолд бид Riemann zeta функцийн өчүүхэн тэгүүдийг энгийн жишээгээр авч үзэж байна. Хөгжүүлэгчдийн надад авчирсан жишээн дээр энэ нь өөр байсан. Тэдний зөв гэдэгт би итгэлтэй байсан бөгөөд бизнесийн логиктой холбоотой бүх онцлог шинж чанаруудыг жишээнээс хасаж эхлэв. Хэзээ нэгэн цагт би тэдний кодыг бүрэн хаяж, өөрийнхөө кодыг бичиж чадна гэдгээ ойлгосон - энэ нь ижил асуудлыг харуулж байна - үйлдвэрлэлд энэ нь 3-4 дахин удаан ажилладаг:

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

Хэрэв бүх зүйл хэвийн байвал тооны анхдагч байдлыг шалгахад 6-7-8 секунд шаардлагатай. Энэ нь хэд хэдэн сервер дээр тохиолдсон. Харин заримд нь шалгахад 25-40 секунд зарцуулсан. Сонирхолтой нь, гүйцэтгэл нь 14 секунд зарцуулдаг сервер байхгүй байсан - код нь маш хурдан эсвэл маш удаан ажилладаг байсан, өөрөөр хэлбэл асуудал нь хар цагаан байсан гэж хэлье.

Би юу хийчихэв ээ? VMware хэмжигдэхүүнийг ашигласан. Тэнд бүх зүйл сайхан байсан - маш их нөөц байсан, бэлэн цаг = 0, бүх зүйл хангалттай байсан, нэг vCPU дээр CPU = 100 хурдан ба удаан сервер дээр туршилт хийх явцад. Би Pi тоог тооцоолох тест өгсөн - тест нь ямар ч сервер дээр ижил үр дүнг харуулсан. Хар ид шидийн анхилуун үнэр улам хүчтэй болж байв.

Би DEV фермд очсоны дараа серверүүдтэй тоглож эхэлсэн. Хостоос хост руу шилжих vMotion нь серверийг "эмчлэх" боломжтой болохоос гадна "хурдан" серверийг "удаан" болгож чаддаг нь тогтоогдсон. Энэ нь ийм юм шиг санагдаж байна - зарим хостууд асуудалтай байна ... гэхдээ ... үгүй. Зарим виртуал машин нь хост дээр удаан байсан гэж хэлье, гэхдээ B хост дээр хурдан ажиллаж байсан. Мөн өөр виртуал машин, эсрэгээр, А дээр хурдан ажиллаж, B дээр удаашруулсан! "Хурдан" болон "удаан" машин хоёулаа хост дээр ихэвчлэн эргэлддэг!

Энэ мөчөөс эхлэн агаарт хүхрийн тодорхой үнэр үнэртэв. Эцсийн эцэст, асуудлыг виртуал машинтай холбож болохгүй (жишээ нь Windows засварууд) - эцэст нь энэ нь vMotion-ийн тусламжтайгаар "хурдан" болж хувирав. Гэхдээ асуудал нь хосттой холбоотой байж болохгүй - эцэст нь энэ нь "хурдан" болон "удаан" машинтай байж болно. Түүнчлэн, энэ нь ачаалалтай холбоогүй - би хост дээр "удаан" машин авч чадсан бөгөөд үүнээс өөр юу ч байхгүй.

Би цөхрөнгөө барсандаа Sysinternals-аас Process Explorer програмыг ажиллуулж, SQL стекийг харлаа. Удаан машинууд дээр энэ шугам шууд миний анхаарлыг татав:

ntoskrnl.exe!KeSynchronizeExecution+0x5bf6
ntoskrnl.exe! Олон Объектыг Хүлээгээрэй+0x109d
ntoskrnl.exe! Олон Объектыг Хүлээгээрэй+0xb3f
ntoskrnl.exe!KeWaitForSingleObject+0x377
ntoskrnl.exe!KeQuerySystemTimePrecise+0x881 < — !!!
ntoskrnl.exe!ObDereferenceObjectDeferDelete+0x28a
ntoskrnl.exe!KeSynchronizeExecution+0x2de2
sqllang.dll!CDiagThreadSafe::PxlvlReplace+0x1a20
... алгассан
sqldk.dll!SystemThread::MakeMiniSOSThread+0xa54
KERNEL32.DLL!BaseThreadInitThunk+0x14
ntdll.dll!RtlUserThreadStart+0x21

Энэ нь аль хэдийн ямар нэг зүйл байсан. Хөтөлбөрийг бичсэн:

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

Энэ програм нь илүү тодорхой удаашралыг харуулсан - "хурдан" машинууд дээр секундэд 16-18 сая циклийг харуулдаг бол удаан машинууд дээр нэг сая хагас, бүр 700 мянган циклийг харуулдаг. Энэ нь ялгаа нь 10-20 дахин (!!!). Энэ бол аль хэдийн жижиг ялалт байсан: ямар ч тохиолдолд Microsoft болон VMware-ийн дэмжлэгийн хооронд гацах аюул байгаагүй бөгөөд ингэснээр тэд бие бие рүүгээ сум эргүүлэх болно.

Дараа нь ахиц дэвшил зогссон - амралт, чухал асуудлууд, вирусын гистери, ажлын ачаалал огцом нэмэгдсэн. Би шидэт асуудлын талаар хамт ажиллагсаддаа байнга хэлдэг байсан ч заримдаа тэд надад итгэдэггүй юм шиг санагддаг - VMware кодыг 10-20 дахин удаашруулдаг гэсэн мэдэгдэл хэтэрхий аймшигтай байсан.

Намайг удаашруулж буй зүйлийг би өөрөө ухаж гаргах гэж оролдов. Заримдаа би халуун залгууруудыг асааж унтраах, санах ойн хэмжээ эсвэл процессорын тоог өөрчлөх зэрэг нь машиныг "хурдан" болгож хувиргах шийдлийг олсон юм шиг санагддаг. Гэхдээ үүрд биш. Гэхдээ үнэн болсон зүйл бол гараад дугуй тогшиход л хангалттай, өөрөөр хэлбэл өөрчлөлт ямар ч виртуал машины параметр

Эцэст нь миний америк хамт олон гэнэт үндсэн шалтгааныг олж мэдэв.

Тийм ээ, миний хуучин зөөврийн компьютер таны үйлдвэрлэлийн серверээс хэд дахин илүү хүчтэй

Хөтлөгчид давтамжаараа ялгаатай байсан!

  • Дүрмээр бол энэ нь тийм ч том асуудал биш юм. Гэхдээ: "уугуул" хостоос "өөр" давтамжтай хост руу шилжих үед VMware GetTimePrecise үр дүнг тохируулах ёстой.
  • Дүрмээр бол, SQL сервер шиг секундэд хэдэн сая удаа яг цагийг шаарддаг програм байхгүй бол энэ нь асуудал биш юм.
  • Гэхдээ энэ нь аймшигтай биш юм, учир нь SQL сервер үүнийг үргэлж хийдэггүй (Дүгнэлтийг үзнэ үү)

Гэхдээ энэ тармуур хүчтэй цохих тохиолдол байдаг. Гэсэн хэдий ч, тийм ээ, дугуй дээр дарснаар (VM тохиргоон дахь ямар нэг зүйлийг өөрчилснөөр) би VMware-г тохиргоог "дахин тооцоолох" шаардлагатай болгосон бөгөөд одоогийн хостын давтамж нь машины "уугуул" давтамж болсон.

шийдвэр

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

Та TSC-ийн виртуалчлалыг идэвхгүй болгох үед виртуал машин дотроос TSC-г унших нь физик машины TSC утгыг буцаадаг бөгөөд виртуал машин дотроос TSC бичих ямар ч нөлөө үзүүлэхгүй. Виртуал машиныг өөр хост руу шилжүүлэх, түр зогссон төлөвөөс нь үргэлжлүүлэх эсвэл агшин зуурын зураг руу буцах нь TSC-г тасалдалгүй үсрэхэд хүргэдэг. Зарим зочны үйлдлийн системүүд TSC виртуалчлал идэвхгүй болсон үед ачаалагдахгүй, эсвэл бусад цаг хөтлөлтийн асуудал гардаг. Өмнө нь энэ функцийг заримдаа TSC-ийг байнга уншдаг програмуудын гүйцэтгэлийг сайжруулахыг зөвлөдөг байсан, гэхдээ виртуал TSC-ийн гүйцэтгэл одоогийн бүтээгдэхүүнүүдэд мэдэгдэхүйц сайжирсан. Энэ функцийг виртуал машинд бодит цагийн нарийн эх сурвалж шаарддаг хэмжилт хийх үед ашиглахыг зөвлөж байна.

Товчхондоо та параметрийг нэмэх хэрэгтэй

monitor_control.virtual_rdtsc = ХУДАЛ

дүгнэлт

Танд асуулт байгаа байх: SQL яагаад GetTimePrecise гэж байнга дууддаг вэ?

Надад SQL серверийн эх код байхгүй ч логик нь үүнийг хэлж байна. SQL бол урсгал бүр нь үе үе "бууж өгөх" ёстой хамтын ажиллагаатай бараг л үйлдлийн систем юм. Үүнийг хийх хамгийн тохиромжтой газар хаана байна вэ? Байгалийн хүлээлт байгаа газар - цоож эсвэл IO. За, гэхдээ бид тооцооллын гогцоо эргүүлж байвал яах вэ? Дараа нь дараагийн мэдэгдлийг гүйцэтгэсний дараа тодорхой бөгөөд бараг цорын ганц газар нь орчуулагч (энэ нь үнэхээр орчуулагч биш) юм.

Ерөнхийдөө SQL серверийг цэвэр тооцооллын хадаас хийхэд ашигладаггүй бөгөөд энэ нь асуудал биш юм. Гэхдээ бүх төрлийн түр зуурын хүснэгтүүдтэй ажилладаг гогцоонууд (тэр даруйд хадгалагддаг) кодыг маш хурдан гүйцэтгэсэн хэллэгүүдийн дараалал болгон хувиргадаг.

Дашрамд хэлэхэд, хэрэв та NATIVELY COMPILED функцийг боож өгвөл энэ нь цаг хугацаа асуухаа больж, хурд нь 10 дахин нэмэгддэг. Хамтарсан олон үйлдэл яах вэ? Гэхдээ эхнээс нь эмхэтгэсэн кодын хувьд бид SQL дээр УРЬДЧИЛАН ОЛОН ДААЛГАТ хийх шаардлагатай болсон.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх