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

Expirement with cas for doubles #62

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

deadtrickster
Copy link
Owner

@deadtrickster deadtrickster commented Apr 28, 2017

Now for handling doubles prometheus.erl uses gen_server (because there is no ets:update_counter for doubles). This PR intended to provide nif based alternative for gen_server.

Benchmark for ets:update_counter-based counter:

Running single counter benchmark:
  Pids: 1
  Iterations: 1000000
  Expected Value: 1000000
  Duration (sec): 0.22 (100.0%)
  Counter value: 1000000
Running single counter benchmark:
  Pids: 5
  Iterations: 1000000
  Expected Value: 6000000
  Duration (sec): 0.398 (100.0%)
  Counter value: 6000000
Running single counter benchmark:
  Pids: 10
  Iterations: 1000000
  Expected Value: 16000000
  Duration (sec): 0.74 (100.0%)
  Counter value: 16000000
Running single counter benchmark:
  Pids: 100
  Iterations: 1000000
  Expected Value: 116000000
  Duration (sec): 7.231 (100.0%)
  Counter value: 116000000
Finished

Results for dinc (without call_timeout adjusted):

Running single counter benchmark:
  Pids: 1
  Iterations: 1000000
  Expected Value: 1000000
  Duration (sec): 0.885 (100.0%)
  Counter value: 1000000
Running single counter benchmark:
  Pids: 5
  Iterations: 1000000
  Expected Value: 6000000
  Duration (sec): 7.3 (100.0%))
  Counter value: 2182338
Running single counter benchmark:
  Pids: 10
  Iterations: 1000000
  Expected Value: 16000000
  Duration (sec): 15.367 (100.0%)
  Counter value: 7739012

Results for double + atomic_compare_exchange_strong

Running single counter benchmark:
  Pids: 1
  Iterations: 1000000
  Expected Value: 1000000
  Duration (sec): 0.043 (100.0%)
  Counter value: 1000000
Running single counter benchmark:
  Pids: 5
  Iterations: 1000000
  Expected Value: 6000000
  Duration (sec): 0.382 (100.0%)
  Counter value: 6000000
Running single counter benchmark:
  Pids: 10
  Iterations: 1000000
  Expected Value: 16000000
  Duration (sec): 0.79 (100.0%)
  Counter value: 16000000
Running single counter benchmark:
  Pids: 100
  Iterations: 1000000
  Expected Value: 116000000
  Duration (sec): 8.237 (100.0%)
  Counter value: 116000000
Finished

cc @benoitc

@deadtrickster
Copy link
Owner Author

So there is no big speed difference, and in theory dincs can be removed entirely.
OTOH doubles are finite on both ERTS and C sides while int counters currently not.
And we going NIF-way inc can be implemented with fetch_and_add.

However:
CAS loop can be very long - we can block scheduler.
Current NIF benchmark doesn't perform counter resolving - this has to be done as ETS lookup
with possible optimization (like Benoit does) - provide with wrapper and store resource in process-dict.
Also on lookups - first metric use looks now like this:
inc -> badarg -> insert_metric, Next call: just inc (ets:update_counter)
first call when using nif:
inc -> no_resource -> create_resource -> insert to ets -> increment
Next call -> ets:lookup -> increment.
And with replaces ets:lookup with get and adds put to the first call.

@deadtrickster
Copy link
Owner Author

Since dirty nifs are experimental I need to limit number of cas iterations and add loop inside incr_counter on erlang side to allow context switching

@deadtrickster deadtrickster mentioned this pull request May 3, 2017
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant