mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-15 07:53:23 -05:00
perf: reuse diffs and raise the file size cap
This commit is contained in:
1 parent
77dff6377e
commit
77a39b2f4e
3 files changed
+52
-11
No files matched your search
@@ -5,7 +5,7 @@ source: "https://github.com/libretro/FBNeo"
|
|||||||
upstream: "https://github.com/finalburnneo/FBNeo"
|
upstream: "https://github.com/finalburnneo/FBNeo"
|
||||||
profiled_date: "2026-03-23"
|
profiled_date: "2026-03-23"
|
||||||
source_commit: "ef1f64b7023bc511858e96b8961f99c18a09f112"
|
source_commit: "ef1f64b7023bc511858e96b8961f99c18a09f112"
|
||||||
core_version: "v1.0.0.03"
|
core_version: "v1.0.0.2"
|
||||||
display_name: "Arcade (FinalBurn Neo) (CPS-1 / CPS-2)"
|
display_name: "Arcade (FinalBurn Neo) (CPS-1 / CPS-2)"
|
||||||
cores:
|
cores:
|
||||||
- fbneo_cps12
|
- fbneo_cps12
|
||||||
|
|||||||
+39
-6
@@ -40,7 +40,10 @@ REVIEW_STATUSES = ("CHANGED", "GONE", "AMBIGUOUS")
|
|||||||
REBASE_STATUSES = ("SHIFTED", "RENAMED", "MOVED")
|
REBASE_STATUSES = ("SHIFTED", "RENAMED", "MOVED")
|
||||||
|
|
||||||
WIDEN_STEPS = (0, 3, 6, 12, 25, 50)
|
WIDEN_STEPS = (0, 3, 6, 12, 25, 50)
|
||||||
MAX_MATCH_LINES = 20000
|
# A 30k-line driver diffs in about five seconds, and the biggest files the
|
||||||
|
# corpus cites sit just above that. The cap stays as a guard against
|
||||||
|
# pathological inputs, not as a limit on real source files.
|
||||||
|
MAX_MATCH_LINES = 40000
|
||||||
|
|
||||||
PIN = "pin"
|
PIN = "pin"
|
||||||
HEAD = "head"
|
HEAD = "head"
|
||||||
@@ -257,14 +260,32 @@ def _map_index(opcodes, index: int) -> int | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
_OPCODE_CACHE: dict[tuple[int, int], list] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def _opcodes(pin: list[str], head: list[str]) -> list:
|
||||||
|
"""Opcodes for one pair of revisions, computed once per run.
|
||||||
|
|
||||||
|
Every ref citing the same file would otherwise redo the same diff, and a
|
||||||
|
driver of thirty thousand lines takes seconds each time.
|
||||||
|
"""
|
||||||
|
key = (id(pin), id(head))
|
||||||
|
cached = _OPCODE_CACHE.get(key)
|
||||||
|
if cached is None:
|
||||||
|
cached = difflib.SequenceMatcher(
|
||||||
|
None, pin, head, autojunk=False
|
||||||
|
).get_opcodes()
|
||||||
|
_OPCODE_CACHE[key] = cached
|
||||||
|
return cached
|
||||||
|
|
||||||
|
|
||||||
def _map_changed(pin: list[str], head: list[str], lo: int, hi: int) -> AnchorResult:
|
def _map_changed(pin: list[str], head: list[str], lo: int, hi: int) -> AnchorResult:
|
||||||
"""Map a pinned range onto HEAD once exact anchoring has failed."""
|
"""Map a pinned range onto HEAD once exact anchoring has failed."""
|
||||||
if len(pin) > MAX_MATCH_LINES or len(head) > MAX_MATCH_LINES:
|
if len(pin) > MAX_MATCH_LINES or len(head) > MAX_MATCH_LINES:
|
||||||
return AnchorResult(
|
return AnchorResult(
|
||||||
"CHANGED", None, None, [], f"file over {MAX_MATCH_LINES} lines"
|
"CHANGED", None, None, [], f"file over {MAX_MATCH_LINES} lines"
|
||||||
)
|
)
|
||||||
matcher = difflib.SequenceMatcher(None, pin, head, autojunk=False)
|
opcodes = _opcodes(pin, head)
|
||||||
opcodes = matcher.get_opcodes()
|
|
||||||
if not any(tag == "equal" for tag, *_ in opcodes):
|
if not any(tag == "equal" for tag, *_ in opcodes):
|
||||||
return AnchorResult("GONE", None, None, [])
|
return AnchorResult("GONE", None, None, [])
|
||||||
new_lo = _map_index(opcodes, lo)
|
new_lo = _map_index(opcodes, lo)
|
||||||
@@ -837,10 +858,22 @@ def build_report(
|
|||||||
candidates = near
|
candidates = near
|
||||||
return None, candidates
|
return None, candidates
|
||||||
|
|
||||||
|
lines_cache: dict[tuple[str, str], list[str] | None] = {}
|
||||||
|
|
||||||
def fetch(which: str, path: str):
|
def fetch(which: str, path: str):
|
||||||
view, actual = resolve_path(path)
|
"""Lines for one path at one revision, read once per run.
|
||||||
sha = view.pin if which == PIN else view.head
|
|
||||||
return upstream.fetch_file(view.repo, sha, actual, cache_dir, offline)
|
The same object is handed back every time so the opcode cache can key
|
||||||
|
on identity.
|
||||||
|
"""
|
||||||
|
key = (which, path)
|
||||||
|
if key not in lines_cache:
|
||||||
|
view, actual = resolve_path(path)
|
||||||
|
sha = view.pin if which == PIN else view.head
|
||||||
|
lines_cache[key] = upstream.fetch_file(
|
||||||
|
view.repo, sha, actual, cache_dir, offline
|
||||||
|
)
|
||||||
|
return lines_cache[key]
|
||||||
|
|
||||||
def describe(path: str) -> tuple[str | None, str | None, str]:
|
def describe(path: str) -> tuple[str | None, str | None, str]:
|
||||||
view, actual = resolve_path(path)
|
view, actual = resolve_path(path)
|
||||||
|
|||||||
@@ -283,14 +283,22 @@ class TestAnchorBlock(unittest.TestCase):
|
|||||||
result = anchor_block(["a", "", "b"], ["a", "", "b"], 2, 2)
|
result = anchor_block(["a", "", "b"], ["a", "", "b"], 2, 2)
|
||||||
self.assertEqual(result.status, "CHANGED")
|
self.assertEqual(result.status, "CHANGED")
|
||||||
|
|
||||||
def test_large_file_skips_mapping_with_reason(self):
|
def test_a_file_past_the_cap_skips_mapping_with_reason(self):
|
||||||
pin = [f"line {i}" for i in range(25000)]
|
size = profile_sync.MAX_MATCH_LINES + 1
|
||||||
head = [f"other {i}" for i in range(25000)]
|
pin = [f"line {i}" for i in range(size)]
|
||||||
|
head = [f"other {i}" for i in range(size)]
|
||||||
result = anchor_block(pin, head, 10, 10)
|
result = anchor_block(pin, head, 10, 10)
|
||||||
self.assertEqual(result.status, "CHANGED")
|
self.assertEqual(result.status, "CHANGED")
|
||||||
self.assertIsNotNone(result.reason)
|
self.assertIn(str(profile_sync.MAX_MATCH_LINES), result.reason)
|
||||||
self.assertIsNone(result.start)
|
self.assertIsNone(result.start)
|
||||||
|
|
||||||
|
def test_a_thirty_thousand_line_file_is_still_mapped(self):
|
||||||
|
pin = [f"line {i}" for i in range(30000)]
|
||||||
|
head = ["pad"] + pin[:-1]
|
||||||
|
result = anchor_block(pin, head, 10, 10)
|
||||||
|
self.assertEqual(result.status, "SHIFTED")
|
||||||
|
self.assertEqual(result.start, 11)
|
||||||
|
|
||||||
|
|
||||||
def _part(path, old, new, status):
|
def _part(path, old, new, status):
|
||||||
return PartResult(RefPart(path, old, old), status, None, new, new, [])
|
return PartResult(RefPart(path, old, old), status, None, new, new, [])
|
||||||
|
|||||||
Reference in new issue
Block a user