mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-06-07 08:41:16 +08:00
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:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user