Ping Hesaplama Yöntemimizdeki İyileştirmeler

05.02.2019
Yazar: Fortnite Ekibi
Herkese merhaba! Ben Bart Hawthorne. Epic’te oyun motoru ekibinde Kıdemli Ağ Mühendisi olarak çalışıyorum. Fortnite’taki ping değerlerini gösterme yöntemimiz, 7.30 güncellemesinde denediğimiz yeni hesaplama yönteminin çıkardığı sorunlar ve ping göstergemizin doğruluğunu geliştirmeye yönelik gelecek planlarımız hakkında biraz konuşmak istiyorum.

Ama öncelikle yazı boyunca dilimden düşürmeyeceğim bazı terimler hakkında biraz bilgi vereceğim. Bu terimlere aşina olmayanların sıkılmasını istemeyiz:

İstemci ve sunucu: Her konsol, mobil cihaz, PC ve Mac bir istemcidir. İstemciler oyunun bulunduğu özel sunucuya bağlanırlar. Sunucu, oyunun genel durumuna (oyuncuların konumları, çemberin durumu, açılmamış sandıklar ve daha birçok şeye) hâkimdir. Sunucu ayrıca oyunun durumunda değişiklik olduğunda bütün istemcileri güncellemekten sorumludur.

Paket: Paketler, ağ bağlantısı üzerinden istemcilerin sunucuya veya sunucunun istemcilere yolladığı verilerdir. İstemciler ve sunucular bu şekilde birbirleriyle iletişim kurar. Fortnite’ta (ve UE4’te) ping hesaplarken bu paketleri kullanıyoruz.

Kare hızı: Kareler, sunucunun yeni paketleri kontrol etmek, oyunun durumunu güncellemek ve istemcileri güncelleme yollamak gibi görevlerini ne sıklıkla tamamladığını gösterir. İstemcideyse ekrandaki görüntünün ne sıklıkla yenilendiğini gösterir. Kare hızı, saniyede kare hızı ya da en bilindik haliyle FPS, bir saniye içinde sunucuda veya istemcide kaç karenin işlendiğini gösterir. Yani istemcinin 60 FPS ile çalıştığını söylediğimizde her saniyenin içine 60 kare bulunduğunu kastediyoruz.

Bunları da açıklığa kavuşturduğumuza göre ping hakkında konuşmanın vakti geldi demektir!

Eski Ping Paketi Hesaplama Yöntemimiz

Ping dendiğinde akla ilk gelen şey, “istemciyle sunucu arasında yollanan paketin adrese ulaşma süresi ve bu birimlerin birbirine cevap verme hızı” oluyor. Buna aynı zamanda sinyal gidiş-dönüş süresi veya RTT de deniyor. Bu, birçok oyuncu için önemi bir bilgiyi sağlıyor: İstemci sunucudan ve sunucu istemciden bilgi alırken harcanan süre. Sahip olduğunuz ping değeri arttıkça diğer oyuncuların ışınlandığını görme, beklenmedik şekilde ölme veya sandıklar ya da başka nesnelerle etkileşime girerken gecikmeler yaşama ihtimaliniz de artar.

Biz ping’i milisaniye ile gösteriyoruz. Ping ne kadar düşükse sizin için o kadar iyidir. Sunucularımıza ev sahipliği yapan bir veri merkezine yakın oturuyorsanız ping değerinizin tek haneli olduğuna bile şahit olabilirsiniz! Fakat dünyanın öbür ucunda bulunan bir sunucuya bağlanıyorsanız ping değeriniz 100 milisaniye, hatta daha fazla bile olabilir.

İstemci-sunucu arasındaki ilişki, paketlerin gönderilme veya alınma süresinden daha başka faktörleri de içeriyor. Fortnite’ta genellikle her karenin başında hem sunucu hem de istemci için yeni paket gelip gelmediğini kontrol ederiz. Bu da demek oluyor ki, istemci veya sunucu paket gelmiş mi diye kontrol ettikten hemen sonra yeni bir paket gelirse, sonradan gelen paket kontrol edilene kadar aradan neredeyse tam bir kare geçmiş oluyor. Ayrıca paketi aldıktan sonra okumak ve oyunun durumunu paketin içerdiği verilere göre güncellemek de zaman alan bir işlem.

Bu şema, işlemleri gözünüzde canlandırmanıza yardımcı olacak:


