<enebo[m]>
I will update this gist as I get more results
<headius>
try update and see if MRI is even close to us
<headius>
for me it is like two orders of magnitude slower
<enebo[m]>
ok I am running indy on same bench for us atm
<headius>
I am trying to get 2.7 installed but it is not compatible with openssl 3
<headius>
lord how do people deal with this env
<enebo[m]>
JRuby updated in gist
<enebo[m]>
HAHAHA
<headius>
you see how the rehearsals just slow down?
<enebo[m]>
it is slowing down in real time in rehearsal
<enebo[m]>
Something is growing here
<enebo[m]>
This update I think is a weird form
<enebo[m]>
because it is a hash update
<enebo[m]>
and I don't think this is how people normally update data
<headius>
hmm
<headius>
maybe?
<enebo[m]>
I have to wonder if this is just no finalizing a ocmmit
<headius>
I tried putting all the updates in transactions and it did not change
<headius>
transaction per iter
<headius>
landing now but I will be working on this until I get something I can use
<headius>
2.7.6 behaves the same
<headius>
bbiab
<enebo[m]>
headius: I believe I have part of the answer. I moved the ```record = BenchRecord.create.reload``` into the block and that obviously slowed down the bench a lot but I no longer see any slow down
<enebo[m]>
So what I am pretty sure is happening is JRuby is implicit commit on update and MRI is saving all these changes and then going through them all some day
<enebo[m]>
so the perf difference is a fucking ginormous changeset which is never applied
<enebo[m]>
kares: So whatever reason .update(hash) is not committing and it is just growing some massive set of changes
<enebo[m]>
I changed it to record.send(field + "=", value); record.save! and we got reasonable behavior from MRI
<enebo[m]>
Ultimately I think this bench should be record.a_boolean = true; record.save! with one measure per field
<headius>
I will try doing the save with the hash version of the update and hopefully that will also fix it
<headius>
We really don't need these benchmarks to be quite so meta so we could just hard code them to the field names
<headius>
Or for Pete's sake, aren't there good benchmarks out there for active record yet?
<headius>
yeah it is something weird with the hash update version
<headius>
I wonder why we don't slow down
<headius>
enebo: save! isn't needed to fix the slowdown, just switching to the send version eliminates the problem
<headius>
but of course it is not saving, and save cuts the IPS way down
<headius>
we are still comfortably 2x faster in both cases but who knows if this bench is still valid
<headius>
it's doing something
subbu has joined #jruby
subbu has quit [Ping timeout: 260 seconds]
subbu has joined #jruby
subbu has quit [Quit: Leaving]
<kares[m]>
<enebo[m]> "kares: So whatever reason ...." <- hmm I guess it detects no changed are made - the previous code with multiple record entries tried to get smart about this
<kares[m]>
<enebo[m]> "I changed it to record.send(..." <- that should be the same as update! field -> value ... which is pretty much update field -> value but with a raise if validation fails
<kares[m]>
guess the best approach here would be to have enough records up front to update ...
<kares[m]>
that or making sure the value always changes - but that could interfere as to how expensive the op to generate the next value is
<kares[m]>
think it's best to rely on the create use-case for AR ... the update use-case is still relevant in terms of Ruby perf -> most ops end up no-op in terms of a DB operation
<headius>
I'm going to hit up a few folks this week and see if I can figure out what they're using to optimize active record on the rails side
<headius>
There's got to be better benchmarks that are known to work properly and test these things
<headius>
For what it's worth the update benchmark seems to be the only problematic one
<kares[m]>
yeah I looked at some Rails benchmarks but the update code isn't better
<headius>
It's just the one that most interested in because it would create the least amount of objects
<kares[m]>
yeah - one think we could do is disable the dirty tracking ... it would mess with AR internals a bit but would make sure each change is considered a DB operation
<headius>
is that something we are doing differently than the CRuby code?
<headius>
The update numbers might be affected by that but I am seeing a similar 2:1 ratio for selects too... we seem to be doing very well on overall AR perf
<headius>
the end to end view numbers are not 2x but still comfortably ahead
<kares[m]>
this enforces the update operation and numbers should be more realistic ...
<kares[m]>
JRuby is faster than MRI, except for the `update!(all_fields)` case, which is interesting.
<kares[m]>
indy is almost double the speed of non-indy except again the `update(all_fields)` case which seems to degrade compare to non-indy (must be a lot of invalidation going on or what not)
<kares[m]>
enebo: not sure how the `record.send(field + '=', value); save!` trick worked - would have expected that to not issue an update if record stayed the same
<kares[m]>
the PR I mentioned above achieves the forced DB update with some dirty AR tricks
<kares[m]>
literally dirty tricks ... so I guess it's dirty dirty AR tricks 😉
<enebo[m]>
kares: so if MRI realizes it is the same value it saves it somewhere and keeps growing smoething?
<enebo[m]>
That is what I am confused about. Why would it get progressively slower with update unless it was saving that state into something which is continuously growing?
<enebo[m]>
My wife said the same thing to me this morning that it detecting no change may mean no operation but that does not explain the continual slowdown
<enebo[m]>
and save! might not be changing the db but without save! the results were millions of i/s which is consistent with no updating. save! brought it back into the ballpark of other results (although maybe a little higher)
<enebo[m]>
I guess one other thing she said was record.field = also performs validation but I would assume update{,!} does too
<headius>
good morning
<headius>
kares: the numbers in that PR still slow down as they progress and are an order of magnitude slower than the JRuby results for most of them
<enebo[m]>
headius: Since you must have ran that can you look at memory of that process
<headius>
the results with enebo's send seem more naturally 2x or so and don't slow down linearly
<enebo[m]>
I never bothered because the behavior seems like it must just be a growing array
<headius>
enebo: that's a thought... I can reset your changes locally and see about the memory
<enebo[m]>
I cannot really think of anything else which explains a slow down like that
<enebo[m]>
some data structure is just growing and never cleaning up
<enebo[m]>
headius: so update! is doing it as well?
<enebo[m]>
I had thought I tried that last night but I don't recall now
<kares[m]>
<enebo[m]> "My wife said the same thing to..." <- nice!
<headius>
I have not run the numbers in that PR but you can see them there
<headius>
the warmup phase has each case slower than the previous
<kares[m]>
<enebo[m]> "kares: so if MRI realizes it..." <- which one are you confused about here the `update(all_attrs)` seems like a bug to me - not sure what's going on underneath, the others I can explain 😉
<kares[m]>
a Rails bug of some kind - haven't looked really just assumed a growing internal Hash/Array somewhere would cause a liner slowdown
<enebo[m]>
yeah it must be a bug
<enebo[m]>
record.field = value is insanely fast without save so I assume that is not committing and not doing anything brcauise value is the same
<enebo[m]>
s/and/or
<kares[m]>
record.field = value is just an assingment ... there's update_attribute if you intent to also save
<enebo[m]>
It more or less is method call fast
<kares[m]>
even record.field = value; record.save! is going to be fast is you run it with the same value twice - only the first save will happen
<enebo[m]>
ok that is what my wife said at first...you can just use update_attribute
<kares[m]>
AR tracks the values and if they did not change in the record object save! is a noop
<enebo[m]>
but it is much much slower than a normal call
<enebo[m]>
So I guess that is just value tracking overhead
<kares[m]>
which one the update_attribute or the save?
<enebo[m]>
the save!
<enebo[m]>
Adding record.save! reduces results from 1M i/s to about 1600 i/s
<enebo[m]>
which is close to other results which are accessing the database
<enebo[m]>
but it may not actually be saving anything
<enebo[m]>
I just observed it is close to a db operation speed so I assumed it was
<kares[m]>
yep that's the bug - underneath `r.update(field => value)` and `r.field = value; r.save` are doing the same thing
<headius>
wow, graalvm community edition download for linux is 422MB