Skip to content

Commit fa27574

Browse files
committed
Default to re2 parser is available
After benchmarking, the results are out, at least on the current sample file: First, re2 is ridiculously faster than the basic parser, even with tons of caching. re2 does benefit from caching, but it's so fast that it needs very high hitrates (so a very large cache) for the caching to have a real impact, it's fast enough that at low hitrates (small sizes) the cache does slow down parsing visibly which is not the case of the basic parser. Second, LRU is confirmed to be a better cache replacement policy than clearing (which... duh), it's not super sensible at very low sizes but at 100 entries it starts really pulling ahead, so definitely the better default at 200 (where even with the overhead of the more layered approach it's ahead of the legacy parser and its immutable 20 entries clearing cache). The locking doesn't seem to have much impact without contention, and even contended the LRU seems to behave way better than the clearing cache still. So fallback onto locked LRU if re2 is not available.
1 parent 9960dbd commit fa27574

1 file changed

Lines changed: 14 additions & 5 deletions

File tree

src/ua_parser/__init__.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@
4646

4747
VERSION = (1, 0, 0)
4848

49-
from typing import Optional
49+
import contextlib
50+
from typing import Callable, Optional, Type
51+
5052
from .core import (
5153
DefaultedParseResult,
5254
Device,
@@ -65,17 +67,24 @@
6567
from .caching import CachingParser, Clearing, LRU, Locking
6668
from .loaders import load_builtins, load_data, load_yaml
6769

70+
Re2Parser: Optional[Callable[[Matchers], Parser]] = None
71+
with contextlib.suppress(ImportError):
72+
from .re2 import Parser as Re2Parser
73+
6874

6975
parser: Parser
7076

7177

7278
def __getattr__(name: str) -> Parser:
7379
global parser
7480
if name == "parser":
75-
parser = CachingParser(
76-
BasicParser(load_builtins()),
77-
LRU(200),
78-
)
81+
if Re2Parser is not None:
82+
parser = Re2Parser(load_builtins())
83+
else:
84+
parser = CachingParser(
85+
BasicParser(load_builtins()),
86+
Locking(LRU(200)),
87+
)
7988
return parser
8089
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
8190

0 commit comments

Comments
 (0)