-
Notifications
You must be signed in to change notification settings - Fork 48
fix opaque error messages in lunatik_monitor #398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Testing summary: $ sudo lunatik run bind_bug
bad argument #2 to 'bind' (out of bounds)
stack traceback:
[C]: in ?
[C]: in method 'bind'
/lib/modules/lua/bind_bug.lua:10: in main chunk
[C]: in ?
$ sudo lunatik run syscall_bug
stack overflowEDIT: I realized |
This patch introduces better error handling and fixes opaque error messages by passing method name as second upvalue to lunatik_monitor. Signed-off-by: Ashwani Kumar Kamal <ashwanikamal.im421@gmail.com>
54bab74 to
d1eda2f
Compare
Yup, exactly. Also, it shouldn't be related to your patch, right? Did you try it on master? One thing we could do though to improve the error message in this case is to show stack trace on the driver. |
Yup this issue is unrelated to this patch. I got confused because of |
| lua_pushvalue(L, lua_upvalueindex(2)); /* method name */ | ||
| lua_pushcclosure(L, lunatik_error_handler, 1); /* stack: object, args..., errhandler */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one concern I have is creating this other closure on every call.. perhaps it's a bit of premature optimization on my side, but it would be good if you can run some benchmarks for this change.. overall, I found it quite an elegant solution.. I'm most concerned on this on hotpaths..
btw, one thing that I've left for later and never got back is to apply memoization to monitor; perhaps it's a good opportunity to do it now..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw, one thing that I've left for later and never got back is to apply memoization to monitor;
Could you give me some pointers on how to memoize it? I'm thinking of caching the wrapped monitor closures (monitorobject) in the registry to avoid recreating them on every call, but I want to make sure I'm following the right pattern for Lunatik.
I thought of doing something like this:
int lunatik_monitorobject(lua_State *L)
{
lua_pushlightuserdata(L, (void*)lunatik_monitorobject);
lua_rawget(L, LUA_REGISTRYINDEX);
if (!lua_isnil(L, -1))
// found closure cached
return 1;
}
lua_pop(L, 1);
// function body
lua_pushlightuserdata(L, (void *)lunatik_monitorobject);
lua_pushvalue(L, -2);
lua_rawset(L, LUA_REGISTRYINDEX);
return 1;
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps we should just update the object metatable, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but I would measure the effect of this change before going to memoization; it's a good exercise anyway ;-).. you can mesure the time of n-calls on a luadata method (e.g., getbyte).. and assess the difference.. it might be negligible.. then we can merge this as is and leave memoization for later.. (or not ;-)
|
Hello @lneto local linux = require("linux")
local data = require("data")
local d = data.new(1024)
local iterations = 1000000
local start_ns = linux.time()
for i = 1, iterations do
d:getbyte(0)
end
local end_ns = linux.time()
local total_ns = end_ns - start_ns
local ns_per_call = total_ns / iterations
print("Total ns: " .. total_ns)
print("Ns per call: " .. ns_per_call) |
Nice job! Perhaps we can add this to our tests? 35% is looking to much for enriching error messages; what do you think? I think we should try memoization. Btw, can you disable lunatik_monitorobject on luadata (by commenting out it on its metatable) and run the same benchmark? Perhaps we are already imposing an unnecessary overhead by creating the monitor closure all the time.. memoization could help us there as well.. also the new "single" option that has been discussed for not sharing objects.. good work! Thanks! |
Yes I agree, we should try memoization.
disabling the monitorobject, I can see latency drops to just ~62 ns/call (avg). |
perhaps, a better idea is to create closures on the object creation instead of memoizing it. what do you think? We could even leverage uservalues.
Wow; that would be a great optimization!
can you share your draft and the stack trace? |
That will be better yes. But where in the lifecycle will we create these closures? Won't this require too many changes in the current implementation, given that __index and
I have a pushed a change which memoizes the monitor, the latency for same script for latest change is ~330 ns/cal
I was trying to mess with metatable and __index, got a kernel panic related to some reentry issue. With the latest push, I’ve been able to safely memoize it to some extent. (330 ns/call, so 21% performance hit) |
|
This is what I could think about creating closures instead of memoization, (taken example of luadata class) C side:
Lua side:
and thus we get rid of what do you think @lneto ? |
I was thinking on something like this, but on lunatik_newclass (or setclass) itself, we could create our modified metatable there.. |
Signed-off-by: Ashwani Kumar Kamal <ashwanikamal.im421@gmail.com>
I was thinking here.. we could also measure the impact of memoization by doing |
Some metrics for the following script local linux = require("linux")
local data = require("data")
local d = data.new(1024)
local iterations = 1000000
local m_getbyte = d.getbyte
local start_ns = linux.time()
for i = 1, iterations do
m_getbyte(d, 0)
end
local end_ns = linux.time()
local total_ns = end_ns - start_ns
print("Localized Method Total ns: " .. total_ns)
print("Localized Method Ns per call: " .. (total_ns / iterations))master: Localized Method Ns per call: 117ns and for the following script local linux = require("linux")
local data = require("data")
local d = data.new(1024)
local iterations = 1000000
local start_ns = linux.time()
for i = 1, iterations do
d:getbyte(0)
end
local end_ns = linux.time()
local total_ns = end_ns - start_ns
local ns_per_call = total_ns / iterations
print("Total ns: " .. total_ns)
print("Ns per call: " .. ns_per_call)latest changes in this branch report ~240ns/call (master reports 266 ns/call) |
| continue; | ||
| } | ||
|
|
||
| // Skip metamethods (starting with __) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please, mind our style; we don't do C++ style comments
I think it's getting very complex. I would give a step back and break up this problem in two. Firstly, I would try to implement the wrapper, without the improved error handling; then, after it's round, I would introduce the error hadling improvement. What do you think? |
Yes, I have created a PR. Once that’s reviewed, we can continue iterating here on the remaining pieces. |
This patch introduces better error handling and fixes opaque error messages by passing method name as second upvalue to
lunatik_monitor.Summary of my approach:
lunatik_monitorobjectby duplicating it on stacklunatik_monitor) with 2 upvalues:lunatik_monitor, it is to be passed correctly tolunatik_error_handlerlunatik_error_handleras the error handler tolua_pcall(this will update the error message)Fixes #382