<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom"><title>Simon Willison's Weblog: profiling</title><link href="http://simonwillison.net/" rel="alternate"/><link href="http://simonwillison.net/tags/profiling.atom" rel="self"/><id>http://simonwillison.net/</id><updated>2024-07-26T13:06:38+00:00</updated><author><name>Simon Willison</name></author><entry><title>Did you know about Instruments?</title><link href="https://simonwillison.net/2024/Jul/26/did-you-know-about-instruments/#atom-tag" rel="alternate"/><published>2024-07-26T13:06:38+00:00</published><updated>2024-07-26T13:06:38+00:00</updated><id>https://simonwillison.net/2024/Jul/26/did-you-know-about-instruments/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://registerspill.thorstenball.com/p/did-you-know-about-instruments"&gt;Did you know about Instruments?&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Thorsten Ball shows how the macOS Instruments app (installed as part of Xcode) can be used to run a CPU profiler against &lt;em&gt;any&lt;/em&gt; application - not just code written in Swift/Objective C.&lt;/p&gt;
&lt;p&gt;I tried this against a Python process running &lt;a href="https://llm.datasette.io/"&gt;LLM&lt;/a&gt; executing a Llama 3.1 prompt with my new &lt;a href="https://github.com/simonw/llm-gguf"&gt;llm-gguf&lt;/a&gt; plugin and captured this:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of a deep nested stack trace showing _PyFunction_Vectorcall from python3.10 calling PyCFuncPtr_call _ctypes.cpython-310-darwin.so which then calls ggml_ methods in libggml.dylib" src="https://static.simonwillison.net/static/2024/instruments-ggml.jpg" /&gt;

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://lobste.rs/s/kr9od0/did_you_know_about_instruments"&gt;lobste.rs&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/observability"&gt;observability&lt;/a&gt;&lt;/p&gt;



</summary><category term="profiling"/><category term="python"/><category term="observability"/></entry><entry><title>Making Code Faster</title><link href="https://simonwillison.net/2022/Jun/13/making-code-faster/#atom-tag" rel="alternate"/><published>2022-06-13T19:40:43+00:00</published><updated>2022-06-13T19:40:43+00:00</updated><id>https://simonwillison.net/2022/Jun/13/making-code-faster/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.tbray.org/ongoing/When/202x/2022/06/10/Quamina-Optimizing"&gt;Making Code Faster&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Tim Bray’s detailed guide to using the Go profiler.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/go"&gt;go&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/tim-bray"&gt;tim-bray&lt;/a&gt;&lt;/p&gt;



</summary><category term="go"/><category term="profiling"/><category term="tim-bray"/></entry><entry><title>How I cut GTA Online loading times by 70%</title><link href="https://simonwillison.net/2021/Mar/1/gta-loading-times/#atom-tag" rel="alternate"/><published>2021-03-01T19:12:03+00:00</published><updated>2021-03-01T19:12:03+00:00</updated><id>https://simonwillison.net/2021/Mar/1/gta-loading-times/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/"&gt;How I cut GTA Online loading times by 70%&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Incredible debugging war story:  t0st was fed up of waiting six minutes (!) for GTA Online to load on their PC, so they used a host of devious debugging tricks to try and figure out what was going on. It turned out the game was loading a 10MB JSON file detailing all of the available in-game purchases, but inefficient JSON parsing meant it was pegging an entire CPU for 4 minutes mainly running the strlen() C function. Despite not having access to source code or debugging symbols t0st figured out the problem and managed to inject a custom DLL that hooked some internal functions and dropped load times down from 6m down to to 1m50s!

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="https://news.ycombinator.com/item?id=26296339"&gt;Hacker News&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/debugger"&gt;debugger&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/hacking"&gt;hacking&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;&lt;/p&gt;



</summary><category term="debugger"/><category term="hacking"/><category term="profiling"/></entry><entry><title>Using memory-profiler to debug excessive memory usage in healthkit-to-sqlite</title><link href="https://simonwillison.net/2019/Jul/24/memory-profiler/#atom-tag" rel="alternate"/><published>2019-07-24T08:25:07+00:00</published><updated>2019-07-24T08:25:07+00:00</updated><id>https://simonwillison.net/2019/Jul/24/memory-profiler/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/dogsheep/healthkit-to-sqlite/issues/7"&gt;Using memory-profiler to debug excessive memory usage in healthkit-to-sqlite&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
This morning I figured out how to use the memory-profiler module (and mprof command line tool) to debug memory usage of Python processes. I added the details, including screenshots, to this GitHub issue. It helped me knock down RAM usage for my healthkit-to-sqlite from 2.5GB to just 80MB by making smarter usage of the ElementTree pull parser.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/elementtree"&gt;elementtree&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/memory"&gt;memory&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/xml"&gt;xml&lt;/a&gt;&lt;/p&gt;



