perf: optimize rust acceleration paths

Rust vs Python benchmark results:

- RSS: Rust 0.299 ms/loop vs Python 7.913 ms/loop, 26.47x faster

- Filter: Rust 12.740 ms/loop vs Python 57.187 ms/loop, 4.49x faster

- MetaInfo: Rust 64.680 ms/loop vs Python 316.158 ms/loop, 4.89x faster

- Indexer agsvpt: Rust 145.76 ms vs Python 3686.50 ms, 25.29x faster

- Indexer pttime: Rust 166.51 ms vs Python 4019.87 ms, 24.14x faster

- Indexer chdbits: Rust 161.17 ms vs Python 3604.28 ms, 22.36x faster

- Indexer iptorrents: Rust 77.82 ms vs Python 17615.52 ms, 226.36x faster

Validation:

- cargo fmt/check/test for rust/moviepilot_rust

- pytest Rust-related coverage: tests/test_rust_accel.py tests/test_torrent_filter.py tests/test_metainfo.py tests/test_indexer_spider_search_url.py tests/test_workflow_fetch_rss.py

- tests/run.py legacy suite

- pylint app/ --errors-only
This commit is contained in:
jxxghp
2026-05-23 19:35:55 +08:00
parent a6826e6a4e
commit 0bf228d29d
15 changed files with 1727 additions and 392 deletions

View File

@@ -4,13 +4,14 @@ from functools import lru_cache
from typing import List, Tuple, Union, Dict, Optional
from app.core.context import TorrentInfo, MediaInfo
from app.core.metainfo import MetaInfo
from app.core.metainfo import MetaInfo, clear_rust_parse_options_cache, _rust_parse_options
from app.helper.rule import RuleHelper
from app.log import logger
from app.modules import _ModuleBase
from app.modules.filter.RuleParser import RuleParser
from app.modules.filter.builtin_rules import BUILTIN_RULE_SET
from app.schemas.types import ModuleType, OtherModulesType, SystemConfigKey
from app.utils import rust_accel
from app.utils.string import StringUtils
@@ -60,7 +61,12 @@ def _parse_publish_time(publish_time: str) -> Tuple[float, ...]:
class FilterModule(_ModuleBase):
CONFIG_WATCH = {SystemConfigKey.CustomFilterRules.value}
CONFIG_WATCH = {
SystemConfigKey.CustomFilterRules.value,
SystemConfigKey.CustomIdentifiers.value,
SystemConfigKey.CustomReleaseGroups.value,
SystemConfigKey.Customization.value,
}
# 保留一份只读内置规则定义,方便查询工具准确区分“内置规则”和“自定义规则”。
builtin_rule_set: Dict[str, dict] = deepcopy(BUILTIN_RULE_SET)
@@ -76,6 +82,13 @@ class FilterModule(_ModuleBase):
self.rule_set = deepcopy(self.builtin_rule_set)
self.__init_custom_rules()
def on_config_changed(self):
"""
自定义过滤或 Meta 识别配置变更后重建规则集并刷新 Rust Meta 配置缓存。
"""
clear_rust_parse_options_cache()
self.init_module()
def __init_custom_rules(self):
"""
加载用户自定义规则,如跟内置规则冲突,以用户自定义规则为准
@@ -131,25 +144,37 @@ class FilterModule(_ModuleBase):
"""
if not rule_groups:
return torrent_list
parser = RuleParser()
# 同一轮过滤里,相同的优先级层级会被多个种子反复使用;按需解析并缓存,
# 既减少 pyparsing 开销,也保留原来“命中高优先级后不解析低层级”的容错行为。
parsed_rule_cache: Dict[str, Union[list, str]] = {}
# 查询规则表详情
groups = self.rulehelper.get_rule_group_by_media(media=mediainfo, group_names=rule_groups)
if groups:
for group in groups:
# 过滤种子
torrent_list = self.__filter_torrents(
rule_string=group.rule_string,
rule_name=group.name,
torrent_list=torrent_list,
mediainfo=mediainfo,
parser=parser,
parsed_rule_cache=parsed_rule_cache,
)
group_defs = [group.model_dump() if hasattr(group, "model_dump") else vars(group) for group in groups]
matched_orders = rust_accel.filter_torrents(
groups=group_defs,
torrent_list=torrent_list,
rule_set=self.rule_set,
mediainfo=mediainfo,
metainfo_options=_rust_parse_options() if self.__needs_metainfo_options(group_defs) else None,
)
ret_torrents = []
for index, pri_order in matched_orders:
torrent = torrent_list[index]
torrent.pri_order = pri_order
ret_torrents.append(torrent)
return ret_torrents
return torrent_list
def __needs_metainfo_options(self, groups: List[dict]) -> bool:
"""
判断当前规则链是否会触发 size_range避免无大小规则时读取 MetaInfo 运行配置。
"""
rule_ids = set()
for group in groups:
rule_string = group.get("rule_string")
if not rule_string:
continue
rule_ids.update(re.findall(r"[A-Za-z][A-Za-z0-9]*|[0-9]+[A-Za-z][A-Za-z0-9]*", rule_string))
return any(self.rule_set.get(rule_id, {}).get("size_range") for rule_id in rule_ids)
def __filter_torrents(self, rule_string: str, rule_name: str,
torrent_list: List[TorrentInfo],
mediainfo: MediaInfo,