Cribl puts your IT and Security data at the center of your data management strategy and provides a one-stop shop for analyzing, collecting, processing, and routing it all at any scale. Try the Cribl suite of products and start building your data engine today!
Learn more ›Evolving demands placed on IT and Security teams are driving a new architecture for how observability data is captured, curated, and queried. This new architecture provides flexibility and control while managing the costs of increasing data volumes.
Read white paper ›Cribl Stream is a vendor-agnostic observability pipeline that gives you the flexibility to collect, reduce, enrich, normalize, and route data from any source to any destination within your existing data infrastructure.
Learn more ›Cribl Edge provides an intelligent, highly scalable edge-based data collection system for logs, metrics, and application data.
Learn more ›Cribl Search turns the traditional search process on its head, allowing users to search data in place without having to collect/store first.
Learn more ›Cribl Lake is a turnkey data lake solution that takes just minutes to get up and running — no data expertise needed. Leverage open formats, unified security with rich access controls, and centralize access to all IT and security data.
Learn more ›The Cribl.Cloud platform gets you up and running fast without the hassle of running infrastructure.
Learn more ›Cribl.Cloud Solution Brief
The fastest and easiest way to realize the value of an observability ecosystem.
Read Solution Brief ›AppScope gives operators the visibility they need into application behavior, metrics and events with no configuration and no agent required.
Learn more ›Explore Cribl’s Solutions by Use Cases:
Explore Cribl’s Solutions by Integrations:
Explore Cribl’s Solutions by Industry:
April 24 | 10am PT / 1pm ET
3 ways to fast-track your data lake strategy without being a data expert
REGISTER ›Try Your Own Cribl Sandbox
Experience a full version of Cribl Stream and Cribl Edge in the cloud.
Launch Now ›Get inspired by how our customers are innovating IT, security and observability. They inspire us daily!
Read Customer Stories ›Sally Beauty Holdings
Sally Beauty Swaps LogStash and Syslog-ng with Cribl.Cloud for a Resilient Security and Observability Pipeline
Read Case Study ›Experience a full version of Cribl Stream and Cribl Edge in the cloud.
Launch Now ›Transform data management with Cribl, the Data Engine for IT and Security
Learn More ›Cribl Corporate Overview
Cribl makes open observability a reality, giving you the freedom and flexibility to make choices instead of compromises.
Get the Guide ›Stay up to date on all things Cribl and observability.
Visit the Newsroom ›Cribl’s leadership team has built and launched category-defining products for some of the most innovative companies in the technology sector, and is supported by the world’s most elite investors.
Meet our Leaders ›Join the Cribl herd! The smartest, funniest, most passionate goats you’ll ever meet.
Learn More ›Whether you’re just getting started or scaling up, the Cribl for Startups program gives you the tools and resources your company needs to be successful at every stage.
Learn More ›Want to learn more about Cribl from our sales experts? Send us your contact information and we’ll be in touch.
Talk to an Expert ›May 1, 2018
If you’re a Javascript developer you probably already know the utility of the debounce / throttle function. For those unfamiliar/new with JS, debounce/throttle are basically utilities to generate a function that is limited in execution frequency independent of the call frequency. For example, execute a function at most every 250ms, no matter how frequently the function is called. This is useful when the frequency of triggering events spikes and the work done for the early events would be thrown away or repeated – a typical use-case would be type-ahead information in a search bar. You can read more about these functions here
Note: while the following is JS specific, the pattern of throttling/debouncing is not language specific.
Race conditions are some of the nastiest bugs to troubleshoot, mostly due to being hard to reproduce. They’re generally species that prefer to live in multi-threaded systems. Javascript on the other hand, uses an event loop concurrency model, meaning that your code runs in a single thread. Even though it might be mentally harder to get used to, there are lots of benefits to this model – eg. locking is simply not necessary. Single threaded also means that race conditions are minimized, but not guaranteed to be eliminated – generally anything that introduces non-deterministic behavior in an application increases the chances of race conditions.
One potential use of debounce is to buffer events and process them in batches at some given max frequency – e.g the following code would process batches of events every 10ms.
const events = []; let count = 0; const processEvents = throttle(() => { // do something with the events ... i'm just wasting time count += events.length; events.length = 0; }, 10); const gotEvent = (e) => { events.push(e); processEvents(); }
So now let’s see where the evil of debounce/throttle comes in – hint: it’s the non-determinism that introduces race conditions. Say we were to use the above functions to generate batches of events every 9ms:
let intervalCalls = 10; let interval = setInterval(() => { for(let i=0; i<10; i++) { gotEvent(i) } console.log(`count=${count}`); if(intervalCalls-- < 1) { clearInterval(interval); } }, 9);
In the above code there is no guarantee at what the output would be – that would depend very much on what else is executing on the system and/or the clock of the CPU. Feel free to run the above code a number of times yourself here
While in the above code it could be easy to spot the race condition – non-determinism (throttle) + state (count) = race condition (breaking serializibility). Using throttle/debounce in deep library functions, mostly to improve performance, has the potential to result in race conditions that are hard to troubleshoot.
There two ways to go about solving this issue:
a. guarantee serializibility in your library
b. document the behavior of your code as eventually-consistent and give callers and ability to force consistency at will. You can test out the full example here
const processEventsNow = () => { // do something with the events ... count += events.length; events.length = 0; }; const processEvents = throttle(processEventsNow, 10);
We ran into this issue while building out Bots with actions – the race condition was between archive files being expanding and Bots executing and adding metadata about archive content files. Processing of the content files was throttled (think 10K files in an archive) resulting in files not being “present” in the state table even though bots had seen them. We went with solution b) from above as throttling is still beneficial for performance.
If you found the above interesting, we’re hiring and would like to talk to you – send a quick line: ledion at cribl.io to connect!
Ryan Conway Apr 9, 2024
Perry Correll Apr 4, 2024