Skip to content

Instantly share code, notes, and snippets.

@yonatanzunger
Created August 11, 2022 00:24
Show Gist options
  • Save yonatanzunger/c28074e66cd07ed6dfb09b15ba1928ff to your computer and use it in GitHub Desktop.
Save yonatanzunger/c28074e66cd07ed6dfb09b15ba1928ff to your computer and use it in GitHub Desktop.
from dis import cmp_op
from typing import List, NamedTuple, Optional
from fast_comparator import Comparison
class KeyRange(NamedTuple):
exact_value: Optional[bytes]
min_value: Optional[bytes]
max_value: Optional[bytes]
def matches(self, value: bytes) -> bool:
if self.exact_value is not None:
return value == self.exact_value
return (self.min_value is None or value >= self.min_value) and (
self.max_value is None or value < self.max_value
)
def asComparators(self, index: int, comparisons: List[Comparison]) -> None:
if self.exact_value is not None:
comparisons.append(Comparison(index, cmp_op.index('=='), self.exact_value))
return
if self.min_value is not None:
comparisons.append(Comparison(index, cmp_op.index('>='), self.min_value))
if self.max_value is not None:
comparisons.append(Comparison(index, cmp_op.index('<'), self.max_value))
THEN IN THE QUERY OBJECT:
def __init__(self, ...) -> None:
....
if not USE_SLOW_COMPARE:
# Precompile a matcher function which compares a List[bytes] against the specified key
# ranges. We do this because matchesEncodedKeys() is often called in a tight inner
# loop, and its performance therefore matters a lot.
comparators = []
for index, keyInfo in enumerate(self._keys):
keyInfo.keyRange.asComparators(index, comparators)
self._encodedKeyMatcher = makeFastComparator(len(self._keys), comparators)
else:
self._encodedKeyMatcher = self._match
def _match(self, *encodedKeys: bytes) -> bool:
"""The slow, default implementation."""
return all(
keyInfo.keyRange.matches(encodedKey)
for keyInfo, encodedKey in zip(self._keys, encodedKeys)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment