systemed / tilemaker

Make OpenStreetMap vector tiles without the stack
https://tilemaker.org/
Other
1.44k stars 229 forks source link

lua: use non-member functions for interop #589

Closed cldellow closed 9 months ago

cldellow commented 9 months ago

Currently, Tilemaker uses member functions for interop:

function node_function(node)
    node:Layer(...)

This PR changes Tilemaker to use global functions:

function node_function()
    Layer(...)

The chief rationale is performance. Every member function call needs to push an extra pointer onto the stack when crossing the Lua/C++ boundary.

Kaguya serializes this pointer as a Lua userdata. That means every call into Lua has to malloc some memory, and every call back from Lua has to dereference through this pointer.

And there are a lot of calls! For OMT on the GB extract, I counted ~1.4B calls from Lua into C++.

A secondary rationale is that a global function is a bit more honest. A user might believe that this is currently permissible:

last_node = nil
function node_function(node)
    if last_node ~= nil
        -- do something with last_node
    end

    -- save the current node for later, for some reason
    last_node = node

But in reality, the OSM objects we pass into Lua don't behave quite like Lua objects. They're backed by OsmLuaProcessing, who will move on, invalidating whatever the user thinks they've got a reference to.

This PR has a noticeable decrease in reading time for me, measured on the OMT profile for GB, on a 16-core computer:

Before:

real    1m28.230s
user    19m30.281s
sys 0m29.610s

After:

real    1m21.728s
user    17m27.150s
sys 0m32.668s

The tradeoffs:

cldellow commented 9 months ago

Closing to retarget against master