Ok, after looking up some details.
new Array(2500) would also create a sparse array. So it is no difference.
Array.apply(null, Array(2500)) would create an efficient dense array.
However, I think a sparse array was wanted here, because this
spatial is used for
look and you already said, it's usually far from full.
I've read about sparse arrays and tested it:
new Array(0x7FFFFFFF) should use up all your heap, but it doesn't.
That means, I don't expect a positive impact by changing it to
I've spend some time now looking at the engines code for that lazy
What I see in code looks like
lookFor are fully precached, it's recreated at every request and uses that
spatial array, but it doesn't need to search for anything thanks to that sparse array. See
But look for area is a different story, it uses a different cache.
find is cached and only for exitTiles lazily evaluated. The
findCache is initialized when the
Game-Object is constructed. See
find just reads directly from the prefilled cache, it's cached for maximum performance. But I'm sure it's not needed to precompute it for every type of
find. Maybe a
Map helps for the
findCache.... which is already an object. In fact, every object that has roomNames as keys could use
Map instead. But I don't know if
Map uses less memory than object, I just know that it performs better. But I'm not sure if
Map also performs better than a sparse array, after all a sparse array can be optimized for integer keys.
However, conclusion: creating
spatial on demand might be less performant if it's used on every room, but it's a win for those who rarely
look. However, there is at least one thing which can only be seen by
look and not by
find, like spawning hostile creeps, but also here,
look would only be used in some hostile rooms.
I think a big impact could have a compressed terrain data, which is in
Terrain data is very big and the usage looks like it's an
staticTerrainData[id][y*50+x] with values 0,1,2,3 each.
staticTerrainData in the driver. It's an
If every tile is compressed to 2 bits in that
Uint8Array, then the size for terrain decreases from 2500 bytes + overhead to 625 bytes + overhead per room. That's something.
Compressing terrain data will come with a performance cost.
However, I'm really not sure if such optimizations (as well as the packed
RoomPosition fix) should be done without profiling how much memory is really used and where optimizations can be done.
Talking about packed RoomPositions... to pack
RoomObject could also save a little memory, likely even more than the last change of
RoomPosition. An access of the property
pos would unpack the
RoomPosition... but since
RoomPosition itself is already packed, it would effectively just wrap the integer in an instance of
One last note: deft-code mentioned that lazy initialization of look could also decrease CPU. I think that depends if the cpu time for the creation
Game counts to the users cpu or not. Means, if the user doesn't pay cpu for the creation of
Game right now, then it's obvious what happens on lazy creation of
Edit: What about giving bots more memory? Obviously the problem here are temporary objects which exist only during one tick. The memory of ivm is persistent, but it doesn't need to be persistent for these temporary objects. So my idea is, to allow all bots to use more memory during his execution time, but at the end of the bots
loop, free up the space used by temporary engine objects, garbage collect and if then the memory still exceeds the current ivm memory limit, then reset the ivm.
This way we introduce a hard limit, which is what the ivm can persist, and a soft limit which is what the ivm can use while active.
I looked up the isolated-vm from laverdet. If more than 100% of memory is used, then that's already possible for a very short amount of time. So you would install the soft limit and hard limit here, so that it's just checked for the soft limit during execution and there is one explicit check for the hard limit after the temporary objects are released.
Maybe that's also possible without changing the code of ivm, if the memory limit can be changed on the fly. Then you can set the higher soft limit before
Game is initialized and the lower hard limit after
Game is destructed.