<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Paul Bone</title>
    <description>Paul Bone is a software engineer and computer scientist.  His interests include programming languages, declarative programming, programming language implementation, parallelism and concurrency.  Paul works for Mozilla on Firefox&apos;s JavaScript engine&apos;s garbage collector by day, and the Plasma programming language by night.</description>
    <link>https://paul.bone.id.au/</link>
    <atom:link href="https://paul.bone.id.au/blog.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Sun, 08 Feb 2026 01:05:40 +1100</pubDate>
    <lastBuildDate>Sun, 08 Feb 2026 01:05:40 +1100</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>3D Printing Diffusers for LED strips</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This light is a 3D printed diffuser over a COB LED strip, and this post is
how to make your own.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/assets/img/diffusers/led-diffuser-cob.jpeg&quot; alt=&quot;LED diffuser over an illumenated LED strip on the underside of a red shelf.  It is supported by a red plastic grid.  The light fills the bar created by the diffuser.&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It also works for non-COB LED strips.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/assets/img/diffusers/led-diffuser.jpeg&quot; alt=&quot;LED diffuser over a aRGB LED strip.  Bright spots of individual LEDs can be seen through the diffuser. Although they are more blended than without a diffuser.&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;opengrid-and-underware&quot;&gt;openGrid and Underware&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Instead of uploading some models for you to print I&amp;#8217;m going to refer to
existing systems that we&amp;#8217;re going to customise.
The first is
&lt;a href=&quot;https://makerworld.com/en/models/1179191-opengrid-wall-desk-mounting-framework-ecosystem&quot;&gt;openGrid&lt;/a&gt;,
a flexible-yet-simple wall storage system.  It
provides the square grid that everything else is clipped to.
I used the &quot;light&quot; grid and screwed it into my wooden shelves with screws at
each end of 2-square-wide grids.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Try &lt;a href=&quot;https://gridfinity.perplexinglabs.com/pr/opengrid/0/0&quot;&gt;this generator&lt;/a&gt; to
make grids of the exact size you need. You can even customise the screw
holes to the exact screws you have.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We&amp;#8217;ll also use the
&lt;a href=&quot;https://handsonkatie.com/underware-2-0-the-made-to-measure-collection/&quot;&gt;Underware
2.0&lt;/a&gt; cable management system, but in particular this is what we need to
customize to make the diffusers.  In particular, we&amp;#8217;ll use
&lt;a href=&quot;https://makerworld.com/en/models/1329404-underware-for-opengrid-customizer-beta&quot;&gt;This
customiser&lt;/a&gt; since it&amp;#8217;s compatible with openGrid and lets us generate
whatever shape we need.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Both of these systems are great in their own right.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;customising-underware&quot;&gt;Customising Underware&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;After printing your grid and mounting it, open the
&lt;a href=&quot;https://makerworld.com/en/models/1329404-underware-for-opengrid-customizer-beta?from=search#profileId-1367368&quot;&gt;underware generator&lt;/a&gt;.
Click Customize and choose the basic shape to start with, eg a straight &quot;I&quot;
piece.
In the new browser tab click &quot;Code&quot; to open the OpenSCAD code that
generates this model - you don&amp;#8217;t need to know anything about programming or
OpenSCAD.
Scroll down until you see:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*[Hidden]*/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Change it to&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/*[Not Hidden]*/&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And Press the &quot;X&quot; in the top right of the code view.  Now the hidden
settings are available to you.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Change the following settings, they&amp;#8217;re in different sections.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Channel Total Height: 15
Channel Length Units: how long do you need the channel?
Suppress Connectors: NBNBNBN
topChamfer: 6
snapWallThickness: 1.2&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;About Suppress Connectors.
Each channel will have connectors that grip into the grid.
But they also get in the way of placing tiles that will hold your LED strip
in place.
I have chosen to make channels 7 units long with grips every other tile.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Generate the model then download it.
The download window will ask you what kind of printer you have.
Don&amp;#8217;t worry if you don&amp;#8217;t have a Bambulab printer, just click Confirm then
Download.
Sometimes the download button asks me if I&amp;#8217;d prefer to download an STL file,
I would, it&amp;#8217;s printer agnostic.  And sometimes it doesn&amp;#8217;t. I don&amp;#8217;t know why.
If you download a .3mf file you can open it in your slicer anyway, you may
have to switch printers and settings back to your own profiles.  Or if you
already have a project open in, for example OrcaSlicer, and load the file as
a model, it may ask if you want to import Geometry Only, choose Yes.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;printing&quot;&gt;Printing&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;m using Polymaker Polylite PLA Natural, I expect any &quot;Natural&quot; or even
many &quot;White&quot; PLAs would work.  A translucent filament is more transparent if
printed hotter and slower, but I don&amp;#8217;t want transparent, I want a more
&quot;frosted&quot; look, so I didn&amp;#8217;t bother slowing down print speed or anything like
that.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But to go more towards a frosted look I am using a textured build plate and
&quot;fuzzy skin&quot;.  But the fuzzy skin should be applied selectively so it&amp;#8217;s not
on the mechanical parts that grip into the grid.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Add a hight range modifier from 1.2mm to 11mm and apply the fuzzy skin
setting to that.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I used a point distance of 0.2mm and a thickness of 0.1mm.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/assets/img/diffusers/fuzzy-skin.png&quot; alt=&quot;Fuzzy skin settings in OrcaSlicer&quot; width=&quot;Fuzzy skin is applied to contours an layers between 1.2 and 11 mm.  Point Distance is set to 0.2mm&quot; height=&quot;Thickness is set to 0.1mm&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s it!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 07 Feb 2026 00:00:00 +1100</pubDate>
        <link>https://paul.bone.id.au/blog/2026/02/07/3d-printing-led-diffusers/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2026/02/07/3d-printing-led-diffusers/</guid>
        
        <category>3D</category>
        
        <category>Printing,</category>
        
        <category>LED,</category>
        
        <category>Diffuser,</category>
        
        <category>Undersware,</category>
        
        <category>OpenGrid</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>The right amount of poison</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Oh, you don&amp;#8217;t want any poison in your porridge.
