Skip to content

Commit

Permalink
[local-hypertable] Clean up some comments.
Browse files Browse the repository at this point in the history
  • Loading branch information
neboat committed Jan 6, 2024
1 parent 196c959 commit 77c5186
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 24 deletions.
6 changes: 3 additions & 3 deletions runtime/local-hypertable.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,9 @@ bool insert_hyperobject(hyper_table *table, struct bucket b) {
continue;
}

// Otherwise this entry contains have another valid key that does not
// match. Compare the hashes to decide whether or not to continue the
// probe.
// Otherwise this entry contains another valid key that does
// not match. Compare the hashes to decide whether or not to
// continue the probe.
index_t curr_hash = buckets[i].hash;
if (continue_probe(tgt, curr_hash, i)) {
i = inc_index(i, capacity);
Expand Down
44 changes: 23 additions & 21 deletions runtime/local-hypertable.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static const uint64_t salt = 0x96b9af4f6a40de92UL;

static inline index_t hash(uintptr_t key_in) {
uint64_t x = key_in ^ salt;
// mix based on abseil's low-level hash, to convert 64-bit integers into
// mix, based on abseil's low-level hash, and convert 64-bit integers into
// 32-bit integers.
const size_t half_bits = sizeof(uintptr_t) * 4;
const uintptr_t low_mask = ((uintptr_t)(1) << half_bits) - 1;
Expand All @@ -85,48 +85,50 @@ static inline index_t inc_index(index_t i, index_t capacity) {
return i;
}

// For theoretical and practical efficiency, the hash table implements ordered
// linear probing --- consecutive hashes in the table are always stored in
// sorted order --- in a circular buffer. Typically, the ordering optimization
// means any hash-table probe for a target T can stop when it encounters an
// element in the table whose hash is greater than T.
//
// However, the combination of ordering and a circular buffer leads to several
// tricky cases when probing for an element or its insertion point. These cases
// depend on whether the probe wraps around the end of the buffer and whether
// the run --- the ordered sequence of hashes in the table --- wraps around the
// end of the buffer.
//
// Example case 1: no wrapping (common case)
// For theoretical and practical efficiency, the hash table implements
// ordered linear probing --- consecutive hashes in the table are
// always stored in sorted order --- in a circular buffer.
// Intuitively, this ordering means any hash-table probe for a target
// T can stop when it encounters an element in the table whose hash is
// greater than T.
//
// Implementing ordered linear probing on a circular buffer, however,
// leads to several tricky cases when probing for an element or its
// insertion point. These cases depend on whether the probe or the
// run --- the ordered sequence of hashes in the table --- wraps
// around from the end to the beginning of the buffer's allocated
// memory. In general, there are four cases:
//
// Example case 1: No wrapping (common case)
// Index: ... | 3 | 4 | 5 | 6 | ...
// Hashes: ... | 3 | 3 | 3 | 5 | ...
// Target: 4
// The probe starts at index 4 and scans increasing indices, stopping when it
// sees hash = 5 at index 6.
//
// Example case 2: probe and run both wrap
// Example case 2: Probe and run both wrap
// Index: | 0 | 1 | 2 | ... | 6 | 7 |
// Hashes: | 6 | 7 | 0 | ... | 6 | 6 |
// Target: 7
// The run of 6's wraps around, as does the probe for 7.
//
// Example case 3: probe does not wrap, run does wrap
// Example case 3: Probe does not wrap, run does wrap
// Index: | 0 | 1 | 2 | ... | 6 | 7 |
// Hashes: | 6 | 7 | 0 | ... | 6 | 6 |
// Target: 0
// The run of 6's and 7's wrap around. The probe for 0 starts in the middle
// of this wrapped run and must continue past it, even though the hashes in
// the run are larger than the target.
//
// Example case 4: probe wraps, run does not wrap
// Example case 4: Probe wraps, run does not wrap
// Index: | 0 | 1 | 2 | ... | 6 | 7 |
// Hashes: | 6 | 0 | 1 | ... | 6 | 6 |
// Target: 7
// After the wrapped run of 6's is a run starting at 0, which does not wrap.
// The probe for 7 wraps around before encountering the 0. The probe should
// stop at that point, even though 0 is smaller than 7.
//
// We characterize these four cases based on the following:
// We characterize these four cases in terms of the following variables:
//
// - T: The target hash value being probed for.
// - i: The current index in the table being examined in the probe.
Expand Down Expand Up @@ -155,9 +157,9 @@ static inline index_t inc_index(index_t i, index_t capacity) {
// Continue the probe if and only if i-T <= i-H[i], using an _unsigned
// integer_ comparison.
//
// Intuitively, this trick makes the case of wrapping in the probe or run
// coincide with unsigned integer overflow, allowing the same comparison to be
// used for all cases.
// Intuitively, this trick makes the case of wrapping around the table
// coincide with unsigned integer overflow, allowing the same
// comparison to be used in all cases.
//
// We can justify this bit trick in all caes:
//
Expand Down

0 comments on commit 77c5186

Please sign in to comment.