<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>flak</title>
    <link>https://flak.tedunangst.com/</link>
    <description>flak rss</description>
    <managingEditor>tedu</managingEditor>
    <image>
      <url>https://flak.tedunangst.com/icon.png</url>
      <title>flak rss</title>
      <link>https://flak.tedunangst.com/</link>
    </image>
    <item>
      <title>memory leak proof every C program</title>
      <description><![CDATA[<p>Memory leaks have plagued C programs for as long as the language has existed. Many solutions have been proposed, even going so far as to suggest we should rewrite C programs in other languages. But there’s a better way.<p>Presented here is a simple solution that will eliminate the memory leaks from every C program. Link this into your program, and memory leaks are a thing of the past.<p><details><summary>leakproof.c</summary><pre><code><span class=bi>#include &lt;dlfcn.h&gt;</span>
<span class=bi>#include &lt;stdio.h&gt;</span>

<span class=tp>struct</span> leaksaver <span class=st>{</span>
        <span class=tp>struct</span> leaksaver <span class=op>*</span>next;
        <span class=tp>void</span> <span class=op>*</span>pointer;
<span class=st>}</span> <span class=op>*</span>bigbucket;

<span class=tp>void</span> <span class=op>*</span>
malloc<span class=st>(</span>size_t len<span class=st>)</span>
<span class=st>{</span>
        <span class=tp>static</span> <span class=tp>void</span> <span class=op>*</span><span class=kw>(</span><span class=op>*</span>nextmalloc<span class=kw>)</span><span class=kw>(</span>size_t<span class=kw>)</span>;
        nextmalloc <span class=op>=</span> dlsym<span class=kw>(</span>RTLD_NEXT<span class=op>,</span> <span class=st>&#34;malloc&#34;</span><span class=kw>)</span>;
        <span class=tp>void</span> <span class=op>*</span>ptr <span class=op>=</span> nextmalloc<span class=kw>(</span>len<span class=kw>)</span>;
        <span class=kw>if</span> <span class=kw>(</span>ptr<span class=kw>)</span> <span class=kw>{</span>
                <span class=tp>struct</span> leaksaver <span class=op>*</span>saver <span class=op>=</span> nextmalloc<span class=cm>(</span>sizeof<span class=bi>(</span><span class=op>*</span>saver<span class=bi>)</span><span class=cm>)</span>;
                saver<span class=op>-&gt;</span>pointer <span class=op>=</span> ptr;
                saver<span class=op>-&gt;</span>next <span class=op>=</span> bigbucket;
                bigbucket <span class=op>=</span> saver;
        <span class=kw>}</span>
        <span class=kw>return</span> ptr;
<span class=st>}</span></code></pre><p></details><br>Every allocated pointer is saved in the big bucket, where it remains accessible. Even if no other references to the pointer exist in the program, the pointer has not leaked.<p>It is now entirely optional to call <code>free</code>. If you don’t call free, memory usage will increase over time, but technically, it’s not a leak. As an optimization, you may choose to call free to reduce memory, but again, strictly optional. <p>Problem sovled!]]></description>
      <category>c</category>
      <category>programming</category>
      <category>rants</category>
      <link>https://flak.tedunangst.com/post/memory-leak-proof-every-C-program</link>
      <pubDate>Fri, 19 Jan 2024 16:55:19 UTC</pubDate>
      <guid isPermaLink="true">https://flak.tedunangst.com/post/memory-leak-proof-every-C-program</guid>
    </item>
    <item>
      <title>how quick is the go compiler</title>
      <description><![CDATA[<p>Can you use <i>go run</i> for scripting? I wrote a small program to find out.<p><details><summary>gorun.go</summary><pre><code><span class=kw>package</span> main

<span class=bi>import</span> <span class=st>(</span>
    <span class=st>&#34;fmt&#34;</span>
    <span class=st>&#34;os&#34;</span>
    <span class=st>&#34;os/exec&#34;</span>
    <span class=st>&#34;time&#34;</span>
<span class=st>)</span>

<span class=kw>func</span> main<span class=st>(</span><span class=st>)</span> <span class=st>{</span>
    start <span class=op>:=</span> time<span class=op>.</span>Now<span class=kw>(</span><span class=kw>)</span>
    gogo <span class=op>:=</span> fmt<span class=op>.</span>Sprintf<span class=kw>(</span><span class=st>`package main
    import &#34;fmt&#34;
    func main() {
        fmt.Printf(&#34;the time was %s\n&#34;)
    }`</span><span class=op>,</span> start<span class=kw>)</span>
    os<span class=op>.</span>WriteFile<span class=kw>(</span><span class=st>&#34;gogo.go&#34;</span><span class=op>,</span> []<span class=tp>byte</span><span class=cm>(</span>gogo<span class=cm>)</span><span class=op>,</span> <span class=nm>0666</span><span class=kw>)</span>
    cmd <span class=op>:=</span> exec<span class=op>.</span>Command<span class=kw>(</span><span class=st>&#34;go&#34;</span><span class=op>,</span> <span class=st>&#34;run&#34;</span><span class=op>,</span> <span class=st>&#34;gogo.go&#34;</span><span class=kw>)</span>
    cmd<span class=op>.</span>Stdout <span class=op>=</span> os<span class=op>.</span>Stdout
    cmd<span class=op>.</span>Run<span class=kw>(</span><span class=kw>)</span>
    end <span class=op>:=</span> time<span class=op>.</span>Now<span class=kw>(</span><span class=kw>)</span>
    fmt<span class=op>.</span>Printf<span class=kw>(</span><span class=st>&#34;that took %s\n&#34;</span><span class=op>,</span> end<span class=op>.</span>Sub<span class=cm>(</span>start<span class=cm>)</span><span class=kw>)</span>
<span class=st>}</span></code></pre><p></details><pre><code>$ go run gorun.go
the time was 2024-01-05 12:04:01.042488 -0500 EST m=+0.000077959
that took 329.81325ms</code></pre><p>On my somewhat older m3 running openbsd, it takes about 330ms. On a less old chromebook, it takes about 100ms. Not bad. On an M1 macbook, it varies wildly between 150ms and 300ms.<p>So I think not fast enough for interactive use. Probably fast enough for a continuously changing cronjob, though I wonder why you wouldn’t change the inputs. But I guess if you’re a big believer in configuration through compilation, and also have constantly changing requirements, it’s fast enough to get by.<p>For comparison, <a href="https://github.com/traefik/yaegi">yaegi</a> is still 10x or more quicker at putting something on the screen.<h3>go build</h3><p>I almost exclusively run <i>go build</i>. Actually, I run make and that runs go build, because that’s how my fingers work. So it wasn’t until recently that I noticed that go run is as fast as it is. I was used to a very observable one second per build.<p>Turns out go build will run <i>hg stat</i> for every build, which go run skips, and that was the slowest part of the process. Easily remedied by switching to <i>chg</i>.]]></description>
      <category>go</category>
      <link>https://flak.tedunangst.com/post/how-fast-is-the-go-compiler</link>
      <pubDate>Fri, 05 Jan 2024 17:23:23 UTC</pubDate>
      <guid isPermaLink="true">https://flak.tedunangst.com/post/how-fast-is-the-go-compiler</guid>
    </item>
    <item>
      <title>terminal smooth scrolling</title>
      <description><![CDATA[<p>I didn’t realize I needed this until I implemented it, and now, oh wow, can’t imagine life without it.<p>Normally, a terminal draws lines of text at fixed intervals. Line 1 starting at pixel 0, then line 2 at 24 pixels, etc. When the text scrolls, line 2 immediately becomes line 1 and gets drawn at pixel 0. These sudden jumps are incompatible with how your eyes track motion, however. The result is a blurry mess that’s hard to read.<p>Long ago, hardware terminals had the option for smooth scrolling, incrementally shifting each line of text up over several frames, but such wizardry has been lost to the ravages of time. I thought it would be fun to implement, and maybe a cool trick to show off, but before seeing the result figured it would be mostly a gimmick. Instead, it’s entirely changed how I scroll through text.<h3>results</h3><p>Figure we can just start with a video showing before and after. Scrolling through the <i>ls</i> man page. About half way through, the terminal switches to smooth scrolling.<p><video playsinline controls poster="/images/scrollcap.jpg">
<source type="video/mp4" src="/images/scrollcap.mp4">
</video><br>I can’t quite read fast enough to keep up with the scroll rate, not every word anyway, but I can skim the text as it passes by until I find the section I’m looking for. Very helpful for reading code or documentation when I’m not entirely sure what that is.<p>I find that scrolling like this is ultimately more effective than paging one screen at a time, then trying to skim the whole screen. I always miss something when doing that.<h3>implementation</h3><p>There’s an open issue requesting smooth scrolling for just about every terminal I looked at, but none implemented. Usually the discussion gets bogged down in trivialities. I found it’s not hard to do something, and the result is quite pleasing. I guess it helps to only worry about one user.<p>The first big issue is oh, no, it makes things slow. Only when enabled. There’s a terminal mode sequence to turn it on and off. I did find it slightly distracting for regular shell work, like running <i>ls</i>, so only enable it for commands as necessary. And the scrolling speed can be ramped up by the amount to scroll. I picked ten frames as target, although it takes a bit longer than that as it decelerates towards the end.<p>The second big issue relates to the scrolling region. Programs like <i>vi</i> scroll most lines on the screen, but they leave the status bar on the bottom alone. Indeed, it looks funny to scroll that. But this is easily resolved by only applying the smooth scrolling effect to the part of the screen that scrolled.<p>Finally, there’s the question of what to do with the scrolled off content. When a line disappears off the alternate screen, there’s no backlog to send it to. It ceases to exist. So what to draw in that space before the next line finishes scrolling into position? The answer is nothing. You can leave a line or two empty at the top (or bottom) of screen. The new content, the stuff I’m focused on, is appearing at the other side. I’m not watching the disappearing lines; I’m watching the appearing lines.<p>As for actual implementation, every cell on the screen is drawn with some vertices. If we’re smooth scrolling, we offset those vertices in the opposite direction. If the text on the screen just moved up, we push every vertex down, so it appears in the same position as previously. Then we decay the offset each frame, so that the text slides into position.<p>The main part of the code is about 25 lines, plus a few miscellaneous lines here and there.<h3>misc details</h3><p>The proof of concept was very quick to get going, but it did require some experimentation and tuning. If we start too slow, we fall behind the input. If we accelerate too fast, the result looks jerky. Too many derivatives.<p>Current approach is to pick a velocity of distance divided by 10. Then we use a weighted average with previous velocity to smooth the smoothing. If we’re more than ten lines behind, which happens rarely but can happen if the whole screen is redrawn, then do a jump scroll.<p>The region to smooth scroll is determined by the scrolling region at the time of scrolling, not painting. <i>vim</i> for instance will set the scroll region to 1;23 to adjust the file contents displayed, then immediately switch back to 1;24 to update the status line. Since we don’t want to scroll the status bar, we want to apply the effect to the 1;23 region previously set.<p>For now, we scroll interior lines as well, such as for cut and paste operations. This is somewhere between distracting and helpful. The motion turns out to be a helpful hint of what changed, and it’s fast enough it doesn’t get in the way.<p>If an offscreen tab scrolls, the smooth effect is applied when the user switches back. This doesn’t usually happen (unless smooth scrolling is enabled at the shell) but I think it can be a helpful indicator that something changed. This is <i>new</i> compiler output.<p>Drawing the screen ten times for each scroll obviously uses ten times more CPU power.<h3>usage</h3><p>Smooth scrolling is enabled by the standard “\e[4?h” control sequence.<p>Helpful .vimrc:<p><pre><code>set t_TI=^[[4?h
set t_TE=^[[4?l</code></pre><p>]]></description>
      <category>software</category>
      <link>https://flak.tedunangst.com/post/terminal-smooth-scrolling</link>
      <pubDate>Thu, 28 Dec 2023 14:21:53 UTC</pubDate>
      <guid isPermaLink="true">https://flak.tedunangst.com/post/terminal-smooth-scrolling</guid>
    </item>
  </channel>
</rss>
