|
12 | 12 |
|
13 | 13 | from __future__ import annotations |
14 | 14 |
|
| 15 | +import collections |
15 | 16 | import contextlib |
16 | 17 | import errno |
17 | 18 | import gc |
@@ -278,6 +279,8 @@ def _build( |
278 | 279 | TypeState.reset_all_subtype_caches() |
279 | 280 | if options.timing_stats is not None: |
280 | 281 | dump_timing_stats(options.timing_stats, graph) |
| 282 | + if options.line_checking_stats is not None: |
| 283 | + dump_line_checking_stats(options.line_checking_stats, graph) |
281 | 284 | return BuildResult(manager, graph) |
282 | 285 | finally: |
283 | 286 | t0 = time.time() |
@@ -1889,6 +1892,10 @@ class State: |
1889 | 1892 | # Cumulative time spent on this file, in microseconds (for profiling stats) |
1890 | 1893 | time_spent_us: int = 0 |
1891 | 1894 |
|
| 1895 | + # Per-line type-checking time (cumulative time spent type-checking expressions |
| 1896 | + # on a given source code line). |
| 1897 | + per_line_checking_time_ns: dict[int, int] |
| 1898 | + |
1892 | 1899 | def __init__( |
1893 | 1900 | self, |
1894 | 1901 | id: str | None, |
@@ -1956,6 +1963,7 @@ def __init__( |
1956 | 1963 | source = "" |
1957 | 1964 | self.source = source |
1958 | 1965 | self.add_ancestors() |
| 1966 | + self.per_line_checking_time_ns = collections.defaultdict(int) |
1959 | 1967 | t0 = time.time() |
1960 | 1968 | self.meta = validate_meta(self.meta, self.id, self.path, self.ignore_all, manager) |
1961 | 1969 | self.manager.add_stats(validate_meta_time=time.time() - t0) |
@@ -2320,6 +2328,7 @@ def type_checker(self) -> TypeChecker: |
2320 | 2328 | self.tree, |
2321 | 2329 | self.xpath, |
2322 | 2330 | manager.plugin, |
| 2331 | + self.per_line_checking_time_ns, |
2323 | 2332 | ) |
2324 | 2333 | return self._type_checker |
2325 | 2334 |
|
@@ -2945,13 +2954,22 @@ def dumps(self) -> str: |
2945 | 2954 |
|
2946 | 2955 |
|
2947 | 2956 | def dump_timing_stats(path: str, graph: Graph) -> None: |
2948 | | - """ |
2949 | | - Dump timing stats for each file in the given graph |
2950 | | - """ |
| 2957 | + """Dump timing stats for each file in the given graph.""" |
2951 | 2958 | with open(path, "w") as f: |
2952 | | - for k in sorted(graph.keys()): |
2953 | | - v = graph[k] |
2954 | | - f.write(f"{v.id} {v.time_spent_us}\n") |
| 2959 | + for id in sorted(graph): |
| 2960 | + f.write(f"{id} {graph[id].time_spent_us}\n") |
| 2961 | + |
| 2962 | + |
| 2963 | +def dump_line_checking_stats(path: str, graph: Graph) -> None: |
| 2964 | + """Dump per-line expression type checking stats.""" |
| 2965 | + with open(path, "w") as f: |
| 2966 | + for id in sorted(graph): |
| 2967 | + if not graph[id].per_line_checking_time_ns: |
| 2968 | + continue |
| 2969 | + f.write(f"{id}:\n") |
| 2970 | + for line in sorted(graph[id].per_line_checking_time_ns): |
| 2971 | + line_time = graph[id].per_line_checking_time_ns[line] |
| 2972 | + f.write(f"{line:>5} {line_time/1000:8.1f}\n") |
2955 | 2973 |
|
2956 | 2974 |
|
2957 | 2975 | def dump_graph(graph: Graph, stdout: TextIO | None = None) -> None: |
|
0 commit comments