* * * * *
Unicode. Why did it have to be Unicode?
Well, I have my answer [1]. I first found a smaller request that exhibits the
behavior as to not generate half a million lines of output:
Table: Lines of code executed for a small request
gopher 2549
gemini 564
Good. Two and a half thousand lines of code is tractable. Now, just to show
how easy it is to profile Lua code, here's the code I'm using for my gopher
server [2]:
-----[ Lua ]-----
local profile = {}
local function doprofile()
local info = debug.getinfo(2)
local name = info.name or "..."
local file = info.source or "@"
local key = string.format("%s$%s(%d)",file,name,info.currentline)
if not profile[key] then
profile[key] = 1
else
profile[key] = profile[key] + 1
end
end
-----[ END OF LINE ]-----
For each line of code executed, we get the filename, the function name and
the line of code that's executing, turn that into a key, and use that to
count the number of times that line of code is executed. Easy. And then some
code to dump the results:
-----[ Lua ]-----
local function cleanup()
local results = {}
for name,value in pairs(profile) do
results[#results + 1] = { file = name , count = value }
end
table.sort(results,function(a,b)
if a.count > b.count then
return true
elseif a.count < b.count then
return false
else
return a.file < b.file
end
end)
local f = io.open("/tmp/dump.txt","w")
for i = 1 , #results do
f:write(string.format("%6d %s\n",results[i].count,results[i].file))
end
f:close()
end
-----[ END OF LINE ]-----
We sort the results based on line count, then alphabetically by key. And like
before:
-----[ Lua ]-----
local function main(iostream)
debug.sethook(doprofile,'line')
-- The rest of the main code
debug.sethook()
cleanup()
end
-----[ END OF LINE ]-----
I make the request and get some results:
-----[ data ]-----
215 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(202)
211 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(203)
211 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(204)
211 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(268)
210 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(282)
210 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(283)
169 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(219)
169 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(224)
169 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(239)
169 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(240)
42 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(205)
42 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(206)
42 @/usr/local/share/lua/5.4/org/conman/string.lua$wrapt(207)
17 @port70.lua$...(272)
17 @port70.lua$...(273)
9 @/usr/local/share/lua/5.4/org/conman/net/ios.lua$write(547)
..
-----[ END OF LINE ]-----
Oh.
Yeah.
That.
Obvious in hindsight.
I completely forgot about that.
Okay. The function in question, wrapt(), wraps text [3] and it's a rather
heavy function due to Unicode [4] (and I'm not even following the full
specification there). This is the major difference between the gopher and
Gemini servers—I don't wrap text for Gemini (the clients handle that). I
guess I'll have to drop down to C if I want to speed this up.
Sigh.
[1]
gopher://gopher.conman.org/0Phlog:2024/05/30.1
[2]
https://github.com/spc476/port70
[3]
https://github.com/spc476/lua-conmanorg/blob/4ebd6da4f82617bf87a9f6c5a0d9eb5f4f96578f/lua/string.lua#L193
[4]
https://www.unicode.org/reports/tr14/
Email author at
[email protected]