01 · Live from Wikimedia · server sent events
Every Wikipedia edit, live, with each estimate checked against an exact count
This page reads every change to Wikipedia and its sister sites the moment it is published. It counts them twice, once with compact estimators that fit in a few kilobytes (sketches) and once exactly, so you can watch how far each estimate drifts and whether it stays inside its promised error.
Source stream.wikimedia.org/v2/stream/recentchange · Transport: server sent events, resumed with Last-Event-ID · License: the stream states none; linked pages carry their wiki's license (CC BY-SA 4.0 for Wikipedia text, CC0 for Wikidata)
Every edit to Wikipedia and its sister sites, as it happens
Each dot is one edit, sliding left as it ages. Bigger dots changed more text; rings are new pages.
How the river is drawn
Each dot is one change of type edit or new from the scope chosen below; category changes and log actions are counted in the cards. Rows are the 6 wikis with the most edits since the counters started, plus one row for the rest, and they slide into place as the ranking settles. Horizontal position is the edit's age on this computer's clock, so it includes the clock offset in the delay tile; the span grows from 4 to 60 seconds over the first minute. Position inside a row comes from a hash of the event id, so dots do not stack. The river keeps the latest 2,000 edits.
dot area ∝ 1 + 1.5 log10(1 + |bytes changed|)How busy is it right now?
Changes per second over the last 5 minutes, people stacked under bots. Triangles mark bursts.
Waiting for the first complete second.
How this is measured
A burst is a second far above the recent norm. The norm is an exponentially weighted mean μ and standard deviation σ of earlier seconds, with a 60 second half life. A flagged second still updates the norm, and nothing is flagged in the first 30 seconds.
flag second t if x_t > μ + 4σ and x_t ≥ μ + 10Seconds are binned by event time (meta.dt) and close 2 s after the newest event time passes them, so this computer's clock plays no part. Delivery arrives in clumps, and arrival time bins would read those clumps as bursts; the comparison below counts how often.
How many different people are editing?
Error of a 4 KB estimate (HyperLogLog) against an exact count, each second. Lines mark the typical error; the band is twice that.
Waiting for the first editor.
How this is measured
HyperLogLog with p = 12 keeps 4,096 one byte registers (4 KB). The top 12 bits of the MurmurHash3 of a user name pick a register, which keeps the largest rank seen: one plus the leading zeros in the other 20 bits.
E = α_m m² / Σ_j 2^(−M[j]), m = 4,096 if E ≤ 2.5 m and V > 0: E = m ln(m / V) typical error σ = 1.04 / √m = 1.625%Below 2.5 m = 10,240 the linear counting branch (V = registers still zero) is in use, and its error there is a little smaller, close to 1 / √(2m) ≈ 1.1%. Successive points come from one sketch, so they are not independent trials.
Which pages are busiest?
The 15 most edited pages, from 200 counters (Space-Saving). Solid bar: guaranteed minimum. Gray: possible overcount. Tick: exact count.
Waiting for edits.
How this is measured
Space-Saving (Metwally, Agrawal and El Abbadi, 2005) keeps k = 200 counters for edits and page creations. A page it has not seen takes over the smallest counter and inherits that count as possible error.
count − error ≤ exact ≤ count smallest count ≤ N / k, so exact > N / k means trackedBoth guarantees are checked every second against an exact map of every page. For pages near N / k most of a counter is inherited error, so the order of the lower rows is unreliable.
Which wikis are busiest?
Changes per wiki from a fixed table of 4 by 1,024 counters (Count-Min), next to exact counts.
Waiting for events.
How this is measured
Count-Min adds each change to one counter in each of 4 rows and reports the smallest of the 4. Wikis that share a counter inflate each other, so it can overcount and never undercounts. This is the standard update, so the textbook bound applies as stated.
exact ≤ estimate, P(estimate − exact > ε N) ≤ δ ε = e / 1,024 = 0.00265, δ = e^−4 = 0.0183The proof assumes pairwise independent hashes, which seeded MurmurHash3 is not provably. With a few hundred wikis in 1,024 columns an overcount needs a collision in all 4 rows, so it is rare here.
How big are the edits?
Share of each group's edits by bytes added or removed, people and bots side by side.
Waiting for edits.
How this is measured
Byte change is new length minus old length, for edits only. Bins are orders of magnitude and each label is the edge nearest zero: +100 means +100 to +999 bytes. Shares are within each group, so each color sums to 100%.
What kind of change?
Changes by type since the counters started, people and bots side by side.
Waiting for events.
How this is measured
Types come from the stream. An edit changes a page's text and new creates a page. Categorize records a page entering or leaving a category, and log covers actions such as moves, deletions, uploads and new accounts.
The bot flag is the wiki's own: accounts with the bot right. Automated edits from accounts without it count as people.
Latest changes
The 25 newest changes, newest first. Editors are never shown.
Waiting for events.
How this is measured
Each event's meta.id passes through a set of the 5,000 most recent ids, and repeats after a reconnect are dropped. Wikimedia's synthetic canary events are discarded. Times are event times (meta.dt) in this computer's time zone. Byte change is new length minus old length, blank when the event carries no length. User and User talk pages are named after an account, so their titles are hidden.
Method
This page keeps two sets of books on the same stream. One uses sketches, compact summaries that answer “how many” and “which are biggest” in a fixed few kilobytes at the price of a small, bounded error. The other keeps every count exactly, which works here only because the stream is small. Each card puts the two side by side, and the sections below give the details.
Transport and resume
The page opens one EventSource on Wikimedia's recentchange stream. Every message carries an SSE id: a JSON list of Kafka topic and partition positions (in the stream as observed, a millisecond timestamp for the active datacenter's topic). Wikimedia closes every connection after 15 minutes. The browser then reconnects on its own and sends the last id it saw as the Last-Event-ID header, so the stream resumes where it stopped. If the browser gives up (an HTTP error it will not retry), the page reconnects itself with since set 5 seconds before the newest event time, which can replay a few events.
Each event's meta.id passes through a set of the 5,000 most recent ids; repeats are dropped and counted in the tape footer. Wikimedia's synthetic canary events (meta.domain = canary) are discarded before anything is counted. Changing the scope resets every counter and sketch.
Edit river
The river draws events of type edit and new from the chosen scope; category changes and log actions appear in the cards. Rows are the 6 wikis with the most edits since the counters started, plus one row for the rest. A wiki takes a row, or passes the row above, only when its count exceeds that row's by 10% plus one, so rows settle without flapping, and they slide to new places. Horizontal position is age, this computer's clock minus meta.dt, so it includes the clock offset in the delay tile. The span grows from 4 to 60 seconds over the first minute. Vertical position inside a row comes from a hash of the event id, so dots do not stack. The river keeps the latest 2,000 edits.
Hashing
All three sketches hash with MurmurHash3, x86 32 bit, over UTF-8 bytes. The implementation is checked in the test suite against the published test vectors and SMHasher's verification value. Count-Min uses a different seed for each row.
HyperLogLog
Distinct editors are counted by user name with p = 12, so m = 4,096 registers of one byte each. The top 12 bits of the hash choose a register, which keeps the largest rank it has seen; the rank is one plus the number of leading zeros in the remaining 20 bits.
Below 2.5 m = 10,240 the linear counting branch is in use, and its error there is a little smaller than the raw bound (close to 1 / √(2m) ≈ 1.1% for small counts). The chart follows one sketch over time, so neighbouring points are strongly correlated; a coverage test would need many independent sketches.
The exact set beside it stores only a 53 bit hash of each user name (two seeded MurmurHash3 values). The chance of any collision among 100,000 editors is about n² / 2^54 ≈ 6 × 10^−7, so it is exact in practice.
Count-Min
Events per wiki go into a table of 4 rows by 1,024 counters. Each event adds one to a counter in every row and the estimate is the minimum over rows. The page uses the standard update, so the textbook bound applies as stated; the conservative update tightens estimates but falls outside that proof.
The proof assumes pairwise independent hash functions, which seeded MurmurHash3 is not provably. With a few hundred wikis in 1,024 columns, a key is inflated only when it collides in all four rows, so most estimates come out exact and the bound is far from tight here. The card puts the share of inflated keys expected under uniform hashing next to the share observed.
Space-Saving
Pages (edits and creations) are tracked with k = 200 counters, after Metwally, Agrawal and El Abbadi (2005).
Every second the page checks both guarantees against an exact map of every page seen and counts any failure. The guarantees are deterministic, so that count should stay at zero; it is on the page so that a bug would show. The ranking is weaker: for pages near N / k, most of a counter's count is error inherited from the page it evicted, so the order of the lower rows is unreliable. The card counts how many of the 15 rows belong in the exact top 15.
Bursts
μ and σ are taken before second t is added, and flagged seconds still update the baseline. Nothing is flagged during the first 30 seconds. Seconds are binned by event time (meta.dt) because delivery comes in clumps, and a clump of delivery is no burst of editing; the card counts what the same rule flags on arrival time bins for comparison. A second is closed, and judged, once the newest event time seen is 2 seconds past it, so the judgement does not depend on this computer's clock. Events that arrive later still fill the chart, miss the detector, and are counted. The rate tile uses the same closed seconds, smoothed with a 10 second half life.
Delay, bot flag and privacy
The delay is arrival time on this computer minus meta.dt from Wikimedia, over the last 2,000 events. It includes the offset between the two clocks, which can be a second or more and can even make the delay negative. The bot flag is the wiki's own: accounts with the bot right. Automated edits from accounts without it count as people.
User names and IP addresses are never displayed. A name is hashed on arrival, into the HyperLogLog registers and the 53 bit exact set, and the string is not kept. The tape and the river show pages and leave out editors. Pages in the User and User talk namespaces (2 and 3) are named after an account or an IP address, so their titles are counted by hash and shown only as “User page (name hidden)”, without a link. Titles in other namespaces can still mention an account, for example a noticeboard subpage; those are shown as the wiki published them.
What the comparison shows
The exact counters are only affordable because this stream is small, tens of events a second as the rate tile shows. The exact set and maps grow with every new editor and page (the page resets itself if the page map reaches 500,000 keys), while the sketches stay at 4 KB, 4 × 1,024 counters and 200 counters. At a scale where exact counting does not fit in memory, the sketch is all there is; running both here shows what the sketch gives up in exchange.
Data: Wikimedia EventStreams, recentchange stream, published by the Wikimedia Foundation. Page titles link back to the wiki they came from. Nothing is stored between visits and nothing passes through a server of mine. All dashboards · Back to the portfolio