mirror of
https://github.com/isledecomp/isle.git
synced 2026-01-31 12:11:15 +00:00
Sort by avg address with outliers removed
This commit is contained in:
parent
60a7f60cd4
commit
769750a5f3
@ -5,7 +5,8 @@
|
|||||||
import os
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
from typing import List, Optional
|
import statistics
|
||||||
|
from typing import Iterator, List, Optional, Tuple
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from isledecomp import Bin as IsleBin
|
from isledecomp import Bin as IsleBin
|
||||||
from isledecomp.cvdump import Cvdump
|
from isledecomp.cvdump import Cvdump
|
||||||
@ -90,6 +91,19 @@ def truncate_module_name(prefix: str, module: str) -> str:
|
|||||||
return module
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
def avg_remove_outliers(entries: List[int]) -> int:
|
||||||
|
"""Compute the average from this list of entries (addresses)
|
||||||
|
after removing outlier values."""
|
||||||
|
|
||||||
|
if len(entries) == 1:
|
||||||
|
return entries[0]
|
||||||
|
|
||||||
|
avg = statistics.mean(entries)
|
||||||
|
sd = statistics.pstdev(entries)
|
||||||
|
|
||||||
|
return int(statistics.mean([e for e in entries if abs(e - avg) <= 2 * sd]))
|
||||||
|
|
||||||
|
|
||||||
RoadmapRow = namedtuple(
|
RoadmapRow = namedtuple(
|
||||||
"RoadmapRow",
|
"RoadmapRow",
|
||||||
[
|
[
|
||||||
@ -110,10 +124,17 @@ class DeltaCollector:
|
|||||||
"""Reads each row of the results and aggregates information about the
|
"""Reads each row of the results and aggregates information about the
|
||||||
placement of each module."""
|
placement of each module."""
|
||||||
|
|
||||||
def __init__(self, match_type: str = "fun"):
|
def __init__(self, match_type: str = "fun") -> None:
|
||||||
|
# The displacement for each symbol from each module
|
||||||
self.disp_map = {}
|
self.disp_map = {}
|
||||||
|
|
||||||
|
# Each address for each module
|
||||||
|
self.addresses = {}
|
||||||
|
|
||||||
|
# The earliest address for each module
|
||||||
self.earliest = {}
|
self.earliest = {}
|
||||||
self.seen = set()
|
|
||||||
|
# String abbreviation for which symbol type we are checking
|
||||||
self.match_type = "fun"
|
self.match_type = "fun"
|
||||||
|
|
||||||
match_type = str(match_type).strip().lower()[:3]
|
match_type = str(match_type).strip().lower()[:3]
|
||||||
@ -124,11 +145,15 @@ def read_row(self, row: RoadmapRow):
|
|||||||
if row.module is None:
|
if row.module is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.seen.add(row.module)
|
|
||||||
if row.sym_type != self.match_type:
|
if row.sym_type != self.match_type:
|
||||||
return
|
return
|
||||||
|
|
||||||
if row.orig_addr is not None:
|
if row.orig_addr is not None:
|
||||||
|
if row.module not in self.addresses:
|
||||||
|
self.addresses[row.module] = []
|
||||||
|
|
||||||
|
self.addresses[row.module].append(row.orig_addr)
|
||||||
|
|
||||||
if row.orig_addr < self.earliest.get(row.module, 0xFFFFFFFFF):
|
if row.orig_addr < self.earliest.get(row.module, 0xFFFFFFFFF):
|
||||||
self.earliest[row.module] = row.orig_addr
|
self.earliest[row.module] = row.orig_addr
|
||||||
|
|
||||||
@ -138,6 +163,15 @@ def read_row(self, row: RoadmapRow):
|
|||||||
|
|
||||||
self.disp_map[row.module].append(row.displacement)
|
self.disp_map[row.module].append(row.displacement)
|
||||||
|
|
||||||
|
def iter_sorted(self) -> Iterator[Tuple[int, int]]:
|
||||||
|
"""Compute the average address for each module, then generate them
|
||||||
|
in ascending order."""
|
||||||
|
avg_address = {
|
||||||
|
mod: avg_remove_outliers(values) for mod, values in self.addresses.items()
|
||||||
|
}
|
||||||
|
for mod, avg in sorted(avg_address.items(), key=lambda x: x[1]):
|
||||||
|
yield (avg, mod)
|
||||||
|
|
||||||
|
|
||||||
def suggest_order(results: List[RoadmapRow], cmake_modules: List[str], match_type: str):
|
def suggest_order(results: List[RoadmapRow], cmake_modules: List[str], match_type: str):
|
||||||
"""Suggest the order of modules for CMakeLists.txt"""
|
"""Suggest the order of modules for CMakeLists.txt"""
|
||||||
@ -156,14 +190,12 @@ def suggest_order(results: List[RoadmapRow], cmake_modules: List[str], match_typ
|
|||||||
set("/".join(mod.split("/", 2)[:2]) + "/" for mod in leftover_modules)
|
set("/".join(mod.split("/", 2)[:2]) + "/" for mod in leftover_modules)
|
||||||
)
|
)
|
||||||
|
|
||||||
# These may already be sorted by earliest, but make sure
|
computed_order = list(dc.iter_sorted())
|
||||||
first_function = [(earliest, module) for (module, earliest) in dc.earliest.items()]
|
|
||||||
first_function.sort()
|
|
||||||
|
|
||||||
for prefix in cmake_prefixes:
|
for prefix in cmake_prefixes:
|
||||||
print(prefix)
|
print(prefix)
|
||||||
# Show modules ordered by the first appearance of whichever symbol type.
|
# Show modules ordered by the computed average of addresses
|
||||||
for start, module in first_function:
|
for _, module in computed_order:
|
||||||
if not module.startswith(prefix):
|
if not module.startswith(prefix):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -172,10 +204,11 @@ def suggest_order(results: List[RoadmapRow], cmake_modules: List[str], match_typ
|
|||||||
avg_displacement = None
|
avg_displacement = None
|
||||||
displacements = dc.disp_map.get(module)
|
displacements = dc.disp_map.get(module)
|
||||||
if displacements is not None and len(displacements) > 0:
|
if displacements is not None and len(displacements) > 0:
|
||||||
avg_displacement = int(sum(displacements) / len(displacements))
|
avg_displacement = int(statistics.mean(displacements))
|
||||||
|
|
||||||
|
earliest = dc.earliest.get(module)
|
||||||
code_file = truncate_module_name(prefix, module)
|
code_file = truncate_module_name(prefix, module)
|
||||||
print(f"0x{start:08x} {or_blank(avg_displacement):10} {code_file}")
|
print(f"0x{earliest:08x} {avg_displacement:10} {code_file}")
|
||||||
|
|
||||||
# These modules are included in the final binary (in some form) but
|
# These modules are included in the final binary (in some form) but
|
||||||
# they are not represented by whichever type of symbol we were checking.
|
# they are not represented by whichever type of symbol we were checking.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user