But how about in your computer&amp;#8217;s memory?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;papa-bear-too-much-poison&quot;&gt;Papa Bear - too much poison&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Papa Bear likes his chair hard, his porridge hot and his browser written in
a memory safe language that helps engineers avoid memory bugs like
&lt;em&gt;buffer overruns&lt;/em&gt; and &lt;em&gt;use after frees&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But even Papa Bear has to compromise, part of Firefox is written in a
memory safe language and the rest is written in C++.  When using
C++ there are a variety of defenses programmers can take to help
catch memory errors.  One of those is called &lt;em&gt;memory poisoning&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;code&gt;mozjemalloc&lt;/code&gt; the memory allocator built into Firefox will &lt;em&gt;poison&lt;/em&gt; memory
by calling &lt;code&gt;memset(aPtr, 0xE5, size);&lt;/code&gt; before freeing it.
Any memory containing the pattern &lt;code&gt;0xE5E5E5E5&lt;/code&gt; is therefore very likely to be
memory that&amp;#8217;s already been freed.
This has two and a half benefits:
If some code were to free &lt;strong&gt;and then dereference&lt;/strong&gt; some memory
(&lt;em&gt;a use after free bug&lt;/em&gt;)
it would most likely cause the browser to crash, which is much better
than a potentially exploitable bug allowing Goldilocks to steal Papa Bear&amp;#8217;s
banking credentials!
The other benefit is that when Firefox does crash due to such a
use-after-free, the presence of this pattern in the crash report allows
engineers to see the type of error that occurred and hopefully fix the
mistake.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Note that back in March 2023 we
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1609478&quot;&gt;moved the poison
operation outside of the arena lock&amp;#8217;s critical section&lt;/a&gt;;
which improved performance in some tests.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;mama-bear-no-poisoning&quot;&gt;Mama Bear - no poisoning&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You probably figured out by now that I&amp;#8217;m going to persist with this
metaphor.
Mama Bear likes her chair soft, her porridge cold (and congealed (yuck)),
and her browser fast.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But how much faster is Mama Bear&amp;#8217;s experience?
This is the question that was raised recently when
Randell Jesup was benchmarking various memory allocators in Firefox.
He noted that while mozjemalloc performs poisoning, many of the other
allocators do not and to compare the performance of the allocators more
fairly they should either all perform poisoning or none of them should.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And so Randell noted that, depending on the test,
Firefox could be
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1850008#c3&quot;&gt;between 0.5% and 4%
faster&lt;/a&gt;
with poisoning disabled.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There are some results I collected.  The &quot;sp2&quot; (Speedometer 2) and &quot;sp3&quot;
(Speedometer 3) tests are browser benchmarks - larger numbers indicate
better performance.
The amazon and instagram tests are pageload tests measured in seconds with
the &lt;em&gt;ContentfulSpeedIndex&lt;/em&gt; metric - smaller numbers indicate better
performance.&lt;/p&gt;
&lt;/div&gt;
&lt;table class=&quot;tableblock frame-all grid-all stretch&quot;&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;sp2 (score)&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;sp3 (score)&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;amazon (sec)&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;instagram (sec)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Poison&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;178.84 ± 0.84&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;13.32 ± 1.03&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;243.2 ± 1.96&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;419.43 ± 1.04&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;No poisoning&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;179.42 ± 0.48&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;13.39 ± 0.31&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;237.55 ± 2.6&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;414.5 ± 0.8&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The speedometer figures are pretty close and these are the best pageload
figures (the others showed very little difference but nothing regressed, yes
I&amp;#8217;m aware I&amp;#8217;ve cherry-picked data).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This means that if it weren&amp;#8217;t for the lack of security and debugability
Mama Bear would have the right approach.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;baby-bear&quot;&gt;Baby Bear&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Baby Bear loves a compromise, they want their computer to be safe from
Goldilocks&apos; hacking attempts but also love performance improvements.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;One compromise may be to probabilistic poison memory some of the time, e.g.
a roughly 5% chance of poisoning.
That&amp;#8217;s more complex and involves a memory write anyway to keep the &quot;time
until poison&quot; counter updated.
We didn&amp;#8217;t investigate it.
But it&amp;#8217;s worth noting that it would be similar in spirit to the
&lt;a href=&quot;https://groups.google.com/g/mozilla.dev.platform/c/AyECjDNsqUE/m/Jd7Jr4cXAgAJ?pli=1&quot;&gt;Probabilistic Heap Checker (PHC)&lt;/a&gt;
that&amp;#8217;s
&lt;a href=&quot;https://groups.google.com/a/mozilla.org/g/dev-platform/c/C1LcRpii-cI&quot;&gt;rolling out&lt;/a&gt;
in Firefox or the similar &lt;a href=&quot;https://arxiv.org/abs/2311.09394&quot;&gt;GWP-ASan&lt;/a&gt;
capability in Chrome.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Instead we tested &quot;what if we poison only the first cache line of a memory
cell&quot;.
Andrew McCreight and Olli Pettay
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1850008#c9&quot;&gt;pointed out that&lt;/a&gt;
Element, a common DOM structure, is 128 bytes long and poisoning it is
useful to detect memory errors in DOM code, as a lot of DOM code will
involve Element.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We tested poisoning the first 64, 128 and 256 bytes of each structure.
We assume that management of cache and writing cache lines back to RAM is
going to be the dominant cost.  Therefore we round-up our writes to the next
cache line boundary..&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For example, on a computer with 64-byte cache lines, if a 96-byte object is
allocated so that the first 32-bytes is in one cache-line, while the next
64-bytes is in another.  Our 64-byte write would cover two halves of
different cache lines.  In this case we will poison all 96-bytes because
doing so writes to the same number of cache lines as the original 64-byte
write.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Let&amp;#8217;s add these options to our table of results.&lt;/p&gt;
&lt;/div&gt;
&lt;table class=&quot;tableblock frame-all grid-all stretch&quot;&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;col style=&quot;width: 20%;&quot;&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;sp2 (score)&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;sp3 (score)&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;amazon (sec)&lt;/th&gt;
&lt;th class=&quot;tableblock halign-left valign-top&quot;&gt;instagram (sec)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Poison&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;178.84 ± 0.84&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;13.32 ± 1.03&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;243.20 ± 1.96&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;419.43 ± 1.04&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Poison 256&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;179.50 ± 0.55&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;13.35 ± 0.33&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;240.47 ± 2.82&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;415.28 ± 1.30&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Poison 128&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;179.19 ± 0.43&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;13.35 ± 0.59&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;241.62 ± 3.05&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;414.95 ± 1.15&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Poison 64&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;179.09 ± 0.87&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;13.33 ± 0.83&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;242.13 ± 2.56&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;414.11 ± 0.91&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;No poisoning&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;179.42 ± 0.48&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;13.39 ± 0.31&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;237.55 ± 2.60&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;414.5 ± 0.8&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As above, sp2 and sp3 are scores - bigger numbers are better.  While amazon
and instagram are page load tests where smaller numbers are better.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;As expected the partial poisoning results fall between full and no
poisoning. But what&amp;#8217;s a little bit surprising is that in some tests (sp2 and
amazon) poisoning a larger amount of memory made things faster.
This could be because the &lt;code&gt;memset()&lt;/code&gt; routine or the hardware itself is able
to optimise larger writes more effectively.
That said it&amp;#8217;s important to acknowledge that the standard deviation is
fairly high and doing the right statistical analysis is beyond this blog post.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;just-right&quot;&gt;Just right&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Since poisoning more memory isn&amp;#8217;t &lt;em&gt;much&lt;/em&gt; slower and in some
cases is faster than poisoning a little memory, then we might as well choose to
poison
&lt;a href=&quot;https://searchfox.org/mozilla-central/rev/9013524d23da6523a7ec4479b5682407a1323f6c/memory/build/mozjemalloc.cpp#1484&quot;&gt;256 bytes&lt;/a&gt;
which comfortably covers the Element object and most
others and for the others it likely covers many of their most-often accessed
fields.
We&amp;#8217;re confident that this is enough to help us catch many errors that can be
caught with poisoning.
While also performing well enough, especially for the pageload tests where
it is closer to the performance available with poisoning disabled.
We think that Baby Bear would agree, it is &lt;em&gt;Just Right&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;it-gets-better&quot;&gt;It gets better&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With the
&lt;a href=&quot;https://groups.google.com/g/mozilla.dev.platform/c/AyECjDNsqUE/m/Jd7Jr4cXAgAJ?pli=1&quot;&gt;Probablistic Heap Checker (PHC)&lt;/a&gt;
rolling out soon we will have an even greater ability to catch information
related to memory errors.
I&amp;#8217;ll be writing about this in the future.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;why-papa-bear-is-safe-and-mama-bear-is-secure&quot;&gt;Why Papa Bear is safe and Mama Bear is secure?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In some ways it feels more natural to lean in to (negative) gender
stereotypes where Papa Bear wants things fast and Mama Bear is the
cautious one.  I considered this however to make comprehension easier it&amp;#8217;s
easier to explain poisoning before explaining turning poisoning off  and the
nursery tale describes Papa Bear&amp;#8217;s preferences first,
so that&amp;#8217;s the order I introduced them here.
Flipping the script on gender stereotypes was accidental.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Tue, 13 Feb 2024 00:00:00 +1100</pubDate>
        <link>https://paul.bone.id.au/blog/2024/02/13/poisoning-firefox-memory/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2024/02/13/poisoning-firefox-memory/</guid>
        
        <category>planet-mozilla</category>
        
        <category>Firefox</category>
        
        <category>poison</category>
        
        <category>memory</category>
        
        <category>jemalloc</category>
        
        <category>mozjemalloc</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Waiting for web content to do something in a Firefox mochitest</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It&amp;#8217;s not unusual for a Firefox test to have to wait for various things such
as a tab loading.
But recently I needed to write a test that loaded a content tab with a
web worker and wait for that before observing the result in a different tab.
I am writing this for my own reference in the future,
and if it helps someone else, that&amp;#8217;s extra good.
But I don&amp;#8217;t think it will be of much interest if you don&amp;#8217;t work on Firefox
as the problem I&amp;#8217;m solving won&amp;#8217;t be relevant and the APIs won&amp;#8217;t be familiar.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I don&amp;#8217;t think of myself as a JavaScript programmer - I&amp;#8217;m learning what I
need to know when I need to know it, but mainly to write tests.
So I&amp;#8217;m not sure I&amp;#8217;ll pitch this article at any particular level of JS
knowledge, sorry.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;web-workers&quot;&gt;Web Workers&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers&quot;&gt;Web Workers&lt;/a&gt;
provide web pages a way to execute long-running JavaScript tasks in a
separate &lt;em&gt;thread&lt;/em&gt;, where it won&amp;#8217;t block the main event loop.
They solve the same problem, allowing a page to use &lt;em&gt;concurrency&lt;/em&gt;.
However their programming model is more like &lt;em&gt;processes&lt;/em&gt;
because they don&amp;#8217;t share state (global variables or even functions) and
communicate by
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#sending_messages_to_and_from_a_dedicated_worker&quot;&gt;sending
and receiving messages&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I realise this is a tangent but it&amp;#8217;s a topic I like and you may have the
same questions I did:
So if workers are supposed to solve the same problems as threads do in other
languages, why are they more like processes?
Furthermore, at least in Firefox, each worker instantiates another copy of
the JavaScript engine (the &lt;code&gt;JSRuntime&lt;/code&gt; class) with its own instantiation of
JIT, GC etc.
Isn&amp;#8217;t this fairly &lt;strong&gt;heavy&lt;/strong&gt; just to add concurrency?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It is, but there are benefits:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;I&amp;#8217;m not certain, but I think
this was the easiest way to retrofit concurrency to JavaScript (the
language standard) without breaking backwards compatibility with existing
web sites.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Message-passing concurrency makes the boundary between threads very
clear.  This makes it a simpler programming model, especially if you&amp;#8217;re
working on some code that is isolated from the concurrency happening
elsewhere.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It worked for Erlang, although Erlang likely shares bytecode caches
and some other systems.  But not garbage collection.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Anyway, the point is that Web Workers are concurrent &quot;process like&quot; things
that communicate through message-passing.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;aboutperformance&quot;&gt;about:performance&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Firefox has a number of &lt;code&gt;about:&lt;/code&gt; pages, used for diagnostics and tweaking.
&lt;code&gt;about:config&lt;/code&gt; is probably the most infamous (if you touch those settings
you can break your browser or make it insecure).
&lt;code&gt;about:support&lt;/code&gt; is interesting too it contains diagnostic information about
Firefox on your computer.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Today we&amp;#8217;re looking at &lt;code&gt;about:performance&lt;/code&gt;, which is useful when you are
thinking &quot;Firefox seems slow, I wonder why..&quot;.  &lt;code&gt;about:performance&lt;/code&gt; will
show your busiest tabs, how much CPU time/power and memory they&amp;#8217;re using.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Measuring memory usage can be tricky at the best of times
(more on this in an upcoming article).
We can&amp;#8217;t afford to count every allocation since that is too slow for a page
like &lt;code&gt;about:performance&lt;/code&gt;.  Although &lt;code&gt;about:memory&lt;/code&gt; comes closer to doing
this.
For about:performance we can ask major subsystems how much
memory they&amp;#8217;re using and rely on their counters.
This isn&amp;#8217;t accurate but it&amp;#8217;s good enough.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I noticed two major things that weren&amp;#8217;t counted:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Malloc memory used by JS objects was not counted.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Web workers were not counted.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I fixed them in
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1760920&quot;&gt;Bug 1760920&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So I wanted to write a test that would verify that we are indeed counting
memory belonging to web workers.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;my-web-worker&quot;&gt;My web worker&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To make it easier to see if we&amp;#8217;re counting a component&amp;#8217;s memory, it&amp;#8217;s great
of our test causes that component to use a lot of memory then we can test
for that.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here&amp;#8217;s a Web Worker that uses about 40MB of memory using an array with 4
million elements.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;var big_array = [];
var n = 0;

onmessage = function(e) {
  var sum = 0;
  if (n == 0) {
    for (let i = 0; i &amp;lt; 4 * 1024 * 1024; i++) {
      big_array[i] = i * i;
    }
  } else {
    for (let i = 0; i &amp;lt; 4 * 1024 * 1024; i++) {
      sum += big_array[i];
      big_array[i] += 1;
    }
  }
  self.postMessage(`Iter: ${n}, sum: ${sum}`);
  n++;
};&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It registers an &lt;code&gt;onmessage&lt;/code&gt; event hander.  When the page sends it a message it
will execute the anonymous function.
The first time this happens the function will create the array, the next
time it will manipulate the array.
Since the array is a global and is also
captured by the handler I doubt the GC would free it.
But I also don&amp;#8217;t want an optimiser (now or in the future) from reducing the
whole program to a large summation, or caching an answer.
Which is why the array is manipulated each time the event handler is called.
It doesn&amp;#8217;t matter that it&amp;#8217;s ridiculous - it&amp;#8217;s a test - just that it uses
&quot;enough&quot; memory.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;From the main page it can be started like this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;  var worker = new Worker(&quot;workers_memory_script.js&quot;);
  worker.postMessage(n);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But that&amp;#8217;s not enough to make a working test.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;the-test&quot;&gt;The test&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Our test needs to open this page in one tab, and in another tab look at
