move Perf to its own module
This commit is contained in:
43
babi/main.py
43
babi/main.py
@@ -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
47
babi/perf.py
Normal 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')
|
||||||
Reference in New Issue
Block a user