Lua - Module Caching



Module caching refers to keeping a copy of module loaded and checking if it is already loaded before reloading the module. Lua keeps track of each module loaded using require statement. Lua maintains a global table package.loaded and caches the loaded module in this table.

Caching Mechanism

Following section showcases how Lua caches modules.

First require call

-- load the module
stringutils = require("stringutils")

When a require() statement is encountered for the first time, Lua performs following actions −

  • Lua searches for the file name stringutils.lua in the current path or path defined by LUA_PATH environment variable.

  • Once a file is found, its content are loaded into the memory and are executed.

  • The table returned by the module or any other entity is then stored in Lua's internal cache associated with key as module name passed. In this case it is stringutils.

  • The returned table/value by the module is assigned to a variable stringutils.

Subsequent require call

-- load the module again
stringutils1 = require("stringutils")

When a require() statement is encountered again with same module name, Lua checks its cache first −

  • Lua searches for the module name stringutils in its cache, as module is found, the same is returned.

  • The returned cached table/value by the module is assigned to a variable stringutils.

Example - Showcasing Module Caching

Create a Module which executes a message when loaded.

counter_module.lua

print("Counter module is loaded and executed.")

local counter = 0

local counterModule = {}

function counterModule.increment()
   -- increment the counter
   counter = counter + 1
   -- print the counter
   print("Counter:", counter)
end

return counterModule

Create Main Module and load the counter module twice.

moduletutorial.lua

-- load the counter module for the first time
-- prints Counter module is loaded and executed.
local counterModule1 = require("counter_module")

-- call the increment() function to print the counter
-- prints Counter: 1
counterModule1.increment()

-- load the counter module again but it will not print the loaded messaage
-- owing to module caching
local counterModule2 = require("counter_module")

-- call the increment() function to print the counter
-- prints Counter: 2, as cached module counter was incremented initially
counterModule2.increment() 

-- load the counter module again but it will not print the loaded messaage
-- owing to module caching
local counterModule3 = require("counter_module")

-- call the increment() function to print the counter
-- prints Counter: 3, as cached module counter was 
-- incremented again in previous statement
counterModule3.increment() -- Output: Counter: 3

-- compare modules, each comparison prints true
print(counterModule1 == counterModule2)
print(counterModule2 == counterModule3)

Output

In order to run this code, we need to place the two Lua files in the same directory or alternatively, you can place the module file in the package path and it needs additional setup. When we run the above program, we will get the following output−

Counter module is loaded and executed.
Counter:        1
Counter:        2
Counter:        3
true
true

Explanation

counter_module.lua

  • As first line, we're having a print statement which will be printed when the module is loaded.

  • We've created a variable counter and initialized it to zero and an empty table counterModule as a module.

  • As next, we've defined a function increment() which increments the counter and prints the updated counter.

  • In the end, we're returning the counterModule table.

moduletutorial.lua

  • local counterModule1 = require("counter_module") statement is used to load the module for the first time and assign to counterModule1 variable and a message "Counter module is loaded and executed." is printed.

  • counterModule1.increment() is used to increment module counter and print it.

  • local counterModule2 = require("counter_module") tries to reload the same module, but it comes as a cached copy as the loaded message is not getting printed.

  • counterModule2.increment() increments the counter of cached module and prints the same.

  • Finally, we're comparing print(counterModule1 == counterModule2). Being same module internally, comparison returns true.

Advantages of Module Caching

  • Improved Performance − As module is loaded only once, we can avoid file I/O multiple times and faster program startup.

  • Ensures Singletons − In case module is having a singleton then caching will help in maintaining singleton.

  • Initialization − As a module is loaded only once, the initialization block will be called once and can be used to initialize variables of the module.

Advertisements