Skip to content

Commit

Permalink
Implement response heading parsing in rust
Browse files Browse the repository at this point in the history
## Motivation / Description
There was nothing else to optimize in python, but Rust can parse
the string and build a ResponseFlags object in 22-50ns depending
on the number of flags.

While the interface between rust and python will never reach ns
performance, it helps indeed finding the header in the
response buffer.

Initial (before all optimizations):
multithreaded: Overall: 110779.55 RPS / 9.03 us/req
singlethreaded: Overall: 111545.63 RPS / 8.96 us/req

Python optimized:
multithreaded: Overall: 193340.40 RPS / 5.17 us/req
singlethreaded: Overall: 193036.56 RPS / 5.18 us/req

Using rust for header parsing:
multithreaded: Overall: 245898.34 RPS / 4.07 us/req
singlethreaded: Overall: 246165.19 RPS / 4.06 us/req
  • Loading branch information
bisho committed Mar 5, 2024
1 parent d433fda commit a6ab048
Show file tree
Hide file tree
Showing 14 changed files with 302 additions and 311 deletions.
4 changes: 2 additions & 2 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
nox.options.sessions = "lint", "types", "tests"
locations = "src", "tests", "noxfile.py"
DEFAULT_VERSION = "3.8"
DEFAULT_BENCHMARK_VERSION = "3.11"
DEFAULT_BENCHMARK_VERSIONS = ["3.11"]
VERSIONS = ["3.8", "3.11"]


Expand Down Expand Up @@ -57,7 +57,7 @@ def tests(session: Session) -> None:
session.run("pytest", *args, env={"PYTHONHASHSEED": "0"})


@session(python=DEFAULT_BENCHMARK_VERSION)
@session(python=DEFAULT_BENCHMARK_VERSIONS)
def benchmark(session: Session) -> None:
"""Run the benchmark suite."""
args = session.posargs
Expand Down
154 changes: 104 additions & 50 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ packages = [{include = "meta_memcache", from="src"}]
python = "^3.8"
uhashring = "^2.1"
marisa-trie = "^1.0.0"
meta-memcache-socket = "^0.1.0"

[tool.poetry.group.extras.dependencies]
prometheus-client = "^0.17.1"
Expand Down
1 change: 1 addition & 0 deletions src/meta_memcache/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
Miss,
NotStored,
ServerVersion,
ResponseFlags,
SetMode,
Success,
TokenFlag,
Expand Down
16 changes: 8 additions & 8 deletions src/meta_memcache/commands/high_level_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,23 +287,23 @@ def get_or_lease_cas(

if isinstance(result, Value):
# It is a hit.
if result.win:
if result.flags.win:
# Win flag present, meaning we got the lease to
# recache/cache the item. We need to mimic a miss.
return None, result.cas_token
if result.size == 0 and result.win is False:
return None, result.flags.cas_token
if result.size == 0 and result.flags.win is False:
# The value is empty, this is a miss lease,
# and we lost, so we must keep retrying and
# wait for the winner to populate the value.
# wait for the.flags.winner to populate the value.
if i < lease_policy.miss_retries:
continue
else:
# We run out of retries, behave as a miss
return None, result.cas_token
return None, result.flags.cas_token
else:
# There is data, either the is no lease or
# we lost and should use the stale value.
return result.value, result.cas_token
return result.value, result.flags.cas_token
else:
# With MISS_LEASE_TTL we should always get a value
# because on miss a lease empty value is generated
Expand Down Expand Up @@ -378,7 +378,7 @@ def get_cas(
if result is None:
return None, None
else:
return result.value, result.cas_token
return result.value, result.flags.cas_token

def _get(
self: HighLevelCommandMixinWithMetaCommands,
Expand Down Expand Up @@ -414,7 +414,7 @@ def _process_get_result(
) -> Optional[Value]:
if isinstance(result, Value):
# It is a hit
if result.win:
if result.flags.win:
# Win flag present, meaning we got the lease to
# recache the item. We need to mimic a miss, so
# we set the value to None.
Expand Down
Loading

0 comments on commit a6ab048

Please sign in to comment.