My naam is Sergey Kachan, en ek is 'n kliënt ontwikkelaar op die oorlog robots projek. War Robots is al vir baie jare, en gedurende hierdie tyd die spel het opgehoop 'n groot verskeidenheid van inhoud: robotte, wapens, drone, titans, vlieëne, en so aan. Vandag sal ek praat oor hoe balanse in ons projek gestruktureer word, wat met hulle in die afgelope 11 jaar gebeur het, en hoe ons dit hanteer het. Balans in die projek Soos enige ander projek, kan War Robots verdeel word in twee dele: meta en kern spel. is enige aktiwiteit wat verder gaan as die kern van die spel loop, maar nog steeds die spel beïnvloed.Dit sluit in die aankoop en verbetering van spel inhoud, deelneming aan sosiale of gebeurtenis aktiwiteite. Meta gameplay (metagaming) is die hoof herhalende siklus van aksies wat die speler in die spel uitvoer om hul doelwitte te bereik. Core gameplay (core gameplay loop) Elke deel van die projek benodig sy eie balans, so ons verdeel ook balans in twee kategorieë - meta en kern. Oorlogsrobots het ook die sogenaamde , wat hul eie afsonderlike balans vereis. Skirmish modes a is 'n verandering van bestaande modes of kaarte met verskillende eienskappe of reëls. Skirmish modes is dikwels gebeurtenisgebaseer, beskikbaar vir spelers tydens verskillende vakansie, hoofsaaklik vir pret. Skirmish mode So in totaal het ons 4 balans: 2 vir die standaardmodus en 2 vir die Skirmish-modus. Oor 11 jaar het War Robots 'n ton ongelooflike inhoud opgehoop: 95 die robot 21 Titans 175 verskillende wapens 40 drone 16 Moederskap 'n groot aantal skins, hervormings, modules, pilotes, torings, uiteindelike weergawes van inhoud en kaarte En soos jy kan dink, om al hierdie werk te doen, moet ons inligting oor gedrag, statistieke, beskikbaarheid, pryse en baie, baie meer opslaan. As gevolg hiervan het ons balans tot 'n onregverdige grootte gegroei: Default mode Skirmish mode Meta balance 9.2 MB 9.2 MB Core balance 13.1 MB 13.1 MB Meta balance 2.9 MB 2.9 MB Core balance 1.1 Die MB 1.1 Die MB Na 'n paar vinnige berekeninge, het ons bevind dat 'n speler moet aflaai • Dit is baie! 44.6 MB Ons wou regtig nie dwing spelers om so groot hoeveelhede data te laai elke keer as 'n balans verander nie. Net om jou te herinner: Oorlog Robots het bereik In 2024 was ons maandelikse aktiewe gehoor en elke dag ingeskryf word. 300 million registered users 4.7 million people 690 thousand players Nou dink die hoeveelheid data. Baie, reg? Ons het ook so gedink. So, ons het besluit om alles te doen wat ons kon om die grootte van ons balans te verminder! Jaag die probleem af Die eerste stap was om die balans te analiseer en te probeer uitvind: "Wat neem so baie ruimte in?" Handmatig deur alles te gaan was die laaste ding wat ons wou doen - dit sou jare geneem het.So, ons het 'n stel gereedskap geskryf wat al die inligting wat ons nodig het oor die balanse versamel en geaggregeer het. Die instrument sou 'n balans lêer as invoer neem en, met behulp van refleksie, herhaal deur al die strukture, wat data versamel oor watter tipes inligting ons gestoor het en hoeveel ruimte elkeen beset het. Die resultate was ontmoedigend: Meta balans % in balance Usage count String 28.478 % 164 553 Int32 27.917 % 161 312 Boolean 6.329 % 36 568 Double 5.845 % 33 772 Int64 4.682 % 27 054 Custom structures 26.749 % — String 28 478 persentasie 164 553 besoek Int32 27 917 % van die 161 van 312 Boolean 6 29 % van die 36 568 besoek Double 5 854 % van die 33 772 besoek Int64 4 682 persent 27 054 besoek Custom structures 26 749 persentasie — Kernbalans % in balance Usage count String 34.259 % 232 229 Double 23.370 % 158 418 Int32 20.955 % 142 050 Boolean 5.306 % 34 323 Custom structures 16.11 % — String 34 259 % van die 232 229 besoek Double 23370% van die Ek het 158 418 Int32 20 955 % van die 1 2 050 Boolean 5 306 persent 34 323 besoek Custom structures 16,11% van die — Na die analise van die situasie het ons besef dat En daar moes iets daaroor gedoen word. strings were taking up far too much space So, ons het 'n ander instrument gebou. Hierdie een het die balansbestand geskan en 'n kaart van al die stringe saam met die aantal keer wat elkeen gedupliceer is, gegenereer. Die resultate was ook nie bemoedigend nie. Sommige stringe is tienduisende keer herhaal! Ons het die probleem gevind. Nou was die vraag: hoe kan ons dit regmaak? Optimaliseer die balans Om voor die hand liggende redes kon ons nie net stringe heeltemal verwyder nie. Strings word gebruik vir dinge soos lokalisasie sleutels en verskillende ID's. Maar wat ons kon doen, was die verdubbeling van stringe uit te skakel. Die idee was so eenvoudig soos dit kry: Maak 'n lys van unieke strings vir elke balans (in wese, 'n toegewyde opslag). Stuur hierdie lys saam met die data. public class BalanceMessage { public BalanceMessageData Data; public StringStorage Storage; public string Version; } StringStorage is in wese 'n wrapper rondom 'n lys van string. Wanneer ons die stringopslag bou, onthou elke balansstruktuur die indeks van die string wat dit nodig het. public class StringStorage { public List<string> Values; public string GetValue(StringIdx id) => Values[id]; } In plaas daarvan om die string self binne die balansstrukture te slaan, het ons begin om die indeks van waar die string in die stringopslag is, te slaan. Voordat jy: public class SomeBalanceMessage { public string Id; public string Name; public int Amount; } Na die: public class SomeBalanceMessageV2 { public StringIdx Id; public StringIdx Name; public int Amount; } StringIdx is basies net 'n wrapper rondom 'n int. Op hierdie manier het ons heeltemal direkte string oordragte binne die balansstrukture uitgesluit. public readonly struct StringIdx : IEquatable<StringIdx> { private readonly int _id; internal StringIdx(int value) {_id = value; } public static implicit operator int(StringIdx value) => value._id; public bool Equals(StringIdx other) => _id == other._id; } Hierdie benadering het die aantal stringe met tien keer verminder. String usage count String usage count Before After Meta balance 164 553 10 082 Core balance 232 229 14 228 Before After Meta balance 164 553 besoek 10 082 besoek Core balance 232 229 besoek 14 228 besoek Nie sleg nie, nie waar nie? Maar dit was net die begin - ons het nie daar gestop nie. Herwerking van die data protokoll Vir die oordrag en verwerking van balansstrukture het ons gebruik . MessagePack MessagePack is 'n binêre data serialisering formaat ontwerp as 'n meer kompakte en vinnige alternatief vir JSON. Dit is bedoel vir doeltreffende uitruil van data tussen programme of dienste, wat 'n beduidende vermindering in data grootte toelaat - veral nuttig waar prestasie en bandbreedte saak maak. Aanvanklik het MessagePack gekom in 'n JSON-agtige formaat, waar die data gebruik word Dit is beslis gerieflik, maar ook baie ruimteverbruikend.So ons het besluit om 'n bietjie fleksibiliteit op te offer en na 'n . string keys binary byte array Voordat jy: public class SomeBalanceMessage { [Key("id")] public string Id; [Key("name")] public string Name; [Key("amount")] public int Amount; } Na die: public class SomeBalanceMessageV2 { [Key(0)] public StringIdx Id; [Key(1)] public StringIdx Name; [Key(2)] public int Amount; } Ons het ook al die leë versamelings verwyder - in plaas daarvan om hulle te stuur, stuur ons nou nulwaardes. Test die veranderinge 'N Gouden reël van goeie ontwikkeling (en een wat jou baie senuwees sal red) is om altyd nuwe funksies te implementeer op 'n manier wat jou toelaat om hulle vinnig terug te roll as iets fout gaan. Gedurende die ontwikkeling moes ons seker maak dat al die data korrek oorgedra is. Ou en nuwe salarisse - ongeag formaat of struktuur - moes presies dieselfde waardes produseer. Om dit te bereik, het ons 'n groot aantal eenheid toetse vir elke balans geskryf. Aanvanklik het ons al die velde "head-on" vergelyk - elke een eksplisiet ondersoek. Dit het gewerk, maar dit was tydroeiend, en selfs die kleinste verandering in die salarisse sou die toetse breek, wat ons gedwing het om hulle voortdurend op te skryf. Uiteindelik het ons genoeg daarvan gehad en het ons 'n meer gerieflike toetsbenadering vir die vergelyking van balanse uitgevind. Ons het twee weergawes van die balansstrukture geneem, byvoorbeeld SomeBalanceMessage en SomeBalanceMessageV2, en herhaal oor hulle - die vergelyking van veld getalle, name en waardes. Optimalisering van resultate Dankie aan hierdie optimalisasies, het ons daarin geslaag om beide die grootte van die lêers wat oor die netwerk oorgedra word en die tyd wat dit neem om hulle op die kliënt te deserializeer, te verminder. Filtergrootte Old balances Optimized balances Profit Meta balance 9.2 MB 1.28 MB - 86 % Core balance 13.1 MB 2.22 MB - 83 % Meta balance 2.9 MB 1.28 MB van 86% van die Core balance 1.1 Die MB 2.8 MB van 83% van die Deserialisering tyd Old balances Optimized balances Profit Meta balance 967 ms 199 ms - 79 % Core balance 1165 ms 265 ms - 77 % Meta balance 967 van die 199 van die 79% van die Core balance 1165 van die 265 van die Die 77% Data in die geheue Old balances Optimized balances Profit Meta + Core ~ 45.3 MB ~ 33.5 MB - 26 % Meta + Core · 54,3 MB ~ 33,5 MB 26% van die Konklusie Die balans lêers is verminder met meer as 80%. verkeer het gedaal, en die spelers was gelukkig. Om dit op te stel: wees versigtig met die data wat jy oordra, en stuur nie iets onnodig nie. Strings word die beste in unieke opslag geleë om duplikate te vermy. En as jou aangepaste data (pryse, statistieke, ens.) ook baie herhaling bevat, probeer om hulle ook in unieke opslag te verpak.