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

Implement thread-local scope for rate limiters and improve spec format #1928

Merged
merged 4 commits into from Apr 16, 2024

Conversation

jshook
Copy link
Contributor

@jshook jshook commented Apr 16, 2024

This PR implements an optional scope specifier on rate limiters which can control whether a rate limiter is applied across all combined operations of an activity, or alternately, instanced per-thread using ThreadLocal.

Updates to thread-scoped rate limiters are not supported yet, but this can be added by adding event propagation for those configuration events into the component tree's event routing.

Each rate limiter is a full implementation as before, which includes a fully-separate instance of a semaphore and a tasking thread to keep filling the token bucket. As such, many such per-thread rate limiters will consume incrementally more resources, so running thousands of them is not advised.

The session logs below will explain the behavior and formats that need to be documented.

10 threads running at 1 op/s each

(each because of scope thread)

# nb5 run driver=diag cycles=100 rate=1,thread --progress=console:1s threads=10
DIAG0 (pending,current,complete)=(90,0,10) 10.00%
DIAG0 (pending,current,complete)=(80,0,20) 20.00%
DIAG0 (pending,current,complete)=(70,0,30) 30.00%
DIAG0 (pending,current,complete)=(60,0,40) 40.00%
DIAG0 (pending,current,complete)=(50,0,50) 50.00%
DIAG0 (pending,current,complete)=(40,0,60) 60.00%
DIAG0 (pending,current,complete)=(30,0,70) 70.00%
DIAG0 (pending,current,complete)=(20,0,80) 80.00%
DIAG0 (pending,current,complete)=(10,0,90) 90.00%
DIAG0 (pending,current,complete)=(0,0,100) 100.00% (last report)

1 thread running at 10 ops/s

# nb5 run driver=diag cycles=100 rate=10,thread --progress=console:1s threads=1
DIAG0 (pending,current,complete)=(97,0,3) 3.00%
DIAG0 (pending,current,complete)=(87,0,13) 13.00%
DIAG0 (pending,current,complete)=(77,0,23) 23.00%
DIAG0 (pending,current,complete)=(67,0,33) 33.00%
DIAG0 (pending,current,complete)=(57,0,43) 43.00%
DIAG0 (pending,current,complete)=(47,0,53) 53.00%
DIAG0 (pending,current,complete)=(37,0,63) 63.00%
DIAG0 (pending,current,complete)=(27,0,73) 73.00%
DIAG0 (pending,current,complete)=(17,0,83) 83.00%
DIAG0 (pending,current,complete)=(7,0,93) 93.00%
DIAG0 (pending,current,complete)=(0,0,100) 100.00% (last report)

5 threads running at 5 ops/s each

(each because of scope thread)

# nb5 run driver=diag cycles=100 rate=5,thread --progress=console:1s threads=5
DIAG0 (pending,current,complete)=(90,0,10) 10.00%
DIAG0 (pending,current,complete)=(65,0,35) 35.00%
DIAG0 (pending,current,complete)=(40,0,60) 60.00%
DIAG0 (pending,current,complete)=(15,0,85) 85.00%
DIAG0 (pending,current,complete)=(0,0,100) 100.00% (last report)

5 threads running at 5 ops/s aggregate (default behavior)

(aggregate because of scope activity)

nb5 run driver=diag cycles=100 rate=5,activity --progress=console:1s threads=5
DIAG0 (pending,current,complete)=(97,0,3) 3.00%
DIAG0 (pending,current,complete)=(92,0,8) 8.00%
DIAG0 (pending,current,complete)=(87,0,13) 13.00%
DIAG0 (pending,current,complete)=(82,0,18) 18.00%
DIAG0 (pending,current,complete)=(77,0,23) 23.00%
DIAG0 (pending,current,complete)=(72,0,28) 28.00%
DIAG0 (pending,current,complete)=(67,0,33) 33.00%
DIAG0 (pending,current,complete)=(62,0,38) 38.00%
DIAG0 (pending,current,complete)=(57,0,43) 43.00%
DIAG0 (pending,current,complete)=(52,0,48) 48.00%
DIAG0 (pending,current,complete)=(47,0,53) 53.00%
DIAG0 (pending,current,complete)=(42,0,58) 58.00%
DIAG0 (pending,current,complete)=(37,0,63) 63.00%
DIAG0 (pending,current,complete)=(32,0,68) 68.00%
DIAG0 (pending,current,complete)=(27,0,73) 73.00%
DIAG0 (pending,current,complete)=(22,0,78) 78.00%
DIAG0 (pending,current,complete)=(17,0,83) 83.00%
DIAG0 (pending,current,complete)=(12,0,88) 88.00%
DIAG0 (pending,current,complete)=(7,0,93) 93.00%
DIAG0 (pending,current,complete)=(2,0,98) 98.00%
DIAG0 (pending,current,complete)=(0,0,100) 100.00% (last report)

error message for incorrect rate spec

# nb5 run driver=diag cycles=100 rate=5,wrong --progress=console:1s threads=5
    3051 ERROR [main] NBINVOKE     error   [CMD_run {container="default", REDACTED REDACTED}: io.nosqlbench.nb.api.errors.BasicError: Spec format '5,wrong' was not recognized for CycleRateSpec.
Use the format <ops/s>[,<burst ratio][,<verb>][,<scope>]
Examples:
 100 (100 ops per second)
 100,1.1 (with a burst ratio of 10% over)
 100,start (start the rate limiter automatically)
 100,thread (scope the rate limiter to each thread in an activity)
 100,1.1,start,thread (all of the above)
Defaults: burst_ratio=1.1 verb=start scope=activity

@jshook jshook changed the title Nosqlbench 1323 tlrate Implement thread-local scope for rate limiters and improve spec format Apr 16, 2024
Copy link
Contributor

@yabinmeng yabinmeng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Collaborator

@MarkWolters MarkWolters left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jshook jshook merged commit c2aa0bf into main Apr 16, 2024
5 checks passed
@jshook jshook deleted the nosqlbench-1323-tlrate branch April 16, 2024 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants