-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
perf: shortcut for proc with no variadic arg #1636
perf: shortcut for proc with no variadic arg #1636
Conversation
* move json ops tests to JsonOperatorSpec * move phfts operator tests to QuerySpec and RpcSpec * add custom spec for pre-request header guc tests
it "returns last value for repeated params without VARIADIC" $ | ||
get "/rpc/sayhello?name=ignored&name=world" |
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.
@wolfgangwalther I've changed this behavior. It would be a breaking change otherwise.
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.
Oh yes. It was my intention to not introduce a breaking change here - that's why I wrote the test. 👍
Also refactor how rpc params are converted to json
a9c0c84
to
79207e2
Compare
where | ||
mergeParams :: RpcParamValue -> RpcParamValue -> RpcParamValue | ||
mergeParams (Variadic a) (Variadic b) = Variadic $ b ++ a | ||
mergeParams _ v = v -- repeated params for non-variadic arguments are not merged |
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.
I think the order of this needs to be changed to v _
. This is because you changed the test-case from first to last repetition for non-repeated args.
However, since you're change with hasVariadic
this code path is not taken anymore. So we actually need another test case that has a function with regular argument + variadic argument, where the non-variadic one is repeated as well. And then this part kicks in and should show the same behaviour as the regular case.
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.
@wolfgangwalther Hmm.. could you help me with that on another PR?
I mostly wanted to isolate the bits for non-variadic functions here. If the variadic part behaves differently it wouldn't be a breaking change for now since we haven't been supporting variadic.
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.
Sure, see #1639.
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.
Thanks a lot Wolfgang :)
-- | Convert rpc params `/rpc/func?a=val1&b=val2` to json `{"a": "val1", "b": "val2"} | ||
jsonRpcParams :: ProcDescription -> [(Text, Text)] -> PayloadJSON | ||
jsonRpcParams proc prms = | ||
if not $ pdHasVariadic proc then -- if proc has no variadic arg, save steps and directly convert to json |
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.
I'm curious - did you test the performance difference of this? How many req/s does the variadic parsing take away?
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.
Edit: There is a drop in performance. See below #1636 (comment)
You know what, the perf difference is actually negligible.
I did a load test before and I remember getting around 100 req/s
less but I must have made a mistake. I was calling an add_them
func with 10 args.
It's still a nice refactor I guess 😄
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, I get ~1990 req/s
for an /rpc/add_them?a=1&b=2&c=3&d=4&e=5
.
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.
With the code you have in this PR, you could compare the following 3 functions/requests:
-- call with: GET /rpc/add_them1?a=1&b=2&c=3&d=4&e=5
-- will take the "if not pdHasVariadic" path
CREATE FUNCTION add_them1(a int, b int, c int, d int, e int) RETURNS int
LANGUAGE SQL AS $$
SELECT a+b+c+d+e
$$;
-- call with: GET /rpc/add_them2?a=1&b=2&c=3&d=4&e=5
-- will take the "else" path - but is actually not a variadic function (the variadic arg will be ignored, it has a default value)
CREATE FUNCTION add_them2(a int, b int, c int, d int, e int, VARIADIC v int[] DEFAULT '{}') RETURNS int
LANGUAGE SQL AS $$
SELECT a+b+c+d+e
$$;
-- call with: GET /rpc/add_them3?v=1&v=2&v=3&v=4&v=5
-- will take the "else" path - and is really variadic
CREATE FUNCTION add_them3(VARIADIC v int[]) RETURNS int
LANGUAGE SQL AS $$
-- no SUM or anything on purpose to be as much comparable to the other funcs as possible
SELECT v[1]+v[2]+v[3]+v[4]+v[5]
$$;
This should give us a really good idea whether the variadic branch is in fact slower or not.
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.
It's still a nice refactor I guess smile
With most of the refactor I absolutely agree, yes! But if the variadic branch was not really slower, then this branching (and adding the hasVariadic
stuff) would just increase the complexity of the code (one indication of that would be the need for #1639 to make things consistent again).
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.
addthem2 is not working (need to add
v=5
). Should it work with #1639?
I tested this and I'm pretty sure we hit a postgres bug here.
Filed a bug report here: https://www.postgresql.org/message-id/[email protected]
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.
Made new 7 load tests with the corrected addthem2:
addthem2
(1923 + 1908 + 1897 + 1892 + 1911 + 1915 + 1904)/7 = 1907
Seems to be the slowest code path(not sure why).
So the non-variadic path remains to be the fastest.
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.
Filed a bug report here: https://www.postgresql.org/message-id/[email protected]
@wolfgangwalther Nice! I see you already got some replies.
So if it's a pg bug, would there be anything to add on this PR?
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.
Seems to bit the slowest code path(not sure why).
This might be because it's now 6 params instead of 5 that have to be parsed. So you can't really compare it to the first addthem1 you ran, but only to the 2nd modified example I gave, that has 6 params as well.
Anyway, I think it's fine to keep the non-variadic path.
So if it's a pg bug, would there be anything to add on this PR?
Not sure whether they will agree to call it a bug or rather a "limitation". It's currently not possible to call the function in PG that way, so I think we are fine with where we are. If you want to use such a function you can always add an overload that does not have the variadic part - and then everything will work.
Nothing to do here for us right 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.
Got it. Then I'll merge!
@@ -45,6 +49,7 @@ toMime CTTextCSV = "text/csv" | |||
toMime CTTextPlain = "text/plain" | |||
toMime CTOpenAPI = "application/openapi+json" | |||
toMime CTSingularJSON = "application/vnd.pgrst.object+json" | |||
toMime CTUrlEncoded = "application/x-www-form-urlencoded" |
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.
Code coverage drops because of this line. Is this ever going to be used? This would only be needed to return this mimetype, right? I doubt that will ever be the case.
BTW, that's the same case for the CTAny
line below.
If our goal was to increase code coverage (not only technically but also for a nice number :D), this would be some simple things to do.
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.
Hmm.. yeah, it's unused.
How would I go about that? Just delete the lines? Not sure if the compiler would like that..
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.
Yeah, you're right. I didn't think that to the end. But for the code coverage stuff to be useful, we'll have to find a way to "remove" those false alarms, otherwise it's a pain to check for the important stuff.
It looks like the tool for the job are hpc "overlays". I will dig into this further once I find a bit of time and see what we can do.
On #1603, logic for using VARIADIC functions was added. However that logic is also executed for every non-variadic function.
This PR changes that. By adding a cached
pdHasVariadic
toProcDescription
we avoid extra steps for non-variadic functions.Besides that:
/rpc/func?arg1=val1&arg2=val2
to json in a single function. This makes that part of the code more understandable IMO.pgrst.accept
setting to RPC #1582.charset=uft-8
on binary output. Reported on gitter chat.