</summary><category term="elementtree"/><category term="memory"/><category term="profiling"/><category term="python"/><category term="xml"/></entry><entry><title>Using flamegraphs</title><link href="https://simonwillison.net/2018/Mar/21/flame-graphs/#atom-tag" rel="alternate"/><published>2018-03-21T20:56:50+00:00</published><updated>2018-03-21T20:56:50+00:00</updated><id>https://simonwillison.net/2018/Mar/21/flame-graphs/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://rbspy.github.io/profiling-guide/using-flamegraphs.html"&gt;Using flamegraphs&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
I really like flamegraphs as a profiling tool—we have support for them baked into our Tikibar debugging toolbar at Eventbrite—but interpreting them isn’t particularly intuitive on first glance. Julia Evans has put together a great explanation of how to read them as part of the documentation for her rbspy Ruby profiler.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/julia-evans"&gt;julia-evans&lt;/a&gt;&lt;/p&gt;



</summary><category term="profiling"/><category term="julia-evans"/></entry><entry><title>profiling</title><link href="https://simonwillison.net/2017/Oct/28/profiling/#atom-tag" rel="alternate"/><published>2017-10-28T01:06:49+00:00</published><updated>2017-10-28T01:06:49+00:00</updated><id>https://simonwillison.net/2017/Oct/28/profiling/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/what-studio/profiling"&gt;profiling&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
“An interactive continuous Python profiler”. This is really neat—simply run “profiling myscript.py” to get an interactive, navigable console-based profile inspector at the end of your script... or run “profiling live-profile mywebverver.py” to see a live, updating profile of a long-running process. Has options for statistical profiling as well, which has a much lower overhead in exchange for a less accurate view of what is going on.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;&lt;/p&gt;



</summary><category term="profiling"/><category term="python"/></entry><entry><title>Building a statistical profiler in python</title><link href="https://simonwillison.net/2017/Oct/5/profiler/#atom-tag" rel="alternate"/><published>2017-10-05T15:44:20+00:00</published><updated>2017-10-05T15:44:20+00:00</updated><id>https://simonwillison.net/2017/Oct/5/profiler/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.polibyte.com/2017/08/05/building-statistical-profiler/"&gt;Building a statistical profiler in python&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Generating flame graphs of production Python code is surprisingly straight-forward. Brian Pitts built a statistical flame graph profiler into our tikibar debugging tool at Eventbrite and it’s proved extremely useful.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/django"&gt;django&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/python"&gt;python&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/tikibar"&gt;tikibar&lt;/a&gt;&lt;/p&gt;



</summary><category term="django"/><category term="profiling"/><category term="python"/><category term="tikibar"/></entry><entry><title>How to find un-indexed queries in MySQL, without using the log</title><link href="https://simonwillison.net/2009/Aug/19/tcpdump/#atom-tag" rel="alternate"/><published>2009-08-19T11:42:28+00:00</published><updated>2009-08-19T11:42:28+00:00</updated><id>https://simonwillison.net/2009/Aug/19/tcpdump/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.xaprb.com/blog/2009/08/18/how-to-find-un-indexed-queries-in-mysql-without-using-the-log/"&gt;How to find un-indexed queries in MySQL, without using the log&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Use tcpdump(!) to sniff the MySQL protocol and dump out queries that had the “no index used” bit set.

    &lt;p&gt;&lt;small&gt;&lt;/small&gt;Via &lt;a href="http://delicious.com/mattb/maatkit+mysql+query+sql+tcpdump"&gt;Matt Biddulph&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/mysql"&gt;mysql&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/tcpdump"&gt;tcpdump&lt;/a&gt;&lt;/p&gt;



</summary><category term="mysql"/><category term="profiling"/><category term="tcpdump"/></entry><entry><title>Building a Better JavaScript Profiler with WebKit</title><link href="https://simonwillison.net/2009/Apr/29/building/#atom-tag" rel="alternate"/><published>2009-04-29T23:57:26+00:00</published><updated>2009-04-29T23:57:26+00:00</updated><id>https://simonwillison.net/2009/Apr/29/building/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://www.alertdebugging.com/2009/04/29/building-a-better-javascript-profiler-with-webkit/"&gt;Building a Better JavaScript Profiler with WebKit&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Clever hack from Francisco Tolmasky which solves the problem of JavaScript profilers showing ? as the name of any anonymous functions. He patched the WebKit profiler to look for a displayName attribute on a function and show that as the function name instead.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/francisco-tolmasky"&gt;francisco-tolmasky&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/webkit"&gt;webkit&lt;/a&gt;&lt;/p&gt;



