move Perf to its own module

This commit is contained in:
Anthony Sottile
2020-02-22 14:08:04 -08:00
parent 8693894fae
commit 9343805ad0
2 changed files with 48 additions and 42 deletions

View File

@@ -1,7 +1,6 @@
import argparse import argparse
import collections import collections
import contextlib import contextlib
import cProfile
import curses import curses
import enum import enum
import functools import functools
@@ -12,7 +11,6 @@ import os
import re import re
import signal import signal
import sys import sys
import time
from typing import Any from typing import Any
from typing import Callable from typing import Callable
from typing import cast from typing import cast
@@ -34,6 +32,7 @@ from babi.horizontal_scrolling import scrolled_line
from babi.list_spy import ListSpy from babi.list_spy import ListSpy
from babi.list_spy import MutableSequenceNoSlice from babi.list_spy import MutableSequenceNoSlice
from babi.margin import Margin from babi.margin import Margin
from babi.perf import Perf
from babi.prompt import Prompt from babi.prompt import Prompt
from babi.prompt import PromptResult from babi.prompt import PromptResult
from babi.status import Status from babi.status import Status
@@ -105,46 +104,6 @@ class History:
f.write('\n'.join(new_history) + '\n') f.write('\n'.join(new_history) + '\n')
class Perf:
def __init__(self) -> None:
self._prof: Optional[cProfile.Profile] = None
self._records: List[Tuple[str, float]] = []
self._name: Optional[str] = None
self._time: Optional[float] = None
def start(self, name: str) -> None:
if self._prof:
assert self._name is None, self._name
self._name = name
self._time = time.monotonic()
self._prof.enable()
def end(self) -> None:
if self._prof:
assert self._name is not None
assert self._time is not None
self._prof.disable()
self._records.append((self._name, time.monotonic() - self._time))
self._name = self._time = None
@contextlib.contextmanager
def log(self, filename: Optional[str]) -> Generator[None, None, None]:
if filename is None:
yield
else:
self._prof = cProfile.Profile()
self.start('startup')
try:
yield
finally:
self.end()
self._prof.dump_stats(f'{filename}.pstats')
with open(filename, 'w') as f:
f.write('μs\tevent\n')
for name, duration in self._records:
f.write(f'{int(duration * 1000 * 1000)}\t{name}\n')
def _restore_lines_eof_invariant(lines: MutableSequenceNoSlice) -> None: def _restore_lines_eof_invariant(lines: MutableSequenceNoSlice) -> None:
"""The file lines will always contain a blank empty string at the end to """The file lines will always contain a blank empty string at the end to
simplify rendering. This should be called whenever the end of the file simplify rendering. This should be called whenever the end of the file

47
babi/perf.py Normal file
View File

@@ -0,0 +1,47 @@
import contextlib
import cProfile
import time
from typing import Generator
from typing import List
from typing import Optional
from typing import Tuple
class Perf:
def __init__(self) -> None:
self._prof: Optional[cProfile.Profile] = None
self._records: List[Tuple[str, float]] = []
self._name: Optional[str] = None
self._time: Optional[float] = None
def start(self, name: str) -> None:
if self._prof:
assert self._name is None, self._name
self._name = name
self._time = time.monotonic()
self._prof.enable()
def end(self) -> None:
if self._prof:
assert self._name is not None
assert self._time is not None
self._prof.disable()
self._records.append((self._name, time.monotonic() - self._time))
self._name = self._time = None
@contextlib.contextmanager
def log(self, filename: Optional[str]) -> Generator[None, None, None]:
if filename is None:
yield
else:
self._prof = cProfile.Profile()
self.start('startup')
try:
yield
finally:
self.end()
self._prof.dump_stats(f'{filename}.pstats')
with open(filename, 'w') as f:
f.write('μs\tevent\n')
for name, duration in self._records:
f.write(f'{int(duration * 1000 * 1000)}\t{name}\n')