I have written something about hardcoding XML data into the DLL somewhere. Since I can't find it right now, I have decided to add it here as I will look here when I search for it in the future
I have been thinking more about this and have come up with a number of steps. To some degree each step can be used independently and I will write a list here. We can then later decide what we want and what we don't. None of this will be in the next release as it is long term plans.
My take on this is that we should implement all of it. The only one, which has arguments against it is the actual hardcoding of XML data, but it is only for "optimized release" and should tell if people should use the included assert DLL instead. If people change XML files, they should use the assert DLL anyway.
XML enums
A perl script generates a header file where the types from XML are defined. The specific types are defined inside #ifdef HARDCODE_XML_TYPES. HARDCODE_XML_TYPES is then defined by the project, but the makefile will not. This mean the debugger will show the types, but the compiler will cause an error if something is hardcoded into the code itself.
Adding this file to sourceMOD will allow people to compile even though they haven't installed perl. There will be an error while compiling, but the build commands will carry on and produce a DLL anyway. Since it's a matter for the debugger and nothing at runtime is changed, it doesn't matter.
Bonus: all types defined in the debugger and nothing is hardcoded.
Fast size for info arrays
Right now the code use GC.getNum*Infos() and what it does at runtime is this
- Fetch the pointer to CvGlobals
- Use that pointer to call a function
- This function calls a member function of std::vector
- The vector uses some code to tell the length
It works, but it is a whole lot of memory I/O in order to get the answer and this is done each time the loop condition is checked.
Solution:
Define an int somewhere (like the XML reading file) and then add it to a header with the extern keyword. This will make a global variable. If you look up global variables, people advice against them. However the problem with them is that if one thread writes to it and another reads, something undefined happens. We will not encounter this as we will not change the value once set (also I
think they are only used by one thread, but the graphics engine might read this too using a different thread, though it doesn't matter if it does or not).
Bonus:
Getting the length of an array is reading a single int. Reading this repeatably will place it in the CPU cache, making it much faster to handle the loops.
Hardcoding XML values
Requires all previous ideas to be implemented first.
HARDCODE_XML_TYPES is set by the makefile for certain targets (possibly new targets rather than changing existing ones). The header file with the extern int lengths should have an #ifdef #else setup where instead of ints, the same variable names are defined as an enum.
Bonus:
Looping is much faster because no variable is read at runtime. Instead it is hardcoded at compiletime and is possibly optimized as the compiler optimization knows the value. The also result is faster code.
Since this depends on compiler settings, it will be possible to only use this for really optimized DLL files. Also it should contain an error popup telling people to use the assert DLL if the XML mismatch.
Note: unlike before, this time the perl script will be able to affect the resulting DLL file. Building an optimized DLL like this will require perl.
Linear storage
Requires Fast size for info arrays
Instead of storing a vector of pointers, store each XML file in an array where the actual class instances are stored in the array (not pointers to the class instances). This will store the data in a linear fashion, which makes looping predictable to the hardware. If a class use 40 bytes and we loop it to read an int, the hardware will detect that the code read an address, then address +40, then +40 and so on. This will cause it to fetch data from memory and move it to the CPU cache before it is requested because it will likely be requested in the near future.
Bonus:
Memory latency is the biggest performance killer on modern computers. This solution is aimed at "hiding" latency and hence make the game faster.
Note on implementation: read XML data into temp vector using existing code, then copy into newly allocated array. That requires minimal recoding. Info classes should be reviewed to not copy pointers and then free those pointers as this would cause crashes with the copy.
It should likely be something like a wrapper class for the read function, which will make it easy to implement this for a single XML file at a time.