Created
August 23, 2022 12:37
-
-
Save SamMousa/b81e843371edd4af96a921970ad0f89f to your computer and use it in GitHub Desktop.
Lua profiling proxy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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