-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
refactor(runloop/wasm): optimize hash_chain_entity with string.buffer #11304
Conversation
f7e7d3a
to
460e7cd
Compare
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.
runloop/wsam ->runloop/wasm
done, thanks. |
I was curious so I hacked up a micro benchmark for this: https://gist.github.com/flrgh/77263a8cd925aa6259e940fe573d01e5 1k items
10k items
100k items
There doesn't seem to be much of a measurable difference. In general I also expect the time spent in this hash function to be dwarfed by time spent iterating over filter chain entities from the db or fetching routes from the cache/db. I'm not super knowledgeable of luajit internals, so is there something I'm missing? Can you share your own benchmarks? |
Theoretically, But in this case, I think lots of time cost is sha256, so we can not see the improvement of performance. Back to the test result, Keeping the original code may be a good choice. |
Any difference in memory usage / garbage being collected? I removed the SHA256 and ran the microbenchmark with
There is around 5 times difference in favour for string buffer. So I don't think there is doubt that is it better. I didn't check memory usage and garbage generated, but I think that would also favour string.buffer if checked. That said, we can always ask "does it matter" when there are other factors dominating. Perhaps not that much in many places, but on hot path and with huge strings perhaps. Does our plugin iterator speed matter if there is a plugin that does network io and makes client wait for that. Sure it matters but not when that plugin is added. Another thing is that our code base is also used as a source for new code. Thus sometimes it is worth to try to spread the better approach, even if it didn't matter that much in that spot. For example which one of these do you prefer to read: local n = 0
for _, filter in ipairs(chain.filters) do
buf[n + 1] = filter.name
buf[n + 2] = tostring(filter.enabled)
buf[n + 3] = tostring(filter.enabled and sha256(filter.config))
n = n + 3
end
local s = concat(buf, "", 1, n) vs. local filters = chain.filters
for i = 1, #filters do
local filter = filters[i]
buf:put(filter.name)
buf:put(tostring(filter.enabled))
buf:put(tostring(filter.enabled and sha256(filter.config)))
end
local s = buf:get() I think I like the local filters = chain.filters
for i = 1, #filters do
local filter = filters[i]
buf:put(filter.name):put(tostring(filter.enabled)):put(tostring(filter.enabled and sha256(filter.config)))
end
local s = buf:get() If that is preferred or: local filters = chain.filters
for i = 1, #filters do
local filter = filters[i]
buf:putf("%s%s%s", filter.name, tostring(filter.enabled), tostring(filter.enabled and sha256(filter.config)))
end
local s = buf:get() |
Thanks for @bungle's comment. If we think |
I didn't do any real scientific measurements on garbage/memory. I did test each of these with GC disabled and then comparing before/after results of If we wanted to increase performance I think things would get better if we swapped the Anyhow, I don't think it's a bad change and wasn't insinuating we should abandon the PR (sorry @chronolaw if I gave this impression); I just want us to remain focused on the end result when it comes to perf changes. If y'all see this as an improvement overall for the code I'm happy for us to revisit it 👍. Code style/quality-wise I am 50/50 on table vs |
460e7cd
to
23d47cd
Compare
Since we have some new discussion in #11811, I reopen this PR and appreciate any comments. |
As other PRs did, string.buffer can replace table.concat to get more performance. Reference: #11304 (comment)
Summary
We already use
string.buffer
in many fields successfully, especially for replacingstring.concat
.Checklist
Full changelog
string.buffer
clear_tab
concat
Issue reference
Fix #[issue number]