Debouncing & Throttling for taming high frequency code execution

Debouncing and Throttling are two common strategies to tame the code execution that handles high frequency events.

Debouncing & Throttling for taming high frequency code execution
Photo by Josh Calabrese / Unsplash

Debouncing and Throttling are two common strategies to tame the code execution that handles high frequency events.

Like, for instance, keyboard typing. Or mouse movement. Or animation frame changes. Or resizing. Or scrolling. Or zooming. Or... you get the idea.

So what are they and what's the difference between the two?

Throttling

Means execute not more than once every X seconds (or milliseconds, or any time span) while the high-frequency event is happening. Plus the first, initial call.

stateDiagram-v2
  [*] --> A
  A --> B
  B --> C
  C --> D
  D --> E
  E --> F
  F --> [*]

  [*] --> C :Throttle
  C --> F :Throttle
  F --> [*] :Throttle

So, for instance, throttling at 0.5 seconds, means that even if I invoke the execution 42 times in 1 second, it'll actually be executed only 3 times: once every 0.5 seconds + the initial call.

timeline
  title Throttling @ 0.5 seconds
  0s    : Normal, initial, Execution Call โœ…
        : Throttled, initial, Execution Call โœ…
  0.1s  : Normal Execution Call โœ…
        : Throttled Execution Call ๐Ÿ›‘
  0.3s  : Normal Execution Call โœ…
        : Throttled Execution Call ๐Ÿ›‘
  0.5s  : (No explicit execution call)
        : Throttled Execution Call โœ…
  0.7s  : Normal Execution Call โœ…
        : Throttled Execution Call ๐Ÿ›‘
  0.95s : Normal Execution Call โœ…
        : Throttled Execution Call ๐Ÿ›‘
  1.0s  : Normal Execution Call โœ…
        : Throttled Execution Call โœ…

Debouncing

Means don't execute at all while the high-frequency event is happening. Execute only afterwards. Not even the initial call.

stateDiagram-v2
  [*] --> A
  A --> B
  B --> C
  C --> D
  D --> E
  E --> F
  F --> [*]

  [*] --> [*] :Debounce

So, for instance, debouncing at 0.5 seconds, means that even if I invoke the execution 42 times in 1 second, it'll actually be executed exactly 1 time, 0.5 seconds after the high-frequency has stopped, so after 1.5 seconds.

timeline
  title Debouncing @ 0.5 seconds
  0s    : Normal, initial, Execution Call โœ…
        : Debounced Execution Call ๐Ÿ›‘
  0.1s  : Normal Execution Call โœ…
        : Debounced Execution Call ๐Ÿ›‘
  0.3s  : Normal Execution Call โœ…
        : Debounced Execution Call ๐Ÿ›‘
  0.7s  : Normal Execution Call โœ…
        : Debounced Execution Call ๐Ÿ›‘
  0.95s : Normal Execution Call โœ…
        : Debounced Execution Call ๐Ÿ›‘
  1.0s  : Normal Execution Call โœ…
        : Debounced Execution Call ๐Ÿ›‘
  1.5s  : (No explicit execution call)
        : Debounced Execution Call โœ…

Usage

dotnet add package H.Necessaire

H.Necessaire

highFrequencyEventDaemon.OnHighFrequencyEvent += NormalExecution;
highFrequencyEventDaemon.OnHighFrequencyEvent += ThrottledExecution;
highFrequencyEventDaemon.OnHighFrequencyEvent += DebouncedExecution;

await highFrequencyEventDaemon.Start();

StopDaemonAfter(highFrequencyEventDaemon, TimeSpan.FromSeconds(3));

Debounced and Throttled execution setup gist

static async Task NormalExecution(object sender, EventArgs ev)
{
    await Console.Out.WriteAsync('_');
}

Normal execution

static readonly Throttler throttler = new Throttler(async () => await Console.Out.WriteAsync("_Tht"), TimeSpan.FromSeconds(.35));
static async Task ThrottledExecution(object sender, EventArgs ev)
{
    await throttler.Invoke();
}

Throttled execution

static readonly Debouncer debouncer = new Debouncer(async () => await Console.Out.WriteAsync("_Dbc"), TimeSpan.FromSeconds(.35));
static async Task DebouncedExecution(object sender, EventArgs ev)
{
    await debouncer.Invoke();
}

Debounced execution

Running... press Ctrl+C to stop.
__Tht___________________Tht_____________________Tht________________________Tht_______________________Tht________________________Tht______________________Tht________________________Tht_______________________Tht__________Tht_Dbc

Console output

Full implementation on GitHub Samples repo

H.Necessaire.Usage.Samples/Src/H.Necessaire.Samples/H.Necessaire.Samples.ThrottleAndDebounce/Program.cs at master ยท hinteadan/H.Necessaire.Usage.Samples
Usage Samples for H.Necessaire Docs WebSite. Contribute to hinteadan/H.Necessaire.Usage.Samples development by creating an account on GitHub.