DOTS nedir ve neden önemlidir?

Fatih Altuntaş
6 min readMay 22, 2021

Giriş

DOTS, Unity mimarisindeki temel bir değişikliktir. DOTS, nesne yönelimli yaklaşımının (OoP) aksine, veri odaklı tasarım (DoD) kullanarak kod ve veri hakkında düşünmek için farklı bir yaklaşım gerektiren Unity’de yeni olan teknolojilerin (ECS, Job, Burst) bir kombinasyonudur.

DOTS, veri işlemeyi paralel hale getirmek ve Unity projelerinizin performansını artırmak için çok çekirdekli işlemcilerden yararlanmamızı sağlar.

DOTS şimdilik hibrit bir formatta MonoBehaviours ile birlikte çalışmaktadır. Unity’nin hedefi ise hibrit olmayan, tamamıyla DOTS ile çalışan bir sistem kurmaktır. Bununla birlikte DOTS ile çalışmanın uzun vadeli getirisini şimdiden düşünmemiz gerekir.

DOTS yeni bir üründür ve henüz emekleme aşamasındadır. Sürekli bir gelişme içindedir. Unity, API’yi olabildiğince iyi hale getirmek için çalışmaya devam etmektedir.

Şimdilik DOTS’u Unity’nin bir eklentisi olarak düşünebiliriz (preview aşamasındadır). DOTS (ve gerektiğinde MonoBehaviours) kullanarak sıfırdan yeni bir proje oluşturabilir veya mevcut projemizi DOTS’a dönüştürebiliriz.

DOTS API’nin öğeleri değişecek olsa da, DoD’nin temel ilkeleri ve DOTS kullanarak projelerimize nasıl yaklaşmamız gerektiği aynı kalacaktır.

DOTS Nedir?

Data-Oriented Tech Stack (DOTS), Unity’de kodlamaya veri odaklı yaklaşım sunmak için birlikte çalışan teknolojilerin bir kombinasyonudur. Bununla birlikte, hedef donanımımıza daha uygun ve dolayısıyla daha performanslı projeler oluşturmamıza olanak tanır.

DOTS aşağıdaki unsurlardan oluşur:

1- Data-Oriented bir yaklaşım kullanarak kodlama için framework sağlayan Entity Component System (ECS). Editor -> Package Manager aracılığıyla Enities paketini projemize ekleyebiliriz.

2- Multithreaded kod oluşturmak için basit bir metod sağlayan C# Job System. Job paketi olarak projeye eklenir.

3- Hızlı ve optimize edilmiş native kod üreten Burst Compiler. Burst paketi olarak projeye eklenir.

4- Native Containers, bellek üzerinde kontrol sağlayan ECS data structures.

İlk üç paket genellikle DOTS’un üç sütunu olarak adlandırılır. Birlikte yüksek performanslı data-orianted çözümler sunmanın temelini oluştururlar.

DOTS kullanmaya en yaygın başlangıç Entity Component System (ECS)’dir. ECS, bilgileri (MonoBehaviours gibi) verilerden ayırmamıza olanak tanıyan bir kod yapılandırma ve yazma yoludur. CPU tarafından kaybedilen önbellek miktarını azaltan ve ardından bellekten verilere erişim hızını artıran mantıksal bir şekilde düzenlememize olanak tanır. Pek çok senaryoda bu, DOTS olmadan başka türlü mümkün olmayacak önemli performans artışları sağlayabilir.

ECS, verilerin bellekte nasıl düzenlendiğini ve bunlara CPU tarafından nasıl erişildiğini kolayca tanımlamanız için bir yol sağlar. MonoBehavior scripts yerine doğrusal veri ve veri setlerini işleyen sistemlerle çalışarak, gelecek için daha ölçeklenebilir bir temel sağlayabiliriz. Başka bir deyişle, ECS ile nesneye yönelik bir şeyler yapmanın yolundan veri odaklı bir tasarıma geçiyoruz.

ECS’ye giriş için bazı kaynaklar : Video tutorial, makale.

Ayrıca, özellikle mobil cihazlar gibi daha fazla donanım sınırlaması olan cihazları hedefleyen hafif bir DOTS sürümü oluşturuldu. Project Tiny, küçük, hafif oyunlar ve uygulamalar oluşturmanız için Editör’de bir DOTS modu sağlayan ayrı bir Unity Paketidir.

