Original Post — Direct link

After updating I played one game and already noticed:

  • No stutters when I try to play a land on 0.4x the speed of light
  • The "double click to go to attack and attack all" is waaaaaaaay faster
  • Visible progress on the weekly/daily, great QoL improvement!
  • Again, the game runs soooo smoooooooth!!!
  • Also, friends!

Honestly, I was pretty disappointed on having different performance on every patch, but this one seems to be THE patch.

Congrats guys!

Thanks!

External link ā†’
over 4 years ago - /u/wotc_beastcode - Direct link

Originally posted by oreguayan

Can you nerd out for a bit on this and elaborate? Iā€™m curious what that entails

DID SOMEONE SAY NERD OUT?!

I can do that. :D

SoneEv is pretty much correct with their explanation.

As a programming team gets more familiar with the problem they are solving, they learn better and better ways to approach it. It's always a careful balance between adding new features and "cleaning up" what you've done in the past. Too much cleanup and you stop making progress. Too little and you start moving too slowly make any progress.

Another manifestation of this is when you start hitting scaling limits. For example, Arena has a lot of rich visual effects and situational graphical elements. We have an elaborate set of rules for which one to play in a given situation. Hand-coding is inefficient because it's hard to maintain and limits the work to only engineers. So we have a flexible data system to specify all the rules. Our first system was fine when we had a few hundred visual assets and a dozen variables that affected them. But now we have thousands of elements and hundreds of conditions that need to be taken into account, and the system wasn't quite keeping up. Some of the big performance gains we got over the last few patches was transferring some of the high-frequency lookups to a much faster system (For those we want the nerdspeak, we moved our constraint satisfaction system from linear search with weighting to something more akin to an abstract syntax tree or a behavior tree with a blackboard).

The new asset system is also more memory efficient. However, this situation is somewhat different than the memory leak issue. A memory leak is when you ask for memory, but never give it back. The old asset system did give memory back, but in Unity, just the act of allocating and freeing memory leads to a lot of performance issues. The process itself is slow and it can cause your memory space to be fragmented, thus making further operations slower.

The memory leak situation is a little different. There are a number of places where we were (and still are) grabbing memory and never letting go. We are still working on sorting some of those out. Nebbii brings up an excellent point about an automated system. Unity, in fact, does that for you! The underlying technology (.Net/Mono) uses a thing called "garbage collection". The way it works is that the system looks at all your memory and if it determine that something isn't in use, it will go ahead and reclaim it for you. But it's criteria for "in use" is whether your code could hypothetically still get to it. So if we have some list of cards stashed away somewhere (say for statistics or cards you just crafted or whatever) or we have a variable that is still set from the previous game, then the Garbage Collector says "Oh, you might still use that. I'll go ahead and leave it there". So a lot of our work on performance has been "Wait. Why is that thing still in memory. Who the heck is holding onto it?" and then spelunking to find some rogue reference and cleaning it up.

Thanks for taking an interest. This wall of text is your reward. Maybe next time you'll think twice before putting out nerd bait. ;)

over 4 years ago - /u/wotc_beastcode - Direct link

Originally posted by Alikont

There is a thing that finds most of the "leaks", it's called Garbage Collector, and .net already have it.

The problem is that it's very conservative in what it considers a leak, because if program can theoretically reach the object, even if it will never use it again, it's still a valid object.

There are few ways to make memory leak in C#, one of the common leaks is event handlers.

For example, when you create a new game, it creates an object, and game object needs to handle mouse input. So it's subscribing to mouse input evens. What it means is that input manager now have a valid reference on Game object, and notifies it about every mouse movement.

If after game is finished you throw away Game object, the reference on it still exists in Input Manager, and because it's theoretically reachable it will be invalid to remove Game from memory, because it will crash Input Manager.

This person knows what's up! We've had a few of the event handler one. :D

over 4 years ago - /u/wotc_beastcode - Direct link

Originally posted by voltaiclv

Any thoughts to pre-allocating larger blocks of memory, and using those, instead of hitting the wall with memory fragmentation?

Something more akin to the object pool pattern would probably be more helpful and squeeze performance out of your engine before even further tweaks would be needed.

Automatic garbage collecting is (usually) something to be avoided in the world of optimizing game engines, as I'm sure you're learning. I'm glad your team is making strides!

For sure. We use a fair amount of object pooling, both with GameObjects (like cards) to avoid instantiation costs and with Unity-agnostic data types (like Lists) to avoid allocations.