프로젝트 기록

PROJECT RECORD

Checking how code estimates the difference between two lists

EN 한국어

Suppose two computers have almost identical file lists. If a few entries have been added on one side, they might want to find those differences without sending the entire list again.

One approach is to make a compact summary table of each list. If comparing the summaries can recover the differing entries, the computers can avoid exchanging both long lists in full. A summary that is too small may not hold enough information to recover the differences; making it larger than necessary increases what must be sent. That creates a reason to estimate how many entries differ before recovering which entries they are.

The code I reviewed did not follow one of the assumptions used in that estimate. Its formula assumed that information from each entry would be placed in three distinct cells. The implementation instead drew three positions and removed any repeats. Drawing the same position twice could leave only two cells. I supplied evidence reproducing the mismatch. The original project changed the code and acknowledged my contribution by name in its official repository.

What a cell is, and how an entry reaches it

A cell here is a small unit in the summary table, not a location where a computer stores a file. Information calculated from an entry is added to several cells. Subtracting one side's summary from the other's cancels the contributions of shared entries, after which the remaining information is used to find the differences. An IBLT is a data structure used for this kind of set reconciliation: finding the difference between two collections of entries.

The Self-sizing work estimates the size of that difference so the next comparison can allocate enough space. The estimator calculates the number of differing entries. The mapper decides which cells receive an entry's information. Because the estimate depends on the placement rule, those two parts have to use compatible assumptions.

I preserved commit bb959c5aeda95a82fdfbb2690795badff7c478da for the review on 1 September 2026. A commit identifies a particular version of the code so it can still be examined after later changes. In this version, the Go Positions function generated three candidate positions and removed duplicates. An entry could therefore reach one, two or three distinct cells.

The estimator continued to calculate with K=3, where K is the assumed number of distinct cells per entry. That number is called the entry's degree.

One differing entry gave an estimate of about 0.678

The small reproduction used one entry present on only one side and a summary with 64 cells, numbered 0 through 63. The seed was 0. A seed is an input that lets the position calculation be repeated under the same conditions. The entry was represented by the fingerprint 0xa4712c74562914, a numeric value; the 0x prefix means the number is written in hexadecimal.

For these inputs, the first three positions were [0, 16, 16]. Cell 16 had been selected twice, leaving [0, 16] after the repeated position was removed. There had been three draws, but only two distinct cells.

The recorded run went through insertion into the summary, subtraction of the two summaries, and recovery of the differing entry. The true difference size was one, while the estimate was approximately 0.678. Recovery itself succeeded. This was a mismatch in the count estimate, not an example of an entry being lost because it reached two cells.

Three symbols are needed to follow the calculation. M is the total number of cells. K is the assumed number of distinct cells used by an entry. cᵢ is the count left in cell i after subtracting the summaries; the count can be signed according to which side contributed an entry. The code calculates:

T = Σcᵢ² − (Σcᵢ)²/M
γ = K(1 − K/M)
estimated number of differing entries = T/γ

The Σ symbol means to sum across the cells. T takes the sum of squared cell counts and subtracts a term based on their total. The denominator, γ, is the adjustment for the assumed placement rule. In this one-entry example, two cells each contain a count of 1, so T = 2 − 4/64 = 1.9375. The denominator still assumes three cells: 3(1 − 3/64) = 2.859375. Dividing gives 1.9375 / 2.859375 ≈ 0.677596.

Had the entry reached three distinct cells, the numerator in this example would also have been 3 − 9/64, equal to the denominator. The estimate would then be 1, the actual difference size. This isolates a mismatch between the estimator's assumption and the placement rule. It does not demonstrate data corruption or refute the paper's theorem.

The existing tests had passed

The preserved records showed successful runs of the existing tests and checks reproducing the paper's table values. Those results might suggest that the code and calculations used the same conditions. But the calibration simulation retried repeated positions until it had three distinct cells. The mapper in the actual reconciliation path stopped after removing repeats.

The simulation used to check the table values followed the formula's assumption; the other execution path used a different rule. I therefore looked beyond whether the tests passed and checked which code path they exercised and whether it followed the estimator's assumptions.

The broader check examined whether the mismatch also appeared with other inputs. It used table sizes of 64, 256, 512, 1,024 and 4,096 cells, with three seeds and one million fingerprints for each size-and-seed combination. The fingerprints were generated deterministically so the input sequence could be reproduced. Five sizes, three seeds and one million inputs made 15 million mappings in total.

Of those mappings, 203,097 returned fewer than three distinct cells. That is a count of placements that did not meet the three-cell assumption, not a count of failed recoveries. Results also vary with table size, so the total should not be treated as a general failure rate. At 512 cells with seed 0, for example, the mean one-entry estimate was about 0.194% below the true value of 1.

These are results for the preserved implementation and fixed input sequences. They do not measure the change in the next round's recovery-failure probability in a deployed service, or performance under every condition after the fix. Deduplication was already documented in the released mapper. My review related that behavior to the fixed-degree estimator and calibration simulation, and supplied evidence that their conditions did not match.

The project changed the code and recorded the contribution

The mapper correction, dated 4 September 2026, adds retries for repeated positions and a check that both sides use the same mapper version. If the same entry is placed according to different rules on the two sides, their summaries may not compare correctly. The version check therefore addresses compatibility between implementations.

The subsequent verification-tooling commit adds checks comparing the Java and Go fixed-degree mappers and an acknowledgment in the README. The acknowledgment credits Byungwoong Yoo (Independent Researcher) with identifying the calibration mismatch between the fixed-degree estimator and the mapper implementation.

The original project wrote and published the fix. My role was finding the mismatch and supplying reproduction evidence. The public acknowledgment records that contribution; it does not establish coauthorship or mean that I revalidated all performance results and deployments after the change.

I retained the frozen code and original run records so the change can be examined against the version that prompted the report.

Original research · Byungwoong Yoo — ORCID · 한국어로 읽기

연구 목록 · 작업 목록

Research index · Work index

Discover more from Woong Works

Subscribe now to keep reading and get access to the full archive.

Continue reading