</summary><category term="francisco-tolmasky"/><category term="javascript"/><category term="profiling"/><category term="webkit"/></entry><entry><title>Heap Dump Analysis</title><link href="https://simonwillison.net/2009/Apr/2/jabbering/#atom-tag" rel="alternate"/><published>2009-04-02T10:34:15+00:00</published><updated>2009-04-02T10:34:15+00:00</updated><id>https://simonwillison.net/2009/Apr/2/jabbering/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://happygiraffe.net/blog/2009/04/02/heap-dump-analysis/"&gt;Heap Dump Analysis&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Using jmap to dump the JVM’s memory to disk, then analysing it using the visualvm GUI tool.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/dominic-mitchell"&gt;dominic-mitchell&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/heapdump"&gt;heapdump&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/java"&gt;java&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jvm"&gt;jvm&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/memory"&gt;memory&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/visualvm"&gt;visualvm&lt;/a&gt;&lt;/p&gt;



</summary><category term="dominic-mitchell"/><category term="heapdump"/><category term="java"/><category term="jvm"/><category term="memory"/><category term="profiling"/><category term="visualvm"/></entry><entry><title>Using the New MySQL Query Profiler</title><link href="https://simonwillison.net/2008/Oct/1/mysql/#atom-tag" rel="alternate"/><published>2008-10-01T01:20:24+00:00</published><updated>2008-10-01T01:20:24+00:00</updated><id>https://simonwillison.net/2008/Oct/1/mysql/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://dev.mysql.com/tech-resources/articles/using-new-query-profiler.html"&gt;Using the New MySQL Query Profiler&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Extremely powerful new feature in MySQL 5.0.37. Definitely something for the Django debug toolbar.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/django"&gt;django&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/django-debug-toolbar"&gt;django-debug-toolbar&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/mysql"&gt;mysql&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;&lt;/p&gt;



</summary><category term="django"/><category term="django-debug-toolbar"/><category term="mysql"/><category term="profiling"/></entry><entry><title>Deep Profiling jQuery Apps</title><link href="https://simonwillison.net/2008/Jun/16/john/#atom-tag" rel="alternate"/><published>2008-06-16T10:20:36+00:00</published><updated>2008-06-16T10:20:36+00:00</updated><id>https://simonwillison.net/2008/Jun/16/john/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://ejohn.org/blog/deep-profiling-jquery-apps/"&gt;Deep Profiling jQuery Apps&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
Neat plugin from John Resig that monkey-patches most (all?) of the jQuery methods to build up a detailed profile of which methods are being used by a given page.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/javascript"&gt;javascript&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/john-resig"&gt;john-resig&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/jquery"&gt;jquery&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;&lt;/p&gt;



</summary><category term="javascript"/><category term="john-resig"/><category term="jquery"/><category term="profiling"/></entry><entry><title>YSlow: Bug (fix) in Firebug's Net Panel</title><link href="https://simonwillison.net/2007/Oct/5/yslow/#atom-tag" rel="alternate"/><published>2007-10-05T22:26:10+00:00</published><updated>2007-10-05T22:26:10+00:00</updated><id>https://simonwillison.net/2007/Oct/5/yslow/#atom-tag</id><summary type="html">
    
&lt;p&gt;&lt;strong&gt;&lt;a href="http://developer.yahoo.com/yslow/netpanelpatch.html"&gt;YSlow: Bug (fix) in Firebug&amp;#x27;s Net Panel&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
The latest release of the YSlow page analysis plugin (announced at FOWA) also fixes a misleading bug in Firebug’s Net panel.


    &lt;p&gt;Tags: &lt;a href="https://simonwillison.net/tags/firebug"&gt;firebug&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/firefox"&gt;firefox&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/fowa"&gt;fowa&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/profiling"&gt;profiling&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/steve-souders"&gt;steve-souders&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yahoo"&gt;yahoo&lt;/a&gt;, &lt;a href="https://simonwillison.net/tags/yslow"&gt;yslow&lt;/a&gt;&lt;/p&gt;



</summary><category term="firebug"/><category term="firefox"/><category term="fowa"/><category term="profiling"/><category term="steve-souders"/><category term="yahoo"/><category term="yslow"/></entry></feed>