Fandom Developers Wiki
Advertisement

Optimisation is generally only necessary when Lua modules are misused or inefficient.

Important note

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." [1]

General guidelines

If for whatever reason your modules are exceeding the limit, you should then consider optimising.

Whenever possible[2]:

  • Use local functions or variables
  • Avoid nested functions
  • Use arrays instead of tables (hashing)
  • Use local variables instead of indexing tables

Simple optimisations such as copying a global function (e.g. string.match) may greatly improve performance of a module.

Tip: Use os.clock() before and after a code "chunk" and subtract the two results to evaluate the code section's  performance.

String vs table concatenation

When dealing with potentially huge strings, it is more efficient to add them to a table and use table.concat rather than simply using "join" or concatenating them [3].

-- This is slower

local people = {"John", "Mary", "Parker", "Sue", "Anonymous", "..."}
local text = ""

for i = 1, #people do
    if i > 1 then
        text = text .. ", "
    end

    text = text .. people[i]
end

print(text)

-- This is faster

local people = {"John", "Mary", "Parker", "Sue", "Anonymous", "..."}
local text = table.concat(people, ", ")

print(text)

Use tables for SQL-IN alike compares

This means that instead of having a lot of if statements a better alternative is to put them all in a set-like table[4]. For example, this is a typical if structure:

local function foo(value)
    if value == "foo" or value == "bar" or value == "baz" or value == "qux"
    or value == "lorem" or value == "ipsum" then
        return "something"
    end

    return "something else"
end

... and this is a more efficient, table-based one:

local function foo(value)
    local validValues = {
        foo = true,
        bar = true,
        baz = true,
        qux = true,
        lorem = true,
        ipsum = true
    }

    if validValues[value] then
        return "something"
    end

    return "something else"
end

Note that you can use any truthy value, instead of just true.

Templates

Using too many template transclusions in a single page is one common problem that affects the speed of lua. Each invocation will count towards the lua limit.

There are multiple techniques to overcome this:

  • Consolidate - move all code to a module, and restructure it to only be called fewer times
  • Rewrite the code to be more efficient.

Change template "databases" into data modules

Making templates databases causes a lot of issues such as becoming cumbersome to use, and slower if they use parser functions. One idea is adding them to a module, as described in Lua templating/Converting Wikitext templates.

If the template is used several times on a page, consider using mw.loadData to load its data, instead of require:

      local data = mw.loadData("Module:Mystuff")
      return data[frame.args[1]]

Avoid multiple invocations to the same module

Instead of this for example:

local p = {}

function p.showpopulation(frame)
     local pop = {['china'] = 50, ['australia'] = 20, ['ghana'] = 10}
     return pop[frame.args[1]]
end

return p
{{#invoke:mymodule|showpopulation|china}}
{{#invoke:mymodule|showpopulation|australia}}
{{#invoke:mymodule|showpopulation|ghana}}

Do this:

local p = {}

function p.showpopulation(frame)
    local pop = {['china'] = 50, ['australia'] = 20, ['ghana'] = 10}
    local args = frame.args
    return pop[args[1]] .." ".. (pop[args[2]] or "") .. " " ..(pop[args[3]] or "")
end

return p
{{#invoke:mymodule|showpopulation
|china
|australia
|ghana
}}

References

Text above can be found here (edit)
Advertisement