&lt;code&gt;about:performance&lt;/code&gt; and observe that the memory is being used.
Opening and managing multiple tabs and is standard faire for a browser test,
but what we need is for our test to wait for the tab with the worker to be
/ready/.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Waiting for a tab to be loaded is also very easy, which means that the tab
will have executed &lt;code&gt;worker.postMessage(n)&lt;/code&gt; by the time the test code checks.
But that doesn&amp;#8217;t mean that the worker &lt;strong&gt;has received the message&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So we need to make our test wait for the worker to start and complete one
iteration (creating its array).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the test we can add code such as:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;  let tabContent = BrowserTestUtils.addTab(gBrowser, url);

  // Wait for the browser to load the tab.
  await BrowserTestUtils.browserLoaded(tabContent.linkedBrowser);

  // For some of these tests we have to wait for the test to consume some
  // computation or memory.
  await SpecialPowers.spawn(tabContent.linkedBrowser, [], async () =&amp;gt; {
    await content.wrappedJSObject.waitForTestReady();
  });&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The last three lines here are the interesting ones.  &lt;code&gt;SpecialPowers.spawn&lt;/code&gt;
allows us to execute code in the context of the tab.  In which we wait on a
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise&quot;&gt;promise&lt;/a&gt; that the test is ready.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now we need to add this promise to the page that owns the worker:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;  var result = document.querySelector(&apos;#result&apos;);
  var worker = new Worker(&quot;workers_memory_script.js&quot;);
  var n = 1;

  var waitPromise = new Promise(ready =&amp;gt; {
    worker.onmessage = function(event) {
      result.textContent = event.data;
      ready();

      // We seem to need to keep the worker doing something to keep the
      // memory usage up.
      setTimeout(() =&amp;gt; {
        n++;
        worker.postMessage(n);
      }, 1000);
    };
  });

  worker.postMessage(n);

  window.waitForTestReady = async () =&amp;gt; {
    await waitPromise;
  };&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Starting at the bottom.
For some reason I had to wrap the promise up in a function, I can&amp;#8217;t remember
why!
I&amp;#8217;m tempted to complain about JavaScript and it&amp;#8217;s inconsistent rules here,
but it could also be my limited understanding preventing me from getting it.
What I do know is that this function must be in the &lt;code&gt;window&lt;/code&gt; object so that
the test code above can find it in &lt;code&gt;wrappedJSObject&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The promise wrapped here (&lt;code&gt;waitPromise&lt;/code&gt; I could have picked a better name)
is resolved when &lt;code&gt;ready()&lt;/code&gt; is called, which happens after we receive the
worker&amp;#8217;s response.
Finally we use &lt;code&gt;setTimeout()&lt;/code&gt; to post another message to keep memory usage
up.
I don&amp;#8217;t know why this was necessary either.  Was the worker completely
terminated without it?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;one-more-thing&quot;&gt;One more thing&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Our test almost works.
For whatever reason when the test accesses the right part of the
&lt;code&gt;about:performance&lt;/code&gt; page there&amp;#8217;s no value for how much memory is being used.
Waiting for a single update fixes this:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;  if (!memCell.innerText) {
    info(&quot;There&apos;s no text yet, wait for an update&quot;);
    await new Promise(resolve =&amp;gt; {
      let observer = new row.ownerDocument.ownerGlobal.MutationObserver(() =&amp;gt; {
        observer.disconnect();
        resolve();
      });
      observer.observe(memCell, { childList: true });
    });
  }
  let text = memCell.innerText;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For the complete code for this test checkout
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1760920&quot;&gt;Bug 1760920&lt;/a&gt;
and
&lt;a href=&quot;https://searchfox.org/mozilla-central/source/toolkit/components/aboutperformance/tests/browser&quot;&gt;toolkit/components/aboutperformance/tests/browser&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;theres-things-i-dont-know&quot;&gt;There&amp;#8217;s things I don&amp;#8217;t know&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There&amp;#8217;s three places here where I&amp;#8217;ve said &quot;it needs this code, I don&amp;#8217;t know
why&quot;.
I hate programming like this, and I feel shameful writing it in a blog post
and calling myself an engineer.
I don&amp;#8217;t want to spin it as a joke on JavaScript, or myself &quot;lol, that&amp;#8217;s
programming!  AMIRITE?!&quot;
There&amp;#8217;s obviously some further subtleties I don&amp;#8217;t know the rules for, and
JavaScript does have some pretty
&lt;a href=&quot;https://www.destroyallsoftware.com/talks/wat&quot;&gt;inconsistent rules&lt;/a&gt;,
throw in a browser, two tabs and a web worker and feeling like you don&amp;#8217;t
know how something works is relatable.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Do I wish I knew?  Sure, I&amp;#8217;m uncomfortable not knowing, but I&amp;#8217;ve already
spent enough time on this.  But this is also why I wrote down what I &lt;strong&gt;do&lt;/strong&gt;
know.
Next time I&amp;#8217;ll be able to find this much and solve my problem quicker.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Fri, 25 Nov 2022 00:00:00 +1100</pubDate>
        <link>https://paul.bone.id.au/blog/2022/11/25/how-to-wait-for-content-in-a-test/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2022/11/25/how-to-wait-for-content-in-a-test/</guid>
        
        <category>planet-mozilla</category>
        
        <category>Firefox</category>
        
        <category>tests</category>
        
        <category>mochitest</category>
        
        <category>promises</category>
        
        <category>race</category>
        
        <category>javascript</category>
        
        <category>concurrency</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Running the AWSY benchmark in the Firefox profiler</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The are we slim yet (AWSY) benchmark measures memory usage.
Recently when I made a
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1728273&quot;&gt;simple change to
firefox&lt;/a&gt; and expected it might save a bit of memory,
it actually
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1729890&quot;&gt;increased memory usage&lt;/a&gt;
on the AWSY benchmark.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We have lots of tools to hunt down memory usage problems.  But to see an
almost &quot;log&quot; of when garbage collection and cycle collection occurs, the
&lt;a href=&quot;https://profiler.firefox.com&quot;&gt;Firefox profiler&lt;/a&gt; is amazing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I wanted to profile the AWSY benchmark to try and understand what was
happening with GC scheduling.  But it didn&amp;#8217;t work out-of-the-box.
This is one of those blog posts that I&amp;#8217;m writing down so next time this
happens, to me or anyone else, although I am selfish.
And I websearch for &quot;AWSY and Firefox Profiler&quot; I want this to be the number
1 result and help me (or someone else) out.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;the-normal-instructions&quot;&gt;The normal instructions&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;First you need a build with profiling enabled.  Put this in your &lt;code&gt;mozconfig&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;ac_add_options --enable-debug
ac_add_options --enable-debug-symbols
ac_add_options --enable-optimize
ac_add_options --enable-profiling&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The instructions to get the profiler to run came from Ted Campbell.  Thanks
Ted.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Ted&amp;#8217;s instructions disabled stack sampling, we didn&amp;#8217;t care about that since
the data we need comes from profile markers.  I can also run a reduced awsy
test because 10 entries is enough to create the problem.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;export MOZ_PROFILER_STARTUP=1
export MOZ_PROFILER_SHUTDOWN=awsy-profile.json
export MOZ_PROFILER_STARTUP_FEATURES=&quot;nostacksampling&quot;
./mach awsy-test --tp6 --headless --iterations 1 --entities 10&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But it crashes due to
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=1710408&quot;&gt;Bug 1710408&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So I can&amp;#8217;t use &lt;code&gt;nostacksampling&lt;/code&gt;, which would have been nice to save some
memory/disk space, never mind.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So I removed that option, then I get profiles that are too short.  The
profiler records into a circular buffer so if that buffer is too small it&amp;#8217;ll
discard the earlier information.  In this case I want the earlier
information because I think something at the beginning is the problem.
So I need to add this to get a bigger buffer.  The default is 4 million
entries (32MB).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;export MOZ_PROFILER_STARTUP_ENTRIES=$((200*1024*1024))&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;But now the profiles are too big and Firefox shutdown times out (over 70
seconds) so the marionette test driver kills Firefox before it can write out
the profile.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The solution&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;So we hack
&lt;code&gt;testing/marionette/client/marionette_driver/marionette.py&lt;/code&gt;
to replace shutdown_timeout with &lt;code&gt;300&lt;/code&gt; in some places.
Setting &lt;code&gt;DEFAULT_SHUTDOWN_TIMEOUT&lt;/code&gt; and also &lt;code&gt;self.shutdown_timeout&lt;/code&gt; to 300
will do.
There&amp;#8217;s probably a way to pass a parameter, but I didn&amp;#8217;t find it yet.
So after making that change and running &lt;code&gt;./mach build&lt;/code&gt; the invocation is now:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;export MOZ_PROFILER_STARTUP=1
export MOZ_PROFILER_SHUTDOWN=awsy-profile.json
export MOZ_PROFILER_STARTUP_FEATURES=&quot;&quot;
export MOZ_PROFILER_STARTUP_ENTRIES=$((200*1024*1024))
./mach awsy-test --tp6 --headless --iterations 1 --entities 10&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And it writes a &lt;code&gt;awsy-profile.json&lt;/code&gt; into the root directory of the project).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Hurray!&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;follow-up&quot;&gt;Follow-up&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Whimboo says that setting &lt;code&gt;toolkit.asyncshutdown.crash_timeout&lt;/code&gt; might help.
But it may wait until after some stuff has been implemented:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;quoteblock&quot;&gt;
&lt;blockquote&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;a solution here should also be to extend the toolkit.asyncshutdown.crash_timeout value&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;oh wait. actually we haven&amp;#8217;t fixed that yet, but only use it via
geckodriver`&lt;/p&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;div class=&quot;attribution&quot;&gt;
&amp;#8212; Whimboo
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Sat, 18 Sep 2021 00:00:00 +1000</pubDate>
        <link>https://paul.bone.id.au/blog/2021/09/18/how-to-profile-awsy/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2021/09/18/how-to-profile-awsy/</guid>
        
        <category>planet-mozilla</category>
        
        <category>Firefox</category>
        
        <category>Profiler</category>
        
        <category>AWSY</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Project MemShrink</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I asked, and have been given a new project at work.
Together with another engineer I will be working on reducing Firefox&amp;#8217;s
memory footprint.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Mozilla has run a
&lt;a href=&quot;https://blog.mozilla.org/nnethercote/2017/05/30/memshrink-status/&quot;&gt;MemShrink
project in the past&lt;/a&gt;,
which even though it has wound-down,
Firefox is still regarded as being more memory efficient than Chrome and the
other chromium-based browsers.
However keeping this accolade is going to be difficult.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lately we&amp;#8217;re working towards
&lt;a href=&quot;https://wiki.mozilla.org/Project_Fission&quot;&gt;project fission&lt;/a&gt; - a site isolation
feature and new process model for Firefox.
This will necessarily require more OS processes for Firefox (particularly
for users who browse multiple different sites in many tabs)
which requires more memory.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We&amp;#8217;ve started a new memory reduction project to ensure we can enable
Fission without excessive memory use:
&lt;a href=&quot;https://wiki.mozilla.org/Project_Fission/Memory&quot;&gt;Fission MemShrink&lt;/a&gt;.
This was actually started in 2018, but now we have two full time engineers
on it and one of them is me.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;so-far&quot;&gt;So far&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A lot of the &quot;easy wins&quot; have already been won:
we reduced the base memory usage on Windows from 21.5MB in 2018 to 14.8MB in
2019, and now 11.5MB in September 2020.
This included situations where memory was used excessively, or not released
when it could be, and other low-hanging-fruit.
However that&amp;#8217;s just base memory, the memory used by a content process before
it loads a page.
Memory usage of the whole browser has increased over the past year (by about
10% as best I can tell from our tracking).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;where-to-optimise&quot;&gt;Where to optimise&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(TL;DR: use a profiler.)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The main goal is to reduce the overhead from enabling fission.  There&amp;#8217;s
multiple places to look:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Reduce the number / size of structures that are used more commonly with
fission.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reduce the amount of memory an &quot;empty&quot; Firefox content process consumes
(that&amp;#8217;s the base memory above).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Reduce the overall memory usage of the browser - that&amp;#8217;s always a good
thing!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve picked the 2nd, or almost-2nd one: Reduce the amount of memory
overhead for a process loading a tiny page (or iframe).
Firefox can generate a memory report, showing where memory is allocated.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With fission enabled I load &lt;a href=&quot;http://example.com&quot; class=&quot;bare&quot;&gt;http://example.com&lt;/a&gt; in one tab (because it&amp;#8217;s a
small page), and open &lt;code&gt;about:memory&lt;/code&gt; in another tab, click &quot;Measure&quot; and
Firefox will generate a memory report.  We&amp;#8217;re using this as the starting
point for where to concentrate our optimisation efforts.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;jemalloc&quot;&gt;jemalloc&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;openblock floatright&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;table class=&quot;tableblock frame-all grid-all stretch&quot;&gt;
&lt;caption class=&quot;title&quot;&gt;Table 1. jemalloc size classes&lt;/caption&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 33.3333%;&quot;&gt;
&lt;col style=&quot;width: 33.3333%;&quot;&gt;
&lt;col style=&quot;width: 33.3334%;&quot;&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th class=&quot;tableblock halign-center valign-top&quot;&gt;Category&lt;/th&gt;
&lt;th class=&quot;tableblock halign-center valign-top&quot;&gt;Subcategory&lt;/th&gt;
&lt;th class=&quot;tableblock halign-center valign-top&quot;&gt;Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot; rowspan=&quot;11&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Small&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot; rowspan=&quot;2&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Tiny&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;4&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;8&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot; rowspan=&quot;7&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Quantum-spaced&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;16&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;32&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;48&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;&amp;#8230;&amp;#8203;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;480&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;496&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;512&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot; rowspan=&quot;2&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Sub-page&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;1 kB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;2 kB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot; colspan=&quot;2&quot; rowspan=&quot;7&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Large&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;4 kB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;8 kB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;12 kB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;&amp;#8230;&amp;#8203;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;1012 kB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;1016 kB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;1020 kB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-left valign-top&quot; colspan=&quot;2&quot; rowspan=&quot;4&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;Huge&lt;/p&gt;&lt;/td&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;1 MB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;2 MB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;3 MB&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;tableblock halign-right valign-top&quot;&gt;&lt;p class=&quot;tableblock&quot;&gt;&amp;#8230;&amp;#8203;&lt;/p&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;For a small process we noted that the memory allocator has more overhead
than we&amp;#8217;d like, &amp;gt;1.90MiB out of a 20.7MiB process (9.21%)
and it may be worth-while looking here as place to reduce overheads.
This overhead is the &lt;code&gt;bin-unused&lt;/code&gt; item on these memory reports.
So this is where I&amp;#8217;m starting.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Firefox uses a fork of the jemalloc memory allocator,
which has now been heavily modified.
jemalloc allocates memory in several size classes,
the most popular comment in the mozjemalloc.cpp file contains
&lt;a href=&quot;https://searchfox.org/mozilla-central/source/memory/build/mozjemalloc.cpp#53-88&quot;&gt; a table explaining its size classes&lt;/a&gt; (Table 1):&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Note that these sizes can vary with different settings, this is the default
on a 32bit build with 4KB pages.
On a 64bit build the 4-byte class is missing and windows is always missing
the word-sized class.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The &apos;bin-unused&apos; item on the memory reports is only relevant for the small
size classes in this table.
In these size classes an area of memory that jemalloc calls a &lt;code&gt;run&lt;/code&gt; (one or
more pages) is divided up into allocations of this size class,
So a request for 12 bytes is rounded up to 16 and allocated in
a &lt;code&gt;run&lt;/code&gt; that contain other 16 byte allocations.
&apos;bin-unused&apos; measures all the unallocated slots in these runs.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This is not wasted memory or lost memory.  But it&amp;#8217;s not &quot;merely unused&quot;
either.  For example, there may be many unused 16-byte slots, even some
close together, but they cannot be used to satisfy a request for 32 bytes.
And because they&amp;#8217;re less than 4KB, they represent physical memory - they
cannot be paged out without paging out the rest of that memory page.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
I think I owe you an article on what a memory page is.  Since I haven&amp;#8217;t
defined that and have used it fairly liberally.  If you don&amp;#8217;t know then just
pretend I&amp;#8217;m saying &quot;4KiB area&quot; and await a future article!
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
A &lt;code&gt;run&lt;/code&gt; may be one or more pages.  Packing 2KB annotations, one per
page would be inefficient so when allocations are larger (or don&amp;#8217;t align
well with their header) jemalloc will use longer runs of pages.
Here is
&lt;a href=&quot;https://searchfox.org/mozilla-central/source/memory/build/mozjemalloc.cpp#859-871&quot;&gt;a table with examples of run lengths&lt;/a&gt;.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;(or sometimes more, but for this article I&amp;#8217;ll
assume a page) will only store items of that specific size class.
This reduces overheads since the size information and if this were a GC
other metadata) could be shared between all the items in the same page.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;wish-me-luck&quot;&gt;Wish me luck&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I could go on with what I&amp;#8217;ve found, and I will but in future posts.
By keeping this post shorter I can publish it today.
Generally this may help me write more generally, if each post is less
time-consuming.
So forgive me for leaving you in suspense, but that&amp;#8217;s what&amp;#8217;s best to maintain a blog at all.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the next post I&amp;#8217;ll write more about &lt;code&gt;bin-unused&lt;/code&gt; and something called &lt;em&gt;slop&lt;/em&gt;
and describe what I might be able to do / have done to fix them.
I&amp;#8217;ll also write an introductory post about paging.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Thanks for reading.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Fri, 25 Sep 2020 00:00:00 +1000</pubDate>
        <link>https://paul.bone.id.au/blog/2020/09/25/memshrink/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2020/09/25/memshrink/</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Case Sensitivity In Grammars</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A
&lt;a href=&quot;https://plasmalang.org/2020/05/05/removing-case-sensitivity.html&quot;&gt;recent change&lt;/a&gt;
to
&lt;a href=&quot;https://plasmalang.org&quot;&gt;Plasma&lt;/a&gt; caused me to think choices that various
languages make with regard to case in their grammar.
I originally assumed there are just two choices in certain grammars,
Case sensitivity or sigils.
But there are some other options and I&amp;#8217;ll share them here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;parsing&quot;&gt;Parsing&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Computer languages are compiled or interpreted in a number of stages.
The first four stages are:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Tokenisation (aka lexical analysis)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Parsing (aka syntactic analysis)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Symbol resolution&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Semantic analysis&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Often some of these stages are combined,
many languages historically did symbol resolution during parsing,
and some do tokenisation and parsing at the same time.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This article is concerned with parsing: taking a list of tokens and
generating an abstract syntax tree.
The parser must figure out what each token&amp;#8217;s role is.
For example in a C program does the &apos;*&apos; symbol represent multiplication, or
pointer-dereference, figuring that out is the parser&amp;#8217;s job.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;One important consideration is that information &lt;em&gt;should&lt;/em&gt; not flow backwards
from later stages to earlier ones.
This means that the parser should not need information from semantic
analysis to make such decisions.
It &lt;em&gt;should&lt;/em&gt; be possible to decide from the token stream and grammar
alone.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you&amp;#8217;re wondering why I&amp;#8217;ve emphasised &quot;should&quot; and are thinking &quot;but this
just seems sensible, surely all languages do this?&quot;
there are popular languages that definitely break this &lt;em&gt;guideline&lt;/em&gt;.
One example is C++,
which needs to lookup the meaning of symbols to figure
out if a &lt;code&gt;&amp;lt;&lt;/code&gt; symbol is a less than token or the beginning of a template
variable list.
So if C++ can do it why is it so bad?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It makes compilers more complex,
usually this is handled by performing more than one compilation stage at a
time,
and that means both making the implementation more complex and requiring
other changes to the language.
In C and C++
declarations must be parsed and have some types of semantic analysis
performed before uses of those declarations can be parsed.
That means that the declaration must occur before the use in the source
file, and even in header files.
Which is why the order that header files are included matters.
All this makes the language more difficult for programmers to use, that&amp;#8217;s
something we want to avoid with Plasma.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Additionally, by making the tools more complex it makes it harder to make
new tools like documentation generators, linters and autoformatters.
They may need to run more compilation stages to achieve their job when
languages break this &lt;em&gt;guideline&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;ambiguity&quot;&gt;Ambiguity&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In Plasma the ambiguity we&amp;#8217;re concerned about is that in some cases
identifiers could refer to either a type or a type variable -
syntactically different concepts we&amp;#8217;d like to distinguish during parsing.
The above guideline says that we have to be able to make this distinction
without looking at anything but the parsing context and the identifier itself.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;admonitionblock note&quot;&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td class=&quot;icon&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Note&lt;/div&gt;
&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;
Identifiers are the names of variables, functions, types and other
symbols appearing in a language - they&amp;#8217;re not keywords such as &quot;return&quot; or
&quot;if&quot;, or other symbols.
&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;languages-with-case-sensitivity&quot;&gt;Languages with case sensitivity&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Languages such as Haskell, Prolog and Mercury are case sensitive,
they use case to distinguish the role of some symbols from others:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Haskell: Types begin with an uppercase letter while type variables begin
with a lower case letter:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;-- Haskell allows the [ ] syntax in type declarations,
-- but we use the word &apos;List&apos; for our example.
length :: List a -&amp;gt; Integer&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Prolog &amp;amp; Mercury: Atoms, predicates and functors begin with lower case
letters and variable begin with upper case.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;length([], 0).
length([X | Xs], N+1) :-
   length(Xs, N).&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Mercury also distinguishes types from type variables like Haskell, but
with upper and lower case reversed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;:- pred length(list(T)::in, int::out) is det.&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;There are other examples of languages with case sensitivity in their
syntax, such as Java, but I don&amp;#8217;t know if they&amp;#8217;d be ambiguous without it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Prolog is a particularly strong case where an ambiguity could be a problem.
In Prolog both atoms and variables are created just by using them once.
Mixing them would make Prolog even more permissive than it already is.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;languages-with-sigils&quot;&gt;Languages with sigils&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;OCaml resolves the same ambiguity between types and type variables that
both Haskell and Mercury have, but it does so using sigils (&lt;code&gt;&apos;&lt;/code&gt;) for type
variables:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;val length : &apos;a list -&amp;gt; int&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We&amp;#8217;ve made the same change to Plasma, and used the same symbol.
This was made to
&lt;a href=&quot;https://github.com/PlasmaLang/plasma/issues/66&quot;&gt;support programming in
scripts without case&lt;/a&gt;,
however I hope that while people program in a language with the roman script
(e.g: English) we will use case as a matter of style:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;// Plasma will allow the [ ] syntax in the type signature in the future
func length(list : List(&apos;x)) -&amp;gt; Int {
   match (list) {
      [] -&amp;gt;               { return 0 }
      [var x | var xs] -&amp;gt; { return 1 + length(xs) }
   }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Note also that we have changed the pattern matching syntax to also use the
&lt;code&gt;var&lt;/code&gt; keyword to introduce new variables.
This functions a lot like the sigil in type expressions to disambiguate
data constructors from new variables.
It has the interesting property that it is now used in two out of three
places where a new variable is introduced (the remaining one is parameter
lists).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;live-with-ambiguity&quot;&gt;Live with ambiguity?&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Of course, one option is to just live with ambiguity.
Let&amp;#8217;s look at a type declaration.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;type List(x) = Nil
             | Cons { x, List(x) }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There&amp;#8217;s actually nothing ambiguous here at all!
Each identifier here is introduced in the same declaration.
&lt;code&gt;Nil&lt;/code&gt; and &lt;code&gt;Cons&lt;/code&gt; are their own declarations, and the other two identifiers
&lt;code&gt;List&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; are declared on the left-hand-side of &lt;code&gt;=&lt;/code&gt; then used on the
right.
When they occur on the right we&amp;#8217;ve already parsed their declaration on the
left.
This means, depending on how you look at it, the grammar is either context
sensitive or we&amp;#8217;ve broken the guideline above that parsing must not depend
on later stages.
Let&amp;#8217;s call it a &quot;weak&quot; case of breaking the above guideline, because it&amp;#8217;s
within the same declaration we can allow it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Even if other symbols appeared on the right-hand-side of &lt;code&gt;=&lt;/code&gt; their role (in
valid programs) would be unambiguous.
They&amp;#8217;d &lt;em&gt;have&lt;/em&gt; to be names of types because all variables must be introduced
on the left.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;However a type expression when it appears inside a function declaration is
ambiguous:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;func length(list : List(x)) -&amp;gt; Int&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here &lt;code&gt;x&lt;/code&gt; may be a type name or a type variable.
We &lt;em&gt;may&lt;/em&gt; resolve the ambiguity by checking if a type named &lt;code&gt;x&lt;/code&gt; already
exists, and if it does assume this is a name.
This &lt;em&gt;could&lt;/em&gt; be resolved after parsing, preserving our guideline above which
would allow us to define the type &lt;code&gt;x&lt;/code&gt; after using it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Depending on the type system &lt;code&gt;List&lt;/code&gt; may also be ambiguous, e.g: it could be a
type variable of kind &lt;code&gt;* &amp;#8594; *&lt;/code&gt; or the name of a type.
However if the language has only kind &lt;code&gt;*&lt;/code&gt; then we know it must be a type&amp;#8217;s
name,
because only type names can take parameters.
Depending on what languages you&amp;#8217;ve used before, this may have made no sense,
if that&amp;#8217;s the case I&amp;#8217;ll just say it&amp;#8217;s an important detail in Haskell because
monads use the kind &lt;code&gt;* &amp;#8594; *&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;How about that other case we had in Plasma, of pattern matching?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;   match (list) {
      [] -&amp;gt;       { return 0 }
      [x | xs] -&amp;gt; { return 1 + length(xs) }
   }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Again we could lookup &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;xs&lt;/code&gt; in a symbol table and find out if they&amp;#8217;re
data constructors, and if that fails we can assume they&amp;#8217;re type names.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;While this is possible, and means sense for &lt;strong&gt;valid&lt;/strong&gt; programs, but ambiguity
becomes a pain in the neck when a program is not what the programmer intends
to write.
I&amp;#8217;ve not said &lt;strong&gt;invalid&lt;/strong&gt; programs because it&amp;#8217;s possible that many of these
programs &lt;em&gt;would&lt;/em&gt; be accepted by the compiler but then be buggy.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;type MyTypeA
type MyList = List(MyTypeB)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There&amp;#8217;s a spelling error here. The programmer has written &lt;code&gt;MyTypeB&lt;/code&gt; instead
of &lt;code&gt;MyTypeA&lt;/code&gt;.  Either way the compiler may accept this program but now
MyList has a different meaning.
Arguably that&amp;#8217;s no worse than if there were two types with names with
similar spellings, but that&amp;#8217;s a code smell programmers may wish to avoid
because it leads to the same type of confusion.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Likewise, let&amp;#8217;s say a programmer writes:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;func length(list : List(x)) -&amp;gt; Int&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And they expect &lt;code&gt;x&lt;/code&gt; to be a type variable, and use it as such:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;var a = length([1, 2, 3])
var b = length([&apos;a&apos;, &apos;b&apos;, &apos;c&apos;])&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s fine until elsewhere in the same module they add a type called &apos;x&apos;!
Now they have compilation errors where they expect to use their generic
list.  But of course their length function where the identifier list occurred
won&amp;#8217;t be where the compilation error is reported, it may even be reported in
a separate module if &lt;code&gt;length&lt;/code&gt; is exported but not used in this module.
They&amp;#8217;re going to be very annoyed with the language designer!
This may also work fine until some time six months from now they add the
type &lt;code&gt;x&lt;/code&gt;!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I generally want to avoid this kind of ambiguity while designing Plasma.
Plus it breaks one of my design philosophies for Plasma and that is a thing
should look like what it is.
That&amp;#8217;s another way to say the language should be unambiguous, or even that
the grammar should be context free (but I&amp;#8217;m not making that a hard rule,
there&amp;#8217;ll be times when I break it).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I also considered allowing partial ambiguity.
That is using case to hint to the compiler the role an identifier plays,
and if it doesn&amp;#8217;t make sense then the compiler can re-evaluate the meaning.
This ends up being very similar to a complete ambiguity that it&amp;#8217;s not worth
much discussion.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;languages-that-declare-type-parameters&quot;&gt;Languages that declare type parameters&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There&amp;#8217;s one other way to avoid ambiguity. And we saw it above:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;type List(x) = Nil
             | Cons { x, List(x) }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here all the identifiers are introduced in such a way as they&amp;#8217;re
unambiguous.
There&amp;#8217;s other languages that do this with type variables appearing in
function declarations and definitions, e.g: C++.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;template&amp;lt;typename T&amp;gt;
int length(List&amp;lt;T&amp;gt; list);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The &lt;code&gt;template&lt;/code&gt; keyword introduces a parameter list of type variables.
We could do that in Plasma:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;generic(x)
func length(list : List(x)) -&amp;gt; Int {
   match (list) {
      [] -&amp;gt;         { return 0 }
      var x, xs:
      [x | xs] -&amp;gt;   { return 1 + length(xs) }
   }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Note that we also did the same to introduce &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;xs&lt;/code&gt; as variables before
they occurred in the pattern.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Java doesn&amp;#8217;t have the &lt;code&gt;template&lt;/code&gt; keyword like C++, instead
its grammar allows it to use
use &lt;code&gt;&amp;lt; &amp;gt;&lt;/code&gt; brackets to give the parameter list.
I assume that C++ can&amp;#8217;t do this because it&amp;#8217;d be ambiguous.
In Plasma that could look like:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;func length&amp;lt;x&amp;gt;(list : List(x)) -&amp;gt; Int&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s not terrible, and would certainly solve the ambiguity with type
variables.
I personally have a gut-reaction against this because it reminds me of C++
and gnarly template errors,
but I realise as I&amp;#8217;m writing this, I wouldn&amp;#8217;t rule it out because it could
also make it easier to add constraints (such as interfaces) on these type
variables in a way that fits the syntax:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;func sort&amp;lt;x : Ord&amp;gt;(list : List(x)) -&amp;gt; List(x)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We can&amp;#8217;t reasonably extend this concept to the pattern match,
there the functor (in the syntactical sense) is the &lt;code&gt;&amp;#8594;&lt;/code&gt; and I wouldn&amp;#8217;t
want to add parameters to that.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We can however use this idea to remove Haskell&amp;#8217;s case sensitive grammar
without introducing sigils, with a slight modification to the typeclass
constraint syntax:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;list :: a =&amp;gt; [a] -&amp;gt; Int&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There&amp;#8217;s more than just the two choices I had initially assumed.  I&amp;#8217;ve found
five:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Case sensitive grammar&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sigils&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ambiguity&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Declare new type variables with a keyword (C++)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Declare new type variables with a parameter list (Java)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And I&amp;#8217;m surprised to find that although I&amp;#8217;ve made the decision to use
sigils, I&amp;#8217;m also drawn to the parameter list idea such as Java uses.
Plasma is far from 1.0, and for now I reserve the right to change these
decisions as necessary and may revisit this decision in the future.
For now I will at the very least sleep on it.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Wed, 20 May 2020 00:00:00 +1000</pubDate>
        <link>https://paul.bone.id.au/blog/2020/05/20/case-sensitivity-in-grammars/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2020/05/20/case-sensitivity-in-grammars/</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Reorg&amp;#8217;d</title>
        <description>&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;You may have heard recent news of the
&lt;a href=&quot;https://techcrunch.com/2020/01/15/mozilla-lays-off-70-as-it-waits-for-subscription-products-to-generate-revenue/&quot;&gt;changes&lt;/a&gt;
happening at &lt;a href=&quot;https://mozilla.org&quot;&gt;Mozilla&lt;/a&gt; where I work.
As part of those changes we&amp;#8217;ve also re-organised
(&lt;a href=&quot;http://arewereorganizedyet.com/&quot;&gt;reorg&amp;#8217;d&lt;/a&gt;) many teams and individuals.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;My team assignment has changed and I no-longer work on SpiderMonkey&amp;#8217;s
garbage collector.
This is a bit of a bummer because I was hoping to make memory management and
garbage collection my career focus and become an expert,
like I had already done with
&lt;a href=&quot;/pub/pbone-2012-thesis/&quot;&gt;automatic parallelism&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;My new team is the &lt;a href=&quot;https://wiki.mozilla.org/Project_Fission&quot;&gt;Fission team&lt;/a&gt;, a
new team to work in stronger process isolation for Firefox.
So far I&amp;#8217;ve been working on DocumentChannel with several other engineers.
DocumentChannel is a feature/project for launching new page/iframe loads
from the parent process so that redirects to not spawn two many short-lived
processes.
This feature has landed in Firefox Nightly but there&amp;#8217;s still refinements to
make.
So far I&amp;#8217;m enjoying working with another team and getting to know more
people within the organisation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When we roll-out Fission it&amp;#8217;s going to add new challenges for Firefox&amp;#8217;s
memory usage.
I&amp;#8217;ll be putting myself forward at that time to work on reducing memory usage
(or making smarter choices with memory),
with any luck that will mean working on memory allocators or the GC again.&lt;/p&gt;
&lt;/div&gt;</description>
        <pubDate>Mon, 17 Feb 2020 00:00:00 +1100</pubDate>
        <link>https://paul.bone.id.au/blog/2020/02/17/reorg/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2020/02/17/reorg/</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Cpu Cache</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Whenever discussing CPU-bound performance
(at least in the last 10-15 years)
CPU cache is almost always a dominant factor.
However often people say &quot;oh probably cache&quot; when explaining away some
observation.
They&amp;#8217;re probably right, but let&amp;#8217;s dive a little deeper into how exactly a
modern CPU cache (or caches) works.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;We&amp;#8217;re going to learn how to unpack jargon such as:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Level 1 32KB i-cache and 32KB d-cache, 8-way set associative,&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Shared level 3 8MB cache.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And also talk about cache behaviour in multi-processor systems as well as
another type of cache called a TLB.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;m working on a set of articles that are going to deal with cache effects,
and wanted to start with this background information, not all of it will be
needed but all of it is interesting (or tedious, depends on how tightly
wound your propeller-hat is).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;m going to assume you already know that cache is a type of fast memory
that is &quot;nearer&quot; to the processor and so communication with it is faster
with lower latency.  That it holds copies of some things from regular memory
to speed up program execution, because programs will tend to access memory
near memory they&amp;#8217;ve already accessed recently.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;While I write this I was checking my knowledge with some web
searching.  I found that there are plenty of other resources online
including worked examples.  But I thought I&amp;#8217;d summarise it anyway.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;cache-levels&quot;&gt;Cache levels&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I remember owning a 486 motherboard that had an extra slot, next to the CPU
that someone told me was for &quot;cache&quot;. I found a circuit board that fitted
there but I never tested to see if it made a difference.
Point is that when the slot was empty, or if your 486 motherboard didn&amp;#8217;t
have it, it had 0 levels of cache.  When you put the right card in that
slot, then you had &quot;one level of cache&quot;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Edit 2019-05-03&lt;/div&gt;
&lt;p&gt;I mis-remembered, and just started reading the
&lt;a href=&quot;http://fabiensanglard.net/gebbdoom/&quot;&gt;Game Design Black Book: Doom&lt;/a&gt; (which
looks great! so excited!):
The 486 has an integrated L1 cache and the slots/sockets available on
motherboards are for L2.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;My i7 Desktop has 3 levels of cache.  The neat hwloc-ls tool on Linux will
show you something like:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;openblock floatright&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Memory hierarchy&lt;/div&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/assets/img/cpu-cache/heirarchy.svg&quot; alt=&quot;Memory heirarchy of an i7&quot; width=&quot;300&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Package L#0 + L3 L#0 (8192KB)
  L2 L#0 (256KB) + L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0
    PU L#0 (P#0)
    PU L#1 (P#4)
  L2 L#1 (256KB) + L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1
    PU L#2 (P#1)
    PU L#3 (P#5)
  L2 L#2 (256KB) + L1d L#2 (32KB) + L1i L#2 (32KB) + Core L#2
    PU L#4 (P#2)
    PU L#5 (P#6)
  L2 L#3 (256KB) + L1d L#3 (32KB) + L1i L#3 (32KB) + Core L#3
    PU L#6 (P#3)
    PU L#7 (P#7)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I have four cores, two &lt;em&gt;processing units&lt;/em&gt; (PU) in each, and three levels of
cache.
Each core has three types of cache: L1d (level 1 data), L1i (level 1
instruction), both 32KB large, and a 256KB L2 (instructions and data).
The &lt;em&gt;package&lt;/em&gt; (that&amp;#8217;s what you&amp;#8217;re holding when you&amp;#8217;re installing a CPU)
itself has another level of cache (L3) shared between all four cores.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cache is expensive memory, and the faster you need it the more expensive it
is.
It&amp;#8217;s common to arrange it in levels, with the most expensive fastest cache
memory nearest (or inside) the core.  That&amp;#8217;s our L1i and L1d.  Because it&amp;#8217;s
expensive there&amp;#8217;s only 64KB of it per core.  We can afford 8MB of the least
expensive cache (but still expensive relative to main memory).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Since this is a multi-processor we notice that if there&amp;#8217;s only a single
thread running it can use only its cores&apos; 64KB and 256KB of L1 and L2.  But
it can use the whole 8MB of L3.  When tasks run on other threads they
share this 8MB (with whatever policy the CPU chooses).  if some threads
access the same data, they benefit by communicating through this shared
last-level cache.  There&amp;#8217;s another term you may encounter: &lt;em&gt;last-level
cache&lt;/em&gt; (LLC) it&amp;#8217;s whatever cache is furthest from the processor.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The other thing going on here is that the L1 is split between instructions
(code) and data.
There&amp;#8217;s probably a good reason for that, it may be because code and data are
typically fetched through different pathways and that code is almost always
read-only.  But those are just my guesses.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;cache-lines&quot;&gt;Cache lines&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Cache is arranged in &lt;em&gt;lines&lt;/em&gt;.  Let&amp;#8217;s see ask /proc/cpuinfo:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;clflush size    : 64
cache_alignment : 64&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That&amp;#8217;s not exactly the answer for the question I was asking, but it&amp;#8217;s close
enough for jazz.  Also I happen to know based on other sources.  This CPU
has 64-byte cache lines.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In other words, the cache manages 64-byte long (and aligned) blocks, or
&lt;em&gt;lines&lt;/em&gt; of memory.
Managing cache in lines improves its use, since if you read the first word
from a line, you&amp;#8217;re likely to read following ones and now they&amp;#8217;re &lt;em&gt;hot&lt;/em&gt; in
your cache (words are 8 bytes (64-bits) long on a 64bit system).
Larger cache lines reduce bookkeeping costs since the CPU will keep
data per-line.
However large lines will also reduce how well the cache can handle random
access workloads.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;cache-associativity&quot;&gt;Cache associativity&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When a CPU wishes to retrieve some memory it asks the cache;
if the cache is 8MB and contains lines of 64 bytes each,
then the CPU needs to know which of the 131,072 cache lines to check.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The simplest method uses the low-order bits of the address shifted right so
that the bits that address the byte within the cache line aren&amp;#8217;t used.
For an 8MB cache with 131,072 64-byte lines that&amp;#8217;s:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;openblock floatright&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Example&lt;/div&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/assets/img/cpu-cache/line.png&quot; alt=&quot;Example cache line calculation showing that bits 7-22 of a 32bit address are used as the cache line&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;line = (address &amp;gt;&amp;gt; 6) &amp;amp; 0x1FFFF&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Then the CPU compares that line&amp;#8217;s address to the address for the memory
request.
This means that the cache must store the addresses for each cache line,
but in case of my i7 it can skip the 6 lowest bits since that&amp;#8217;s how
it&amp;#8217;s aligned.
And also skip the 29 highest bits, because my i7 has only a 39-bit &lt;strong&gt;physical&lt;/strong&gt;
address space despite a 48-bit virtual address space and 64-bit general
purpose registers.
Leaving only 30 bits of the cache line&amp;#8217;s address that need to be stored,
less than half!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Anyway, if that matches then the cache lookup is a &lt;em&gt;hit&lt;/em&gt; and the cache elides
(FIRST TIME I used that word) the memory access.
If it doesn&amp;#8217;t match then the lookup is a &lt;em&gt;miss&lt;/em&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In this scheme every physical address maps to exactly one cache line.  To
improve the cache&amp;#8217;s hit rate we can increase this.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now we change the equation above to calculate the &quot;set&quot;, we also take a bit
of precision away - there are half as many sets as there are cache lines.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;openblock floatright&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Example&lt;/div&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/assets/img/cpu-cache/set.png&quot; alt=&quot;Example cache set calculation showing that bits 7-21 of a 32bit address are used as the cache set&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;set = (address &amp;gt;&amp;gt; 6) &amp;amp; 0xFFFF&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Each set in this example has two cache lines in it, the memory we&amp;#8217;re looking
up can be cached in either;
the cache system will check both.
This is a 2-way set associative cache.
My i7 has a 16-way level 3 cache (the cpuid program on Linux will tell
you).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This improves the hit rate, because if two addresses would have been stored
in the same cache line, and accessing one may have evicted the other, even
if it was recently used and going to be used again.
However with an associative cache these collisions don&amp;#8217;t lead to evictions as
often.
The CPU will use an &quot;eviction policy&quot; to decide which line within a set will
be evicted.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It&amp;#8217;s also possible to have a &lt;em&gt;fully-associative&lt;/em&gt; cache, where any memory
address can be stored in any cache line.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;inclusive-or-exclusive-cache&quot;&gt;Inclusive or exclusive cache&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If some data is present in the level 2 cache then is it required/expected to be
present in L3?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Yes: the L3 cache is inclusive&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No: the L3 cache is not inclusive&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Edit 2019-05-02&lt;/div&gt;
&lt;p&gt;Harold reminded me about Victim Caches, which is related to
inclusive/exclusive.
L2 is a victim cache if when something is evicted from L1 it is then stored
in L2.
Lines arn&amp;#8217;t usually stored in L2 due to misses there.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;write-back-vs-write-through&quot;&gt;Write-back vs write-through&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When some data is written to that address, and it is cached, will it be
written out to to memory/the next cache level immediately?&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Yes: Write-through&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No: Write-back&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I&amp;#8217;ve never knowingly seen a write-through CPU cache, I&amp;#8217;ve usually heard
this term for disk caches.
But there&amp;#8217;s a chance I&amp;#8217;m wrong and write-through is useful for CPU caches
for memory regions that map hardware.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;div class=&quot;title&quot;&gt;Edit 2019-05-02&lt;/div&gt;
&lt;p&gt;Mike remembers seeing configuration for write-through/write-back
in a recent system&amp;#8217;s BIOS.
I have vague memories of this from a long time ago,
memories I didn&amp;#8217;t trust to be accuruate enough to report.
Maybe it&amp;#8217;s true, or maybe we both saw an option for disk cache.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;multiprocessor-behaviour&quot;&gt;Multiprocessor behaviour&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here&amp;#8217;s where things get complicated.
Let&amp;#8217;s forget my i7, or at least forget the L1 and L3 from my i7.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Processor A reads memory location 5 into its cache (let&amp;#8217;s assume it
initially contains the value 3), modifies it and the result (4) is stored in
Processor A&amp;#8217;s write-back cache.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// ptr points to memory location 5,
int *ptr = 5;
// read and update
*ptr = *ptr + 1;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now processor B wants to read the same memory location:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// ptr points to memory location 5,
int *ptr = 5;
printf(&quot;The number is %d\n&quot;, *ptr);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Does B see the number 3, or the number 4.  We&amp;#8217;re assuming that B runs
&lt;em&gt;after&lt;/em&gt; A.  But even so there&amp;#8217;s a good chance B will report &quot;3&quot;. That&amp;#8217;s
because the &quot;4&quot; is in A&amp;#8217;s cache.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;To solve this we need some system of &lt;em&gt;cache coherence&lt;/em&gt; which is almost
always combined with some atomic operations and/or fences so that the
processors can opt-in to ensuring that things are coherent.
They don&amp;#8217;t do it all the time because that would be slower / take more
energy.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If A uses atomic instructions to read and update memory location 5.
When B reads it, then depending on what kind of cache-coherence protocol is
used either:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;ulist&quot;&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The correct value (4) can be read from main memory because A flushed it
there and invalidated anyone else&amp;#8217;s copy.  So B knows it must read it
from main memory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The correct value might or might not be in main memory, but B knows that
A has a valid copy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;B already knows the correct value, because it saw it go by on the memory
bus when A wrote it, so it stored it in its own cache then (snooping).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There are more variations, and the 3rd option isn&amp;#8217;t the only option for
snooping.  For example snooping might have noticed that A updated the value
but B recorded only that its own value (if it had one) is invalid, and
didn&amp;#8217;t record the new one.  Or only records values that look &quot;interesting&quot;
according to some heuristic.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This is a very brief overview.  What I really want to share here is that
cache coherency is a thing that exists.  It&amp;#8217;s also one of the reasons why
it&amp;#8217;s difficult to scale up CPUs to many dozens of cores: the access to
memory and coherency is a place where they must coordinate.  Alternatives do
exist, including NUMA (systems where each processor or small group of
processors has its own memory) which may communicate between memories via
other (often slower) means.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;memory-barriersfences&quot;&gt;Memory barriers/fences&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Above we introduced atomic instructions, these work well when operating on a
single memory location.  When more than one location is involved fences are
often required.  Let&amp;#8217;s imagine we have a buffer that two processors use to
communicate, this buffer might be used by something like a channel in the Go
language.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Write a value into the buffer
buffer[pos] = new_value;
pos++;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The write into the buffer and the write to the current buffer position are
likely to both be cached.  But what if the update to the position (pos)
is flushed or evicted from the processors cache before the change to the
buffer itself?
Then another processor reading the buffer might read an invalid or
incomplete item.  What we need is a &lt;em&gt;memory barrier&lt;/em&gt; (aka &lt;em&gt;memory fence&lt;/em&gt;)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// Write a value into the buffer
buffer[pos] = new_value;
sfence();
pos++;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This &lt;em&gt;store fence&lt;/em&gt; (an x86 instruction) tells the CPU that all the stores
must be visible to other processors before any of the stores that follow.
It ensures that the buffer&amp;#8217;s contents are ready before the position is
updated.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Provided there&amp;#8217;s only one thread allowed to update pos then this code is
now thread-safe.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;There are also other types of fences and atomic instructions, providing
various levels of strength.  Each architecture is different.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;false-sharing&quot;&gt;False sharing&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When two unrelated things are used by different processors but stored in the
same cache line this can lead to a lot of thrashing as the cache system
tries to keep a coherent view of this busy cache line.
This is known as &lt;em&gt;false sharing&lt;/em&gt;.
Normally unrelated things end up on different cache lines, but that&amp;#8217;s not
always true and sometimes they do appear on the same cache line.
If that happens try to add padding or otherwise arrange for them to be
allocated separately.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;other-cache-types&quot;&gt;Other cache types&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;CPUs have other things that are either types of cache or things that just
&quot;use&quot; cache.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;μop-cache&quot;&gt;μOP cache&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Some more recent Intel CPUs use a μOP cache (micro-operation cache).
This is like the L1 instruction cache and stores pre-decoded instructions.
It&amp;#8217;s good for accelerating short loops and avoids the need to re-decode
instructions in these loops (but the loops have to be sufficiently short).&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;page-translation-and-tlbs&quot;&gt;Page translation and TLBs&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;em&gt;Translate look-aside buffers&lt;/em&gt; (TLBs) may be even more significant than
cache.
Memory addresses used by your program are known as virtual addresses.
These must be translated into physical addresses before they can be
retrieved, which is known as page address translation, or just translation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;openblock floatright&quot;&gt;
&lt;div class=&quot;title&quot;&gt;32-bit Paging on x86 (From Intel manual)&lt;/div&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;&lt;span class=&quot;image&quot;&gt;&lt;img src=&quot;/assets/img/cpu-cache/paging.png&quot; alt=&quot;A diagram of page translation&quot; width=&quot;for an accessible version it&amp;#8217;s probably best to find the tables/description in the Intel manuals&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The operating system is responsible for maintaining page tables (structures
in memory) that tell the CPU what the physical address for a given virtual
address is.
In the figure these are shown as the page directory and page table.
However since these tables are stored in memory to look them up requires
memory accesses (two in the example shown).
This could be quite painful, so the CPU will cache the results of these
lookups in a special case known as a translate look aside buffer (TLB).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Here&amp;#8217;s what my i7 says about its L2 TLB (it also has L1 TLBs but they&amp;#8217;re
more complex.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0xc1: L2 TLB: 4K/2M pages, 8-way, 1024 entries&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Page translation is based around memory pages.  Like cache lines, pages break
the memory into pieces that get handled in a similar way.
x86 pages are normally 4KB,
more recent CPUs can support larger pages (we&amp;#8217;ll see why in a moment).
My L2 TLB for 4K or 2M pages stores 1024 entries and is 8-way associative.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;With 1024 entries for typical 4K pages, this can cache page lookups for 4MB
of memory.  With 2MB pages this increases to 8GB.  However I think operating
systems and possibly even the CPU tend to prefer 4K pages.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;My CPU also supports 4MB and 1GB pages, the former has a TLB at L1 for data
only and the latter at L1 for instructions only.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;branch-predictor&quot;&gt;Branch predictor&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A modern CPU does its work in a &lt;em&gt;pipeline&lt;/em&gt;.  While some instructions are
being executed or having their results stored, others will be being fetched
and decoded.  Keeping this pipeline full keeps performance up.
One thing that can cause the pipeline to &lt;em&gt;stall&lt;/em&gt; is conditional or indirect
branch instructions.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In the case of conditional instructions usually some computation is needed
to determine whether the branch will be &lt;em&gt;taken&lt;/em&gt;.
This computation will still be in progress at the time the CPU will want to
start fetching instructions and keeping the pipeline full.  The CPU will
make a guess about the branch and execute instructions tentatively, not
storing their results until it knows if the branch will definitely be
taken/not-taken.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If it guesses correctly then everything is good and the tentative
instructions can &lt;em&gt;retire&lt;/em&gt;.
If it guesses incorrectly the pipeline must be flushed and refilled with the
correct instructions.
This can create a significant delay so it&amp;#8217;s important to guess accurately.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A simple and reasonable branch predictor (modern CPUs probably use something
&lt;strong&gt;much&lt;/strong&gt; more complex) can be implemented with a single bit for every entry.
The CPU will take the low bits of the current &lt;em&gt;program counter&lt;/em&gt; (aka
&lt;em&gt;instruction pointer&lt;/em&gt;) and use this to index into a table of entries where
it stored the result of the last branch that matched this entry.
If that entry is a 1 then the branch was taken last time and will probably
be taken this time, if it was 0 then the branch was not taken.  When a
branch instruction is retired then the &quot;takenness&quot; is stored in the matching
entry.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This is similar to looking up the cache line or set for a memory access.
Where it&amp;#8217;s different is that collisions don&amp;#8217;t matter, they only result in an
incorrect prediction which may slow down the program, not an incorrect result.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;A more advanced version might have N bits per entry, storing the most recent
N results of the matching branches and perform some computation such as if
there are more 1s than 0s to determine if the branch is likely to be taken
again.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect2&quot;&gt;
&lt;h3 id=&quot;shadow-stack&quot;&gt;Shadow stack&lt;/h3&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;x86 and x86_64 use call and ret instructions to implement a call stack.
They&amp;#8217;re not necessary as the sp/esp/rsp register can be manipulated
directly, but they&amp;#8217;re the typical instructions that compilers generate for
procedure calls.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Modern x86/x86_64 chips accelerate them by buffering the values pushed on
the stack by the call instruction and using this buffer to accelerate
ret instructions.
It is more of a buffer than a cache, but I wanted to include it anyway.
If call and ret instructions become misaligned or the buffer
under/overflows than a more general slow-path is used,
so it&amp;#8217;s not something the programmer or even the operating system needs to
manage.
It is something that you might wish to be aware of when optimising code
though.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;remarks&quot;&gt;Remarks&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I wanted to provide a breadth of information about CPU caches.  If you want
to go deeper on any particular topic I&amp;#8217;m sure a web search will point you in
the right direction, but hopefully I&amp;#8217;ve collected a reasonable overview
here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Next time you hit a performance problem and you want to say &quot;Oh probably
cache&quot; and dismiss the artifact,
you now have a few clues for deeper investigation.
One case where this came up was for the Mercury team
(but before I joined the Mercury project).
They improved &lt;a href=&quot;https://mercurylang.org&quot;&gt;Mercury&lt;/a&gt;&apos;s performance by ensuring
that a bunch of memory regions &lt;em&gt;were not&lt;/em&gt; aligned.
With paged-aligned regions the commonly used addresses (near the bottom of
each region) mapped to the same cache line or set and conflicted with each
other.
By randomising their alignment the team avoided this conflict and improved
performance.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you liked this article you might also like:
&lt;a href=&quot;/2018/09/26/more-x86-addressing/&quot;&gt;x86 Addressing Under the Hood&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Wed, 01 May 2019 00:00:00 +1000</pubDate>
        <link>https://paul.bone.id.au/blog/2019/05/01/cpu-cache/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2019/05/01/cpu-cache/</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Recursive Lambdas In Plasma</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;While implementing closures in
&lt;a href=&quot;https://plasmalang.org&quot;&gt;Plasma&lt;/a&gt;
I hit this problem and think it might be an interesting example to
demonstrate where theory and practice meet in programming language
implementation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Lambda expressions are anonymous (lambda expression means anonymous
function).
and because things need to be named so we can refer to them (in most
languages) a lambda expression cannot refer to itself and be recursive.
So why would I want to make them recursive?
We&amp;#8217;ll get to that, but first some background.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Statements in &lt;a href=&quot;https://plasmalang.org&quot;&gt;Plasma&lt;/a&gt;
work like let expressions might in typical functional languages.
The first statement here binds x and subsequent statements may now refer
to it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;x = a + b
print!(int_to_string(x) ++ &quot;\n&quot;)&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;x can&amp;#8217;t be used before it is defined, including the right-hand-side of an
binding (=) in the same statement.  So this is illegal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;x = x + 1&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Meanwhile functions are recursive:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;func foo(x) -&amp;gt; Int {
   return foo(x + 1)
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;is legal, but not a good idea.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Next we want to support nested functions and lambda expressions.  Nested
functions look like:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;func main() uses IO -&amp;gt; Int {
    greeting = &quot;Hello &quot;
    func hi(name : String) uses IO {
        print!(greeting ++ name ++ &quot;\n&quot;)
    }

    hi!(&quot;Paul&quot;)
    return 0
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And lambda expressions might look like:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;func main() uses IO -&amp;gt; Int {
    greeting = &quot;Hello &quot;
    hi = func(name : String) uses IO {
        print!(greeting ++ name ++ &quot;\n&quot;)
    }

    hi!(&quot;Paul&quot;)
    return 0
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In fact, both are equivalent, and therefore, to keep the compiler and other
tools simpler one is usually implemented in terms of the other.
Often as a &quot;syntax sugar&quot; (but not always).
In the case of functions in Plasma, the lambda expression is more general,
so we&amp;#8217;ll implement the nested function definitions in terms of lambda
expressions.
(In Plasma this is not a syntax sugar since the &lt;em&gt;desugaring&lt;/em&gt; of nested
functions happens at a later compilation stage, after parsing.)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Everything is fine until we attempt recursion.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;func length(l : List(x)) -&amp;gt; Int {
   match (l) {
      case [] -&amp;gt; {
         return 0
      }
      case [x|xs] -&amp;gt; {
         return length(xs) + 1
      }
   }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If this is nested inside another function and implemented in terms of
lambda, then it becomes:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;length = func(l : List(x)) -&amp;gt; Int {
   match (l) {
      case [] -&amp;gt; {
         return 0
      }
      case [x|xs] -&amp;gt; {
         return length(xs) + 1      // UNDEFINED
      }
   }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;And if we think about our x = x + 1 example above, we can&amp;#8217;t access
length before it has been bound.
This is not only restrictive and surprising, but it&amp;#8217;s also against one
principal I have for Plasma, that is that the same thing (syntax-wise)
should behave the same regardless of context.
If this function was at the top level then it would not be transformed this
way and would be able to be recursive.
(A related principal is that things that look the same should &lt;strong&gt;be&lt;/strong&gt; the
same.)&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Naturally if we wrote a lambda it should not be able to access itself.
Maybe the above case looks okay, however:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;greetings = map(func(name : String) -&amp;gt; String {
      return &quot;G&apos;day &quot; ++ name
   }, names);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;It makes no-sense for the lambda, which is very definitely an expression
in map&apos;s first argument, to access the greetings variable.
Because things that look the same (lambdas) should be the same, we need
the same rule for the above length lambda as we do here.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;That brings us to the decision that we have to make the lambda syntax, and
nested function syntax behave differently &lt;strong&gt;even though they map to the same
internal thing&lt;/strong&gt;.
This is where we may add some &lt;em&gt;exceptions to the rules&lt;/em&gt; of our
language&amp;#8217;s internal consistency,
in order to provide external consistency from the user&amp;#8217;s perspective.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In my opinion, the solution isn&amp;#8217;t the interesting part.
What you just read, how we &lt;em&gt;decide&lt;/em&gt; how to make a language consistent is the
interesting part.
Read on for how we usually solve this within a compiler.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;When a function is defined as a statement, such as:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;func length(l : List(x)) -&amp;gt; Int {
   ...
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;and we transform it to a statement containing an expression which is a
lambda.
The compiler can attach to the lambda the name it was defined with and the
knowledge that it must be able to access its own name from within.
Compilers attach a lot of data to the &lt;em&gt;nodes&lt;/em&gt; that represent the program,
this is just one other thing.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;length = func(l : List(x)) Int
   #pragma lambda name &quot;length&quot;
   {
      ...
   }&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Now when we process this lambda we know to make the name &quot;length&quot; refer to
itself and to allow it to be resolved from within.
And when performing later analyses we have to check such annotations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;What Plasma actually does is slightly more complex because it fits with the
structure of the compiler better (and is not implemented yet).
At the time when these statements are transformed to lambdas, a name for the
function that tracks the lambda is generated (and used for other reasons)
We can search the body of such functions to look for the name &quot;length&quot; and
replace it with the internal name.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;listingblock&quot;&gt;
&lt;div class=&quot;content&quot;&gt;
&lt;pre&gt;length = func lambda_23_length_2(l : List(x)) -&amp;gt; Int {
   match (l) {
      case [] -&amp;gt; {
         return 0
      }
      case [x|xs] -&amp;gt; {
         return lambda_23_length_2(xs) + 1
      }
   }
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;If you&amp;#8217;re wondering where the numbers come from, they&amp;#8217;re the line and column
numbers from the source file, they&amp;#8217;ll always be unique and this symbol won&amp;#8217;t
be exported.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;update-2019-02-13&quot;&gt;Update 2019-02-13&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The simple solution presented here won&amp;#8217;t work for mutually recursive
functions, which should work because they &lt;em&gt;do&lt;/em&gt; work at the top level so they
should work in nested levels.
I think the solution here could be made to work, subject to other bindings
and causality.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Wed, 13 Feb 2019 00:00:00 +1100</pubDate>
        <link>https://paul.bone.id.au/blog/2019/02/13/recursive-lambdas-in-plasma/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2019/02/13/recursive-lambdas-in-plasma/</guid>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Happy Holidays</title>
        <description>&lt;div id=&quot;preamble&quot;&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Last year, for over half a year I was in the practice of
writing company-wide e-mails, bothering everyone at Mozilla, about why I
wouldn&amp;#8217;t be at work the next day due to a public holiday.  It started with
the most hilarious holiday the &quot;Friday before the AFL grand final public
holiday&quot; (remind me this September, and I&amp;#8217;ll explain) and finished after we
got into some much less fun holidays such as invasion day (Jan 26th).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I remembered this recently and felt like sharing what I wrote for Christmas
last year.  Pretending that Christmas is something celebrated only in
Australia and I had to explain it to the rest of the world, I wrote:&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;Australia will be celebrating two very significant local holidays this December
25th and 26th.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;25th-of-december-christmas-day&quot;&gt;25th of December: Christmas Day.&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;On Christmas Day we celebrate the birth of Sir Isaac Newton, he is gracious
enough to share his birthday with Jesus Christ (who is significant to many
Australians, but not myself, so this e-mail will be mostly-secular).&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The day begins with coffee (like every day) followed by
gift-giving.  Santa aka Father Christmas brings gifts for the children.
Santa comes from the North Pole where it is winter all the time.  In
Australia it is summertime and there is no snow on the ground for his sleigh
to work properly, so instead he rides on a firetruck.  Also due to the heat
Santa perspires a lot and needs to replace those fluids quickly, so it isn&amp;#8217;t
unusual to see Santa quickly drink a beer underneath his beard.  The beard
helps to conceal this from the children.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The main feast is called Christmas Lunch, it can consist of ham, roast
chicken, roast pork and roast veggies or salads.  Sometimes BBQd or boiled
prawns are also served, I prefer boiled.  No we don&amp;#8217;t &quot;throw another shrimp
on the barbie&quot; they&amp;#8217;re called prawns.  The meats are often served cold with
salads since the weather is warm.  If the weather is cold then serving them
warm with roast veggies is also normal.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;In our family and I gather in many others the afternoon is spent napping or
with quiet activities like reading or board games.  Children will often
watch a film, many of the films feature cold weather and winter iconography.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;december-26th-boxing-day&quot;&gt;December 26th: Boxing Day&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This holiday is called Boxing Day after the Boxing Day test cricket match.
We send our greatest champions out into 35-40c heat to play cricket against
the champions of another nation with hot weather.  Such as New Zealand,
South Africa, West Indies, India, Pakistan, Sri Lanka, Zimbabwe, Bangladesh,
and Afghanistan.  We also let England and Ireland play even though they
don&amp;#8217;t have hot weather, but they did invent the game so we invite them
anyway.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;The cricket match can last up to 5 days.  And although our champions have to
spend this time in the hot weather.  I believe this is really to the benefit
of the spectators in their air-conditioned homes.  They are socially
permitted to watch sports for 5 days while drinking beer.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;sect1&quot;&gt;
&lt;h2 id=&quot;january-1st-new-years-day&quot;&gt;January 1st: New years day.&lt;/h2&gt;
&lt;div class=&quot;sectionbody&quot;&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;This is also a public holiday, but I got bored and didn&amp;#8217;t write anything for
it.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;paragraph&quot;&gt;
&lt;p&gt;I hope you enjoy your local holidays, if you have them, otherwise enjoy your
not-holidays.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
        <pubDate>Fri, 21 Dec 2018 00:00:00 +1100</pubDate>
        <link>https://paul.bone.id.au/blog/2018/12/21/christmas/</link>
        <guid isPermaLink="true">https://paul.bone.id.au/blog/2018/12/21/christmas/</guid>
        
        
        <category>blog</category>
        
      </item>
    
  </channel>
</rss>
