Soket oqimini so‘nggi joylashuvni yo‘qotmasdan cheklash

112 dispetcherlik xaritasida har bir favqulodda transport o‘z joylashuvini sekundiga bir necha marta yuboradi. Buni mamlakat bo‘ylab smenadagi transportlar soniga ko‘paytiring: brauzer daqiqasiga minglab xabar oladi. Har biri uchun OpenLayers qatlamini qayta chizish dispetcher ekranini qotirishning men bilgan eng tez yo‘li.

Bu maqola soket bilan xarita o‘rtasida turgan kichik RxJS bo‘lagi haqida va nega u aynan shunday shaklda.

Haddan ortiq yangilanish qanday ko‘rinadi

Belgi halokat emas edi. Xarita ishlashda davom etdi, lekin har bir harakat qo‘ldan orqada qolardi: surish sichqoncha to‘xtaganidan yarim soniya keyin tugardi, transportga bosish boshqasini ochardi, chunki u shu orada siljib ulgurgan bo‘lardi. Profillash kutilgan narsani ko‘rsatdi. Asosiy oqim vaqtining ko‘p qismini obyektlarni yangilash va stillarni qayta hisoblashga sarflardi, foydalanuvchi kiritishiga navbat kelguncha kadr byudjeti tugab bo‘lardi.

Ikki fakt yozib qo‘yilgach, yechim ravshan bo‘ldi. Dispetcher bir necha pikseldan kichik joylashuv o‘zgarishini sezmaydi, transport esa bundan ancha ko‘p yangilanish yuboradi. Xabarlarning aksariyati ko‘rinadigan natijasiz ish edi.

Buferlash, so‘ng eng so‘nggisini qoldirish

Yechim: har bir xabarni alohida chizish deb qarashni to‘xtatish. Xabarlarni belgilangan oyna davomida yig‘ing, har bir transport uchun faqat oxirgi joylashuvni qoldiring va to‘plamni bir marta chizing. bufferTime yig‘adi; transport id si bo‘yicha Map takrorlarni olib tashlaydi.

vehicle-positions.ts
// Joylashuvlar { id, lat, lon, ts } ko‘rinishida sekundiga bir necha marta keladi.
readonly positions$ = this.socket.messages$.pipe(
  bufferTime(250),
  filter(batch => batch.length > 0),
  map(batch => {
    const latest = new Map<string, Position>();
    for (const p of batch) latest.set(p.id, p);
    return [...latest.values()];
  }),
  share(),
);

Ikki yuz ellik millisekund — murosa. Qisqaroq oynalar ko‘rinadigan foydasiz tez-tez qayta chizadi; uzunroqlari transport burilayotganda kechikkandek his qilina boshlaydi. Bir nechta qiymatni bitta yozib olingan oqimda sinab ko‘rdim.

Oyna Sekundiga qayta chizish His
yo‘q har bir xabarga bittadan cho‘qqida qotib qoladi
100 ms 10 silliq, CPU hali ham yuqori
250 ms 4 silliq
1 000 ms 1 sezilarli sakrab-sakrab

Nega throttleTime emas

Birinchi versiya throttleTime ishlatardi: u har bir oynadagi birinchi xabarni o‘tkazadi, qolganini tashlab yuboradi. Joylashuvlar uchun bu aynan teskarisi: tashlab yuborilgan xabar yangirog‘i. Transport xaritada allaqachon tark etgan nuqtada turib qolishi mumkin, chorrahaga yaqinlashayotgan tez yordam uchun esa bu bezak xatosi emas.

Xarita chorak soniya kechikishi mumkin. Qaysi joylashuv eng yangi ekani haqida hech qachon yanglishmasligi kerak.

Bu qoidani birinchi tekshiruvdan keyin jamoa yozuvlariga kiritdim va u operatorni hal qildi: eng so‘nggi qiymatni tashlab yuboradigan har qanday narsa chiqib ketadi.

Nima o‘zgardi

Yozib olingan cho‘qqi oqimida qayta chizish har bir xabarga bittadan sekundiga to‘rttaga tushdi, asosiy oqim esa yana vaqtining ko‘p qismini bo‘sh o‘tkaza boshladi. Dispetcherlar jamoasi birinchi haftadayoq noto‘g‘ri transport ochilishi haqida xabar berishni to‘xtatdi.

Endi oqim xarita joylashuvlar haqida biladigan yagona joy, bu esa oqimni yozib olib, test uchun qayta ijro etishni ham osonlashtirdi. Maqsad bu emas edi, lekin eng ko‘p ishlatadigan qismim shu.

  1. Integratsiyalangan grafikali o‘rta darajadagi ofis kompyuterlari, ikkita monitor, Chrome. Dasturchi mashinasi muammoni butunlay yashirgan edi.