DOTS Neden Önemlidir?

Teknoloji hızlı ilerliyor. Tarih bize, günümüzün yüksek kaliteli AAA oyunlarının ve sürükleyici 3D deneyimlerinin yakın gelecekte eskimiş kalıntılar olarak kabul edileceğini gösterecektir. Bu olduğunda, Unity motorunun yeni nesil gerçek zamanlı 3B geliştirmeyi desteklemeye hazır olması gerekmektedir. CPU ve bellek performansının uygulamaların ihtiyaçları doğrultusunda artmaması, bu nedenle donanım özelliklerini ve kısıtlamalarını en iyi şekilde kullanabilen bir yazılım mimarisi, bu ihtiyaçların karşılanması için uygun bir çözüm sağlar ve bunı, DOTS ile sağlayabiliriz.

DOTS performansı nasıl artırır?

Unity, belirli bir donanım aralığındaki cihazları hedefler, ancak tüm donanımlarda ve ele alabileceğimiz alanlarda ortak sorunlar vardır. Basit bir ifadeyle, bu sorunlar şunlardır:

  • CPU işlem hızı göreceli olarak yavaşlıyor. Son 20 yılda gördüğümüz artış oranını tekrar yakalamamız pek olası değil.
  • Birçok donanım sistemi için, bellek erişim hızı, işlem (processing) hızına paralel olarak artmamıştır. Unity’nin belleğe son derece yüksek hızlarda erişmesi gerekiyor. Hızlı bellek erişime sahip olan platformlar için, bu hızı etkili bir şekilde kullanabilen bellekteki verileri düzenlemek ve bunlara erişmek için bir yönteme ihtiyacınız var.
  • GPU’lar, paralel işleme sağlayarak performansı artırmak için bir çözüm sunar.

Yazılım, performansı artırmak için bu tür donanım kısıtlamaları etrafında çalışmanın anahtarıdır. Pratikte bu, daha az güç tüketimi ve daha uzun pil ömrü anlamına gelir.

Bu sorunları çözmek için:

  • Entity Component System (ECS), kodlamaya veri odaklı bir tasarım yaklaşımı sağlar. Veri odaklı bir yaklaşımla, veri yapıları, verilerinize erişimi daha verimli ve daha hızlı hale getiren önbellek kayıplarını önlemek için düzenlenir. Nesne yönelimli tasarım veri organizasyonuna odaklanmadığından, önbellekte eksiklikler yaygındır ve ana bellekteki verilere daha sık erişmesi gerektiğinden CPU’nun verilere erişimini yavaşlatır.
  • C# Job System bugün mevcut olan çok çekirdekli işlemcileri tam olarak kullanmak için C # ile hızlı, paralelleştirilmiş kod yazmayı kolaylaştırır.
  • Burst compiler derlemekte olduğunuz platform donanımından yararlanan yüksek düzeyde optimize edilmiş kod üretir.

İşte Unity’nin Megacity projesini gösteren bir video. Megacity, DOTS’tan yararlanır ve DOTS ile elde edilebilecek ölçeğin bir örneğidir:

Veri odaklı tasarım (DoD) nedir ve nesne tabanlı tasarımdan (OoP) farkı nedir?

Veri odaklı tasarım, verilerinize erişimin olabildiğince verimli olmasını sağlamak için verilerinizi önceliklendirip düzenleyerek kodlama sorunlarının çözümüne vurgu yapar. Bu, kod tasarımının yaratmakta olduğunuz dünyanın modeli tarafından yönetilmesi gerektiği şeklindeki nesne yönelimli ilkeyle çelişir.

DOTS’tan önce Unity, yalnızca nesne yönelimli bir programlama modeli üzerinde çalışıyordu.

Tipik nesne yönelimli iş akışı şudur:

1- Bir GameObject oluşturun

2- Oluşturulan nesneye bir component ekleyin

3- Bu component özelliklerini değiştiren MonoBehaviour script yazın

Runtime’da GameObject, componentlere yapılan refaranslara bağlıdır. MonoBehaviour scriptler component verilerini aradığında, erişmesi zaman alan belleğe dağılır.

