You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are two major memory management methods in computer programming, manual releasing and auto releasing. While Bitty Engine uses Lua, it benefits from Garbage Collecting which is a type of auto releasing method, so a user can focus on program logic other than memory details. This article guides you understanding and practicing with Bitty Engine's memory management.
Lua's Garbage Collection
Lua implements two GC modes, incremental and generational.
"In incremental mode, each GC cycle performs a mark-and-sweep collection in small steps interleaved with the program's execution."
"In generational mode, the collector does frequent minor collections, which traverses only objects recently created. If after a minor collection the use of memory is still above a limit, the collector does a stop-the-world major collection, which traverses all objects."
Bitty Engine uses the generational mode (a.k.a. collectgarbage('generational', 0, 0)) by default.
Bitty Engine's Resources.collect()
Assets are loaded as resources before rendering in Bitty Engine, then cached for better performance. A variable value that holds a loaded resource are managed by GC, however the resource itself won't be auto released until you do it manually.
Consider Resources.unload(...) to unload each unused resource properly, or in a simpler way Resources.collect() to determine automatically and unload all unused resources. Call this function when a new level is loaded and the old one is obsolete, etc.
Memory Management Patterns
Consider an appropriate pattern in practice for better overall balance among "less code modification", "memory efficiency" and "CPU efficiency", although GC manages memory automatically.
1. Default
You don't need to do any extra step to use the default GC pattern for small programs, prototypes, and other programs that won't allocate very often. Thus with this pattern, it doesn't add extra CPU load. But you might see continuous footprint increasing along with continuous running.
2. Periodical Collecting
The second pattern is to use a frame/time counter to accumulate how long the program has ran, then collect garbage after every constant interval, i.e.
localGC_INTERVAL_FRAMES<const>=60*5-- Around 5 seconds.localn=0functionupdate(delta)
n=n+1ifn>=GC_INTERVAL_FRAMESthenn=0collectgarbage()
Resources.unload()
endend
This pattern requires a few more lines of code. The footprint will be maintained under a reasonable level, even after long time run. The time counting and manual collecting code won't add remarkable CPU load. But the manual releasing might lead to unexpected short pause if there were more garbage than usual.
3. Fine Collecting
The final pattern offers fine management, it doesn't come with standard routine. You can organize it in your own way according to specific project, i.e. call collecting when a new level is loaded, a new GUI pops up, a number of enemies are defeated, etc.
functiononSomethingHappened()
collectgarbage()
Resources.unload()
end
You can also mix the Periodical and Fine Collecting patterns together.
Finally, try adjusting the GC options to optimize your program:
collectgarbage ([opt [, arg]]): This function is a generic interface to the garbage collector. It performs different functions according to its first argument, opt:
"collect": Performs a full garbage-collection cycle. This is the default option.
"stop": Stops automatic execution of the garbage collector. The collector will run only when explicitly invoked, until a call to restart it.
"restart": Restarts automatic execution of the garbage collector.
"count": Returns the total memory in use by Lua in Kbytes. The value has a fractional part, so that it multiplied by 1024 gives the exact number of bytes in use by Lua.
"step": Performs a garbage-collection step. The step "size" is controlled by arg. With a zero value, the collector will perform one basic (indivisible) step. For non-zero values, the collector will perform as if that amount of memory (in Kbytes) had been allocated by Lua. Returns true if the step finished a collection cycle.
"isrunning": Returns a boolean that tells whether the collector is running (i.e., not stopped).
"incremental": Change the collector mode to incremental. This option can be followed by three numbers: the garbage-collector pause, the step multiplier, and the step size (see §2.5.1). A zero means to not change that value.
"generational": Change the collector mode to generational. This option can be followed by two numbers: the garbage-collector minor multiplier and the major multiplier (see §2.5.2). A zero means to not change that value.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
There are two major memory management methods in computer programming, manual releasing and auto releasing. While Bitty Engine uses Lua, it benefits from Garbage Collecting which is a type of auto releasing method, so a user can focus on program logic other than memory details. This article guides you understanding and practicing with Bitty Engine's memory management.
Lua's Garbage Collection
Lua implements two GC modes, incremental and generational.
"In incremental mode, each GC cycle performs a mark-and-sweep collection in small steps interleaved with the program's execution."
"In generational mode, the collector does frequent minor collections, which traverses only objects recently created. If after a minor collection the use of memory is still above a limit, the collector does a stop-the-world major collection, which traverses all objects."
Bitty Engine uses the generational mode (a.k.a.
collectgarbage('generational', 0, 0)
) by default.Bitty Engine's
Resources.collect()
Assets are loaded as resources before rendering in Bitty Engine, then cached for better performance. A variable value that holds a loaded resource are managed by GC, however the resource itself won't be auto released until you do it manually.
Consider
Resources.unload(...)
to unload each unused resource properly, or in a simpler wayResources.collect()
to determine automatically and unload all unused resources. Call this function when a new level is loaded and the old one is obsolete, etc.Memory Management Patterns
Consider an appropriate pattern in practice for better overall balance among "less code modification", "memory efficiency" and "CPU efficiency", although GC manages memory automatically.
1. Default
You don't need to do any extra step to use the default GC pattern for small programs, prototypes, and other programs that won't allocate very often. Thus with this pattern, it doesn't add extra CPU load. But you might see continuous footprint increasing along with continuous running.
2. Periodical Collecting
The second pattern is to use a frame/time counter to accumulate how long the program has ran, then collect garbage after every constant interval, i.e.
This pattern requires a few more lines of code. The footprint will be maintained under a reasonable level, even after long time run. The time counting and manual collecting code won't add remarkable CPU load. But the manual releasing might lead to unexpected short pause if there were more garbage than usual.
3. Fine Collecting
The final pattern offers fine management, it doesn't come with standard routine. You can organize it in your own way according to specific project, i.e. call collecting when a new level is loaded, a new GUI pops up, a number of enemies are defeated, etc.
You can also mix the Periodical and Fine Collecting patterns together.
Finally, try adjusting the GC options to optimize your program:
collectgarbage ([opt [, arg]])
: This function is a generic interface to the garbage collector. It performs different functions according to its first argument, opt:Beta Was this translation helpful? Give feedback.
All reactions