Debouncing, Throttling, Rate Limiting, and Exponential
Backoff
These are four techniques used to control the execution of
functions/events and handle load effectively. Each technique serves a specific
purpose and is applied differently, especially in performance-sensitive
scenarios.
1. Debouncing
Debouncing is a technique to ensure that a function
is only executed once after a specified period of inactivity. The event
keeps resetting the timer if it happens again within the delay.
Use Cases:
- Search
bar: Execute the search request only after the user stops typing for a
certain period.
- Resize
events: Trigger expensive layout calculations only when the user has
finished resizing the window.
How It Works:
- A
function is triggered, and a timer starts.
- If the
event is triggered again before the timer ends, the timer is reset.
- The
function will only be executed when no event has been triggered for the
delay period.
Java Example (Debouncing):
java
import
java.util.Timer; import
java.util.TimerTask; public class
Debouncer { private Timer timer = new Timer(); public void debounce(Runnable task, int
delay) { if (timer != null) { timer.cancel(); } timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { task.run(); } }, delay); } public static void main(String[] args) { Debouncer debouncer = new
Debouncer(); // Simulating typing action for (int i = 0; i < 5; i++) { debouncer.debounce(() ->
System.out.println("Search triggered"), 500); try { Thread.sleep(100); //
Simulate typing delay } catch (InterruptedException e)
{ e.printStackTrace(); } } } } |
In this example, the search is triggered after the user
stops typing for 500ms.
Debounce |
2. Throttling
Throttling ensures that a function is executed at
most once in a given time interval, no matter how many times the event is
triggered. This is useful when you want to control the rate of event execution.
Use Cases:
- Scroll
event: Limit the number of times an expensive function is executed
during a scroll event.
- API
calls: Ensure that the function/API is called at regular intervals
(e.g., every second), no matter how many times the user triggers it.
How It Works:
- A
function is triggered, and the next invocation is ignored until the
specified interval has passed.
Java Example (Throttling):
java
public class
Throttler { private long lastExecutionTime = 0; public void throttle(Runnable task, int
interval) { long currentTime =
System.currentTimeMillis(); if (currentTime - lastExecutionTime
>= interval) { lastExecutionTime = currentTime; task.run(); } } public static void main(String[] args) { Throttler throttler = new
Throttler(); // Simulating scroll action for (int i = 0; i < 10; i++) { throttler.throttle(() ->
System.out.println("Scroll triggered"), 1000); try { Thread.sleep(200); //
Simulate scroll event every 200ms } catch (InterruptedException e)
{ e.printStackTrace(); } } } } |
In this example, the Scroll triggered message is printed once
every 1000ms, even though the scroll event is happening every 200ms.
3. Rate Limiting
Rate Limiting controls the number of times an
action can be performed in a given time frame. This is commonly used in APIs to
prevent excessive requests that can overload the system.
Use Cases:
- API
requests: Ensure that an API can only be called a certain number of
times within a time frame (e.g., max 5 requests per second).
- Login
attempts: Prevent brute force attacks by limiting the number of login
attempts per minute.
How It Works:
- Limits
the number of executions within a time window. After the limit is reached,
no more executions are allowed until the window resets.
Java Example (Rate Limiting):
java
import
java.util.concurrent.TimeUnit; public class
RateLimiter { private final int maxRequests; private final long timeWindow; private int requestCount = 0; private long startTime; public RateLimiter(int maxRequests, long
timeWindow, TimeUnit unit) { this.maxRequests = maxRequests; this.timeWindow =
unit.toMillis(timeWindow); this.startTime =
System.currentTimeMillis(); } public synchronized boolean
allowRequest() { long currentTime =
System.currentTimeMillis(); if (currentTime - startTime >
timeWindow) { startTime = currentTime; requestCount = 0; } if (requestCount < maxRequests) { requestCount++; return true; } else { return false; } } public static void main(String[] args) { RateLimiter rateLimiter = new
RateLimiter(5, 1, TimeUnit.SECONDS); for (int i = 0; i < 10; i++) { if (rateLimiter.allowRequest()) {
System.out.println("Request allowed"); } else {
System.out.println("Request denied"); } try { Thread.sleep(200); //
Simulate request every 200ms } catch (InterruptedException e)
{ e.printStackTrace(); } } } } |
In this example, the rate limiter allows 5 requests per
second. Any additional requests are denied.
4. Exponential Backoff
Exponential Backoff is a retry strategy where the
wait time between retries increases exponentially, often used when handling
failures such as network timeouts or API rate limits.
Use Cases:
- Retrying
failed API requests: Increase the time between retries to avoid
overwhelming the server.
- Database
connection retries: If a database connection fails, retry with
increasing delays.
How It Works:
- On
failure, the wait time between retries increases exponentially (e.g., 1
second, 2 seconds, 4 seconds, etc.).
Java Example (Exponential Backoff):
java
public class
ExponentialBackoff { public void retryWithBackoff(Runnable
task, int maxRetries) { int retryCount = 0; int delay = 1000; // Initial delay in
milliseconds while (retryCount < maxRetries) { try { task.run(); System.out.println("Task
succeeded"); return; } catch (Exception e) { System.out.println("Task
failed, retrying in " + delay + "ms..."); try { Thread.sleep(delay); } catch (InterruptedException
ie) { ie.printStackTrace(); } delay *= 2; // Exponentially
increase the delay retryCount++; } } System.out.println("Max retries
reached. Task failed."); } public static void main(String[] args) { ExponentialBackoff backoff = new
ExponentialBackoff(); backoff.retryWithBackoff(() -> { if (Math.random() > 0.3) { throw new
RuntimeException("Simulated failure"); } }, 5); } } |
In this example, the task retries with exponentially
increasing delay times (1s, 2s, 4s, etc.) until it succeeds or the maximum
retry count is reached.
Summary Table
Feature |
Debouncing |
Throttling |
Rate Limiting |
Exponential Backoff |
Goal |
Delay function execution until
inactivity |
Limit function calls at a fixed
interval |
Limit number of executions in a time
frame |
Increase retry delay after each
failure |
Use Case |
Search input, resize events |
Scroll event, API polling |
API rate limits, login attempts |
Network retries, API failure
handling |
Execution Frequency |
Once after event inactivity |
Regular intervals during event
firing |
Limited to a number of times per
period |
Retries increase delay exponentially |
Example Scenario |
Trigger search only after user stops
typing |
Update UI at most every second
during scroll |
Allow max 5 requests per second |
Retry API request with increasing
delay |
Each of these techniques has a specific application depending on the type of event.
Scrolling interactions
One of the most common examples in timing functions is limiting the number of scroll events. Let's look at how many events scroll can generate with Live event:
Technique |
Event Count |
Last Execution |
Debounce |
0 |
N/A |
Throttle |
0 |
N/A |
Rate Limit |
0 |
N/A |
Exponential Backoff |
0 |
N/A |
Summary
This example demonstrates how to efficiently manage
scroll events using debouncing, throttling, rate limiting, and exponential
backoff. Each technique ensures better performance by controlling how
frequently a function executes during scrolling. You can apply these concepts
to prevent unnecessary API calls, improve user experience, and
avoid server overload.
0 Comments