# Demonstrate the effects of a slow stream (that's causing a build up of
# waiting requests) being disconnected. This test is similar to the one in
# range_controller_single_slow_stream, except the slow stream is eventually
# disconnected.

init
handle=h
----

# Set up a triply connected handle (to s1, s2, s3) and start issuing writes at
# 1MiB/s. For two of the streams, return tokens at exactly the rate its being
# deducted (1MiB/s). For the third stream (s3), we return flow tokens at only
# 0.5MiB/s. At t=35s, disconnect the slow stream.
timeline
t=0s       handle=h op=connect    stream=t1/s1
t=0s       handle=h op=connect    stream=t1/s2
t=0s       handle=h op=connect    stream=t1/s3
t=[0s,50s) handle=h class=regular adjust=-1MiB/s   rate=10/s
t=[0s,50s) handle=h class=regular adjust=+1MiB/s   rate=10/s stream=t1/s1
t=[0s,50s) handle=h class=regular adjust=+1MiB/s   rate=10/s stream=t1/s2
t=[0s,35s) handle=h class=regular adjust=+0.5MiB/s rate=10/s stream=t1/s3
t=35s      handle=h op=disconnect stream=t1/s3
----

simulate
----

# Zoom in near the point where writes are being shaped by the slowest stream
# (s3, at 0.5MiB/s). We see the blocked stream count bouncing between 0 and 1
# as tokens get depleted and replenished (demand here is higher than the
# replenishment rate).
#
# As soon as s3 is disconnected, we see a release of 16MiB of held tokens back
# into the node-level controller (32MiB -> 48MiB). We see a burst in the number
# of stream-specific requests bypassing Admit() due to the stream
# disconnecting. At the handle-level this just appears as a burst in admitted
# requests. After s3 disconnects, the handle-level admission rate goes back to
# what it was before traffic was shaped by s3.
#
# TODO(kvoli,sumeerbhola): The post-stream disconnection burst might lead to
# severe over-admission since it may have been long since we observed available
# tokens for the still connected streams. In fact, many requests that started
# waiting on the soon-to-be-disconnected-stream are in the same boat, all of
# which will now get admitted. One thing we could do is to try and observe
# available tokens again for still-connected streams.
plot t=[30s,40s)
kvflowcontrol.streams.eval.regular.blocked_count                   unit=streams
kvflowcontrol.tokens.eval.regular.available                        unit=MiB
kvflowcontrol.eval_wait.elastic.requests.bypassed                  unit=reqs/s rate=true
kvflowcontrol.eval_wait.regular.requests.{admitted,waiting}        unit=reqs/s rate=true
kvflowcontrol.tokens.{eval,send}.regular.returned.disconnect       unit=MiB
----
----
 1.0 ┤            ╭╮
 0.9 ┤            ││
 0.9 ┤        ╭╮  ││  ╭╮
 0.8 ┤        ││  ││  ││
 0.7 ┤        ││  ││  ││
 0.7 ┤        ││  ││  ││
 0.6 ┤        │╰╮ ││ ╭╯│
 0.5 ┤        │ │ ││ │ │
 0.5 ┤        │ │╭╯╰╮│ │
 0.4 ┤        │ ││  ││ │
 0.3 ┤       ╭╯ ││  ││ ╰╮
 0.3 ┤       │  ││  ││  │
 0.2 ┤       │  ││  ││  ╰╮
 0.1 ┤       │  ││  ││   │
 0.1 ┤       │  ╰╯  ╰╯   │
 0.0 ┼───────╯           ╰───────────────────
      streams.eval.regular.blocked_count (streams)


 48.0 ┤                   ╭───────────────────
 46.9 ┤                   │
 45.9 ┤                   │
 44.8 ┤                   │
 43.7 ┤                   │
 42.6 ┤                   │
 41.6 ┤                   │
 40.5 ┤                   │
 39.4 ┤                   │
 38.3 ┤                   │
 37.3 ┤                   │
 36.2 ┤                   │
 35.1 ┤                   │
 34.0 ┤                   │
 33.0 ┼─╮                 │
 31.9 ┤ ╰─────────────────╯
         tokens.eval.regular.available (MiB)


 0.0 ┼───────────────────────────────────────
      rate(eval_wait.elastic.requests.bypassed) (reqs/s)


  25.0 ┤                     ╭─╮
  22.3 ┤                    ╭╯ │
  19.7 ┤                    │  │
  17.0 ┤                   ╭╯  │
  14.3 ┤                   │   │
  11.7 ┼───────╮           │   ╰───────────────
   9.0 ┤       ╰─╮         │
   6.3 ┤         ╰╭────────╮
   3.7 ┤        ╭─╯        │
   1.0 ┼────────╯          │   ╭───────────────
  -1.7 ┤                   │   │
  -4.3 ┤                   │   │
  -7.0 ┤                   ╰╮  │
  -9.7 ┤                    │  │
 -12.3 ┤                    ╰─╮│
 -15.0 ┤                      ╰╯
        rate(eval_wait.regular.requests.{admitted,waiting}) (reqs/s)


 16.1 ┤                   ╭───────────────────
 15.0 ┤                   │
 14.0 ┤                   │
 12.9 ┤                   │
 11.8 ┤                   │
 10.7 ┤                   │
  9.7 ┤                   │
  8.6 ┤                   │
  7.5 ┤                   │
  6.4 ┤                   │
  5.4 ┤                   │
  4.3 ┤                   │
  3.2 ┤                   │
  2.1 ┤                   │
  1.1 ┤                   │
  0.0 ┼───────────────────╯
       tokens.{eval,send}.regular.returned.disconnect (MiB)
----
----

# vim:ft=conf