İstemci ve sunucuya ait siyah oklar süreyi temsil ediyor. Bu örnekte hem sunucu hem de istemci senkronize olmuş ve aynı kare içerisinde çalışıyor. Siyah yatay çizgiler her bir karenin başlangıcını temsil ediyor. Mavi çentikler sunucunun veya istemcinin işlenecek yeni bir paket olup olmadığını kontrol ettiği zamanları temsil ediyor. Turuncu çizgilerse sunucunun veya istemcinin paket gönderdiği zamanı temsil ediyor. Mor kısa çizgiler bir paketin internet üzerinden ilerleyişini temsil ediyor.

Bu olayların sırası ise şu şekilde:

  1. İstemci sunucuya bir paket gönderir.
  2. Sunucu, istemcinin gönderdiği paketi alır.
  3. Sunucu yeni paket gelmiş mi diye kontrol eder ve yalnızca bu işlemi yaptıktan sonra istemciden gelen paketi görebilir. Sunucunun paket gelip gelmediğini kontrol etmesinden hemen sonra gelen bir paketin neredeyse bütün bir kare boyunca olduğu yerde beklediğini de böylece görüyoruz.
  4. Sunucu, istemciye paketi aldığını haber verir.
  5. Sunucunun yolladığı haber istemciye ulaşır.
  6. İstemci, sunucunun cevabını okur.
Sadece yeşil oklarla gösterilen gidiş-dönüş zamanını göstermek ve kırmızı oklarla gösterilen zamanı çıkarmak istiyoruz. Bu konuda elimizden gelenin en iyisini yapmaya çalışıyoruz. Sunucudan istemciye bir paket gönderdiğimizde buna sunucu kare süresini de dahil ediyoruz. Bu nedenle belirli bir paket için, paketi işlediğimiz zamana kadar geçen sunucu kare süresini ve istemci kare süresini çıkarıyoruz. Ardından da ping hesaplamamız şu şekilde görünüyor:
Ping = Paketin sunucuya ulaşma süresi + Paketin istemciye ulaşma süresi - Sunucunun kare süresi - O zamana kadar geçen istemci kare süresi

Göstereceğimiz ping değerinin daha tutarlı olması için paketleri kullanarak birkaç saniye boyunca hesaplamaya devam ettiğimiz değerlerin ortalamasını alıyoruz.

Fakat uygulamaya gelince bu istediğimiz kadar doğru bir sonuç vermiyor. Bu hesaplama yöntemi paketlerin geldiği ve işlenmeyi beklediği süreyi hesaba katmıyor; bu yüzden görüntülenen ping değeri genellikle çok yüksek oluyor. Buradaki esas sıkıntı çoğu platformun belirli bir paketin ne zaman geldiğini öğrenebileceğimiz bir yol sunmaması. Bu yüzden de ne kadar süre çıkarmamız gerektiğini tam bilmiyoruz.

7.30’daki Ping Paketi Hesaplama Yöntemimiz

7.30 güncellemesi için bir fikrimiz vardı ve yeni bir şeyler denemek istemiştik. Aklımızdaki şey istemciden sunucuya en kısa sürede giden ve geri yanıt alan paketleri kullanmaktı. Planımıza göre en kısa süre içinde ilerleyen paketlerin işlemi hızlıca tamamlanacaktı. Bu sayede bekleme süresini göz ardı edebilecektik çünkü bu süre neredeyse sıfıra yakın olacaktı. Ping değerimizi hesaplarken paketlerimizin içindeki en hızlı %25’lik kısmı kullandık. Hem en hızlı paketleri seçip hem de gerçekçi değerler alabileceğimiz miktarda veri incelediğimiz için dengeyi sağladığımızı düşünüyorduk.

Yanlış Giden Neydi?

7.30 güncellemesinin ardından oyuncularımız ping’lerinin çok olması gerekirken tek haneli değerlerde seyrettiğini bildirdi. Hatta bazı oyuncularımız ping’lerinin 0 olarak göründüğünü rapor etti. Bu verileri doğru olabilmesi için dosya hızımızın ışık hızından daha hızlı olması gerekir. UE4 mükemmel olsa da, kabul edelim günümüz teknolojisi düşünüldüğünde henüz bu kadar iyi olamaz! Bir yanlışlık olduğu apaçık ortada.

Bu problemin bir kısmı ping hesaplama sistemimizden kaynaklı. Daha önce verdiğim şu bilgiyi rehber olması açısından tekrarlıyorum:
Ping = Paketin sunucuya ulaşma süresi + Paketin istemciye ulaşma süresi - Sunucunun kare süresi - O zamana kadar geçen istemci kare süresi

Buradaki sorun, sunucu kare süresinin çıkarılmasından kaynaklıydı. Yalnızca en hızlı paketleri hesaba kattığımızda, çok fazla şeyi çıkarıyorduk. Çünkü bir paket sunucuya ulaşır ulaşmaz işlenirse, sunucunun paketin içeriğini işlemesi ve yanıt göndermesi yalnızca birkaç milisaniye alabilir. Sunucunun tüm kare süresi ise bu sürenin 5 katı kadar olabilir!

Bu şema, bunun nasıl olduğunu gösteriyor:



Bu istemcinin kare hızı sunucununkinden çok daha fazla. Sadece sunucu paket gelmiş mi diye kontrol etmeden hemen önce ulaşan yeşil paketleri hesaba katıyoruz. Bu durumda sunucu kilitli kare hızından daha hızlı çalışmış oluyor. Bu yüzden de karenin başlangıcı ile paketleri kontrol etmeye başladığı zaman aralığında uykuda oluyor (yani bu aralıkta hiçbir şey yapmıyor).
 



Kırmızı çizgi, sunucu kare hızı olarak çıkardığımız kısmı gösteriyor. Fakat doğrusu turuncu çizgi. Arada çok fazla vakit olduğu ortada. İstemcilerden bazılarının 0 ping göstermeye başlamasının sebebi de buydu.

Bu, daha fazla çeşit paket kullanarak hesaplama yaptığımız eski yöntemimizi kullanırken de sorun yaratıyor. Bununla birlikte, işleme alınmak için uzun süre sıra bekleyen paketleri değerlendirme şansımız daha yüksek; böylece bu paketler, çok fazla süre çıkardığımız paketlerin önüne geçebilir.

Gelecek Planları

Görülen ping değerini daha doğru hale getirmek için gelecek güncellemelerde için planladığımız iyileştirmeler var. Yazının başlarında söylediğim gibi:

“Buradaki esas sıkıntı çoğu platformun belirli bir paketin ne zaman geldiğini öğrenebileceğimiz bir yol sunmaması. Bu yüzden de ne kadar süre çıkarmamız gerektiğini bilmiyoruz.”


Neyse ki Linux biliyor! Sunucularımız sadece Linux ile çalıştığı için ping hesaplamasını aşağıdaki gibi değiştirebiliriz:

Ping = Paketin sunucuya ulaşma süresi + Paketin istemciye ulaşma süresi - Paketin teslim alınması ve sunucunun yanıt gönderme süresi - O zamana kadar geçen istemci kare süresi


Bunu uyguladığımızda, sunucunun kare süresini çıkarıp tahminler üzerinden çalışmaya da son vermiş oluyoruz. Bunun daha doğru değerler vermesini bekliyoruz, ancak daha yapılacak çok daha fazla test var.

Ayrıca istemcinin daha hızlı paket kontrol edip edemeyeceğini de araştırıyoruz. Çünkü bu mümkün olursa denklemdeki “o zamana kadar geçen istemci kare süresi” kısmını atabiliriz.

Bu iki değişiklik birleştiğinde daha doğru bir ping değeri gösterebileceğimizi umuyoruz.

Sonuç

Umarım ping’i nasıl hesapladığımızı ve ping göstergemizi geliştirmek için nasıl çalıştığımızı açıklayabilmişimdir. Böyle bir bilgiyi gösterdiğimizde, doğru olması çok önemli. Çünkü bu gibi durumlarda yanlış değerler göstermek hiçbir bilgi vermemekten çok daha kötü olabilir. Yaptığınız atışı gerçekten isabet ettiremediğiniz için mi kaçırdınız yoksa oyundaki yüksek ping değerinden kaynaklanan “kasma” sorunu mu kaçırmanıza sebep oldu? Bunu bilmeniz önemli çünkü sorunun kaynağını bilirseniz önlem alabilirsiniz.

Sorularınızı görmek için yorumları takip edeceğim, cevaplamaktan mutluluk duyarım. Okuduğunuz için teşekkürler!