+ /**
+ * Prepare to skip to `value`. This is a constant-time operation that will
+ * prefetch memory required for a `skipTo(value)` call.
+ *
+ * @return position of reader
+ */
+ SizeType prepareSkipTo(ValueType v) const {
+ auto position = position_;
+
+ if (Encoder::skipQuantum > 0 && v >= value_ + Encoder::skipQuantum) {
+ auto outer = outer_;
+ const size_t steps = v / Encoder::skipQuantum;
+ const size_t dest = folly::loadUnaligned<SkipValueType>(
+ this->skipPointers_ + (steps - 1) * sizeof(SkipValueType));
+
+ position = dest - 1;
+ outer = (dest + Encoder::skipQuantum * steps) / 8;
+
+ // Prefetch up to the beginning of where we linear search. After that,
+ // hardware prefetching will outperform our own. In addition, this
+ // simplifies calculating what to prefetch as we don't have to calculate
+ // the entire destination address. Two cache lines are prefetched because
+ // this results in fewer cycles used (based on practical results) than
+ // one. However, three cache lines does not have any additional effect.
+ const auto addr = start_ + outer;
+ __builtin_prefetch(addr);
+ __builtin_prefetch(addr + kCacheLineSize);
+ }
+
+ return position;
+ }
+