-
Notifications
You must be signed in to change notification settings - Fork 21.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
Fix calculation of SQL runtime #50767
Conversation
cc @fatkodima |
So this just reverts the change made in #50493.
|
Yes, but the bug must be elsewhere. |
@fatkodima if you can provide a sample repository where I can investigate the misbehaviour I am willing to help. If you check the referenced code, seconds is what we receive from the monotonic subscribe, you can test that in a new Rails app too. Our application was showing the contrary behaviour. Using the changes in this PR, DB time displayed from the queries matched the total time for ActiveRecord. Without these changes, DB time displayed was several milliseconds, however ActiveRecord would always display |
https://github.com/fatkodima/test_app When hit
|
When async is not used, the numbers are correct. User Load (0.5ms) SELECT "users".* FROM "users"
↳ app/views/users/index.html.erb:2
Rendered users/index.html.erb within layouts/application (Duration: 1.1ms | Allocations: 858)
Rendered layout layouts/application.html.erb (Duration: 4.0ms | Allocations: 2663)
Completed 200 OK in 6ms (Views: 4.0ms | ActiveRecord: 0.5ms | Allocations: 4297) So the PR you previously proposed breaks sync in order to fix the async. So, in my opinion, the fix does not belong here. I am going to investigate where the wrong value comes from and will hopefully have a fix ready soon. |
@byroot I think I have found out the origin of the issue, but I can't figure out an easy fix for it. I'll explain although I think it's simple:
I think the issue is not local to this, but broader due to the existing inconsistency in the unit used to measure time. Other example that makes me thing something is not too right. Given this script. republished = false
ActiveSupport::Notifications.monotonic_subscribe("test") do |name, start, finish, id, payload|
puts "subscriber using start and finish ===="
puts start
puts finish
end
ActiveSupport::Notifications.monotonic_subscribe("test") do |event|
puts "subscriber using event ===="
puts event.time
puts event.end
republished_was = republished
republished = true
unless republished_was
puts "Republishing..."
ActiveSupport::Notifications.publish_event(event) unless republished_was
end
end
ActiveSupport::Notifications.instrument("test") do
sleep(1)
end This is the output: subscriber using start and finish ====
4108.368805
4109.369614
subscriber using event ====
4108368.826
4109369.962
Republishing...
subscriber using start and finish ====
4108368.826
4109369.962
subscriber using event ====
4108368.826
4109369.962 |
Good catch. Should be easy to fix. |
I came up with the following solution, which seems like works diff --git a/activerecord/lib/active_record/runtime_registry.rb b/activerecord/lib/active_record/runtime_registry.rb
index 408b36c3aa..03742b3ba4 100644
--- a/activerecord/lib/active_record/runtime_registry.rb
+++ b/activerecord/lib/active_record/runtime_registry.rb
@@ -34,7 +34,7 @@ def reset
end
ActiveSupport::Notifications.monotonic_subscribe("sql.active_record") do |name, start, finish, id, payload|
- runtime = (finish - start) * 1_000.0
+ runtime = finish - start
if payload[:async]
ActiveRecord::RuntimeRegistry.async_sql_runtime += (runtime - payload[:lock_wait])
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb
index af70faf407..0a3299ad91 100644
--- a/activesupport/lib/active_support/notifications/fanout.rb
+++ b/activesupport/lib/active_support/notifications/fanout.rb
@@ -139,14 +139,14 @@ def finish(name, id, payload)
class MonotonicTimedGroup < BaseTimeGroup # :nodoc:
private
def now
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
end
end
class TimedGroup < BaseTimeGroup # :nodoc:
private
def now
- Time.now
+ Time.now.to_f * 1000
end
end So we use milliseconds everywhere. I am not very familiar with AS::Notifications internals, so maybe this is not a correct/best fix. |
I have been in conversation with @byroot and we agree on unifying units as best solution. Said that, Rails documentation would need to be amended if we do so as this would be a major change (started/finished are supposed to be time objects when subscribe is used), so probably it's better to change the other place (Event) not to use milliseconds but seconds. |
The key is to unify unit internally and to do conversions as needed to keep public interfaces unchanged. |
Ref: rails#43502 Fix: rails#50767 Fix: rails#50493 When republishing a an event into a `start, finish` tuple, we need to convert the timestamps back into seconds.
Ref: rails#43502 Fix: rails#50767 Fix: rails#50493 When republishing a an event into a `start, finish` tuple, we need to convert the timestamps back into seconds.
Motivation / Background
This Pull Request has been created because this other PR seems to have introduced a bug in the
db_runtime
emitted as part ofsql.active_record
notification.The time is calculated using
ActiveSupport::Notifications.monotonic_subscribe
which uses Process.clock_gettime(Process::CLOCK_MONOTONIC) with the default unit (seconds).This being run in a Rails console prints 1.
Also, when an
ActiveSupport::Notifications::Event
is used, it needs to multiply start and ending by1_000.0
same as we are proposing here.Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]