Nesne yönelimli bir yaklaşım uygularken (nesneler, class olarak oluşturulmuş), kod genellikle nesnelerin yapısını (hangi veri nesnelerine sahip olduğu) ve daha sonra bunların ne işe yaradığının ve diğerleriyle nasıl etkileşimde bulunduklarını tanımlar. Bu, gerçek dünyada bir şeyleri nasıl yarattığımızın neredeyse doğal bir uzantısıdır. Ancak, nesnelerin içerdiği bilgileri yapılandırma açısından, bu yaklaşım, verilerin nasıl organize edildiğini bozabilen ve ona erişimi yavaşlatabilen, temeldeki verilerin üstüne bir abstraction (soyutlama) katmanı ekler. Örneğin, bir fonksiyonun bir nesne içindeki farklı bir veri parçası üzerinde çalışmasını istiyorsanız, işlevin bir üst sınıftan miras alması veya yeniden yazılması gerekir.

Veri odaklı tasarımda, her şeyi nesne olarak değil de veri olarak düşünmeniz gerekir. Bunu yapmak, tüm verilerin kolayca erişilebilir olmasını ve hiyerarşik class kısıtlamaları olmadan kullanılabilmesini sağlamaya yardımcı olur.

Veri odaklı bir yaklaşımla, tipik iş akışı, uygulamak istediğiniz en yaygın görevlerin temelini oluşturan verileri tanımlayarak ve sonra organize ederek başlamaktır. En yaygın sorunlar, runtimeda en sık çözmeniz gerekecek olanlardır, bu nedenle geliştirmenizde bunlara öncelik vermek çok önemlidir. Kodu veriler ve bu verilerin akışı etrafında organize etmek, runtimeda ona erişimin birden çok class aracılığıyla veri getirmekten çok daha verimli olabileceği anlamına gelir.

DOTS Kullanmanın Fırsat ve Riskleri Nelerdir?

DOTS, Unity projelerimizin performansını artırmak için muazzam bir potansiyel sağlar. Ancak, DOTS kullanırken projemizin zaman çizelgesi, bütçesi ve geliştirme ekipleri gibi dikkate alınması gereken hususlar vardır. Bu gibi proje önceliklerimizi belirlememiz gerekir. Bu hususlar riskler ve fırsatlar olarak kategorize edilebilir.

Fırsatlar

Geliştirilmiş performans. DOTS’u tanımlamak için genellikle Performans terimini varsayılan olarak kullanırız. Bununla ne demek isteniyor? Data-orianted tasarım ve multithreading ile DOTS, bellek, çalışma süresi ve pil performansında üstel bir artış sağlayabilir. Oyunumuzda görüntülenen öğelerin sayısı arttıkça performans iyileştirme potansiyeli artar. Tersi durumda, düşük sayıda öğeye sahip oyunlar için daha az performans iyileştirmeleri gözlemlenir.

Kod kontrolü. DOTS, bir projenin boyutu büyüdükçe kod karmaşıklığının daha iyi kontrol edilmesini sağlar. Kod refactoring, unit testler ve geliştiriciler arasında iş dağıtımı daha kolaydır.

Riskler

DoD’ye aşina değilseniz, DOTS’un bir öğrenme aşaması vardır. DoD, bilgisayar biliminde köklü bir yere sahip olmasına ve uzun yıllardır var olmasına rağmen DoD yaklaşımı, OOP yaklaşımından önemli ölçüde farklı olmasına rağmen, DoD, doğası gereği OOP’den daha az karmaşıktır. Bu, ECS’nin, öğrenmek için zaman gerektiren mevcut Unity MonoBehaviour yaklaşımından farklı bir kod mimarisi olduğu anlamına gelir. Şu anda, DOTS kullanımında profesyonel olarak yetkin hale gelmenin ortalama bir profesyonel Unity geliştiricisi için 1 ay gibi sürdüğü varsayılıyor.

Sınırlı destek. DOTS şu anda yalnızca Unity’deki sınırlı bir özellik kümesiyle uyumludur. Sonunda DOTS, Unity’nin tüm özellikleriyle tamamen uyumlu olacak, ancak şu anda tam uyumluluk için bir zaman çizelgesine sahip değiliz.

Kaynakça: What is DOTS and why is it important?

--

--