[HN Gopher] Show HN: Austin-Tui - Spy inside a running Python pr... ___________________________________________________________________ Show HN: Austin-Tui - Spy inside a running Python program at no performance cost Author : p403n1x87 Score : 220 points Date : 2020-10-27 11:08 UTC (11 hours ago) (HTM) web link (github.com) (TXT) w3m dump (github.com) | emddudley wrote: | This is a TUI for the profiler Austin, whose README has a bit | more detail on what it can do: | | https://github.com/P403n1x87/austin | shepardrtc wrote: | Love the TUI! Which library did you use for it? | p403n1x87 wrote: | I wrote a blog post about the technology behind the TUI | | https://p403n1x87.github.io/the-austin-tui-way-to-resourcefu... | | It's a custom resource-based framework that uses curses as | back-end. | kingosticks wrote: | This looks really interesting - thanks! | | One question: in the first XML example (minimal-view.xml), | why is the root element a <aui:MinimalView ...> but then the | last line ends it with </aui:MiniTop> ? Is it a typo or is | there something else going on? | p403n1x87 wrote: | Ah! Totally a typo, thanks for that :) | tr33house wrote: | looks awesome. how easy is it to use this to profile a webapp | written in a framework like django? Open-metrics? just curious | p403n1x87 wrote: | as easy as profiling with Austin itself. Just pass the pid of | the web server | | sudo austin-tui -Cp <webserverpid> | | See https://github.com/P403n1x87/austin#examples for more | details. To avoid using sudo on Linux you can do | | sudo setcap cap_sys_ptrace+ep `which austin` | | and then simply | | austin-tui -Cp <webserverpid> | galacticdessert wrote: | Pyinstrument might be easier to profile web requests: | https://github.com/joerick/pyinstrument#profile-a-web-reques... | p403n1x87 wrote: | One benefit of Austin-based tools is that they don't require | any instrumentation/extra configuration. The low overhead | means that you can just attach to an application that is | running in production. | Pulcinella wrote: | What's the difference between a TUI and a CLI? | | (Also my preferred TUI acronym is tactile user interface). | pjmlp wrote: | Back in the MS-DOS days a TUI would be something done with | Turbo Vision or Clipper, simulating GUIs with text. | ktpsns wrote: | Another example: | | https://en.wikipedia.org/wiki/Ed_(text_editor) has a CLI, but | | https://en.wikipedia.org/wiki/Vim_(text_editor) has a TUI. | MaxBarraclough wrote: | Both use the terminal, but in different ways. A CLI interface | uses the basic terminal functionality of writing and perhaps | reading lines, or even simply accepting flags and running non- | interactively. A TUI uses the terminal's advanced features, | using the terminal as the basis for a kind of GUI, generally | occupying the full area of the terminal. | | _Vim_ , _Midnight Commander_ , and _htop_ have TUIs. They rely | heavily on the terminal 's 'control character' features to | accomplish this. _apt-get_ has a CLI, as its interactive IO is | handled with printing lines and having the user submit lines | (even if it 's just the letter _y_ ). | | Somewhere in the middle are interfaces like _bash_ and _zsh_ | which make light use of the terminal 's advanced features for | things like auto-complete, but which don't take over the whole | terminal area. | | I'd count non-interactive applications like _gcc_ and _sort_ as | command-line applications, although strictly speaking you could | just as well use a graphical interface to configure their flags | and run commands. | | See also https://en.wikipedia.org/wiki/Text- | based_user_interface | junon wrote: | God these explanations suck. Reminds me of the "two boats meet | in an ocean" explanation of IRC. | | A CLI (command line interface) just uses the streams to show | and take in data. | | A TUI uses escape codes or proprietary console commands (the | latter on Windows, the former on most other things) to take | control of the entire console window and display a user | interface (hence Text User Interface or TUI). Usually mouse | input is handled on modern systems too. | emddudley wrote: | I would say that a CLI is primarily for entering commands, | while a TUI is primarily for viewing and interacting with data. | m4r35n357 wrote: | TOP User interface (from TFA). | mehrdadn wrote: | CLI refers to interacting with a program by typing commands. | Commands need not come from a terminal (a terminal need not | even exist). They might be just passed in from a different | program. | | TUI refers to interacting with a program via the terminal--the | terminal _is_ the program 's user interface (think 'nano', | which you can't really run without a terminal). The terminal | need not interact via commands, although many TUI programs also | accept commands. | frou_dh wrote: | If a CLI program ceases to make sense when its standard-output | is a physical line-printer onto a roll of paper, then it's a | TUI. | jvns wrote: | Two other profilers that also let you spy on a running Python | program: | | - py-spy: https://github.com/benfred/py-spy (written in Rust) | | - pyflame: https://github.com/uber-archive/pyflame (C++, seems to | be not maintained anymore) | | The "no performance cost" thing is interesting: my experience | writing a similar profiler is that there are a couple of things | that can affect performance a little bit: | | 1. You have to make a lot of system calls to read the memory of | the target process, and if you want to sample at a high rate then | that does use some CPU. This can be an issue if you only have 1 | CPU. | | 2. you have two choices when reading memory from a process: you | can either race with the program and hope that you read its | memory to get the function stack before it changes what function | it's running (and you're likely to win the race, because C is | faster than Python), or you can pause the program briefly while | taking a sample. py-spy has an option to choose which one you | want to do: https://github.com/benfred/py-spy#how-can-i-avoid- | pausing-th... | | Definitely this method is a lot lower overhead than a tracing | profiler that instruments every single function call, and in | practice it works well. | | One thing I think is nice about this kind of profiler is that | reading memory from the target process sounds like a complicated | thing, but it's not: you can see austin's code for reading memory | here, and it's implemented for 3 platforms in just 130 lines of | C: | https://github.com/P403n1x87/austin/blob/877e2ff946ea5313e47... | p403n1x87 wrote: | All good points. The "no performance cost" is indeed more like | "negligible performance costs". That's because these days | multicore architectures are quite ubiquitous and standard | Python applications are single process. For multi-process | Python applications, a busy profiler would certainly steal a | good chunk of a core, so the impact might be noticeable in that | case. | | As for the race conditions, Austin does not introduce any | pauses. Even if it did, there would be no guarantee that it | paused at a "good" point, so there are no real benefits in | terms of accuracy in pausing. Error rates are quite low anyway, | so the actual benefit comes from not pausing at all. | benfrederickson wrote: | > you can either race with the program and hope that you read | its memory to get the function stack before it changes what | function it's running (and you're likely to win the race, | because C is faster than Python), or you can pause the program | briefly while taking a sample. | | Py-spy defaults to blocking because the results can be pretty | wrong otherwise: https://github.com/benfred/py-spy/issues/56 . | You can see this problem profiling a program like | https://github.com/benfred/py-spy/blob/master/tests/scripts/... | with or without the nonblocking flag in py-spy - the | nonblocking version produces garbage output. | | Somewhat interestingly, this problem doesn't seem to occur with | Ruby - and rbspy can get away without pausing the target | program with only minor errors seen when profiling a similar | function. I suspect this is because of differences between how | the Ruby and Python interpreters store call stack information, | but haven't had a chance to dig into the specifics. | teh_matt wrote: | Note that tracing profilers don't need to be high overhead - | Python is slow enough that efficient tracing can be mostly | hidden. For example, https://functiontrace.com tends to have | <10% overhead when tracing. | jvns wrote: | Also, this kind of profiler is great because you can use it on | any running Python program, which is pretty magical and very | useful. (especially when it's an application you didn't write) | | But it's not right for every use case: by design austin/py-spy | can only really profile the whole program, and if you want to | profile a specific function or endpoint in your program, | something like PyInstrument | https://github.com/joerick/pyinstrument (which includes Django | middlewares & Flask decorators) is a lot more useful. | p403n1x87 wrote: | For these kind of things one could use | | https://github.com/P403n1x87/austin-python | | An early attempt at an APM that was specifically designed to | measure endpoint response times was here | | https://github.com/P403n1x87/austin/blob/apm/austin/apm.py | | The problem with statistical profilers is that they might | fail to catch every single call, especially when they are | fast. | dTal wrote: | >you're likely to win the race, because C is faster than Python | | Heh, so the only reason there's "no performance cost" is the | enormous performance cost of using Python in the first place? | Demiurge wrote: | Yes, enormous performance cost in CPU hours and enormous | performance gain in human life hours. hehe | junon wrote: | I seriously, seriously beg to differ. | junon wrote: | Correct. | p403n1x87 wrote: | Running Python is not a performance cost. The meaning behind | "no performance cost" is that a tool like this is unlikely | going to impact the performance of the application that is | being profiled. The fact that Python is not a "fast" | programming language is then a different matter. | dTal wrote: | The point is that it's only possible in the first place | _because_ Python leaves so much performance on the table. | You can 't snoop inside a C++ program in the same way - | unless you throw a bunch of sleep() calls everywhere to | slow it down, and then hey presto you can! | | Or, to put it another way, taking Python from 500x | SlowerThanCee to 501x is "negligible", but taking C from 1x | to 2x slower isn't. | p403n1x87 wrote: | true that | RantyDave wrote: | Wasn't there lots of work around using dtrace for this? | iwebdevfromhome wrote: | Is it possible to spy from a python script running in a virtual | python 2 environment? | p403n1x87 wrote: | yep :) | iwebdevfromhome wrote: | Great news, can't wait to try it on some long running | reports. ___________________________________________________________________ (page generated 2020-10-27 23:00 UTC)