Skip to content

Commit ad2b72b

Browse files
authored
Micro-optimize cache primitives in librt.internal (#20194)
This includes the following optimizations: * Split Buffer into ReadBuffer and WriteBuffer which are more specialized * Only check buffer types in wrapper functions, not in C primitives * Use pointers instead of integer indexes in the buffer objects This improves the performance of a micro-benchmark that reads integers in a loop by 5%, but this could help more if we'd inline some of the smaller functions (in the future). By making the functions simpler, inlining is more feasible. I'm not sure what's the best way to merge this -- maybe we'll need to have broken master for a while, and then we ca publish a new version of `librt`, and then update mypy to work using the new `librt` version.
1 parent 566ba1e commit ad2b72b

File tree

8 files changed

+517
-275
lines changed

8 files changed

+517
-275
lines changed
Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
from mypy_extensions import u8
22

3+
# TODO: Remove Buffer -- right now we have hacky support for BOTH the old and new APIs
4+
35
class Buffer:
46
def __init__(self, source: bytes = ...) -> None: ...
57
def getvalue(self) -> bytes: ...
68

7-
def write_bool(data: Buffer, value: bool) -> None: ...
8-
def read_bool(data: Buffer) -> bool: ...
9-
def write_str(data: Buffer, value: str) -> None: ...
10-
def read_str(data: Buffer) -> str: ...
11-
def write_bytes(data: Buffer, value: bytes) -> None: ...
12-
def read_bytes(data: Buffer) -> bytes: ...
13-
def write_float(data: Buffer, value: float) -> None: ...
14-
def read_float(data: Buffer) -> float: ...
15-
def write_int(data: Buffer, value: int) -> None: ...
16-
def read_int(data: Buffer) -> int: ...
17-
def write_tag(data: Buffer, value: u8) -> None: ...
18-
def read_tag(data: Buffer) -> u8: ...
9+
class ReadBuffer:
10+
def __init__(self, source: bytes) -> None: ...
11+
12+
class WriteBuffer:
13+
def getvalue(self) -> bytes: ...
14+
15+
def write_bool(data: WriteBuffer | Buffer, value: bool) -> None: ...
16+
def read_bool(data: ReadBuffer | Buffer) -> bool: ...
17+
def write_str(data: WriteBuffer | Buffer, value: str) -> None: ...
18+
def read_str(data: ReadBuffer | Buffer) -> str: ...
19+
def write_bytes(data: WriteBuffer | Buffer, value: bytes) -> None: ...
20+
def read_bytes(data: ReadBuffer | Buffer) -> bytes: ...
21+
def write_float(data: WriteBuffer | Buffer, value: float) -> None: ...
22+
def read_float(data: ReadBuffer | Buffer) -> float: ...
23+
def write_int(data: WriteBuffer | Buffer, value: int) -> None: ...
24+
def read_int(data: ReadBuffer | Buffer) -> int: ...
25+
def write_tag(data: WriteBuffer | Buffer, value: u8) -> None: ...
26+
def read_tag(data: ReadBuffer | Buffer) -> u8: ...
1927
def cache_version() -> u8: ...

mypyc/codegen/emit.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,13 +705,25 @@ def emit_cast(
705705
self.emit_lines(f" {dest} = {src};", "else {")
706706
self.emit_cast_error_handler(error, src, dest, typ, raise_exception)
707707
self.emit_line("}")
708-
elif is_object_rprimitive(typ) or is_native_rprimitive(typ):
708+
elif is_object_rprimitive(typ):
709709
if declare_dest:
710710
self.emit_line(f"PyObject *{dest};")
711711
self.emit_arg_check(src, dest, typ, "", optional)
712712
self.emit_line(f"{dest} = {src};")
713713
if optional:
714714
self.emit_line("}")
715+
elif is_native_rprimitive(typ):
716+
# Native primitive types have type check functions of form "CPy<Name>_Check(...)".
717+
if declare_dest:
718+
self.emit_line(f"PyObject *{dest};")
719+
short_name = typ.name.rsplit(".", 1)[-1]
720+
check = f"(CPy{short_name}_Check({src}))"
721+
if likely:
722+
check = f"(likely{check})"
723+
self.emit_arg_check(src, dest, typ, check, optional)
724+
self.emit_lines(f" {dest} = {src};", "else {")
725+
self.emit_cast_error_handler(error, src, dest, typ, raise_exception)
726+
self.emit_line("}")
715727
elif isinstance(typ, RUnion):
716728
self.emit_union_cast(
717729
src, dest, typ, declare_dest, error, optional, src_type, raise_exception

mypyc/ir/rtypes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,7 @@ def __hash__(self) -> int:
514514

515515
KNOWN_NATIVE_TYPES: Final = {
516516
name: RPrimitive(name, is_unboxed=False, is_refcounted=True)
517-
for name in ["librt.internal.Buffer"]
517+
for name in ["librt.internal.WriteBuffer", "librt.internal.ReadBuffer"]
518518
}
519519

520520

0 commit comments

Comments
 (0)