|
11 | 11 | import sys |
12 | 12 | import threading |
13 | 13 | import time |
14 | | -import tracemalloc |
| 14 | +import types |
15 | 15 | from typing import ( |
16 | 16 | Any, |
17 | 17 | Callable, |
|
38 | 38 | ) |
39 | 39 | from .caching import Cache, Local |
40 | 40 | from .loaders import load_builtins, load_yaml |
41 | | -from .re2 import Resolver as Re2Resolver |
| 41 | + |
| 42 | +try: |
| 43 | + from .re2 import Resolver as Re2Resolver |
| 44 | +except ImportError: |
| 45 | + pass |
| 46 | +try: |
| 47 | + from .regex import Resolver as RegexResolver |
| 48 | +except ImportError: |
| 49 | + pass |
42 | 50 | from .user_agent_parser import Parse |
43 | 51 |
|
44 | 52 | CACHEABLE = { |
45 | 53 | "basic": True, |
46 | 54 | "re2": True, |
| 55 | + "regex": True, |
47 | 56 | "legacy": False, |
48 | 57 | } |
49 | 58 |
|
|
58 | 67 | ] |
59 | 68 | ) |
60 | 69 |
|
| 70 | +try: |
| 71 | + import tracemalloc |
| 72 | +except ImportError: |
| 73 | + snapshot = types.SimpleNamespace( |
| 74 | + compare_to=lambda _1, _2: [], |
| 75 | + ) |
| 76 | + tracemalloc = types.SimpleNamespace( # type: ignore |
| 77 | + start=lambda: None, |
| 78 | + take_snapshot=lambda: snapshot, |
| 79 | + ) |
| 80 | + |
61 | 81 |
|
62 | 82 | def get_rules(parsers: List[str], regexes: Optional[io.IOBase]) -> Matchers: |
63 | 83 | if regexes: |
@@ -178,6 +198,8 @@ def get_parser( |
178 | 198 | r = BasicResolver(rules) |
179 | 199 | elif parser == "re2": |
180 | 200 | r = Re2Resolver(rules) |
| 201 | + elif parser == "regex": |
| 202 | + r = RegexResolver(rules) |
181 | 203 | else: |
182 | 204 | sys.exit(f"unknown parser {parser!r}") |
183 | 205 |
|
@@ -327,6 +349,7 @@ def run_threaded(args: argparse.Namespace) -> None: |
327 | 349 | ("locking-lru", CachingResolver(basic, caching.Lru(CACHESIZE))), |
328 | 350 | ("local-lru", CachingResolver(basic, Local(lambda: caching.Lru(CACHESIZE)))), |
329 | 351 | ("re2", Re2Resolver(load_builtins())), |
| 352 | + ("regex", RegexResolver(load_builtins())), |
330 | 353 | ] |
331 | 354 | for name, resolver in resolvers: |
332 | 355 | print(f"{name:11}: ", end="", flush=True) |
@@ -436,14 +459,14 @@ def __call__( |
436 | 459 | bench.add_argument( |
437 | 460 | "--bases", |
438 | 461 | nargs="+", |
439 | | - choices=["basic", "re2", "legacy"], |
440 | | - default=["basic", "re2", "legacy"], |
| 462 | + choices=["basic", "re2", "regex", "legacy"], |
| 463 | + default=["basic", "re2", "regex", "legacy"], |
441 | 464 | help="""Base resolvers to benchmark. `basic` is a linear search |
442 | 465 | through the regexes file, `re2` is a prefiltered regex set |
443 | | - implemented in C++, `legacy` is the legacy API (essentially a |
444 | | - basic resolver with a clearing cache of fixed 200 entries, but |
445 | | - less layered so usually slightly faster than an equivalent |
446 | | - basic-based resolver).""", |
| 466 | + implemented in C++, `regex` is a prefiltered regex set implemented |
| 467 | + in Rust, `legacy` is the legacy API (essentially a basic resolver |
| 468 | + with a clearing cache of fixed 200 entries, but less layered so |
| 469 | + usually slightly faster than an equivalent basic-based resolver).""", |
447 | 470 | ) |
448 | 471 | bench.add_argument( |
449 | 472 | "--caches", |
|
0 commit comments