austin-python 2.1.0__py3-none-any.whl → 2.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- austin/events.py +1 -2
- austin/format/collapsed_stack.py +2 -2
- austin/format/mojo.py +21 -2
- austin/format/pprof/__main__.py +7 -4
- austin/format/speedscope.py +23 -15
- austin/stats.py +18 -15
- {austin_python-2.1.0.dist-info → austin_python-2.1.2.dist-info}/METADATA +1 -1
- {austin_python-2.1.0.dist-info → austin_python-2.1.2.dist-info}/RECORD +13 -13
- {austin_python-2.1.0.dist-info → austin_python-2.1.2.dist-info}/WHEEL +0 -0
- {austin_python-2.1.0.dist-info → austin_python-2.1.2.dist-info}/entry_points.txt +0 -0
- {austin_python-2.1.0.dist-info → austin_python-2.1.2.dist-info}/licenses/AUTHORS +0 -0
- {austin_python-2.1.0.dist-info → austin_python-2.1.2.dist-info}/licenses/COPYING +0 -0
- {austin_python-2.1.0.dist-info → austin_python-2.1.2.dist-info}/licenses/LICENSE.md +0 -0
austin/events.py
CHANGED
austin/format/collapsed_stack.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import typing as t
|
|
2
1
|
from functools import singledispatchmethod
|
|
3
2
|
from pathlib import Path
|
|
3
|
+
import typing as t
|
|
4
4
|
|
|
5
5
|
from austin.events import AustinEvent
|
|
6
6
|
from austin.events import AustinEventIterator
|
|
@@ -48,7 +48,7 @@ def parse_frame(frame: str) -> AustinFrame:
|
|
|
48
48
|
filename, function, line = frame.rsplit(":", maxsplit=2)
|
|
49
49
|
except ValueError:
|
|
50
50
|
raise InvalidFrame(frame) from None
|
|
51
|
-
return AustinFrame(filename=filename, function=function, line=int(line))
|
|
51
|
+
return AustinFrame(filename=filename, function=function, line=int(line or 0))
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
def parse_collapsed_stack(sample: str) -> AustinSample:
|
austin/format/mojo.py
CHANGED
|
@@ -277,7 +277,12 @@ def str_reader() -> t.Generator[t.Optional[str], bytes, str]:
|
|
|
277
277
|
(b,) = yield bytes(buffer[:i]).decode(errors="replace")
|
|
278
278
|
i = 0
|
|
279
279
|
else:
|
|
280
|
-
|
|
280
|
+
try:
|
|
281
|
+
buffer[i] = b
|
|
282
|
+
except IndexError:
|
|
283
|
+
# Expand the buffer if needed
|
|
284
|
+
buffer += bytearray(i - len(buffer) + 1)
|
|
285
|
+
buffer[i] = b
|
|
281
286
|
(b,) = yield None
|
|
282
287
|
i += 1
|
|
283
288
|
|
|
@@ -353,6 +358,14 @@ class BaseMojoStreamReader(AustinEventIterator):
|
|
|
353
358
|
|
|
354
359
|
return metadata
|
|
355
360
|
|
|
361
|
+
@property
|
|
362
|
+
def mode(self) -> t.Optional[str]:
|
|
363
|
+
return self.metadata.get("mode")
|
|
364
|
+
|
|
365
|
+
@property
|
|
366
|
+
def gc(self) -> t.Optional[str]:
|
|
367
|
+
return self.metadata.get("gc")
|
|
368
|
+
|
|
356
369
|
def _finalize_sample(self) -> AustinSample:
|
|
357
370
|
"""Finalize the current sample."""
|
|
358
371
|
assert self._running_sample is not None, self._running_sample
|
|
@@ -395,7 +408,13 @@ class BaseMojoStreamReader(AustinEventIterator):
|
|
|
395
408
|
if self._running_sample is not None:
|
|
396
409
|
self._finalize_sample()
|
|
397
410
|
|
|
398
|
-
self._running_sample = _RunningSample(
|
|
411
|
+
self._running_sample = _RunningSample(
|
|
412
|
+
pid=pid,
|
|
413
|
+
iid=iid,
|
|
414
|
+
thread=thread,
|
|
415
|
+
idle=False if self.mode == "full" else None,
|
|
416
|
+
gc=False if self.gc is not None else None,
|
|
417
|
+
)
|
|
399
418
|
|
|
400
419
|
return MojoStack(pid, iid if iid is not None else -1, thread)
|
|
401
420
|
|
austin/format/pprof/__main__.py
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
23
23
|
|
|
24
24
|
from argparse import ArgumentParser
|
|
25
|
+
from pathlib import Path
|
|
25
26
|
|
|
26
27
|
from austin.events import AustinMetadata
|
|
27
28
|
from austin.events import AustinSample
|
|
@@ -41,19 +42,21 @@ def main() -> None:
|
|
|
41
42
|
|
|
42
43
|
arg_parser.add_argument(
|
|
43
44
|
"input",
|
|
44
|
-
type=
|
|
45
|
+
type=Path,
|
|
45
46
|
help="The input file containing Austin samples.",
|
|
46
47
|
)
|
|
47
48
|
arg_parser.add_argument(
|
|
48
|
-
"output",
|
|
49
|
+
"output",
|
|
50
|
+
type=Path,
|
|
51
|
+
help="The name of the output pprof file.",
|
|
49
52
|
)
|
|
50
53
|
|
|
51
|
-
arg_parser.add_argument("-V", "--version", action="version", version="0.2.
|
|
54
|
+
arg_parser.add_argument("-V", "--version", action="version", version="0.2.1")
|
|
52
55
|
|
|
53
56
|
args = arg_parser.parse_args()
|
|
54
57
|
|
|
55
58
|
try:
|
|
56
|
-
with
|
|
59
|
+
with args.input.open() as austin, AustinFileReader(austin) as fin:
|
|
57
60
|
pprof = None
|
|
58
61
|
for e in fin:
|
|
59
62
|
if isinstance(e, AustinMetadata) and e.name == "mode":
|
austin/format/speedscope.py
CHANGED
|
@@ -26,6 +26,7 @@ from dataclasses import asdict
|
|
|
26
26
|
from dataclasses import dataclass
|
|
27
27
|
from dataclasses import field
|
|
28
28
|
from enum import Enum
|
|
29
|
+
from pathlib import Path
|
|
29
30
|
from typing import Dict
|
|
30
31
|
from typing import List
|
|
31
32
|
from typing import Optional
|
|
@@ -33,13 +34,14 @@ from typing import TextIO
|
|
|
33
34
|
from typing import Union
|
|
34
35
|
|
|
35
36
|
from austin.events import AustinFrame
|
|
37
|
+
from austin.events import AustinMetadata
|
|
36
38
|
from austin.events import AustinSample
|
|
37
39
|
from austin.format import Mode
|
|
38
40
|
from austin.format.collapsed_stack import AustinFileReader
|
|
39
41
|
from austin.format.collapsed_stack import InvalidSample
|
|
40
42
|
|
|
41
43
|
|
|
42
|
-
__version__ = "0.3.
|
|
44
|
+
__version__ = "0.3.1"
|
|
43
45
|
|
|
44
46
|
SpeedscopeJson = Dict
|
|
45
47
|
SpeedscopeWeight = int
|
|
@@ -208,11 +210,11 @@ def main() -> None:
|
|
|
208
210
|
|
|
209
211
|
arg_parser.add_argument(
|
|
210
212
|
"input",
|
|
211
|
-
type=
|
|
213
|
+
type=Path,
|
|
212
214
|
help="The input file containing Austin samples in normal format.",
|
|
213
215
|
)
|
|
214
216
|
arg_parser.add_argument(
|
|
215
|
-
"output", type=
|
|
217
|
+
"output", type=Path, help="The name of the output Speedscope JSON file."
|
|
216
218
|
)
|
|
217
219
|
arg_parser.add_argument(
|
|
218
220
|
"--indent", type=int, help="Give a non-null value to prettify the JSON output."
|
|
@@ -223,24 +225,30 @@ def main() -> None:
|
|
|
223
225
|
args = arg_parser.parse_args()
|
|
224
226
|
|
|
225
227
|
try:
|
|
226
|
-
with
|
|
227
|
-
|
|
228
|
-
speedscope = Speedscope(os.path.basename(args.input), mode, args.indent)
|
|
228
|
+
with args.input.open() as austin, AustinFileReader(austin) as fin:
|
|
229
|
+
speedscope = None
|
|
229
230
|
for event in fin:
|
|
230
|
-
if
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
if isinstance(event, AustinMetadata):
|
|
232
|
+
if event.name == "mode":
|
|
233
|
+
speedscope = Speedscope(
|
|
234
|
+
os.path.basename(args.input), event.value, args.indent
|
|
235
|
+
)
|
|
236
|
+
elif isinstance(event, AustinSample):
|
|
237
|
+
if speedscope is not None:
|
|
238
|
+
speedscope.add_sample(event)
|
|
239
|
+
else:
|
|
240
|
+
raise ValueError("Invalid sample found in input file")
|
|
241
|
+
|
|
242
|
+
if speedscope is None:
|
|
243
|
+
raise RuntimeError("Invalid input file: no mode metadata found")
|
|
244
|
+
|
|
245
|
+
with args.output.open("w") as fout:
|
|
246
|
+
speedscope.dump(fout)
|
|
236
247
|
|
|
237
248
|
except FileNotFoundError:
|
|
238
249
|
print(f"No such input file: {args.input}")
|
|
239
250
|
exit(1)
|
|
240
251
|
|
|
241
|
-
with open(args.output, "w") as fout:
|
|
242
|
-
speedscope.dump(fout)
|
|
243
|
-
|
|
244
252
|
|
|
245
253
|
if __name__ == "__main__":
|
|
246
254
|
main()
|
austin/stats.py
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
# You should have received a copy of the GNU General Public License
|
|
22
22
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
23
23
|
|
|
24
|
+
from collections import namedtuple
|
|
24
25
|
from copy import deepcopy
|
|
25
26
|
from dataclasses import dataclass
|
|
26
27
|
from dataclasses import field
|
|
@@ -39,10 +40,12 @@ from austin.events import AustinMetadata
|
|
|
39
40
|
from austin.events import AustinMetrics
|
|
40
41
|
from austin.events import AustinSample
|
|
41
42
|
from austin.events import ProcessId
|
|
42
|
-
from austin.events import ThreadName
|
|
43
43
|
from austin.format.collapsed_stack import AustinEventCollapsedStackFormatter
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
ThreadInfo = namedtuple("ThreadInfo", ["thread", "iid"])
|
|
47
|
+
|
|
48
|
+
|
|
46
49
|
COLLAPSED_STACK_FORMATTER = AustinEventCollapsedStackFormatter()
|
|
47
50
|
|
|
48
51
|
|
|
@@ -136,12 +139,12 @@ class FrameStats(HierarchicalStats):
|
|
|
136
139
|
class ThreadStats(HierarchicalStats):
|
|
137
140
|
"""Thread statistics."""
|
|
138
141
|
|
|
139
|
-
label:
|
|
142
|
+
label: ThreadInfo
|
|
140
143
|
children: Dict[AustinFrame, FrameStats] = field(default_factory=dict) # type: ignore[assignment]
|
|
141
144
|
|
|
142
145
|
def collapse(
|
|
143
146
|
self, stats_type: AustinStatsType
|
|
144
|
-
) -> Generator[Tuple[
|
|
147
|
+
) -> Generator[Tuple[ThreadInfo, List[AustinFrame], AustinMetrics], None, None]:
|
|
145
148
|
"""Collapse the hierarchical statistics."""
|
|
146
149
|
|
|
147
150
|
if self.own:
|
|
@@ -166,7 +169,7 @@ class ProcessStats:
|
|
|
166
169
|
"""Process statistics."""
|
|
167
170
|
|
|
168
171
|
pid: ProcessId
|
|
169
|
-
threads: Dict[
|
|
172
|
+
threads: Dict[ThreadInfo, ThreadStats] = field(default_factory=dict)
|
|
170
173
|
|
|
171
174
|
def collapse(
|
|
172
175
|
self, stats_type: AustinStatsType
|
|
@@ -175,22 +178,22 @@ class ProcessStats:
|
|
|
175
178
|
yield from (
|
|
176
179
|
AustinSample(
|
|
177
180
|
pid=self.pid,
|
|
178
|
-
iid=
|
|
179
|
-
thread=
|
|
181
|
+
iid=thread_info.iid,
|
|
182
|
+
thread=thread_info.thread,
|
|
180
183
|
frames=tuple(frames),
|
|
181
184
|
metrics=metric,
|
|
182
185
|
)
|
|
183
186
|
for thread in self.threads.values()
|
|
184
|
-
for
|
|
187
|
+
for thread_info, frames, metric in thread.collapse(stats_type)
|
|
185
188
|
)
|
|
186
189
|
|
|
187
|
-
def get_thread(self,
|
|
190
|
+
def get_thread(self, thread_info: ThreadInfo) -> Optional[ThreadStats]:
|
|
188
191
|
"""Get thread statistics from this process by name.
|
|
189
192
|
|
|
190
193
|
If the given thread name is not registered with this current process
|
|
191
194
|
statistics, then ``None`` is returned.
|
|
192
195
|
"""
|
|
193
|
-
return self.threads.get(
|
|
196
|
+
return self.threads.get(thread_info)
|
|
194
197
|
|
|
195
198
|
|
|
196
199
|
@dataclass
|
|
@@ -286,8 +289,8 @@ class AustinStats:
|
|
|
286
289
|
return
|
|
287
290
|
|
|
288
291
|
pid = sample.pid
|
|
289
|
-
|
|
290
|
-
thread_stats = ThreadStats(
|
|
292
|
+
thread_info = ThreadInfo(sample.thread, sample.iid or 0)
|
|
293
|
+
thread_stats = ThreadStats(thread_info, own=0, total=metric)
|
|
291
294
|
|
|
292
295
|
# Convert the list of frames into a nested FrameStats instance
|
|
293
296
|
stats: HierarchicalStats = thread_stats
|
|
@@ -300,15 +303,15 @@ class AustinStats:
|
|
|
300
303
|
|
|
301
304
|
with self._lock:
|
|
302
305
|
if pid not in self.processes:
|
|
303
|
-
self.processes[pid] = ProcessStats(pid, {
|
|
306
|
+
self.processes[pid] = ProcessStats(pid, {thread_info: thread_stats})
|
|
304
307
|
return
|
|
305
308
|
|
|
306
309
|
process = self.processes[pid]
|
|
307
|
-
if
|
|
308
|
-
process.threads[
|
|
310
|
+
if thread_info not in process.threads:
|
|
311
|
+
process.threads[thread_info] = thread_stats
|
|
309
312
|
return
|
|
310
313
|
|
|
311
|
-
process.threads[
|
|
314
|
+
process.threads[thread_info] << thread_stats
|
|
312
315
|
|
|
313
316
|
def flatten(self) -> Generator[AustinSample, None, None]:
|
|
314
317
|
for process in self.processes.values():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: austin-python
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: Python wrapper for Austin, the CPython frame stack sampler.
|
|
5
5
|
Project-URL: homepage, https://github.com/P403n1x87/austin-python
|
|
6
6
|
Project-URL: documentation, https://austin-python.readthedocs.io
|
|
@@ -4,26 +4,26 @@ austin/base.py,sha256=wAYVZQi3hcgJA9cVg3mfc3f3E0qwFXmeX7UX6qgn2Pk,7554
|
|
|
4
4
|
austin/cli.py,sha256=--PKm2I4NBBSSSBV5l-YC0mcmLjrvb1FHzxgY4dkby4,7826
|
|
5
5
|
austin/config.py,sha256=PEwdG2Cy8ay1SrFr2N6YfQSZwseYBA1BA5dMfocKR3A,2091
|
|
6
6
|
austin/errors.py,sha256=lCDSTANW_95Az_eDXbn__JRBllB9yw7tGnFo1-tw09Q,1046
|
|
7
|
-
austin/events.py,sha256=
|
|
7
|
+
austin/events.py,sha256=NppffZg_lbKIin2TyvIGgfJXnOmBKzB2e0nQV4_94JA,2160
|
|
8
8
|
austin/simple.py,sha256=iTmJGAjSBeUv82SgdMTwdNlAQwuK33RyU8FkBCE8rRg,5579
|
|
9
|
-
austin/stats.py,sha256=
|
|
9
|
+
austin/stats.py,sha256=4kVeZ5NJsoSEnogqiDyjAbLeuf5DPiELHfCEbjFb0zk,10990
|
|
10
10
|
austin/threads.py,sha256=AvcoOkr3FeFAGBcqgXukNIt9xOZUipv7pXMqPIL_Qts,3649
|
|
11
11
|
austin/format/__init__.py,sha256=ZtBJCLpTiZaLFwCN1UbMXLQvYjOSpwmtyGwqgK8yruQ,405
|
|
12
|
-
austin/format/collapsed_stack.py,sha256=
|
|
12
|
+
austin/format/collapsed_stack.py,sha256=VCkTJssgcF4IHGP6kzV5dT9AC9Qjbq8eGx9AVOp6cyU,7246
|
|
13
13
|
austin/format/compress.py,sha256=YEceebWzVB7eSCntnJ89_rIcbzBskvZGy86D5QgZli0,3741
|
|
14
|
-
austin/format/mojo.py,sha256=
|
|
15
|
-
austin/format/speedscope.py,sha256=
|
|
14
|
+
austin/format/mojo.py,sha256=mEcKgaZkVkH4YGVLj4m31_MAPKfYK-BNI7oWyiPub0U,28824
|
|
15
|
+
austin/format/speedscope.py,sha256=RvlFugm0S3ATMf9lmzH8jrX4oBt8PJ0j9EsuXWayOQc,8381
|
|
16
16
|
austin/format/pprof/__init__.py,sha256=DvY1CDnPqBc-GUv9fidtMplshIIXj_HWZ3SlWOJoLxc,6805
|
|
17
|
-
austin/format/pprof/__main__.py,sha256=
|
|
17
|
+
austin/format/pprof/__main__.py,sha256=pzWoSmlFrjfmAAq5I4SIIDmxavdLStCnlw3NlBxgyDo,2652
|
|
18
18
|
austin/format/pprof/profile.proto,sha256=fPfBgzXIEmFdrrwgTQWs-9GwKjt-TShRmJq-eaxDx88,8840
|
|
19
19
|
austin/format/pprof/profile_pb2.py,sha256=i_uM8lDExR95yz7qnEVikhpkpNvetKaYzoiH7AbMAt8,28214
|
|
20
20
|
austin/tools/diff.py,sha256=KnY9kD5mmSKALCNxnSe-dSObC4LgkoxLGnoTiklKa5M,4821
|
|
21
21
|
austin/tools/mojodbg.py,sha256=BGdngj-r1c-GAQDrs_oJ_x4QZxuL4t_OQ194fvJJm7A,2817
|
|
22
22
|
austin/tools/resolve.py,sha256=pEOBiP8FNkaJqDTj3fOK8dx5-EocroqZDXLL3CzCWLY,7677
|
|
23
|
-
austin_python-2.1.
|
|
24
|
-
austin_python-2.1.
|
|
25
|
-
austin_python-2.1.
|
|
26
|
-
austin_python-2.1.
|
|
27
|
-
austin_python-2.1.
|
|
28
|
-
austin_python-2.1.
|
|
29
|
-
austin_python-2.1.
|
|
23
|
+
austin_python-2.1.2.dist-info/METADATA,sha256=wdZJGpu-uI1aH1NwbKstmCYnYdsXzX2UZ-6c-gFzjTg,7535
|
|
24
|
+
austin_python-2.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
25
|
+
austin_python-2.1.2.dist-info/entry_points.txt,sha256=YatHOUQsHQ3WABcrNKPf4RWatQ0CzbR-1ClXjMjZys8,329
|
|
26
|
+
austin_python-2.1.2.dist-info/licenses/AUTHORS,sha256=pARRmpJQYH8iWy_0SonXsxOiV02AFitowle4AtURxUI,45
|
|
27
|
+
austin_python-2.1.2.dist-info/licenses/COPYING,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
|
28
|
+
austin_python-2.1.2.dist-info/licenses/LICENSE.md,sha256=edVDhmEiPf2W5lWzqLkrj6EYLSrCeYg9MJy28YsiMFU,34937
|
|
29
|
+
austin_python-2.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|