7 years ago

The fight with performance


Performance has always been in issue in software. In older days because the hardware was limited, in the present because coders are a bit lazy choosing easy code above efficient code.

It’s hard to imagine, but in the world of gaming, language like C were used like we use languages like Python, Squirrel and Lua today…. And the core language was always assembly.

Pinball Fantasies for example was entirely coded in 100% assembler, and that is quite something if you mention that the game was originally for the AMIGA, and later ‘ported’ to DOS and lateron even game consoles, such as PlayStation. Yes, I put “ported” between quotes, since you technically cannot port assembler code from one machine to another, since the differences are too great, especially when taken into account that AMIGA uses BigEndian and DOS LittleEndian and both kind of processors come with that much difference of a CPU, that they had to recode the entire game completely from scratch. Only the graphics and music files did not have to be redone. Beyond insanity, don’t you think?

This was solely done since C, fast as it is, could never be fast enough to handle the quick movements a pinball simulator required at the day in which the original versions were coded. Some games used C only to do the menus and configuration screens and other parts in which performance was less of an issue, but the real hard core engine programming was done in assembler. Since C has been set up to easily interface with Assembler, this could be done.

Now that we have ultra-fast machines (compared to what we had in the old days) and loads of RAM, the use of assembler has become less of a requirement and even C is more and more discouraged, due to it being a pretty dangerous language, although I guess it will take some time before C is really gonna disappear. And although there’s C++ now which is less dangerous than C, but still not the safest language around, safer languages such as Java, Go, and C# are getting more and more wanted.

Go is one of the most aggressive languages when it comes to code that can be unsafe. Go refuses to compile when you have variables declared you never used, and during runtime it still keeps checking anything that can go wrong and always giving a complete traceback report in which you can easily look up the faulty code in the source code. C does not have this kind of run-time protection, and that is one of the reasons why C is much faster than Go. Actually Go is one of the slowest, full-machine-code compilers I even used.

Auto memory management also made our lives as coders easier, but in the same time it has become rather costly. It requires some discipline from us as coders as well. Strings in C# have become such a source of evil.

		
			string test = "";
for (int  i=0;i<10000;i++) test+=".";
Console.WriteLine(test);
		
	

The (C#) code above is such a way in which wanting to go the easy way can strike back on you. This code is SLOW as hell, and needlessly slow also. Why is that? Well C does not support strings, and just uses char arrays. Downside, you always have a string limit. C# uses an object for strings, and allocates the memory needed for a string whenever a string is defined. “test+=”.”;” should actually be read as “test=test+”.”;”, and that means that a complete new object is created and “test+”.”” is added to it, and the old test object falls through the garbage collector and is disposed. In the example above 10,000 memory allocations and disposals take place, and that is what slows it down.

		
			StringBuilder test = new StringBuilder(1);
for(int i=0;i<10000;i++) test.Append(".");
string test_result = test.ToString();
Console.WriteLine(test_result);
		
	

This looks a bit more complicated, but the result is roughly the same. StringBuilder creates a 1 byte object at first, but as soon as the string length goes over the max, it creates an object that is twice as big and doesn’t add new bytes with append, but rather keeps filling up until the max is reached again, and so on.
So the test object will be 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384 bytes long respectively, and that makes 15 memory allocations in stead of 10,000, effectively winning 9985 needless allocations in the process. It’s not the amount of bytes allocated that slows things down, it’s the number of allocation requests that slows stuff down. Laziness however often brings us to use the first code in stead of the 2nd simply because it’s easier to code.

Lua coders are often recommended to do this:

		
			-- Locals appear to be faster than globals
local table = table
local os    = os
local math  = math
		
	

It just copies some stuff globally defined by Lua itself to locals with the same name. Locals always take priority over globals in Lua, and are a lot faster, but be honest, here I only used three Lua modules. Are you willing to do this with all of them?

Now that computers have become faster, we easily overlook performance issues, and that can lead to some trouble, especially when your games are played with people with cheaper devices than you used.

Odd as it may sound, but less code, does mostly mean slower results (although you cannot claim this 1 on 1, but quite often this is true). Now I cannot ask from beginning programmers to mind this too much. Experienced programmers should do this a lot more (although I confess myself guilty here). Now you may easily think that when you use high-level tools such as Unity you may not mind this too much as the guys of Unity did this for you, well, that is only true to a certain extend. Even with tools like these some performance issues might be your own fault. And in a lot of cases there are a few “tricks” that already make your program faster, like my StringBuilder example in C# and my copy-global-to-local example in Lua. It’s quite often a lot of hassle to get code faster, and sometimes it’s just a silly trick you just had to know… Funny, eh?



0 comments

Loading...

Next up

Celebrities (almost) killed by one of their biggest fans

Can you see why this pyramid deal could never be solved from the start (regardless what the already removed cards are)?

A few facts and fables about fire.

A #phrase of #wisdom from the French scientist and philosopher #BlaisePascal Two stories, the one tied to this game (new version), and a prequel novel based on this game have this quote. Perhaps you understand why....

BallPlay future

Disney Princesses go to Hogwarts

Current situation on TFT REVAMPED

Killing only brings you so far!

Game redo on Cynthia Johnson

Why do people wanna be a #moderator? Is it really such a #cooljob?