Skip to content

Instantly share code, notes, and snippets.

@SamMousa
Created August 23, 2022 12:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SamMousa/b81e843371edd4af96a921970ad0f89f to your computer and use it in GitHub Desktop.
Save SamMousa/b81e843371edd4af96a921970ad0f89f to your computer and use it in GitHub Desktop.
Lua profiling proxy
local proxy = {
__metatable = false,
__newindex = function ()
error("Can't write to proxy table!")
end,
__index = function(table, key)
local result = _G[key]
if (result == nil) then
error(string.format("Attempt to access undefined global %s"), key)
end
return result
end
}
local timeInMs
if (type(os.clock) == 'function') then
timeInMs = function()
return os.clock()
end
else
timeInMs = function()
return debugprofilestop()
end
end
local function profileFunction(f, dataStore, functionName)
return function(...)
dataStore.count = dataStore.count + 1
local start = timeInMs()
local result = {f(...)}
local duration = timeInMs() - start
dataStore.totalTime = dataStore.totalTime + duration
if dataStore.max < duration then
dataStore.max = duration
end
if dataStore.min > duration then
dataStore.min = duration
end
return unpack(result)
end
end
local profilingProxy
profilingProxy = {
__metatable = false,
__newindex = function ()
error("Can't write to proxy table!")
end,
__index = function(table, key)
local value = table.__reference[key]
if (value == nil) then
error(string.format("Attempt to access undefined value %s", key))
end
local result
--use profiling
local valueType = type(value)
local profileKey = table.__keyprefix .. '.' .. key
if (valueType == "function") then
local store = table.__profiling[profileKey]
if (store == nil) then
store = {
count = 0,
totalTime = 0,
min = 1000000,
max = -1
}
table.__profiling[profileKey] = store
end
result = profileFunction(value, store, key)
elseif (valueType == "table") then
-- simple recursion, we create a proxy for the table
-- we set the profiling data table to be the primary one.
local proxyTable = {
__profiling = table.__profiling,
__keyprefix = table.__keyprefix .. '.' .. key,
__reference = value
}
setmetatable(proxyTable, profilingProxy);
result = proxyTable
end
-- cache the proxied value
-- rawset(table, key, result)
return result
end
}
function createProxy()
local result = {}
setmetatable(result, proxy);
return result
end
function createProfilingProxy()
local result = {
__profiling = {},
__keyprefix = "",
__reference = _G
}
setmetatable(result, profilingProxy);
return result
end
local function runDemo()
local ApiProxy = createProfilingProxy()
ApiProxy.print("cool stuff")
ApiProxy.print("cool stuff2")
function VerySlowBigFunction()
local dataSet = {}
for i = 0, 10000 do
for j = 0, 10000 do
dataSet[j] = math.random()
end
end
end
ApiProxy.VerySlowBigFunction()
ApiProxy.math.random()
-- print profiling results
print("Profiling data below:\n")
for k, metrics in pairs(ApiProxy.__profiling) do
print(string.format("Profile info for function %s", k))
for metric, value in pairs(metrics) do
print(string.format("Metric %s, value %f", metric, value))
end
end
end
runDemo()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment