Some time ago, Mexa and I were messing a bit around with memory limitations and noticed a few things:
Every string literal (eg. "hello") allocates 4 bytes. 4 bytes that cannot be recovered. Something like someString="hello"+"hello"; allocates 8 bytes. Optimizers should help saving memory space by replacing string literals with global constants wherever sensible to do.
Native functions can be used without having to declare them.
Dependencies can force SC2 to load script files. MapScript.galaxy can be empty and NativeLib.galaxy will still be loaded. You can import empty files to replace those forcefully loaded by dependencies.
Dependencies can force SC2 to load script files. MapScript.galaxy can be empty and NativeLib.galaxy will still be loaded. You can import empty files to replace those forcefully loaded by dependencies.
Care to elaborate on this point? I don't really understand how this is useful.
Imagine you dont use any function inside NativeLib.galaxy. Why include it in MapScript.galaxy? Now, if you think that should be enough to not load NativeLib.galaxy, youre mistaken. The only way to prevent loading content from NativeLib.galaxy is to either mess with the dependencies, which sometimes, like with the Liberty dependecy, is not such a good idea, since theres data and art that wouldnt be accessible without the dependency, or you overwrite the files with files containing what you want them to contain.
I recently discovered as well, that you can circumvent the need of overriding nativelib and libertylib.galaxy, and as well computer.galaxy
This is, at least, when having the Liberty mod as a dependency on your map.
Seeing in the Data Editor, and then under Gameplay Data, there's a field AI which you can set to load specific AI scripts (computer.galaxy) by default.
Theres also a field called Trigger Libraries which loads LibertyLib.galaxy (and LibertyLib will preload NativeLib as well). Removing these should solve many weird preloadings.
If no external mod is loaded but the Core.mod at all, I think the way we found out is the way to do it, eg, overriding it with empty scripts.
The tests we did focused on data limitations. I have no idea what influences code space.
But i doubt declaring natives takes up code space.
However, removing Galaxy code thats unused would free up code space.
@Mexaprone: Go
Oh, now i remember. But isnt NativeLib loaded by Core.SC2Mod? So, wouldnt removing LibertyLib only avoid loading LibertyLib, but not NativeLib, since Core still loads NativeLib? Thus, wouldnt you always have to import an empty NativeLib?
Strangely enough, it does not seem to do that. Or rather, if you create a map with no external dependencies but Core, all external variables you will find when testing the map is the ones retrieved from natives.galaxy, ai.galaxy etc, and not NativeLib itself. And the default field for Trigger Libraries in the Gameplay Data is empty here.
<-> Oh wait, I see what you mean now. Yes, if you create a trigger and allow it to generate a mapscript, it will include NativeLib as default, and thus load it.
If you save the map as folder format and override mapscript.galaxy to not include NativeLib, but natives.galaxy instead, NativeLib wont be loaded at all.
(Conclusively, the problem seems to be somewhat less severe.)
---
A few more points on galaxy memory limitations and overriding:
All constants, triggers, variables etc, not created by the user, eg constants in natives.galaxy, everything in NativeLib and so on, will drastically decrease the amount of memory you can use. The 2MB limit is set for the entire memory pool, included what Blizzard loads within their libraries (that's what I got out of it when I overrided natives.galaxy, could perhaps need verification).
Bools have the same size as a byte.
You can override natives.galaxy and even define and implement the main entry point of the map (void InitMap()) here.
This is true down to the assembly. Bools are treated as bytes because it is faster to pass them around that way (no bit fiddling). 1 is true and not 1 is false.
Actually, 0 is false, any other value is true.
And i suspect blizzard doesnt compile Galaxy JIT. At least not to x86 ASM. The VM most likely interprets the bytecode it compiles Galaxy into.
you can do it with the standard editor. Just define a byte array in GUI and choose an array size of 1048576, if that fails when loading the map, reduce size by 524288 (half of 1048576), if it works, add 524288. Repeat until youve added/subtracted 1. 2095103 ((2^21)-1-2048) minus the size of the byte array at that point is about the size of all global allocations. I say about because i think allocations after the allocation of the byte array dont get factored into the calculation.
Some time ago, Mexa and I were messing a bit around with memory limitations and noticed a few things:
@Deaod: Go
Dependencies can force SC2 to load script files. MapScript.galaxy can be empty and NativeLib.galaxy will still be loaded. You can import empty files to replace those forcefully loaded by dependencies.
Care to elaborate on this point? I don't really understand how this is useful.
Imagine you dont use any function inside NativeLib.galaxy. Why
include
it in MapScript.galaxy? Now, if you think that should be enough to not load NativeLib.galaxy, youre mistaken. The only way to prevent loading content from NativeLib.galaxy is to either mess with the dependencies, which sometimes, like with the Liberty dependecy, is not such a good idea, since theres data and art that wouldnt be accessible without the dependency, or you overwrite the files with files containing what you want them to contain.@Deaod: Go Would each the 3 points raise the script limit ingame because you won't fill the memory with code that you don't need?
@Deaod: Go
I recently discovered as well, that you can circumvent the need of overriding nativelib and libertylib.galaxy, and as well computer.galaxy This is, at least, when having the Liberty mod as a dependency on your map.
Seeing in the Data Editor, and then under Gameplay Data, there's a field AI which you can set to load specific AI scripts (computer.galaxy) by default. Theres also a field called Trigger Libraries which loads LibertyLib.galaxy (and LibertyLib will preload NativeLib as well). Removing these should solve many weird preloadings.
If no external mod is loaded but the Core.mod at all, I think the way we found out is the way to do it, eg, overriding it with empty scripts.
The tests we did focused on data limitations. I have no idea what influences code space.
But i doubt declaring natives takes up code space. However, removing Galaxy code thats unused would free up code space.
@Mexaprone: Go Oh, now i remember. But isnt NativeLib loaded by Core.SC2Mod? So, wouldnt removing LibertyLib only avoid loading LibertyLib, but not NativeLib, since Core still loads NativeLib? Thus, wouldnt you always have to import an empty NativeLib?
@Deaod: Go
Strangely enough, it does not seem to do that. Or rather, if you create a map with no external dependencies but Core, all external variables you will find when testing the map is the ones retrieved from natives.galaxy, ai.galaxy etc, and not NativeLib itself. And the default field for Trigger Libraries in the Gameplay Data is empty here.
<-> Oh wait, I see what you mean now. Yes, if you create a trigger and allow it to generate a mapscript, it will include NativeLib as default, and thus load it. If you save the map as folder format and override mapscript.galaxy to not include NativeLib, but natives.galaxy instead, NativeLib wont be loaded at all. (Conclusively, the problem seems to be somewhat less severe.)
---
A few more points on galaxy memory limitations and overriding:This is true down to the assembly. Bools are treated as bytes because it is faster to pass them around that way (no bit fiddling). 1 is true and not 1 is false.
@Iggyhopper: Go
Actually, 0 is false, any other value is true. And i suspect blizzard doesnt compile Galaxy JIT. At least not to x86 ASM. The VM most likely interprets the bytecode it compiles Galaxy into.
@Deaod: Go
Oh, right. Oops.
@Deaod: Go
How do we actually check how much memory our script is currently using?
Do a binary search using a byte array.
@Deaod: Go
Not sure how to do that, does it require 3rd party software? Or can be done within game engine?
you can do it with the standard editor. Just define a byte array in GUI and choose an array size of 1048576, if that fails when loading the map, reduce size by 524288 (half of 1048576), if it works, add 524288. Repeat until youve added/subtracted 1. 2095103 ((2^21)-1-2048) minus the size of the byte array at that point is about the size of all global allocations. I say about because i think allocations after the allocation of the byte array dont get factored into the calculation.
@Deaod: Go
Interesting...
You can import empty files to replace those forcefully loaded by dependencies.
Any specific files I should replace replace prevent these forced loads? I'm thinking TriggerLib/NativeLib.galaxy only?
Tried removing 'include "TriggerLib/NativeLib"' in my map, but it broke, presumably because I call some functions that are preceded with 'libNtve_gf_'
Native functions can be used without having to declare them.
Wondering how to do this right now.. so for example if I have a native function
libNtve_gf_Derp() <- I'm assuming this is a native function. Could I just call Derp without the prefix 'libNtve_gf_' etc etc?
Functions called libNtve_gf... are not actually native functions - they are galaxy functions located in the native lib.
Native functions are those you find defined like
Without an implementation.
@SBeier: Go
Ah, I see, it all makes sense now. This looks to be a good method to cut down load time and prevent unwanted memory usage.