Skip to content
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

Release 0.17.0 #458

Closed
7 of 9 tasks
miry opened this issue Dec 13, 2022 · 3 comments
Closed
7 of 9 tasks

Release 0.17.0 #458

miry opened this issue Dec 13, 2022 · 3 comments
Assignees
Labels

Comments

@miry miry added the Semian label Dec 13, 2022
@miry miry self-assigned this Dec 13, 2022
@miry
Copy link
Contributor Author

miry commented Jan 26, 2023

Performance report

Current version has main 2 performance improvements.
It will not be visible in small application,
but could be effective for application with a lot of client requests.

  1. Remove checking if semian disabled on each acquire

image

potentially saves latency and extra calls of ENV per each client request (4 calls less).

  1. Replace Time.now with Monotonic clock

image

Improve performance of execution Semian::CircuitBreaker#transition_to_half_open? by 25%.

In total execution of Semian::CircuitBreaker#acquire decreased from 41ms to 30ms.

@miry
Copy link
Contributor Author

miry commented Feb 6, 2023

Tested new changes on my project. It required to update tests to not just freeze realtime, but also monotonic.

Found activerecord with opentelemetry uses different kind of invokes clock_gettime:

# frozen_string_literal: true

module TimeHelper
  def time_travel(val)
    now_monotonic = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    now_realtime_nanosec = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond)
    now_timestamp = Time.now
    now_zone_timestamp = Time.zone.now
    cpu_thread_cputime_id = Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID)

    new_monotonic = now_monotonic + val
    Process.stubs(:clock_gettime).with(Process::CLOCK_MONOTONIC).returns(new_monotonic)
    Process.stubs(:clock_gettime).with(Process::CLOCK_MONOTONIC, :float_millisecond).returns(new_monotonic*1000)
    Process.stubs(:clock_gettime).with(Process::CLOCK_MONOTONIC, :nanosecond).returns((new_monotonic*(10**9)).to_i)
    Process.stubs(:clock_gettime).with(Process::CLOCK_REALTIME, :nanosecond).returns(now_realtime_nanosec)
    Process.stubs(:clock_gettime).with(Process::CLOCK_THREAD_CPUTIME_ID).returns(cpu_thread_cputime_id)
    Process.stubs(:clock_gettime).with(Process::CLOCK_THREAD_CPUTIME_ID, :float_millisecond).returns(cpu_thread_cputime_id*1000)

    new_timestamp = now_timestamp + val
    Time.stubs(:now).returns(new_timestamp)

    now_zone_timestamp = now_zone_timestamp + val
    Time.zone.stubs(:now).returns(now_zone_timestamp)

    yield
  ensure
    Time.zone.unstub(:now)
    Time.unstub(:now)
    Process.unstub(:clock_gettime)
  end
end

@miry
Copy link
Contributor Author

miry commented Feb 7, 2023

Tested semian on our biggest private repo. Tests were passed. Going to release a new version tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant