<?xml version="1.0"?>
<rss version="2.0">

<channel>
	<title>Debian Disguised Work</title>
	<link>https://disguised.work/</link>
	<language>en</language>
	<description>Debian Disguised Work - https://disguised.work/</description>


<item>
	<title>Dirk Eddelbuettel: RcppArmadillo 15.6.0-1 on CRAN: New Upstream Minor</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/09/08#rcpparmadillo_15.6.0-1</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/09/08#rcpparmadillo_15.6.0-1</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;&lt;img alt=&quot;armadillo image&quot; src=&quot;https://dirk.eddelbuettel.com/images/armadillo_logo_two.png&quot; style=&quot;float: left; margin: 10px 10px 10px 0;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://arma.sourceforge.net/&quot;&gt;Armadillo&lt;/a&gt; is a powerful
and expressive C++ template library for linear algebra and scientific
computing. It aims towards a good balance between speed and ease of use,
has a syntax deliberately close to Matlab, and is useful for algorithm
development directly in C++, or quick conversion of research code into
production environments. &lt;a href=&quot;https://dirk.eddelbuettel.com/code/rcpp.armadillo.html&quot;&gt;RcppArmadillo&lt;/a&gt;
integrates this library with the &lt;a href=&quot;https://www.r-project.org&quot;&gt;R&lt;/a&gt; environment and languageâ€“and is
widely used by (currently) 1331 other packages on &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt;, downloaded 48.5 million
times (per the partial logs from the cloud mirrors of CRAN), and the &lt;a href=&quot;https://doi.org/10.1016/j.csda.2013.02.005&quot;&gt;CSDA paper&lt;/a&gt; (&lt;a href=&quot;https://cran.r-project.org/package=RcppArmadillo/vignettes/RcppArmadillo-intro.pdf&quot;&gt;preprint
/ vignette&lt;/a&gt;) by Conrad and myself has been cited 727 times according
to Google Scholar.&lt;/p&gt;
&lt;p&gt;This versions updates to the 15.6.0 upstream &lt;a href=&quot;https://arma.sourceforge.net/&quot;&gt;Armadillo&lt;/a&gt; release made
yesterday. It extends solver options for poorly conditioned systems, and
brings some updates and extension to the &lt;code&gt;cube&lt;/code&gt; data type.
For this release, we once again ran the usual complete
reverse-dependency check which came back spotless, and did CRAN so no
email exchange needed despite nearly 1300 reverse dependencies (but it
ended up taking more than a single business day). Still, automation can
be helpful when used with a well-maintained software stack. The package
has also already been updated for &lt;a href=&quot;https://www.debian.org&quot;&gt;Debian&lt;/a&gt;, built for &lt;a href=&quot;https://eddelbuettel.github.io/r2u/&quot;&gt;r2u&lt;/a&gt; and &lt;a href=&quot;https://rcppcore.r-universe.dev/RcppArmadillo&quot;&gt;r-universe&lt;/a&gt;, and
will build shortly at &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt; for
the different binary releases.&lt;/p&gt;
&lt;p&gt;All changes since the last CRAN release follow.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;changes-in-rcpparmadillo-version-15.6.0-1-2026-09-07&quot;&gt;Changes in
RcppArmadillo version 15.6.0-1 (2026-09-07)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Upgraded to Armadillo release 15.6.0 (Medium Roast Cortado)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Expanded &lt;code&gt;solve()&lt;/code&gt; with
&lt;code&gt;solve_opts::scale_thresh&lt;/code&gt; option to widen detection of
poorly conditioned systems&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Expanded &lt;code&gt;trans()&lt;/code&gt; and &lt;code&gt;.t()&lt;/code&gt; to handle
cubes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added &lt;code&gt;permute()&lt;/code&gt; to rearrange dimensions of cubes
(generalised transpose)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Added &lt;code&gt;cubemul()&lt;/code&gt; for batched matrix multiplication of
cube slices&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Courtesy of my &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/&quot;&gt;CRANberries&lt;/a&gt;, there
is a &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/2026/09/08#RcppArmadillo_15.6.0-1&quot;&gt;diffstat
report&lt;/a&gt; relative to previous release. More detailed information is on
the &lt;a href=&quot;https://dirk.eddelbuettel.com/code/rcpp.armadillo.html&quot;&gt;RcppArmadillo
page&lt;/a&gt;. Questions, comments etc should go to the &lt;a href=&quot;https://lists.r-forge.r-project.org/cgi-bin/mailman/listinfo/rcpp-devel&quot;&gt;rcpp-devel
mailing list&lt;/a&gt; off the &lt;a href=&quot;https://r-forge.r-project.org/projects/rcpp/&quot;&gt;Rcpp R-Forge&lt;/a&gt;
page.&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Tue, 08 Sep 2026 15:31:00 +0000</pubDate>

</item> 
<item>
	<title>Enrico Zini: Financial risks in 2026</title>
	<guid>http://www.enricozini.org/blog/2026/financial-risks-in-2026</guid>
	<link>http://www.enricozini.org/blog/2026/financial-risks-in-2026</link>
     <description>  &lt;p&gt;I asked the banker who is my reference at the bank something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Give that we are talking about the consequences of the tantrum of a fascist
foreign government, what happened to them (who are also people close and dear
to me), in some future can very well happen to me.&lt;/p&gt;
&lt;p&gt;Suddenly my risk profile shot up under the roof.&lt;/p&gt;
&lt;p&gt;What do you suggest me to do? Should I find a trusted source of gold bullions
to bury under the cellar at home?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The answer was something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sadly YES, given that the USA have a sort of financial monopoly they can
entitle themselves to arbitrarily define a person/organization as a terrorist
without any trial or judicial course, and as a consequence apply sanctions
that cannot be effectively counteracted, not even abroad.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I didn&#39;t have this in my 2026 bingo card, but here we are.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;For more details, see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;a href=&quot;https://www.inventati.org/campaign/press&quot;&gt;A/I press release&lt;/a&gt; under &quot;12. Banca Etica: the sanction also affected an Italian bank account&quot;&lt;/li&gt;
&lt;li&gt;the &lt;a href=&quot;https://www.bancaetica.it/area-stampa/autistici-inventati-banca-etica-condanna-uso-improprio-ofac-valutazioni-per-non-chiudere-il-conto/&quot;&gt;public statement from the bank&lt;/a&gt; (in Italian)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For some broader context on this kind of actions from the USA, see also:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Francesca_Albanese#Sanctions_by_the_United_States&quot;&gt;The same sactions against UN Special Rapporteur Francesca Albanese&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Executive_Order_14203&quot;&gt;Executive Order 14203 titled &quot;Imposing Sanctions on the International Criminal Court&quot;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt; </description> 
	<pubDate>Tue, 08 Sep 2026 07:05:22 +0000</pubDate>

</item> 
<item>
	<title>Bits from Debian: New Debian Developers and Maintainers (July and August 2026)</title>
	<guid>tag:bits.debian.org,2026-09-07:/2026/09/new-developers-2026-09.html</guid>
	<link>https://bits.debian.org/2026/09/new-developers-2026-09.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dwn.png&quot; width=&quot;77&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;The following contributor got their Debian Developer account in the last two
months:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nicolas Peugnet (nicolasp)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following contributors were added as Debian Maintainers in the last two
months:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Antoine Lassagne&lt;/li&gt;
&lt;li&gt;Ivan Hu&lt;/li&gt;
&lt;li&gt;Jesse Rhodes&lt;/li&gt;
&lt;li&gt;Haolin Xue&lt;/li&gt;
&lt;li&gt;Léo Haf&lt;/li&gt;
&lt;li&gt;Rony João de Sousa&lt;/li&gt;
&lt;li&gt;Luke Yasuda&lt;/li&gt;
&lt;li&gt;Darshaka Pathirana&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Congratulations!&lt;/p&gt; </description> 
	<pubDate>Mon, 07 Sep 2026 21:00:00 +0000</pubDate>

</item> 
<item>
	<title>Colin Watson: Free software activity in August 2026</title>
	<guid>tag:www.chiark.greenend.org.uk,2026-09-07:/~cjwatson/blog/activity-2026-08.html</guid>
	<link>https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2026-08.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/cjwatson.png&quot; width=&quot;70&quot; height=&quot;82&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;My Debian contributions this month were all &lt;a href=&quot;https://www.freexian.com/about/debian-contributions/&quot;&gt;sponsored&lt;/a&gt; by Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via &lt;a href=&quot;https://liberapay.com/cjwatson&quot;&gt;Liberapay&lt;/a&gt; or &lt;a href=&quot;https://github.com/sponsors/cjwatson&quot;&gt;GitHub Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Personal note&lt;/h2&gt;
&lt;p&gt;This month, my Dad unexpectedly passed away after a short illness.  As a result I obviously got less work done than usual, and I still have a lot to take care of (since I’m the executor of his will, as well as helping with funeral arrangements) while grieving and generally having less focus and energy.  Having routine work to do is one of the ways I cope with this sort of thing, but all the same, I hope people will bear with me and maybe remind me if I seem to be dropping the ball on something you especially need.&lt;/p&gt;
&lt;h2&gt;&lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt; vote&lt;/h2&gt;
&lt;p&gt;[Content note: strong opinions.]&lt;/p&gt;
&lt;p&gt;I voted in &lt;a href=&quot;https://www.debian.org/vote/2026/vote_002&quot;&gt;General Resolution: &lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt; usage in Debian&lt;/a&gt;.  My vote was pretty much the opposite of what ended up winning, so I’m quite disappointed.  My personal opinion is that LLMs are &lt;a href=&quot;https://softwarecrisis.dev/letters/llmentalist/&quot;&gt;cognitive hazards to their users&lt;/a&gt; that impose ecological costs far out of proportion to their utility at a time when &lt;a href=&quot;https://wmo.int/publication-series/state-of-global-climate/state-of-global-climate-2025&quot;&gt;the world absolutely cannot afford them&lt;/a&gt;.  When the impossible economics of the large commercial models are finally allowed to catch up with reality, I expect there to be &lt;a href=&quot;https://www.wheresyoured.at/what-happens-if-openai-dies/&quot;&gt;significant macroeconomic consequences&lt;/a&gt;, and that people who have become dependent on them will have problems; and who knows what the copyright situation on their output really is.  I’m not convinced that &lt;a href=&quot;https://blog.glyph.im/2026/09/but-what-about-video-games.html&quot;&gt;local models&lt;/a&gt; are better enough on these axes to be worth the costs.&lt;/p&gt;
&lt;p&gt;Debian’s direct contribution to all that will be negligible on a global scale, and even the most radical proposals in the &lt;span class=&quot;caps&quot;&gt;GR&lt;/span&gt; didn’t expect that we could do much about upstreams that have gone all-in on LLMs.  Even so, I’d hoped that my fellow developers might be more willing to lean on our position in the free software ecosystem to make at least a moderately radical statement.  Instead, we’ve at best presented an undistinguished fence-sitting position to the world, and further entrenched the idea that humans can reliably do a good job of reviewing the output of tools that are designed to produce output plausible to humans.  I certainly don’t trust my own code review skills that far.&lt;/p&gt;
&lt;p&gt;Since I’ve never voluntarily used an &lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt; (not counting LLMs being foisted on me by things like search results, support chatbots, or incoming pull requests, regardless of whether I asked for them), and don’t intend to for the foreseeable future, I doubt this will change much for me in terms of the way I work.  The winning option is a very weak one that imposes no new requirements on developers, which means that it also does nothing to stop me continuing to reject &lt;span class=&quot;caps&quot;&gt;LLM&lt;/span&gt;-generated material from Debian bug reports and merge requests in my areas of responsibility.  I know this probably won’t do much to satisfy people who have decided that Debian is slop now, but it’s the best I can do.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;I finally landed the &lt;a href=&quot;https://www.chiark.greenend.org.uk/~cjwatson/blog/openssh-gssapi-split.html&quot;&gt;&lt;span class=&quot;caps&quot;&gt;GSS&lt;/span&gt;-&lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; key exchange package split&lt;/a&gt; in our OpenSSH packaging.  Here’s the &lt;code&gt;NEWS&lt;/code&gt; entry:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;openssh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;m m-Double&quot;&gt;10.4&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unstable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;urgency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;medium&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;The&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;openssh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;openssh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;packages&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;no&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;longer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;GSS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;API&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authentication&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;exchange&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;support&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;adds&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pre&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;authentication&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;attack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;surface&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;generally&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;increases&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;complexity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;and&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;only&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;be&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;used&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;specifically&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;needed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Users&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;who&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;need&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;these&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;features&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;should&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;openssh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gssapi&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;openssh&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gssapi&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;instead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Colin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Watson&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cjwatson&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;debian&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Sun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Aug&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2026&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;39&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;55&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I &lt;a href=&quot;https://salsa.debian.org/ssh-team/openssh/-/commit/4fec688eb614ba9ba758e66efa361285722dbdf8&quot;&gt;fixed a flaky autopkgtest&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I upgraded from 10.4p1 to 10.5p1, which was a good test of keeping &lt;code&gt;openssh&lt;/code&gt; and the new &lt;code&gt;openssh-gssapi&lt;/code&gt; source package in sync.&lt;/p&gt;
&lt;h2&gt;PuTTY&lt;/h2&gt;
&lt;p&gt;I upgraded from 0.84 to 0.85.&lt;/p&gt;
&lt;h2&gt;Python packaging&lt;/h2&gt;
&lt;p&gt;New upstream versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;anorack&lt;/li&gt;
&lt;li&gt;djangorestframework (fixing a &lt;a href=&quot;https://bugs.debian.org/1143299&quot;&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;isort&lt;/li&gt;
&lt;li&gt;lazr.delegates (&lt;a href=&quot;https://bugs.debian.org/1083458&quot;&gt;dropping pkg_resources&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;lazr.restfulclient (&lt;a href=&quot;https://bugs.debian.org/1083460&quot;&gt;dropping pkg_resources&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;lazr.uri (&lt;a href=&quot;https://bugs.debian.org/1083461&quot;&gt;dropping pkg_resources&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;nbclient (fixing a &lt;a href=&quot;https://bugs.debian.org/1138816&quot;&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pydantic-settings&lt;/li&gt;
&lt;li&gt;python-argcomplete&lt;/li&gt;
&lt;li&gt;python-blockbuster&lt;/li&gt;
&lt;li&gt;python-makefun (fixing a &lt;a href=&quot;https://bugs.debian.org/1143367&quot;&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-persistent&lt;/li&gt;
&lt;li&gt;python-pytest-run-parallel&lt;/li&gt;
&lt;li&gt;python-time-machine&lt;/li&gt;
&lt;li&gt;python-typing-inspection&lt;/li&gt;
&lt;li&gt;wcwidth&lt;/li&gt;
&lt;li&gt;zope.hookable&lt;/li&gt;
&lt;li&gt;zope.i18nmessageid&lt;/li&gt;
&lt;li&gt;zope.interface&lt;/li&gt;
&lt;li&gt;zope.proxy&lt;/li&gt;
&lt;li&gt;zope.security&lt;/li&gt;
&lt;li&gt;zope.testrunner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The version treadmill continues: we’ve just finished dropping Python 3.13 as a supported version, so now we’ve started working on enabling Python 3.15 as a supported version.  Maximiliano Curia has been &lt;a href=&quot;https://lists.debian.org/debian-python/2026/08/msg00065.html&quot;&gt;very helpfully driving this&lt;/a&gt;.  I didn’t get as much done here as I’d have liked (see the top of this post), but I fixed a couple of packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1145192&quot;&gt;pydantic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1145112&quot;&gt;python-typing-extensions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other build/test failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143283&quot;&gt;anorack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143285&quot;&gt;buildbot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1144623&quot;&gt;codespell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1144042&quot;&gt;django-prometheus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143359&quot;&gt;pendulum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143691&quot;&gt;pydantic-core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143365&quot;&gt;python-argcomplete&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1145426&quot;&gt;python-ast-serialize&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143364&quot;&gt;python-bcrypt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143366&quot;&gt;python-cross-web&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1146106&quot;&gt;python-datamodel-code-generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/python-team/packages/python-djangorestframework-flex-fields/-/commit/42cba56dd872332a1b713b914be0f15bd97e7d43&quot;&gt;python-djangorestframework-flex-fields&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143369&quot;&gt;python-openapi-core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143469&quot;&gt;python-treq&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143418&quot;&gt;scikit-build-core&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed some other bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143722&quot;&gt;python-librosa: Hardcoded Python 3.13 in rules file&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1045218&quot;&gt;python-makefun: Fails to build source after successful build&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;bugs.debian.org&lt;/h2&gt;
&lt;p&gt;I deployed the fix for &lt;a href=&quot;https://bugs.debian.org/979319&quot;&gt;Invalid link rel=”canonical” on bugs.debian.org&lt;/a&gt;.  In the process I found a few bugs in recent undeployed code and &lt;a href=&quot;https://salsa.debian.org/debbugs-team/debbugs/-/compare/66628595f23bd079a748ad549dd986cd51dc498e...ecc8def8320b0f5297a2e31f9b3a051d164f5d59&quot;&gt;fixed them&lt;/a&gt;.&lt;/p&gt; </description> 
	<pubDate>Mon, 07 Sep 2026 19:25:04 +0000</pubDate>

</item> 
<item>
	<title>Vincent Bernat: Sidenotes with CSS anchor positioning</title>
	<guid>http://www.luffy.cx/en/blog/2026-css-sidenotes.html</guid>
	<link>https://vincent.bernat.ch/en/blog/2026-css-sidenotes</link>
     <description>  &lt;p&gt;I am a heavy user of sidenotes:&lt;sup id=&quot;fnref:phd&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:phd&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; they keep optional content next to the
text instead of sending the reader to the bottom of the page and back. &lt;a href=&quot;https://edwardtufte.github.io/tufte-css/&quot; title=&quot;Tufte CSS&quot;&gt;Tufte
CSS&lt;/a&gt; renders them without JavaScript but only accepts inline content. &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Anchor_positioning&quot; title=&quot;CSS anchor positioning&quot;&gt;CSS
anchor positioning&lt;/a&gt;, now supported by recent browsers,&lt;sup id=&quot;fnref:anchor-support&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:anchor-support&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; is an
elegant alternative. Sidenotes can hold several blocks, still without
JavaScript, and fall back below the paragraph referencing them on narrow
viewports and older browsers.&lt;/p&gt;
&lt;p&gt;Inâ€¯2023, Eric Meyer demonstrated this technique in â€œ&lt;a href=&quot;https://meyerweb.com/eric/thoughts/2023/09/12/nuclear-anchored-sidenotes/&quot; title=&quot;Nuclear Anchored Sidenotes&quot;&gt;Nuclear Anchored
Sidenotes&lt;/a&gt;.â€� The main improvement over other solutions is that the notes can
sit anywhere in the HTML document. You can place them after the paragraph
referencing them, as regular block elements for text browsers, screen readers,
feed readers, and reader mode to render them properly:&lt;/p&gt;
&lt;figure class=&quot;lf-fullbleed&quot;&gt;&lt;div class=&quot;lf-media-outer&quot; style=&quot;width: 465px;&quot;&gt;&lt;span class=&quot;lf-media-inner&quot;&gt;&lt;img alt=&quot;Sidenotes rendered in Lynx appear after the paragraph they are called from.&quot; class=&quot;lf-media&quot; height=&quot;600&quot; src=&quot;https://d2pzklc15kok91.cloudfront.net/images/css-sidenotes-lynx@1x.62cb4bfb14577a.png&quot; width=&quot;465&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;figcaption&gt;Rendering in Lynx, a text browser&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;When the viewport is too narrow or the browser does not support CSS anchor
positioning, you can style them so the reader can skip them or glance at them
without losing their position in the text:&lt;/p&gt;
&lt;figure class=&quot;lf-fullbleed&quot;&gt;&lt;div class=&quot;lf-media-outer&quot; style=&quot;width: 375px;&quot;&gt;&lt;span class=&quot;lf-media-inner&quot;&gt;&lt;img alt=&quot;Sidenotes rendered on a narrow viewport appear with a distinctive typography after the paragraph they are called from.&quot; class=&quot;lf-media lf-opaque&quot; height=&quot;667&quot; src=&quot;https://d2pzklc15kok91.cloudfront.net/images/css-sidenotes-narrow@1x.9afbc67e0bd4e9.png&quot; width=&quot;375&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;figcaption&gt;Rendering below the paragraph on a narrow viewport&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Once the viewport is large enough, they appear in the margin, at the same
vertical position as the matching reference mark, unless they would collide with
a previous sidenote, as in the example below:&lt;sup id=&quot;fnref:runt&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:runt&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;figure class=&quot;lf-fullbleed&quot;&gt;&lt;div class=&quot;lf-media-outer&quot; style=&quot;width: 1427px;&quot;&gt;&lt;span class=&quot;lf-media-inner&quot;&gt;&lt;img alt=&quot;Sidenotes rendered on a large viewport appear in the margin. There are two of them. The first one is vertically aligned with the matching reference mark, while the second is rendered below as it would collide with the first otherwise.&quot; class=&quot;lf-media lf-opaque&quot; height=&quot;570&quot; src=&quot;https://d2pzklc15kok91.cloudfront.net/images/css-sidenotes-large@1x.b9822706e29afa.png&quot; width=&quot;1427&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;figcaption&gt;Rendering in the margin on a large viewport&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The gist of CSS anchoring is to position an element relative to another
elementâ€”the anchor. For the sidenotes, the anchor is the reference mark. I use
the following markup, with a data attribute to specify the anchor name:&lt;/p&gt;
&lt;div class=&quot;language-html codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;sup&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fnref:YYY&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-anchor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--lf-sn-YYY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#sidenote-YYY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;sup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The matching note is an &lt;code&gt;&amp;lt;aside&amp;gt;&lt;/code&gt; element carrying the same data attribute for
the anchor name. We put it after the paragraph holding the reference mark:&lt;/p&gt;
&lt;div class=&quot;language-html codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;aside&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;note&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sidenote-YYY&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-anchor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;--lf-sn-YYY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;sup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;sup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;A first paragraph.&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;A second paragraph.&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;aside&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On a narrow viewport or when the browser is too old for CSS anchoring, we style
the sidenote, which stays below its paragraph, with a muted color:&lt;/p&gt;
&lt;div class=&quot;language-css codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;aside&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;note&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;margin-block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;rlh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;#444&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On a wide viewport and when the browser is recent enough, we move the sidenote
to the right margin:&lt;/p&gt;
&lt;div class=&quot;language-css codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;supports&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;anchor-name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;data-anchor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;custom-ident&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;)))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;media&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;min-width&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;72rem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;relative&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;sup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;data-anchor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;anchor-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data-anchor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom-ident&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;/* â†’ anchor-name: --lf-sn-YYY */&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;aside&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;note&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;data-anchor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;anchor-name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;--lf-sidenote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;absolute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;position-anchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data-anchor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;custom-ident&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c&quot;&gt;/* â†’ position-anchor: --lf-sn-YYY */&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;anchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;anchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;--lf-sidenote&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;-1&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;rlh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;rlh&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;inherit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;attr()&lt;/code&gt; extracts the anchor name for the reference mark from the &lt;code&gt;data-anchor&lt;/code&gt;
attribute. It returns a string, unless we specify a CSS unit or a type, like
here: the browser parses the data attribute as a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/custom-ident&quot; title=&quot;&amp;lt;custom-ident&amp;gt; on MDN&quot;&gt;custom
identifier&lt;/a&gt;, which &lt;code&gt;anchor-name&lt;/code&gt; validates as a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/dashed-ident&quot; title=&quot;&amp;lt;dashed-ident&amp;gt; on MDN&quot;&gt;dashed
identifier&lt;/a&gt;, a custom identifier starting with two
dashes.&lt;sup id=&quot;fnref:attr-support&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:attr-support&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;The note itself is absolutely positioned past the right edge of the main block.
It selects the matching reference mark as its anchor with &lt;code&gt;position-anchor&lt;/code&gt; set
to the value of the &lt;code&gt;data-anchor&lt;/code&gt; attribute. Each note is also an anchor named
&lt;code&gt;--lf-sidenote&lt;/code&gt;. We use it to keep the next note from colliding with this one.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/anchor&quot; title=&quot;anchor() CSS function on MDN&quot;&gt;&lt;code&gt;anchor()&lt;/code&gt; CSS function&lt;/a&gt; lets us position the noteâ€™s top
edge relative to its anchor: &lt;code&gt;anchor(top)&lt;/code&gt; aligns the top edge of the note with
the top edge of the reference mark. It can also take another anchor as a
parameter: &lt;code&gt;anchor(--lf-sidenote bottom)&lt;/code&gt; would align the top edge of the note
with the bottom edge of the closest preceding anchor named &lt;code&gt;--lf-sidenote&lt;/code&gt;â€”so
the previous note.&lt;sup id=&quot;fnref:reference&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:reference&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; Like &lt;code&gt;attr()&lt;/code&gt;, &lt;code&gt;anchor()&lt;/code&gt; accepts a fallback
value as its second parameter and use it when the named anchor does not exist.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;top&lt;/code&gt; property handles three cases, illustrated in the following diagram:&lt;/p&gt;
&lt;figure class=&quot;lf-fullbleed&quot;&gt;&lt;div class=&quot;lf-media-outer&quot; style=&quot;width: 913px;&quot;&gt;&lt;span class=&quot;lf-media-inner&quot;&gt;&lt;img alt=&quot;Diagram of three sidenotes anchored to their reference marks. The first one is aligned with the top of its own reference mark, as no note comes before it. The second one would overlap the first, so it takes the bottom of the first note as anchor and sits one line below it. The third one comes far enough down the page to align with its own reference mark again.&quot; class=&quot;lf-media&quot; height=&quot;660&quot; src=&quot;https://d2pzklc15kok91.cloudfront.net/images/css-sidenotes-anchors.7ed3294df30cae.svg&quot; width=&quot;913&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;figcaption&gt;The three cases for the vertical position of a note&lt;/figcaption&gt;&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;The first noteâ€™s top edge aligns with the top edge of its reference mark: as
   there is no previous note, &lt;code&gt;anchor(--lf-sidenote bottom, -1rlh) + 1rlh&lt;/code&gt;
   resolves to 0 and &lt;code&gt;max()&lt;/code&gt; returns &lt;code&gt;anchor(top)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When the reference mark of a later note sits above the bottom of the previous
   note, plus some vertical space, the note goes below the previous one to avoid
   a collision. &lt;code&gt;max()&lt;/code&gt; returns &lt;code&gt;anchor(--lf-sidenote bottom) + 1rlh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise, the noteâ€™s top edge aligns with the reference markâ€™s top edge, as
   &lt;code&gt;max()&lt;/code&gt; returns &lt;code&gt;anchor(top)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;p&gt;Have a look at the &lt;a href=&quot;https://github.com/vincentbernat/vincent.bernat.ch/blob/latest/content/media/css/luffy1.sidenotes.css&quot; title=&quot;Stylesheet for the sidenotes of this blog&quot;&gt;complete stylesheet&lt;/a&gt;, which also adapts the
reference mark to the location of the note: a â€œâ†“â€� arrow when the note sits below
the paragraph, a â€œâ†’â€� arrow when it moves to the margin. Gwernâ€™s â€œ&lt;a href=&quot;https://gwern.net/sidenote&quot; title=&quot;Sidenotes In Web Design&quot;&gt;Sidenotes In
Web Design&lt;/a&gt;â€� lists more implementations and their trade-offs.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://danluu.com/bug-blind/&quot; title=&quot;Bug blindness&quot;&gt;Some bloggers&lt;/a&gt; aim to write a post in 30 minutes. I planned to publish
three web-related articles this weekend. Instead, I spent an inordinate amount
of time elsewhere: about 15 commits on the build system, a pull request to
&lt;a href=&quot;https://github.com/pygments/pygments/pull/3294&quot; title=&quot;CSS: support nested rule&quot;&gt;update CSS highlighting for nested selectors in Pygments&lt;/a&gt;, and a
small correction to MDNâ€™s article on the &lt;a href=&quot;https://github.com/mdn/content/pull/45532&quot; title=&quot;Fix wording for return value of anchor() function&quot;&gt;&lt;code&gt;anchor()&lt;/code&gt; CSS function&lt;/a&gt;. The
SVG illustration took a bit less than an hour and the article itself a handful
of hours. The &lt;code&gt;attr()&lt;/code&gt; function came in after I thought â€œinline style looks
ugly, isnâ€™t there a better way?â€� But, hey, I still think this is worth it! ğŸ�¨&lt;/p&gt;
&lt;div class=&quot;footnote&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:phd&quot;&gt;
&lt;p&gt;My PhD advisor told me this is unwise.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:phd&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:anchor-support&quot;&gt;
&lt;p&gt;The first bits of anchor positioning are &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/anchor-name#browser_compatibility&quot; title=&quot;Browser compatibility for anchor-name on MDN&quot;&gt;supported&lt;/a&gt; from Chromeâ€¯125 (Mayâ€¯2024), Firefoxâ€¯147 (Januaryâ€¯2026), and Safariâ€¯26 (Septemberâ€¯2025).&lt;/p&gt;
&lt;p&gt;Before Safariâ€¯26.5, sidenotes may collide due to a &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=315704&quot; title=&quot;[anchor-position-1] anchor referencing an anchor of the same name does not resolve to the previous one.&quot;&gt;bug&lt;/a&gt; in how dependency
chains are handled. You can &lt;a href=&quot;https://github.com/vincentbernat/vincent.bernat.ch/blob/1e6299da5c95dfce6549dfb20da2cea7c9e58664/content/media/js/luffy1.sidenotes.js&quot;&gt;detect this situation with some JavaScript&lt;/a&gt;.
It is, however, not needed in the solution described here as we depend on a
more recent feature.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:anchor-support&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:runt&quot;&gt;
&lt;p&gt;If you noticed the runt in the first note, I share your pain and lament that
Firefox does not implement &lt;code&gt;text-wrap: pretty&lt;/code&gt;.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:runt&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:attr-support&quot;&gt;
&lt;p&gt;Typed &lt;code&gt;attr()&lt;/code&gt; is &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/attr#browser_compatibility&quot; title=&quot;Browser compatibility for attr() on MDN&quot;&gt;supported&lt;/a&gt; from Chromeâ€¯133 (Februaryâ€¯2025),
Firefoxâ€¯155 (Septemberâ€¯2026), and Safariâ€¯27 (not yet released). Check &lt;a href=&quot;https://una.im/advanced-attr&quot; title=&quot;New capabilities for attr()&quot;&gt;Una
Kravetsâ€™ article&lt;/a&gt; for details. To support more
browsers, you can inline the anchor name and the position anchor directly in
the HTML:&lt;/p&gt;
&lt;div class=&quot;language-html codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;sup&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;â€¦&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;anchor-name: --lf-sn-â€¦&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#sidenote-â€¦&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;1&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;sup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;â€œ&lt;a href=&quot;https://blog.master.dev/managing-anchor-associations-with-data-attributes-and-advanced-attr/&quot; title=&quot;Managing Anchor Associations With Data Attributes and Advanced attr()&quot;&gt;Managing Anchor Associations With Data Attributes and Advanced
&lt;code&gt;attr()&lt;/code&gt;&lt;/a&gt;,â€� by Daniel Schwarz, explores CSS
anchors and typed &lt;code&gt;attr()&lt;/code&gt; in more detail.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:attr-support&quot; title=&quot;Jump back to footnote 4 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:reference&quot;&gt;
&lt;p&gt;The exact rule for the &lt;a href=&quot;https://drafts.csswg.org/css-anchor-position-1/#target-anchor-element&quot; title=&quot;CSS Anchor Positioning: target anchor element&quot;&gt;target anchor element&lt;/a&gt; is more complex: â€œif an
ancestor of [the note] satisfies the following conditions, return the
nearest such element to [the note]. Otherwise, return the last element in
tree order that satisfies the conditions.â€� One of these conditions is that
â€œ[the candidate] is an &lt;a href=&quot;https://drafts.csswg.org/css-anchor-position-1/#acceptable-anchor-element&quot; title=&quot;CSS Anchor Positioning: acceptable anchor element&quot;&gt;acceptable anchor element&lt;/a&gt; for [the note],â€� which
requires that â€œ[the candidate] is laid out strictly before [the note],â€�
where the relevant clause is that â€œ[the candidate] is either not absolutely
positioned or occurs earlier in the flat tree order than [the note].â€�Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:reference&quot; title=&quot;Jump back to footnote 5 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Mon, 07 Sep 2026 06:49:58 +0000</pubDate>

</item> 
<item>
	<title>Iustin Pop: AI agents aha moment</title>
	<guid>https://k1024.org/posts/2026/2026-09-06-ai-agents-aha/</guid>
	<link>https://k1024.org/posts/2026/2026-09-06-ai-agents-aha/</link>
     <description>  &lt;p&gt;Looking at the reactions to the Debian AI vote, I think some people still think
the clock can be turned back, as if that ever worked in history. Rather than cry
about spilled milk, I prefer to find a path forward in the new world. There are
many ways to use LLMs, some of them are straightforward, others not so much.&lt;/p&gt;
&lt;p&gt;One of the “not so clear” areas for me is the focus on agentic workloads. For
complex tasks, sure, you want something that can work in the background, but in
general, why does every single tool go the agentic way? I much prefer the
“chat/ask” approach, or even the “code” one, but if I’m at the keyboard, why
would I send a task to an agent, and see it work, instead of directly
implementing it?&lt;/p&gt;
&lt;p&gt;And then, this past Friday, I finally understood one part of that. I was in the
airport, sitting at the gate and waiting to board a flight, and because I
arrived much earlier at the airport (fearing crowds due to Labour Day weekend),
I got one hour of work before boarding started. As the time for boarding
approached, I did one more
&lt;a href=&quot;https://github.com/iustin/corydalis/commit/2b2f520952175b626c4d769c4d46825758954ea3&quot;&gt;commit&lt;/a&gt;
after making sure tests pass, pushed, closed laptop, and went to walk a bit
before getting on the plane.&lt;/p&gt;
&lt;p&gt;As I was getting up, I get a phone notification from GitHub that the CI run
&lt;a href=&quot;https://github.com/iustin/corydalis/actions/runs/33935984250/job/101223903306&quot;&gt;failed&lt;/a&gt;.
I was quite surprised, as the local tests passed, so I open the notification,
and realize that tests via &lt;code&gt;make test&lt;/code&gt; vs CI (which additionally uses
&lt;code&gt;--pedantic&lt;/code&gt;) had slightly different settings, and of course I missed a build
warning (which in CI is an error).&lt;/p&gt;
&lt;p&gt;I thought I’d fix that on the plane, but then I saw a “Copilot agent” button in
the mobile app. I was curious what it did, I click it, and I see Copilot
starting a draft &lt;a href=&quot;https://github.com/iustin/corydalis/pull/21&quot;&gt;pull request&lt;/a&gt;, and saying:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thanks for asking me to work on this. I will get started on it and keep this
PR’s description up to date as I form a plan and make progress.&lt;/p&gt;
&lt;p&gt;Fix the failing GitHub Actions job. Analyze the Actions logs, identify the
root cause of the failure, and implement a fix.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then it goes, finds the failure, writes the fix, and tries to run the tests.
Well, it can’t do it (it runs in a restricted container, so no network, so
&lt;code&gt;stack install&lt;/code&gt; couldn’t actually work). The agent sees that, acknowledges it
has no way to validate the fix, but the error message was clear enough that it
was confident the fix is mostly correct, so it sends the pull request.&lt;/p&gt;
&lt;p&gt;I allow full CI to run on the pull request, and go buy a bottle of water. After
that, I check and see that the CI failed again, as not one but two test files
were broken, and I didn’t have &lt;code&gt;--keep-going&lt;/code&gt;, so the build stopped at the first
failure. I write a comment in the pull request, no reaction, I realize I need to
tag Copilot explicitly, I do that, and it starts another investigation.&lt;/p&gt;
&lt;p&gt;I’m waiting now in the boarding queue, with phone in hand, while Copilot is
fixing my bug. While I scan my boarding pass and walk towards the plane, the
pull request is updated, I trigger another CI, it passes, and I merge it.&lt;/p&gt;
&lt;p&gt;And then, it hit me. Agents allow me to make progress while being “not at
keyboard”, whether that’s physically “not at keyboard”, or while working on
something else. Fixing a simple test failure is not something that needs human
attention per se, whereas improving the test layout might be.&lt;/p&gt;
&lt;p&gt;In that airport, using otherwise-unusable downtime, and without explicitly
intending to, I made progress in understanding a different way to use AI. Now I
have three ways to work with LLMs: ask (tutor mode), code (implement my
request), and agent (fix simple or complex problems, autonomously). I still
don’t know about “plan” mode and really complex tasks, like asking it to
implement features from scratch. That will probably be the next area to tackle.&lt;/p&gt;
&lt;p&gt;And today (Sunday), while waiting for a running race to start, I opened GitHub,
and asked Copilot to increase test coverage for a simple module. It did, and yes
it still can’t run tests (I learned in the meantime that you can
&lt;a href=&quot;https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/customize-cloud-agent/customize-the-agent-environment&quot;&gt;configure&lt;/a&gt;
the environment in which the agent runs, nice), but after two back-and-forth
messages, I have a &lt;a href=&quot;https://github.com/iustin/corydalis/pull/22&quot;&gt;pull request&lt;/a&gt;
ready to review. All in the 20 minutes before a race, where I could either
browse social media or actually do some meaningful work.&lt;/p&gt;
&lt;p&gt;Checking now my GitHub billing, it looks like all of this Copilot use only cost
$1.92. Yes, that is under two dollars! And while it did use compute resources,
the person across the aisle who watched TikTok or Instagram for half an hour
while waiting for takeoff also consumed a lot of compute, and so do the
gazillion cat videos uploaded to YouTube every day.&lt;/p&gt;
&lt;p&gt;To me, this is another tool in the toolbox, that might one day replace me (as it
did to the 19th-century textile workers), or make me five times more productive
— we’ll see where we end up. In the meantime, I can move faster, and make better
use of my limited free time.&lt;/p&gt;
&lt;p&gt;Enjoy the ride!&lt;/p&gt; </description> 
	<pubDate>Sun, 06 Sep 2026 13:29:50 +0000</pubDate>

</item> 
<item>
	<title>Dirk Eddelbuettel: RcppFarmHash 0.0.4 on CRAN: Maintenance</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/09/06#rcppfarmhash_0.0.4</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/09/06#rcppfarmhash_0.0.4</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Another minor maintenance release of the &lt;a href=&quot;https://github.com/eddelbuettel/rcppfarmhash&quot;&gt;RcppFarmHash&lt;/a&gt;
package is now on &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt; as
version 0.0.4.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/eddelbuettel/rcppfarmhash&quot;&gt;RcppFarmHash&lt;/a&gt;
wraps the Google &lt;a href=&quot;https://github.com/google/farmhash&quot;&gt;FarmHash&lt;/a&gt; family of hash
functions (written by Geoff Pike and contributors) that are used for
example by Google BigQuery for the &lt;code&gt;FARM_FINGERPRINT&lt;/code&gt;
digest.&lt;/p&gt;
&lt;p&gt;This releases updates several of package internal files for
continuous intergration and package data.&lt;/p&gt;
&lt;p&gt;The brief NEWS entry follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;changes-in-version-0.0.4-2026-09-06&quot;&gt;Changes in version 0.0.4
(2026-09-06)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Minor updates to continuous integration, README.md and
DESCRIPTION&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Courtesy of my &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/&quot;&gt;CRANberries&lt;/a&gt;, there
is also a diffstat report for &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/2026/09/06#RcppFarmHash_0.0.4&quot;&gt;this
release&lt;/a&gt;. For questions, suggestions, or issues please use the &lt;a href=&quot;https://github.com/eddelbuettel/rcppfarmhash/issues&quot;&gt;issue
tracker&lt;/a&gt; at the &lt;a href=&quot;https://github.com/eddelbuettel/rcppfarmhash&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can now &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Sun, 06 Sep 2026 13:29:00 +0000</pubDate>

</item> 
<item>
	<title>Russell Coker: CoMaps</title>
	<guid>https://etbe.coker.com.au/?p=6288</guid>
	<link>https://etbe.coker.com.au/2026/09/06/comaps/</link>
     <description>  &lt;p&gt;I have just tried &lt;a href=&quot;https://www.comaps.app/&quot;&gt;CoMaps, a free mapping program released under the Apache license [1]&lt;/a&gt;. I have tried it on Android on a Pixel 6a but it also runs on Linux so I’ll try it on a PinePhone or similar at some convenient time. On Android it is in the F-Droid repository among others and for Linux there’s a Flatpak package.&lt;/p&gt;
&lt;p&gt;The data it uses is from &lt;a href=&quot;https://www.openstreetmap.org/&quot;&gt;Open Street Map project [2]&lt;/a&gt; which has extensive and accurate coverage of every place I’ve looked at (Australia and a few other first-world countries). The first thing it does after being installed is start downloading the world data set from Open Street Map and prompt to download the data for the detected region (Melbourne in my case).&lt;/p&gt;
&lt;p&gt;The UI is decent and allows most of the features that I am used to using in Google Maps. The quality of directions seems good, I’ve only tested it with one journey so far which was a 50 minute drive across the city and it gave a set of directions that Google Maps often gives.&lt;/p&gt;
&lt;p&gt;It gives spoken directions which is an important feature but sometimes the way the directions are presented is confusing. When turning off a freeway it didn’t give a spoken direction to do that, it gave a direction to “turn right” which was AFTER leaving the freeway, fortunately the map was clearly displayed.&lt;/p&gt;
&lt;p&gt;In terms of use practices of this program the main difference I recommend is checking which off ramp to use from a freeway before entering the freeway. With Google Maps you can rely on it giving clear directions in that case.&lt;/p&gt;
&lt;p&gt;I recommend this program without reservation. It can do everything that Google Maps does apart from detecting traffic jams because there’s no way of detecting traffic without spying on users. It is designed to preserve user privacy and works well in that regard.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[1]&lt;a href=&quot;https://www.comaps.app/&quot;&gt; https://www.comaps.app/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2]&lt;a href=&quot;https://www.openstreetmap.org/&quot;&gt; https://www.openstreetmap.org/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;yarpp yarpp-related yarpp-related-rss yarpp-template-list&quot;&gt;

&lt;p&gt;Related posts:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2024/09/15/kogan-ax1800-wifi6-mesh/&quot; rel=&quot;bookmark&quot; title=&quot;Kogan AX1800 Wifi6 Mesh&quot;&gt;Kogan AX1800 Wifi6 Mesh&lt;/a&gt; &lt;small&gt;I previously blogged about the difficulties in getting a good...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2012/03/20/introduction-android/&quot; rel=&quot;bookmark&quot; title=&quot;An Introduction to Android&quot;&gt;An Introduction to Android&lt;/a&gt; &lt;small&gt;I gave a brief introductory talk about Android at this...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2011/10/22/occupy-main-street/&quot; rel=&quot;bookmark&quot; title=&quot;Occupy Main Street&quot;&gt;Occupy Main Street&lt;/a&gt; &lt;small&gt;The Occupy Wall St blog has an informative summary of...&lt;/small&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Sun, 06 Sep 2026 11:05:50 +0000</pubDate>

</item> 
<item>
	<title>Enrico Zini: Migrating away from .org/.net/.com domains</title>
	<guid>http://www.enricozini.org/blog/2026/migrating-away-from-org-net-com-domains</guid>
	<link>http://www.enricozini.org/blog/2026/migrating-away-from-org-net-com-domains</link>
     <description>  &lt;p&gt;After having witnessed how easy it is for good people to lose a &lt;code&gt;.org&lt;/code&gt; domain
over a fascist tantrum (you can follow the Autistici/Inventati story
&lt;a href=&quot;https://www.inventati.org/campaign/press&quot;&gt;here&lt;/a&gt; and
&lt;a href=&quot;https://keepitfree.ai/&quot;&gt;here&lt;/a&gt;), I&#39;ve started moving all my infrastructure to
&lt;a href=&quot;https://mastodon.ar.al/@aral/117172339747622841&quot;&gt;differently managed TLDs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;enricozini.org&lt;/code&gt; and &lt;code&gt;enricozini.com&lt;/code&gt; will keep being functional for the time
being, as dropping a domain makes it available for squatting and impersonation.&lt;/p&gt;
&lt;p&gt;These new domains are now online, with working web and emails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ezini.eu&quot;&gt;enricozini.eu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ezini.eu&quot;&gt;ezini.eu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.ezini.eu&quot;&gt;ezini.it&lt;/a&gt; (probably equally subject to fascist
  tantrums these days)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It will take ages to migrate countless accounts that are tied to my primary
email address, so better start early.&lt;/p&gt;
&lt;p&gt;Waiting to see what will happen with &lt;a href=&quot;https://www.dotmeow.org/&quot;&gt;.meow&lt;/a&gt; domains,
which I supported despite not identifying as a cat.&lt;/p&gt; </description> 
	<pubDate>Sun, 06 Sep 2026 09:40:04 +0000</pubDate>

</item> 
<item>
	<title>Steinar H. Gunderson: plocate 1.1.25 released</title>
	<guid>http://blog.sesse.net/blog/tech/2026-09-06-09-02_plocate_1_1_25_released.html</guid>
	<link>http://blog.sesse.net/blog/tech/2026-09-06-09-02_plocate_1_1_25_released.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/sesse.png&quot; width=&quot;74&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I&#39;ve released version 1.1.25 of &lt;a href=&quot;https://plocate.sesse.net/&quot;&gt;plocate&lt;/a&gt;.
This time around, there&#39;s two security issues of unknown severity;
if you chain them with other bugs, they could lead to being able to
list files (but of course not their contents) that you should not
normally be able to see. So an update is probably in order; you can
never be too safe these days.&lt;/p&gt;

&lt;p&gt;The full changelog is:&lt;/p&gt;

&lt;pre&gt;plocate 1.1.25, September 6th, 2026

  - Fix two early-exit bugs with multiple databases.
    Reported by Manpreet Singh and Tyler Spivey.

  - Drop setgid properly, including the saved gid.
    Reported by Michal Sekletar, found with the help of Claude Opus 4.6.

  - Fix a potential symlink-checking race in updatedb.
    Reported by Michal Sekletar, found with the help of Claude Opus 4.6.
&lt;/pre&gt;

&lt;p&gt;As usual, you can get it from &lt;a href=&quot;https://plocate.sesse.net/&quot;&gt;the home page&lt;/a&gt;,
or it&#39;s on the way up in Debian unstable.&lt;/p&gt; </description> 
	<pubDate>Sun, 06 Sep 2026 08:02:00 +0000</pubDate>

</item> 
<item>
	<title>Michael Stapelberg: Debian Code Search: Fast TurboPFor with Go SIMD</title>
	<guid>https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/</guid>
	<link>https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/</link>
     <description>  &lt;p&gt;This August, I accomplished what I wanted for many years: I deleted the last cgo
dependency in Debian Code Search! This was made possible by Goâ€™s recently
introduced SIMD support, because now we can implement the TurboPFor integer
compression format as efficiently â€” more efficiently, in fact, by using the
newer AVX512 instruction set! â€” as the reference implementation.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background: Why does DCS need a fast Integer Codec?&lt;/h2&gt;
&lt;p&gt;Debian Code Search (DCS) is a search engine that allows searching all the Open
Source source code within Debian, with either literal search expressions or
regular expression search queries.&lt;/p&gt;
&lt;p&gt;A search engine uses an inverted index: a map from term to documents containing
the term. Each document is typically represented most efficiently by using an
id, so the index consists of many lists of document ids.&lt;/p&gt;
&lt;p&gt;When searching, it is important to quickly decode these lists to answer the
search query. However, there is a point of diminishing returns where the
decoding speed, even though it can still be measurably improved quite a bit, no
longer influences the overall query duration.&lt;/p&gt;
&lt;p&gt;From 2012 (its inception) to 2019, Debian Code Search used to use a small index
format, and queries were fast because the index was kept entirely in RAM. In
2019, I &lt;a href=&quot;https://michael.stapelberg.ch/posts/2019-09-29-dcs-positional-turbopfor-index/&quot;&gt;implemented the new index
format&lt;/a&gt;, which adds an
on-disk positional index. For literal queries (78.2% of DCS queries), querying
the positional index on disk is faster than querying the non-positional index in
RAM.&lt;/p&gt;
&lt;p&gt;The efficient encoding of the TurboPFor format makes it possible to fit such an
index on a mid-sized Hetzner server, which I rent with two 1 TB SSD disks. The
optimized decoder of the C TurboPFor library is what made decoding fast at query
time.&lt;/p&gt;
&lt;p&gt;If you want to dive deeper into the algorithm, see this blog post from February
2019:&lt;/p&gt;



  &lt;div class=&quot;postlink&quot;&gt;
      &lt;div&gt;
	&lt;a href=&quot;https://michael.stapelberg.ch/posts/2019-02-05-turbopfor-analysis/&quot;&gt;&lt;h3&gt;TurboPFor: an analysis&lt;/h3&gt;&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class=&quot;summary&quot;&gt;
	
	
	
	
	&lt;p&gt;
	  &lt;a href=&quot;https://michael.stapelberg.ch/posts/2019-02-05-turbopfor-analysis/&quot;&gt;
	  Motivation I have recently been looking into speeding up Debian Code Search. As a quick reminder, search engines answer queries by consulting an inverted index: a map from term to documents containing that term (called a â€œposting listâ€�). See the Debian Code Search Bachelor Thesis (PDF) for a lot more details.

	  &lt;span class=&quot;readmore&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;a href=&quot;https://michael.stapelberg.ch/posts/2019-02-05-turbopfor-analysis/&quot;&gt;Read more â†’&lt;/a&gt;
	  
	&lt;/p&gt;
      &lt;/div&gt;
  &lt;/div&gt;


&lt;p&gt;If you want to learn more about the positional index, see this blog post from
September 2019:&lt;/p&gt;



  &lt;div class=&quot;postlink&quot;&gt;
      &lt;div&gt;
	&lt;a href=&quot;https://michael.stapelberg.ch/posts/2019-09-29-dcs-positional-turbopfor-index/&quot;&gt;&lt;h3&gt;Debian Code Search: positional index, TurboPFor-compressed&lt;/h3&gt;&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class=&quot;summary&quot;&gt;
	
	
	
	
	&lt;p&gt;
	  &lt;a href=&quot;https://michael.stapelberg.ch/posts/2019-09-29-dcs-positional-turbopfor-index/&quot;&gt;
	  Over the last few months, I have been developing a new index format for Debian Code Search. This required a lot of careful refactoring, re-implementation, debug tool creation and debugging.
	  &lt;span class=&quot;readmore&quot;&gt;&lt;/span&gt;&lt;/a&gt;&lt;a href=&quot;https://michael.stapelberg.ch/posts/2019-09-29-dcs-positional-turbopfor-index/&quot;&gt;Read more â†’&lt;/a&gt;
	  
	&lt;/p&gt;
      &lt;/div&gt;
  &lt;/div&gt;


&lt;h2 id=&quot;simd-go&quot;&gt;SIMD in Go&lt;/h2&gt;
&lt;p&gt;For many years, you had the following options for using SIMD instructions in Go:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hand-writing &lt;a href=&quot;https://go.dev/doc/asm&quot;&gt;Go assembler code&lt;/a&gt;. This is only doable for
small functions, for example
&lt;a href=&quot;https://pkg.go.dev/bytes#IndexByte&quot;&gt;&lt;code&gt;bytes.IndexByte&lt;/code&gt;&lt;/a&gt; is &lt;a href=&quot;https://cs.opensource.google/go/go/+/refs/tags/go1.27.1:src/internal/bytealg/indexbyte_amd64.s&quot;&gt;implemented with
hand-written Go
assembly&lt;/a&gt;
(including AVX2).&lt;/li&gt;
&lt;li&gt;Generating Go assembler code with tools like &lt;a href=&quot;https://github.com/mmcloughlin/avo&quot;&gt;Michael McLoughlinâ€™s
â€œAvoâ€�&lt;/a&gt;. This is &lt;a href=&quot;https://cs.opensource.google/go/go/+/refs/tags/go1.27.1:src/crypto/internal/fips140/sha256/_asm/sha256block_amd64_avx2.go&quot;&gt;how
&lt;code&gt;crypto/internal/fips140/sha256&lt;/code&gt; uses
AVX2&lt;/a&gt;. While
Avo generator code definitely is higher-level than hand-written assembly, it
is still too close to assembly for my taste.&lt;/li&gt;
&lt;li&gt;Use a C library via &lt;a href=&quot;https://go.dev/wiki/cgo&quot;&gt;cgo&lt;/a&gt; so gcc or clang compiles
SIMD code. Debian Code Search used to use the
&lt;a href=&quot;https://github.com/powturbo/TurboPFor-Integer-Compression&quot;&gt;powturbo/TurboPFor&lt;/a&gt;
C library via cgo for the last 7 years.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The C TurboPFor library has served us well, but Debian Code Search was always
intended to be a project using Go, so I would prefer it if I did not have any C
code in the project.&lt;/p&gt;
&lt;p&gt;Go 1.26 (released in February 2026) introduced the &lt;code&gt;simd/archsimd&lt;/code&gt; package:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Go 1.26 introduces a new &lt;a href=&quot;https://pkg.go.dev/simd/archsimd&quot;&gt;experimental &lt;code&gt;simd/archsimd&lt;/code&gt;
package&lt;/a&gt;, which can be enabled by setting
the environment variable &lt;code&gt;GOEXPERIMENT=simd&lt;/code&gt; at build time. This package
provides access to architecture-specific SIMD operations. It is currently
available on the &lt;code&gt;amd64&lt;/code&gt; architecture and supports 128-bit, 256-bit, and
512-bit vector types, such as &lt;code&gt;Int8x16&lt;/code&gt; and &lt;code&gt;Float64x8&lt;/code&gt;, with operations such
as &lt;code&gt;Int8x16.Add&lt;/code&gt;. The API is not yet considered stable.&lt;/p&gt;
&lt;p&gt;â€” &lt;a href=&quot;https://go.dev/doc/go1.26#simd&quot;&gt;Go 1.26 Release Notes&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For my 2019 TurboPFor analysis, I implemented &lt;a href=&quot;https://github.com/stapelberg/goturbopfor&quot;&gt;&lt;code&gt;goturbopfor&lt;/code&gt;, a native Go
teaching decoder&lt;/a&gt; (without any SIMD),
because I find Go code easier to follow than C code, especially optimized C
code. My implementation was intentionally not optimized so that the code was
easier to study.&lt;/p&gt;
&lt;p&gt;The TurboPFor format/algorithm has a vector-optimized part: &lt;a href=&quot;https://github.com/stapelberg/goturbopfor/blob/920055ddf6e9106fce2904817eaf96734bf7e26e/goturbopfor.go#L35&quot;&gt;bitpacking comes in
a scalar variant (&lt;code&gt;bitunpack32&lt;/code&gt;) and a vector variant
(&lt;code&gt;bitunpack256v32&lt;/code&gt;)&lt;/a&gt;,
where the vector variant is used for full blocks (256 values) and the scalar
variant is used for remainder blocks (&amp;lt; 256 values).&lt;/p&gt;
&lt;p&gt;When Go 1.26 was released, I used Claude Code to explore whether my native Go
decoderâ€™s &lt;code&gt;bitunpack256v32&lt;/code&gt; function (for the vertical vector layout) could be
implemented using Go SIMD, and the answer was yes, it was possible and it was
faster than without SIMD, but not quite at the level of C TurboPFor. If you let
Claude Code try for long enough, it eventually finds enough optimizations (about
10) to match C performance.&lt;/p&gt;
&lt;p&gt;I donâ€™t want to vibe-code Debian Code Search, though, so I figured I would find
some time to review the SIMD code at some point and see if I could implement
something similar myself.&lt;/p&gt;
&lt;p&gt;Before I found enough time and motivation to complete said review, I discovered
that to not regress real-life query performance by more than 10 to 100
milliseconds (which seems acceptable), I donâ€™t actually need to add SIMD code to
my teaching decoder at all; it would be sufficient to reduce allocations in my
teaching decoder and specialize it per bit width.&lt;/p&gt;
&lt;p&gt;Encouraged by the possibility of using the optimized native Go decoder in Debian
Code Search, I explored whether I could also implement a native Go &lt;em&gt;encoder&lt;/em&gt; so
that I could get rid of the C TurboPFor dependency entirely. The answer is yes,
it is doable in a few days, and it isnâ€™t even that much slower: Go is at 76% of
C, see &lt;a href=&quot;https://github.com/Debian/dcs/commit/e920dc7c5dd3f0e05de1cde3d73b99489f2e1bcb&quot;&gt;Debian/dcs commit
&lt;code&gt;e920dc7&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The goal I set myself at that point was to see if I could learn enough SIMD to
optimize the native Go encoder such that its performance would match how DCS
uses C TurboPFor (via cgo).&lt;/p&gt;
&lt;p&gt;Beating C TurboPFor was possible in 2-3 commits (SIMD and bit width
specialization). To my surprise, Claude Fable 5 pointed out that the encoderâ€™s
block scanning could be done more efficiently using a technique called
positional popcount, and that is &lt;strong&gt;another 2x speed-up&lt;/strong&gt;! ğŸ˜²&lt;/p&gt;
&lt;p&gt;To be clear: I am not saying the Go compiler beats C here. Certainly, the C
compiler can also produce fast AVX512 code and can be used to implement
positional popcount.  When comparing apples to apples, i.e. backporting the
AVX512 kernels and positional popcount technique to C TurboPFor, Go benchmarks a
little slower at â‰ˆ1.4x C.&lt;/p&gt;
&lt;p&gt;This spectacular result (much faster than what DCS had before) got me curious
how far I could push the decoder with SIMD after all. I ended up
matching/exceeding the cgo version here, too!&lt;/p&gt;
&lt;p&gt;The rest of this article explains a few classes of optimizations I encountered
along the way.&lt;/p&gt;
&lt;h2 id=&quot;starting-point&quot;&gt;Starting Point&lt;/h2&gt;
&lt;p&gt;When I wrote &lt;a href=&quot;https://github.com/stapelberg/goturbopfor/&quot;&gt;my &lt;code&gt;goturbopfor&lt;/code&gt; teaching
decoder&lt;/a&gt;, I named its functions to
match the upstream C TurboPFor library, but now I want to get away from names
like &lt;code&gt;p4ndec256v32&lt;/code&gt; â€” they make sense from the TurboPFor perspective, but for
Debian Code Search, we can use cleaner names.&lt;/p&gt;
&lt;p&gt;Before writing any code, I audited how DCS uses integer compression /
decompression.&lt;/p&gt;
&lt;h3 id=&quot;api-design&quot;&gt;API design: BlockEncoder, BlockDecoder and streaming&lt;/h3&gt;
&lt;p&gt;In Debian Code Search, we have the following usage patterns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Partial Indexing:&lt;/strong&gt; When a new package (or package version) enters Debian,
all of its (text) files are indexed. If the &lt;a href=&quot;https://packages.debian.org/forky/hello&quot;&gt;&lt;code&gt;hello-2.12.3-1&lt;/code&gt;
package&lt;/a&gt; (hypothetically) contained
only &lt;code&gt;hello.c&lt;/code&gt; with &lt;code&gt;printf(&quot;hello!\n&quot;);&lt;/code&gt;, we would assign document ID &lt;code&gt;1&lt;/code&gt; to
&lt;code&gt;hello.c&lt;/code&gt; and store in the partial index that trigrams &lt;code&gt;pri&lt;/code&gt;, &lt;code&gt;rin&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;,
&lt;code&gt;ntf&lt;/code&gt;, etc. are all found in doc &lt;code&gt;1&lt;/code&gt; (&lt;code&gt;hello.c&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full Index Merging:&lt;/strong&gt; The many thousands of partial index files (for each
Debian package) are combined into a small handful of large index files: When
searching, it would be expensive to consult thousands of indexes. To merge
multiple partial index files into one larger index (which can then be
efficiently queried), we need to re-encode the partial index files: what used
to be document ID &lt;code&gt;1&lt;/code&gt; in the partial index might be document ID &lt;code&gt;2531&lt;/code&gt; in the
full index.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Querying (searching):&lt;/strong&gt; When users enter search queries, these queries need
to be answered as quickly as possible. The relevant entries in the full
indexes are decoded (in parallel).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For reading the index, we do keep the decoded &lt;code&gt;uint32&lt;/code&gt;s fully in memory, so we
only need &lt;code&gt;DecodeN(input []byte, output []uint32) (read int)&lt;/code&gt;, a function that
reads &lt;code&gt;len(output)&lt;/code&gt; values (&lt;code&gt;uint32&lt;/code&gt;) from &lt;code&gt;input&lt;/code&gt; and returns how many bytes it
consumed.&lt;/p&gt;
&lt;p&gt;For writing the index (both in partial indexing, and when merging), keeping the
entire index in memory is prohibitively expensive, so we need a streaming API,
for decoding and for encoding.&lt;/p&gt;
&lt;p&gt;Ultimately, I converged on the following API:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;pforenc&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;BlockEncoder&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// scratch buffers can go here&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// EncodeBlock encodes len(vals)&amp;lt;=256 uint32s into dest (one TurboPFor block).&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;BlockEncoder)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;EncodeBlock&lt;/span&gt;(dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// EncodeN calls EncodeBlock in a loop.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;BlockEncoder)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;EncodeN&lt;/span&gt;(dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;StreamEncoder&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;be&lt;span style=&quot;color: #bbb;&quot;&gt;   &lt;/span&gt;BlockEncoder&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;256&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// scratch buffers&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// if full, you need to call [EncodeBlock]&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;StreamEncoder)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;Add&lt;/span&gt;(val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(full&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;bool&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// EncodeBlock must be called after all data was [Add]ed.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Write the returned buffer to file or send it over the network;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// it is only valid until the next [EncodeBlock] call.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;StreamEncoder)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;EncodeBlock&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;se.n&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// turn an extra EncodeBlock into a no-op&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// â€¦&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This API (the decoder works similarly) allows us to process data in TurboPFor
format without any memory allocations. The types are not safe for concurrent use
by multiple goroutines. The zero value is ready to be used. For the streaming
API, the result only stays valid until the next call.&lt;/p&gt;
&lt;h3 id=&quot;initial-encoder&quot;&gt;Initial Implementation&lt;/h3&gt;
&lt;p&gt;Before we can optimize anything, we need a working decoder and encoder. The
decoder already exists: my &lt;code&gt;goturbopfor&lt;/code&gt; teaching decoder. Next up, I needed an
encoder.&lt;/p&gt;
&lt;p&gt;Writing a TurboPFor encoder has a delightfully simple starting point: You can
encode all values at bit width 32, in little endian, at which point you only
need to add a one-byte TurboPFor block header every 256 values and youâ€™re done:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(be&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;BlockEncoder)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;EncodeN&lt;/span&gt;(dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(vals)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;chunk&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;min&lt;/span&gt;(&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(vals),&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;256&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;be.&lt;span style=&quot;color: #06287e;&quot;&gt;EncodeBlock&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals[:chunk])&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals[chunk:]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(be&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;BlockEncoder)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;EncodeBlock&lt;/span&gt;(dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;append&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;_,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;binary.LittleEndian.&lt;span style=&quot;color: #06287e;&quot;&gt;AppendUint32&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, this is a terribly inefficient compressor, so after the first commit,
the real work starts: implement each block type until the compression matches
the original C TurboPFor implementation (same output file size), or in other
words: do the reverse of the decoder.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The TurboPFor &lt;strong&gt;bitpacking&lt;/strong&gt; block type (&lt;a href=&quot;https://github.com/Debian/dcs/commit/11eafa3d5d56388c0f0badb0c4b393acc80470e1&quot;&gt;bitpacking implementation
commit&lt;/a&gt;)
encodes a bit stream of variable bit width (where the bit width is in range
&lt;code&gt;0 â‰¤ bitWidth â‰¤ 32&lt;/code&gt;) in &lt;a href=&quot;https://en.wikipedia.org/wiki/Endianness&quot;&gt;little
endian&lt;/a&gt; byte order. By scanning all
values and choosing the smallest bit width that allows representing all
values, this technique saves disk space (compresses).&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;bitpacking with exceptions&lt;/strong&gt; block type (&lt;a href=&quot;https://github.com/Debian/dcs/commit/d7b91f6b0ef732cf78eab2c4cd65dab007255197&quot;&gt;bitpacking with exceptions
implementation
commit&lt;/a&gt;)
determines two bit widths: one for values, the other bit width for encoding
exceptions. This allows choosing a lower bit width (that does not cover all
values) compared to the bitpacking block type. A bitmap encodes whether a
value has an exception or not.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;bitpacking with VB exceptions&lt;/strong&gt; block type (&lt;a href=&quot;https://github.com/Debian/dcs/commit/e920dc7c5dd3f0e05de1cde3d73b99489f2e1bcb&quot;&gt;bitpacking with VB
exceptions implementation
commit&lt;/a&gt;)
is a variant which does not use an exception bitmap and encodes exceptions
using a variable byte integer encoding. This is more efficient when there are
few exceptions (less than 20) or the exceptions are very different in bit
width compared to the other values.&lt;/li&gt;
&lt;li&gt;Lastly, the &lt;strong&gt;constant&lt;/strong&gt; block type (&lt;a href=&quot;https://github.com/Debian/dcs/commit/59df3c6e21443496254e263342dd79bfef4ff173&quot;&gt;constant implementation
commit&lt;/a&gt;)
stores just one value on disk. This is useful for all-zero or all-one blocks,
for example.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I found it interesting to realize that the main work of the encoder is to scan
the input values and choose the optimal block type, whereas the actual encoding
itself is cheap in comparison.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Debian/dcs/commit/e920dc7c5dd3f0e05de1cde3d73b99489f2e1bcb&quot;&gt;At this point, we can look at
performance&lt;/a&gt;
and see that the Go encoder is at 76% of the C encoder.&lt;/p&gt;
&lt;p&gt;In all honesty, I could have probably stopped here, but now that the milestone
of a viable replacement was reached, I got curious to see how far it would be
possible to push the encoder (how much work to reach C speeds?) and afterwards,
the decoder, too.&lt;/p&gt;
&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;
&lt;h3 id=&quot;goamd64&quot;&gt;The microarchitecture level: set &lt;code&gt;GOAMD64&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The microarchitecture of a CPU determines which instructions it provides, and
that includes not just SIMD instruction sets (like AVX2), but also other useful
instructions like &lt;code&gt;LZCNT&lt;/code&gt; (Leading Zero Count), which can be used to implement
&lt;a href=&quot;https://pkg.go.dev/math/bits#Len32&quot;&gt;&lt;code&gt;math/bits.Len32&lt;/code&gt;&lt;/a&gt; more efficiently, which
the TurboPFor encoder needs to call on every input value to determine the ideal
bit width.&lt;/p&gt;
&lt;p&gt;Letâ€™s walk through how to set the microarchitecture level when using Go on
64-bit x86 (x86-64).&lt;/p&gt;
&lt;p&gt;Go uses the &lt;a href=&quot;https://go.dev/doc/install/source#environment&quot;&gt;&lt;code&gt;GOARCH&lt;/code&gt; environment
variable&lt;/a&gt; to configure the target
compilation architecture, and I am using the value &lt;code&gt;amd64&lt;/code&gt; to select 64-bit x86
(AVX2 and AVX512 are instruction sets found on x86-64 CPUs). With
&lt;code&gt;GOARCH=amd64&lt;/code&gt;, the architecture-specific variable
&lt;a href=&quot;https://pkg.go.dev/cmd/go#hdr-Environment_variables&quot;&gt;&lt;code&gt;GOAMD64&lt;/code&gt;&lt;/a&gt; configures the
microarchitecture level for which to compile and Go 1.18 &lt;a href=&quot;https://go.dev/wiki/MinimumRequirements#amd64&quot;&gt;introduced these 4
different levels&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;GOAMD64=v1&lt;/code&gt; (default): The baseline. &lt;br /&gt;
Exclusively generates instructions that all 64-bit x86 processors can execute.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GOAMD64=v2&lt;/code&gt;: all v1 instructions, &lt;br /&gt;
plus CMPXCHG16B, LAHF, SAHF, POPCNT, SSE3, SSE4.1, SSE4.2, SSSE3.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GOAMD64=v3&lt;/code&gt;: all v2 instructions, &lt;br /&gt;
plus AVX, &lt;strong&gt;AVX2&lt;/strong&gt;, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, OSXSAVE.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;GOAMD64=v4&lt;/code&gt;: all v3 instructions, &lt;br /&gt;
plus &lt;strong&gt;AVX512F&lt;/strong&gt;, AVX512BW, AVX512CD, AVX512DQ, AVX512VL.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In 2026, I generally recommend compiling with &lt;code&gt;GOAMD64=v3&lt;/code&gt; so that functions
like &lt;a href=&quot;https://pkg.go.dev/math/bits#OnesCount8&quot;&gt;&lt;code&gt;bits.OnesCount8&lt;/code&gt;&lt;/a&gt; are
&lt;a href=&quot;https://cs.opensource.google/go/go/+/master:src/cmd/compile/internal/ssa/_gen/AMD64.rules;l=102-115;drc=64ebd027a7c81f784b4b41f8070355d19e73687b&quot;&gt;compiled into intrinsics
(&lt;code&gt;POPCNT&lt;/code&gt;)&lt;/a&gt;
instead of using a lookup table.&lt;/p&gt;
&lt;p&gt;For Intel CPUs, setting &lt;code&gt;GOAMD64=v3&lt;/code&gt; means your programs will only start on
Haswell CPUs (2013) or newer; for AMD CPUs that means Zen 1 (2017) or newer.&lt;/p&gt;
&lt;p&gt;In this specific case (DCS), I am even compiling with &lt;code&gt;GOAMD64=v4&lt;/code&gt;. The &lt;code&gt;v4&lt;/code&gt;
microarchitecture level requires AVX512, which means AMD Zen 4, Zen 5 or newer
(Intelâ€™s story isâ€¦ complicated). Luckily, both my main development PC (Zen 5)
and the Debian Code Search server (Zen 4) are recent enough. Setting
&lt;code&gt;GOAMD64=v4&lt;/code&gt; has little effect on Go 1.27 itself: the only change is that maps
use one less instruction (&lt;code&gt;VPBROADCASTB&lt;/code&gt; instead of &lt;code&gt;PSHUFB&lt;/code&gt;). But compiling
with &lt;code&gt;GOAMD64=v4&lt;/code&gt; allows us to move one more feature check from runtime to
compile time, see &lt;a href=&quot;https://michael.stapelberg.ch/posts/tags/debian/feed.xml#simd-build-tags&quot;&gt;SIMD build tags&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It makes sense to set the microarchitecture level in your benchmark setup so
that you donâ€™t measure the slow fallback implementations. I use &lt;code&gt;export GOAMD64=v4&lt;/code&gt; in my &lt;code&gt;Makefile&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;benchstat&quot;&gt;Benchmarking setup&lt;/h3&gt;
&lt;p&gt;Goâ€™s built-in &lt;a href=&quot;https://pkg.go.dev/testing#hdr-Benchmarks&quot;&gt;&lt;code&gt;testing&lt;/code&gt; package contains support for
benchmarks&lt;/a&gt; which are written in
functions of the form &lt;code&gt;func BenchmarkXxx(b *testing.B)&lt;/code&gt;. The simplest way to run
such benchmarks is &lt;code&gt;go test -bench=.&lt;/code&gt;, but I ended up configuring a few
convenience &lt;code&gt;make&lt;/code&gt; targets, which write results to &lt;code&gt;bench.txt&lt;/code&gt; and compare
against &lt;code&gt;baseline.txt&lt;/code&gt; (the previous commitâ€™s results, usually), using the very
useful &lt;a href=&quot;https://pkg.go.dev/golang.org/x/perf/cmd/benchstat&quot;&gt;&lt;code&gt;benchstat&lt;/code&gt; tool&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-makefile&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bb60d5;&quot;&gt;GOTEST&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;go &lt;span style=&quot;color: #007020;&quot;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# -count=6 gives pâ‰¤0.002 in benchstat:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# https://pkg.go.dev/golang.org/x/perf/cmd/benchstat
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bb60d5;&quot;&gt;BENCHFLAGS&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;-run&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;^&lt;span style=&quot;color: #bb60d5;&quot;&gt;$$&lt;/span&gt; -bench&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;. -benchtime&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;200000x -count&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# use taskset -c1 to always pin to the same single core,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# avoiding accidental scheduling on different cores on
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# mixed-core CPUs like the Ryzen 9 9950X3D.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bb60d5;&quot;&gt;TASKSET&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;taskset -c &lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bb60d5;&quot;&gt;BENCH&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;TASKSET&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;GOTEST&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;BENCHFLAGS&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;.PHONY&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:&lt;/span&gt; all test bench bench-baseline bench-relative
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;all&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:&lt;/span&gt; test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bench&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:&lt;/span&gt; test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;BENCH&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt; | tee bench.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# Compares compression ratio between C and Go implementation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	benchstat -col /impl -row &lt;span style=&quot;color: #4070a0;&quot;&gt;&#39;/n /vals&#39;&lt;/span&gt; -filter &lt;span style=&quot;color: #4070a0;&quot;&gt;&#39;-/impl:go-stream .unit:(encoded-bytes)&#39;&lt;/span&gt; bench.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# Compares performance between C (cgo) and Go implementation
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	benchstat -col /impl -row &lt;span style=&quot;color: #4070a0;&quot;&gt;&#39;/n /vals&#39;&lt;/span&gt; -filter &lt;span style=&quot;color: #4070a0;&quot;&gt;&#39;.unit:(Mval/s)&#39;&lt;/span&gt; bench.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bench-baseline&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:&lt;/span&gt; test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;BENCH&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt; | tee baseline.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bench-relative&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:&lt;/span&gt; test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;BENCH&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt; | tee bench.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	benchstat -filter &lt;span style=&quot;color: #4070a0;&quot;&gt;&#39;-/impl:go-stream .unit:(encoded-bytes)&#39;&lt;/span&gt; baseline.txt bench.txt
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	benchstat -filter &lt;span style=&quot;color: #4070a0;&quot;&gt;&#39;/impl:go .unit:(Mval/s)&#39;&lt;/span&gt; baseline.txt bench.txt
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;encoded-bytes&lt;/code&gt; and &lt;code&gt;Mval/s&lt;/code&gt; units are custom metrics I am reporting from
the various &lt;a href=&quot;https://go.dev/blog/subtests&quot;&gt;sub-benchmarks&lt;/a&gt;, which are arranged
such that I can filter / report them with &lt;code&gt;benchstat&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The main encoder (and decoder) benchmarks compare 3 different implementations
(cgo, Go, Go with the StreamEncoder API) with a &lt;a href=&quot;https://github.com/Debian/dcs/commit/e4161bebabcf229734f2dc7a9b54c33caa32875a&quot;&gt;number of benchmark
cases&lt;/a&gt;
that are designed to cover the different block types and contain a similar mix
of values as what we see in Debian Code Search:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// reportMetrics adds Mval/s and encoded-bytes metrics to all benchmarks.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;reportMetrics&lt;/span&gt;(b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;testing.B,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;nencoded&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;   &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;ReportMetric&lt;/span&gt;(&lt;span style=&quot;color: #007020;&quot;&gt;float64&lt;/span&gt;(nencoded),&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #4070a0;&quot;&gt;&quot;encoded-bytes&quot;&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;   &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;ReportMetric&lt;/span&gt;(&lt;span style=&quot;color: #007020;&quot;&gt;float64&lt;/span&gt;(b.N&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;n)&lt;span style=&quot;color: #666;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1e6&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;/&lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;Elapsed&lt;/span&gt;().&lt;span style=&quot;color: #06287e;&quot;&gt;Seconds&lt;/span&gt;(),&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #4070a0;&quot;&gt;&quot;Mval/s&quot;&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// BenchmarkEncode/n=&amp;lt;N&amp;gt;/vals=&amp;lt;testcase&amp;gt;/impl=&amp;lt;c|go|go-stream&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// e.g. BenchmarkEncode/n=2048/vals=one-constant/impl=go-stream&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;BenchmarkEncode&lt;/span&gt;(b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;testing.B)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;   &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;_,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;tc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;allBenchCases&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;     &lt;/span&gt;n&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(tc.vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;     &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;Run&lt;/span&gt;(fmt.&lt;span style=&quot;color: #06287e;&quot;&gt;Sprintf&lt;/span&gt;(&lt;span style=&quot;color: #4070a0;&quot;&gt;&quot;n=%d/vals=%s&quot;&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;tc.name),&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;(b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;testing.B)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;       &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;Run&lt;/span&gt;(&lt;span style=&quot;color: #4070a0;&quot;&gt;&quot;impl=c&quot;&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;(b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;testing.B)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;ReportAllocs&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;encoded&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;buf&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;make&lt;/span&gt;([]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;turbopfor.&lt;span style=&quot;color: #06287e;&quot;&gt;EncodingSize&lt;/span&gt;(n))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;Loop&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;           &lt;/span&gt;encoded&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;turbopfor.&lt;span style=&quot;color: #06287e;&quot;&gt;P4nenc256v32Buf&lt;/span&gt;(buf,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;tc.vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;reportMetrics&lt;/span&gt;(b,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(encoded))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;       &lt;/span&gt;})&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;       &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;Run&lt;/span&gt;(&lt;span style=&quot;color: #4070a0;&quot;&gt;&quot;impl=go&quot;&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;(b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;testing.B)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;ReportAllocs&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;be&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;BlockEncoder&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;encoded&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;buf&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;make&lt;/span&gt;([]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;turbopfor.&lt;span style=&quot;color: #06287e;&quot;&gt;EncodingSize&lt;/span&gt;(n))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;Loop&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;           &lt;/span&gt;encoded&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;be.&lt;span style=&quot;color: #06287e;&quot;&gt;EncodeN&lt;/span&gt;(buf,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;tc.vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;reportMetrics&lt;/span&gt;(b,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(encoded))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;       &lt;/span&gt;})&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;       &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;Run&lt;/span&gt;(&lt;span style=&quot;color: #4070a0;&quot;&gt;&quot;impl=go-stream&quot;&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;(b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;testing.B)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;ReportAllocs&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;se&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;StreamEncoder&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;encoded&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b.&lt;span style=&quot;color: #06287e;&quot;&gt;Loop&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;           &lt;/span&gt;encoded&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;           &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;_,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;tc.vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;             &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;se.&lt;span style=&quot;color: #06287e;&quot;&gt;Add&lt;/span&gt;(val)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;               &lt;/span&gt;encoded&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(se.&lt;span style=&quot;color: #06287e;&quot;&gt;EncodeBlock&lt;/span&gt;())&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;             &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;           &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;           &lt;/span&gt;encoded&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(se.&lt;span style=&quot;color: #06287e;&quot;&gt;EncodeBlock&lt;/span&gt;())&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;         &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;reportMetrics&lt;/span&gt;(b,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;encoded)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;       &lt;/span&gt;})&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;     &lt;/span&gt;})&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;   &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&quot;perf&quot;&gt;CPU counters: perf&lt;/h3&gt;
&lt;p&gt;Go has included excellent performance tooling for many years, see the
&lt;a href=&quot;https://go.dev/blog/pprof&quot;&gt;â€œProfiling Go Programsâ€� blog post&lt;/a&gt; (2011) for an
example of how to use &lt;code&gt;pprof&lt;/code&gt;, a sampling profiler. This profiler can help track
down which part of a program runs slow, or where memory allocations happen.&lt;/p&gt;
&lt;p&gt;Once you identified the slow part of a program, how do you know why itâ€™s slow?&lt;/p&gt;
&lt;p&gt;To learn more about the specific bottlenecks your program encounters, you can
consult your CPUâ€™s &lt;a href=&quot;https://en.wikipedia.org/wiki/Hardware_performance_counter&quot;&gt;hardware performance
counters&lt;/a&gt;. For
example, you could check the &lt;a href=&quot;https://en.wikipedia.org/wiki/Branch_predictor&quot;&gt;branch
predictor&lt;/a&gt; counters to see if
your program is slow due to a high number of branch mispredicts.&lt;/p&gt;
&lt;p&gt;On Linux, the &lt;code&gt;perf&lt;/code&gt; tool is the best way to access the CPU hardware performance
counters. A good starting point for working with &lt;code&gt;perf&lt;/code&gt; is the &lt;a href=&quot;https://perfwiki.github.io/main/top-down-analysis/&quot;&gt;documentation on
â€œTop-down analysis with the perf
toolâ€�&lt;/a&gt;, which describes the
optimization method that Intel established.&lt;/p&gt;
&lt;p&gt;In my &lt;code&gt;Makefile&lt;/code&gt;, I set up two &lt;code&gt;perf&lt;/code&gt; targets:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-makefile&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# GOTEST and TASKSET like shown in the earlier benchmarking setup section:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bb60d5;&quot;&gt;GOTEST&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;go &lt;span style=&quot;color: #007020;&quot;&gt;test&lt;/span&gt; -pgo&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;encode.cpuprof
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bb60d5;&quot;&gt;TASKSET&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;taskset -c &lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bb60d5;&quot;&gt;PERFBENCHFLAGS&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;-test.bench&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #4070a0;&quot;&gt;&#39;Encode/n=2048/vals=debian-mix/impl=go$$&#39;&lt;/span&gt; -test.benchtime&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;200000x
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# Use perf(1) to capture AMD IBS (the equivalent to Intel PEBS)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# PipelineL1 is roughly equivalent to Intel TopdownL1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;perf&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;GOTEST&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt; -c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;TASKSET&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt; perf stat -M PipelineL1 ./pforenc.test -test.run&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;^&lt;span style=&quot;color: #bb60d5;&quot;&gt;$$&lt;/span&gt; &lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;PERFBENCHFLAGS&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	sudo perf record -F &lt;span style=&quot;color: #40a070;&quot;&gt;4999&lt;/span&gt; -e ibs_op// --call-graph fp ./pforenc.test -test.run&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;^&lt;span style=&quot;color: #bb60d5;&quot;&gt;$$&lt;/span&gt; &lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;PERFBENCHFLAGS&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	sudo chmod &lt;span style=&quot;color: #40a070;&quot;&gt;644&lt;/span&gt; perf.data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;# 488281 iterations Ã— 2048 values = 1.000e9 values, so counter/1e9 = per value.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;perf-per-value&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;GOTEST&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt; -c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;$(&lt;/span&gt;TASKSET&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;)&lt;/span&gt; perf stat -x, -e cycles:u,instructions:u,branches:u,branch-misses:u ./pforenc.test -test.run&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;^&lt;span style=&quot;color: #bb60d5;&quot;&gt;$$&lt;/span&gt; -test.bench&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #4070a0;&quot;&gt;&#39;Encode/n=2048/vals=debian-mix/impl=go$$&#39;&lt;/span&gt; -test.benchtime&lt;span style=&quot;color: #666;&quot;&gt;=&lt;/span&gt;488281x 2&amp;gt;&amp;amp;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt; &amp;gt;/dev/null | awk -F, &lt;span style=&quot;color: #4070a0;&quot;&gt;&#39;{printf &quot;%-16s %6.2f /val\n&quot;, $$3, $$1/1e9}&#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;perf-per-value&lt;/code&gt; numbers are high level numbers that indicate how much work
the implementation is doing. Reducing the number usually increases speed.&lt;/p&gt;
&lt;p&gt;To see the counters for each instruction (and source code lines), I use &lt;code&gt;make perf&lt;/code&gt;, followed by &lt;code&gt;perf report&lt;/code&gt;. A quick shortcut is &lt;code&gt;perf annotate&lt;/code&gt;, which
directly shows the hottest function.&lt;/p&gt;
&lt;h2 id=&quot;opt-scalar&quot;&gt;Optimizations (scalar)&lt;/h2&gt;
&lt;p&gt;Letâ€™s first see how far we can get without reaching for SIMD instructions.&lt;/p&gt;
&lt;p&gt;(The examples are not necessarily in commit order, but cherry-picked for clarity.)&lt;/p&gt;
&lt;h3 id=&quot;pgo&quot;&gt;Profile-Guided Optimization (PGO)&lt;/h3&gt;
&lt;p&gt;PGO stands for Profile-Guided Optimization and is a feature that Go introduced
as a preview in Go 1.20 (released in February 2023) and shipped as &lt;a href=&quot;https://go.dev/blog/pgo&quot;&gt;ready for
general production use in Go 1.21&lt;/a&gt; (released in August
2023).&lt;/p&gt;
&lt;p&gt;The idea is to capture a CPU profile that records where your program spends most
of its CPU time, which you then provide to the Go compiler to give it more data
to make better decisions.&lt;/p&gt;
&lt;p&gt;Most importantly, this way the Go compiler can &lt;a href=&quot;https://go.dev/blog/pgo#inlining&quot;&gt;inline functions much more
aggressively&lt;/a&gt; than its usual heuristics allow,
which does have a measurably positive effect in my series of optimization
commits. Another optimization that a PGO profile allows the compiler to do is
&lt;a href=&quot;https://go.dev/blog/pgo#devirtualization&quot;&gt;conditional devirtualization&lt;/a&gt; â€” but
our TurboPFor code does not use any interfaces.&lt;/p&gt;
&lt;p&gt;My strategy is to enable PGO before doing any other optimizations, so that we
have the full inlining budget available that PGO gives us, and can measure the
effect of other commits clearly.&lt;/p&gt;
&lt;p&gt;Surprisingly, &lt;a href=&quot;https://github.com/Debian/dcs/commit/d6a44a18b376bf7b33fa01b8c69fa448c776a0f0&quot;&gt;turning on PGO actually decreases our
performance&lt;/a&gt;
(-13% geomean), but a closer investigation reveals that we just got unlucky. Let
me explain.&lt;/p&gt;
&lt;p&gt;Aside from inlining and conditional devirtualization, PGO also influences
alignment: The Go compiler sets &lt;code&gt;PCALIGNMAX(64, 31)&lt;/code&gt; on the first block of a
loop (the â€œloop bodyâ€�) for all loops in hot functions (per the PGO profile),
i.e. Go will insert up to 31 bytes of padding to make the block land on a
64-byte boundary. Documentation like &lt;a href=&quot;https://docs.amd.com/v/u/en-US/58455_1.00&quot;&gt;AMDâ€™s â€œSoftware Optimization Guide for the
AMD Zen5 Microarchitectureâ€�&lt;/a&gt; (2024,
#58455) explicitly recommends aligning hot loops that way:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[â€¦] for hot loops, some further knowledge of trade-offs can be
helpful. Because the processor can read an aligned 64-byte fetch block every
cycle, it is suggested to either align the start of the loop to the beginning
of a 64-byte cache line [â€¦]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Indeed, when compiling with &lt;code&gt;-gcflags=all=-d=alignhot=0&lt;/code&gt; to disable the
alignment, performance remains as good as without PGO. How can the padding hurt
more than help?  The answer is: Itâ€™s not the padding itself! Itâ€™s a side-effect
of the padding moving instructions to different addresses.&lt;/p&gt;
&lt;p&gt;In the unlucky arrangement, a macro-fused &lt;code&gt;CMPQ&lt;/code&gt;+&lt;code&gt;JGE&lt;/code&gt; instruction pair now ends
up &lt;em&gt;exactly on a 32-byte boundary&lt;/em&gt;. However, the Go compiler ensures fused
branch sequences &lt;em&gt;must never cross or end at a 32-byte boundary&lt;/em&gt; to &lt;a href=&quot;https://cs.opensource.google/go/go/+/refs/tags/go1.27.0:src/cmd/internal/obj/x86/asm6.go;l=1978-2020;drc=aee6009ba5e1d71948b03ac0458fbc99e3a14ace&quot;&gt;fix Intel
erratum
SKX102&lt;/a&gt;
(discussion: &lt;a href=&quot;https://github.com/golang/go/issues/35881&quot;&gt;Go issue #35881&lt;/a&gt;) by
inserting &lt;code&gt;NOP&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;This &lt;code&gt;NOP&lt;/code&gt; padding, unlike the loop alignment padding, is not free; these extra
instructions slow down our otherwise dispatch-bound loops.&lt;/p&gt;
&lt;p&gt;Because the commits after the PGO enabling commit change the code, this unlucky
situation is avoided for the rest of the optimization series (by chance).&lt;/p&gt;
&lt;h3 id=&quot;reducing-allocations&quot;&gt;Reducing memory allocations&lt;/h3&gt;
&lt;p&gt;Memory allocations are quite expensive, at least in comparison to
encoding/decoding integers, so I followed my usual strategy of first reducing
memory allocations as much as possible.&lt;/p&gt;
&lt;p&gt;In my &lt;code&gt;goturbopfor&lt;/code&gt; teaching decoder, whenever the code needed a scratch buffer,
it would allocate it right then and there with &lt;code&gt;make()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// p4dec32 decodes one block of TurboPFor-encoded 32 bit ints&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(d&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;decoder)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;p4dec32&lt;/span&gt;(input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;output&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(read&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// â€¦&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockType&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockBitpackingExceptions:&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;bx,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input[&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;],&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input[&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;:]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;n&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(output)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;exmap&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;nex&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// number of exceptions&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #666;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;exmap[i&lt;span style=&quot;color: #666;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;]&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint&lt;/span&gt;(i&lt;span style=&quot;color: #666;&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;))&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;        &lt;/span&gt;nex&lt;span style=&quot;color: #666;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input[(n&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;7&lt;/span&gt;)&lt;span style=&quot;color: #666;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;:]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;exceptions&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;make&lt;/span&gt;([]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;nex)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input[&lt;span style=&quot;color: #06287e;&quot;&gt;bitunpack32&lt;/span&gt;(input,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;exceptions,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bx):]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input[d.&lt;span style=&quot;color: #06287e;&quot;&gt;bitunpack&lt;/span&gt;(input,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;output,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b):]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #666;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;exmap[i&lt;span style=&quot;color: #666;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;]&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint&lt;/span&gt;(i&lt;span style=&quot;color: #666;&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;))&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;        &lt;/span&gt;output[i]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;exceptions[&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;        &lt;/span&gt;exceptions&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;exceptions[&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;:]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;before&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(input)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Go compiler can turn &lt;code&gt;make(T, n)&lt;/code&gt; calls into stack allocations, if &lt;code&gt;n&lt;/code&gt; is
known at compile-time. But, in this case &lt;code&gt;nex&lt;/code&gt; is not known at compile-time. We
can verify that Go calls into the runtime (&lt;code&gt;runtime.makeslice&lt;/code&gt;) by dumping the
object code (assembly) with source annotated (&lt;code&gt;-S&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;% cd ~/go/src/github.com/stapelberg/goturbopfor
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;% git reset --hard 49b7c05cc61e77f0257568eb73833467714d2b4a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;% go test -c  # go1.27.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;% go tool objdump -S goturbopfor.test | perl -nlE &#39;say if /p4dec32/ .. /^$/&#39;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;TEXT github.com/stapelberg/goturbopfor.(*decoder).p4dec32(SB) /home/michael/go/src/github.com/stapelberg/goturbopfor/goturbopfor.go
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;func (d *decoder) p4dec32(input []byte, output []uint32) (read int) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f60		4c8da42460ffffff	LEAQ 0xffffff60(SP), R12
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f68		4d3b6610		CMPQ R12, 0x10(R14)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f6c		0f86d9070000		JBE 0x54a74b
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f72		55			PUSHQ BP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f73		4889e5			MOVQ SP, BP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f76		4881ec18010000		SUBQ $0x118, SP
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f7d		48899c2430010000	MOVQ BX, 0x130(SP)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f85		4889b42448010000	MOVQ SI, 0x148(SP)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;	if len(output) == 0 {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f8d		4d85c0			TESTQ R8, R8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f90		0f84a7030000		JE 0x54a33d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f96		660f1f840000000000	NOPW 0(AX)(AX*1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;  0x549f9f		90			NOPL
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;[â€¦]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;		exceptions := make([]uint32, nex)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;  0x54a4be		488d057bec1700		LEAQ 0x17ec7b(IP), AX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;  0x54a4c5		4c89fb			MOVQ R15, BX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;  0x54a4c8		4889d9			MOVQ BX, CX
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;  0x54a4cb		e8f0ddf3ff		CALL runtime.makeslice(SB)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;[â€¦]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;An easy speed-up was to &lt;a href=&quot;https://github.com/stapelberg/goturbopfor/commit/3c530dbcfc8fe01674e3168c296fcfdf3d06718c&quot;&gt;avoid allocations through
reuse&lt;/a&gt;
(in &lt;code&gt;goturbopfor&lt;/code&gt;). In the DCS &lt;code&gt;pfordec&lt;/code&gt; package (with the &lt;a href=&quot;https://michael.stapelberg.ch/posts/tags/debian/feed.xml#api-design&quot;&gt;improved
API design&lt;/a&gt;), I ended up with a &lt;code&gt;vals [256]uint32&lt;/code&gt; field in the &lt;code&gt;StreamDecoder&lt;/code&gt;
type, which brings us from 773 Mval/s to 858 Mval/s on the debian-mix:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;% benchstat -filter &#39;/impl:go /vals:debian-mix .unit:(Mval/s)&#39; \
  baseline.txt bench.txt
goos: linux
goarch: amd64
pkg: github.com/Debian/dcs/internal/turbopfor/pfordec
cpu: AMD Ryzen 9 9950X3D 16-Core Processor
           â”‚ baseline.txt â”‚             bench.txt              â”‚
           â”‚    Mval/s    â”‚   Mval/s     vs base               â”‚
n=2048        1.089k Â± 1%   1.175k Â± 0%   +7.85% (p=0.002 n=6)
n=2039         974.7 Â± 0%   1046.0 Â± 0%   +7.32% (p=0.002 n=6)
n=160          434.9 Â± 1%    513.6 Â± 5%  +18.11% (p=0.002 n=6)
geomean        772.9         857.7       +10.98%
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Aside from the speed-up, avoiding memory allocations is generally nice in
benchmarks because it removes the garbage collector from the equation and makes
it less likely that your benchmarks get other processes OOM-killed on the same
machine.&lt;/p&gt;
&lt;h3 id=&quot;bit-width-specialization&quot;&gt;Generics for bit width specialization&lt;/h3&gt;
&lt;p&gt;In general, we want to make it easy for the compiler to understand as much as
possible about our algorithm. Consider this &lt;code&gt;bitpack&lt;/code&gt; implementation:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bitpack&lt;/span&gt;(dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;mask&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint64&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;_,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;|=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint64&lt;/span&gt;(val&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;mask)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;binary.LittleEndian.&lt;span style=&quot;color: #06287e;&quot;&gt;AppendUint32&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(acc))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;append&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;byte&lt;/span&gt;(acc))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Letâ€™s think through what determines the iterations and control flow this
function uses:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;em&gt;number of input values&lt;/em&gt; (&lt;code&gt;vals&lt;/code&gt;), but not their actual value.&lt;/li&gt;
&lt;li&gt;The bit width to pack into (&lt;code&gt;bitWidth&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With a bit of careful rearrangement, we can provide the compiler with both, a
fixed number of input values (say, 32), and a bit width, both known at compile
time. Why is this worthwhile? Because we can manually unroll the loop, let the
compiler eliminate much of the repetition and get much faster compiled code as a
result!&lt;/p&gt;
&lt;p&gt;Letâ€™s first fix the number of input values to 32 and rewrite the loop to
calculate the position offsets within &lt;code&gt;dest&lt;/code&gt; instead of changing &lt;code&gt;dest&lt;/code&gt; on each
value (with &lt;code&gt;AppendUint32&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bitpack32Unrolled&lt;/span&gt;(dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// only one bounds check for 32 values&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;dest[:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;bitWidth]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;mask&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint64&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;pos&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Manually unrolled loop starts here.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Each iteration is identical except for the vals[x] index.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;|=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint64&lt;/span&gt;(vals[&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;]&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;mask)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;binary.LittleEndian.&lt;span style=&quot;color: #06287e;&quot;&gt;PutUint32&lt;/span&gt;(dest[pos:pos&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;],&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(acc))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;pos&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// vals[1] .. vals[30] elided for brevity&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Each loop iteration is 8 lines of Go code, so for 32 input values,&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// bitpack32Unrolled contains 8*32 = 256 lines of code.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;|=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint64&lt;/span&gt;(vals[&lt;span style=&quot;color: #40a070;&quot;&gt;31&lt;/span&gt;]&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;mask)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;binary.LittleEndian.&lt;span style=&quot;color: #06287e;&quot;&gt;PutUint32&lt;/span&gt;(dest[pos:pos&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;],&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(acc))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;pos&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// have == 0; for all bitWidths&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next, we want to specialize not just for 32 input values, but also for each of
the 32 bit widths.&lt;/p&gt;
&lt;p&gt;Can we do better than hand-copying &lt;code&gt;bitpack32Unrolled&lt;/code&gt; 32 times (= 8192 lines of Go code)?&lt;/p&gt;
&lt;p&gt;Yes, we can use Go generics to help us with the code generation!&lt;/p&gt;
&lt;p&gt;In Go, &lt;a href=&quot;https://go.dev/ref/spec#Array_types&quot;&gt;array types&lt;/a&gt; like &lt;code&gt;[4]byte&lt;/code&gt; (not
slices like &lt;code&gt;[]byte&lt;/code&gt;!)  contain the length of the array as part of their type,
meaning &lt;code&gt;[1]byte&lt;/code&gt; (an array of length 1) is a different type than &lt;code&gt;[2]byte&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Instead of passing the bit width as a function parameter, we can declare 32
&lt;em&gt;different types&lt;/em&gt; (one for each bit width) and recover the bit width (at compile
time!) from the type system:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidthT&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;interface&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;2&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;3&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;5&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;6&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;7&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;9&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;10&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;11&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;12&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;13&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;14&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;15&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;16&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;17&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;18&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;19&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;20&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;21&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;22&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;23&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;24&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;25&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;26&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;27&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;28&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;29&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;30&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;31&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;|&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[T&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidthT](dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;zero&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;T&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(zero)&lt;span style=&quot;color: #bbb;&quot;&gt;                  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// known at compile time&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;dest[:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;bitWidth]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// make cap known at compile time&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;mask&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint64&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;pos&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Manually unrolled loop starts here.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Each iteration is identical except for the vals[x] index.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;|=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint64&lt;/span&gt;(vals[&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;]&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;mask)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;binary.LittleEndian.&lt;span style=&quot;color: #06287e;&quot;&gt;PutUint32&lt;/span&gt;(dest[pos:pos&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;],&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(acc))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;pos&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// vals[1] .. vals[31] elided for brevity&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When we instantiate &lt;code&gt;bitpack32Unrolled[bitWidthT]&lt;/code&gt; with all 32 different types
(&lt;code&gt;[1]byte&lt;/code&gt;, &lt;code&gt;[2]byte&lt;/code&gt;, â€¦, &lt;code&gt;[32]byte&lt;/code&gt;), the compiler substitutes the &lt;code&gt;bitWidthT&lt;/code&gt;
type parameter and produces 32 copies of the function, which we can find in our
compiled executable with names like
&lt;code&gt;github.com/Debian/dcs/internal/turbopfor/pforenc.bitpack32Unrolled[go.shape.[12]uint8]&lt;/code&gt;. The
â€œshapeâ€� of a generic type is based on its memory layout, so a shape for
&lt;code&gt;[1]byte&lt;/code&gt; must be different than the shape for &lt;code&gt;[2]byte&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Because the &lt;code&gt;bitWidth&lt;/code&gt; is now known at compile time, the Go compiler can
generate close to the optimal machine code for each bit width, which we can
confirm using &lt;code&gt;go tool objdump&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The code is branchless (after the one bounds check per 32 values) and aside from
the loads and stores (from/to memory) consists only of shifts and bit
operations, all with constant operands:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;% go test -c &amp;amp;&amp;amp; go tool objdump -S pforenc.test
[â€¦]
TEXT github.com/Debian/dcs/internal/turbopfor/pforenc.bitpack32Unrolled[go.shape.[28]uint8](SB) /home/michael/dcs/internal/turbopfor/pforenc/bitpackunroll.go
func bitpack32Unrolled[T bitWidthT](dest []byte, vals *[32]uint32) {
  0x660580              55                      PUSHQ BP
  0x660581              4889e5                  MOVQ SP, BP
  0x660584              48895c2418              MOVQ BX, 0x18(SP)
        dest = dest[: 4*bitWidth : 4*bitWidth] // make cap known at compile time
  0x660589              4883ff70                CMPQ DI, $0x70
  0x66058d              0f820b030000            JB 0x66089e
        acc |= uint64(vals[0]&amp;amp;mask) &amp;lt;&amp;lt; have
  0x660593              8b06                    MOVL 0(SI), AX
  0x660595              25ffffff0f              ANDL $0xfffffff, AX
        acc |= uint64(vals[1]&amp;amp;mask) &amp;lt;&amp;lt; have
  0x66059a              8b4e04                  MOVL 0x4(SI), CX
  0x66059d              81e1ffffff0f            ANDL $0xfffffff, CX
  0x6605a3              48c1e11c                SHLQ $0x1c, CX
  0x6605a7              4809c8                  ORQ CX, AX
                acc &amp;gt;&amp;gt;= 32
  0x6605aa              4889c1                  MOVQ AX, CX
  0x6605ad              48c1e820                SHRQ $0x20, AX
                binary.LittleEndian.PutUint32(dest[pos:pos+4], uint32(acc))
  0x6605b1              90                      NOPL
        b[0] = byte(v)
  0x6605b2              890b                    MOVL CX, 0(BX)
        acc |= uint64(vals[2]&amp;amp;mask) &amp;lt;&amp;lt; have
  0x6605b4              8b4e08                  MOVL 0x8(SI), CX
  0x6605b7              81e1ffffff0f            ANDL $0xfffffff, CX
  0x6605bd              48c1e118                SHLQ $0x18, CX
  0x6605c1              4809c1                  ORQ AX, CX
                acc &amp;gt;&amp;gt;= 32
  0x6605c4              4889c8                  MOVQ CX, AX
  0x6605c7              48c1e920                SHRQ $0x20, CX
                binary.LittleEndian.PutUint32(dest[pos:pos+4], uint32(acc))
  0x6605cb              90                      NOPL
        b[0] = byte(v)
  0x6605cc              894304                  MOVL AX, 0x4(BX)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now we need to actually call &lt;code&gt;bitpack32&lt;/code&gt; from the general &lt;code&gt;bitpack&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bitpack&lt;/span&gt;(dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// no payload, sparse block with only exceptions&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(vals)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;size&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(vals)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;existing&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(dest)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;slices.&lt;span style=&quot;color: #06287e;&quot;&gt;Grow&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;size)[:existing&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;size]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bitpack32&lt;/span&gt;(dest[existing:]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;/*append*/&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)(vals),&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals[&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;:]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;mask&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint64&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;_,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;|=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint64&lt;/span&gt;(val&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;mask)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;binary.LittleEndian.&lt;span style=&quot;color: #06287e;&quot;&gt;AppendUint32&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(acc))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;append&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;byte&lt;/span&gt;(acc))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;have&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bitpack32&lt;/span&gt;(dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;2&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;2&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;3&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;3&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;5&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;5&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;6&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;6&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;7&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;7&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;9&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;9&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;10&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;10&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;11&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;11&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;12&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;12&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;13&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;13&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;14&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;14&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;15&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;15&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;16&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;16&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;17&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;17&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;18&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;18&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;19&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;19&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;20&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;20&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;21&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;21&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;22&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;22&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;23&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;23&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;24&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;24&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;25&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;25&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;26&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;26&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;27&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;27&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;28&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;28&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;29&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;29&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;30&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;30&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;31&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;31&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitpack32Unrolled[[&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;](dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Encoding remainder blocks is quite a bit faster (full blocks use the vertical
layout anyway):&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;% benchstat -filter &#39;/impl:go /n:160 .unit:(Mval/s)&#39; baseline.txt bench.txt
goos: linux
goarch: amd64
pkg: github.com/Debian/dcs/internal/turbopfor/pforenc
cpu: AMD Ryzen 9 9950X3D 16-Core Processor
                         â”‚ baseline.txt â”‚             bench.txt              â”‚
                         â”‚    Mval/s    â”‚   Mval/s     vs base               â”‚
vals=bitpacking-bw1          751.2 Â± 3%   1120.5 Â± 0%  +49.15% (p=0.002 n=6)
vals=bitpacking-bw2          716.8 Â± 2%   1176.0 Â± 0%  +64.07% (p=0.002 n=6)
vals=bitpacking-bw7          700.0 Â± 1%   1078.5 Â± 0%  +54.08% (p=0.002 n=6)
vals=bitpacking-bw1-exc      524.8 Â± 1%    736.8 Â± 0%  +40.40% (p=0.002 n=6)
vals=bitpacking-bw2-exc      543.7 Â± 1%    758.2 Â± 0%  +39.46% (p=0.002 n=6)
vals=bitpacking-bw7-exc      566.7 Â± 1%    787.7 Â± 0%  +38.99% (p=0.002 n=6)
vals=bitpacking-vb-exc       442.6 Â± 1%    616.5 Â± 0%  +39.29% (p=0.002 n=6)
vals=sparse-exc              532.4 Â± 0%    787.8 Â± 0%  +47.97% (p=0.002 n=6)
vals=sparse-vb-exc           408.9 Â± 1%    597.8 Â± 0%  +46.20% (p=0.002 n=6)
vals=debian-mix              559.5 Â± 0%    783.8 Â± 9%  +40.09% (p=0.002 n=6)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This performance win comes at the cost of binary size increase. In this case,
the &lt;code&gt;.text&lt;/code&gt; section (executable code) grows by about 20 KB and the &lt;code&gt;.gopclntab&lt;/code&gt;
section grows by another 26 KB. Definitely a price I am very willing to pay, but
the case might not be as clear in all circumstances.&lt;/p&gt;
&lt;h2 id=&quot;simd-bigger-strides&quot;&gt;Optimization: Bigger strides with SIMD&lt;/h2&gt;
&lt;p&gt;Even without reaching for SIMD instructions, a TurboPFor implementation can be
made faster by making it work bigger strides. Take this code from the
&lt;code&gt;goturbopfor&lt;/code&gt; teaching decoder which counts the number of exceptions by checking
if each valueâ€™s bit is set in the exception bitmap:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockBitpackingExceptions:&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;bx,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input[&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;],&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input[&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;:]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;n&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(output)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;exmap,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input[(n&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;7&lt;/span&gt;)&lt;span style=&quot;color: #666;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;:]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;nex&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// number of exceptions&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;exmap[i&lt;span style=&quot;color: #666;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;]&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint&lt;/span&gt;(i&lt;span style=&quot;color: #666;&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;))&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;!=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;nex&lt;span style=&quot;color: #666;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;exceptions&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;d.scratch[:nex]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can use the &lt;a href=&quot;https://pkg.go.dev/math/bits#OnesCount64&quot;&gt;&lt;code&gt;bits.OnesCount64&lt;/code&gt;&lt;/a&gt;
functions to count ones bits in the exception bitmap, 64 values at a time. For
remainder blocks, the rest is processed 8 values (1 byte) at a time:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n&lt;span style=&quot;color: #666;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;xm8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;binary.LittleEndian.&lt;span style=&quot;color: #06287e;&quot;&gt;Uint64&lt;/span&gt;(exmap[i:])&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;nex&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits.&lt;span style=&quot;color: #06287e;&quot;&gt;OnesCount64&lt;/span&gt;(xm8)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(n&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;7&lt;/span&gt;)&lt;span style=&quot;color: #666;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #666;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;xmb&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;exmap[i]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Clear the bits which do not belong to the exception map:&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;rem&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;rem&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;xmb&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;rem&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Go compiles OnesCount32 into an intrinsic,&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// but not OnesCount8, so we convert to uint32:&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;nex&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits.&lt;span style=&quot;color: #06287e;&quot;&gt;OnesCount32&lt;/span&gt;(&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(xmb))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;OnesCount64&lt;/code&gt; uses a 64-bit register. For comparison, AVX2 SIMD instructions use
256-bit registers (= 8 &lt;code&gt;uint32&lt;/code&gt;) and AVX512 SIMD instructions use 512-bit registers.&lt;/p&gt;
&lt;p&gt;In the following sections, we will first set up our build tags for conditional
compilation to use a trivial SIMD instruction, then walk through an AVX2 and
AVX512 SIMD kernel.&lt;/p&gt;
&lt;h3 id=&quot;simd-build-tags&quot;&gt;SIMD build tags&lt;/h3&gt;
&lt;p&gt;Letâ€™s assume we have the following scalar code:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;constant.go&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;pfordec&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;fillConstant&lt;/span&gt;(output&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;output&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;output[i]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To increase throughput, we can use AVX2 instructions if they are available on the CPU on which the program runs, i.e. using runtime dispatch. Weâ€™ll first rename &lt;code&gt;fillConstant&lt;/code&gt; to &lt;code&gt;fillConstantScalar&lt;/code&gt; (itâ€™s now the fallback path):&lt;/p&gt;
&lt;p&gt;&lt;code&gt;constant.go&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;pfordec&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;fillConstantScalar&lt;/span&gt;(output&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;output&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;output[i]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, weâ€™ll supply two different implementations (&lt;code&gt;constant_nosimd.go&lt;/code&gt; and &lt;code&gt;constant_amd64.go&lt;/code&gt;), the latter of which is selected when compiling for &lt;code&gt;GOARCH=amd64&lt;/code&gt; with &lt;code&gt;GOEXPERIMENT=simd&lt;/code&gt; (the latter will hopefully be dropped in a later version of Go). The &lt;code&gt;nosimd&lt;/code&gt; variant just dispatches to the &lt;code&gt;fillConstantScalar&lt;/code&gt;, which will likely be inlined:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;//go:build !goexperiment.simd || !amd64&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;pfordec&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;fillConstant&lt;/span&gt;(output&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;fillConstantScalar&lt;/span&gt;(output,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;constant_amd64.go&lt;/code&gt; variant assigns the &lt;code&gt;hasAVX2&lt;/code&gt; global variable by doing a &lt;code&gt;CPUID&lt;/code&gt; check and then jumps to the scalar fallback if &lt;code&gt;!hasAVX2&lt;/code&gt;, i.e. the CPU is too old:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;//go:build goexperiment.simd &amp;amp;&amp;amp; amd64&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;pfordec&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #4070a0;&quot;&gt;&quot;simd/archsimd&quot;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;hasAVX2&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.X86.&lt;span style=&quot;color: #06287e;&quot;&gt;AVX2&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;fillConstant&lt;/span&gt;(output&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;!hasAVX2&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;fillConstantScalar&lt;/span&gt;(output,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;val8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.&lt;span style=&quot;color: #06287e;&quot;&gt;BroadcastUint32x8&lt;/span&gt;(val)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(output);&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;val8.&lt;span style=&quot;color: #06287e;&quot;&gt;StoreArray&lt;/span&gt;((&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)(output[i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;]))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// use the scalar implementation for the last &amp;lt;= 7 elements&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;fillConstantScalar&lt;/span&gt;(output[i:],&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can go one step further by conditionally compiling &lt;code&gt;const hasAVX2 = true&lt;/code&gt;
when &lt;code&gt;GOAMD64&lt;/code&gt; is set to &lt;code&gt;v3&lt;/code&gt; or higher (i.e. the &lt;code&gt;amd64.v3&lt;/code&gt; build tag is
set). As a practical example from Debian Code Search, we currently need the
following checks / dispatches:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;code&lt;/th&gt;
					&lt;th&gt;function&lt;/th&gt;
					&lt;th&gt;vector instruction set&lt;/th&gt;
					&lt;th&gt;GOAMD64&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;encoder&lt;/td&gt;
					&lt;td&gt;bitpack256v&lt;/td&gt;
					&lt;td&gt;AVX2&lt;/td&gt;
					&lt;td&gt;GOAMD64=v3&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;encoder&lt;/td&gt;
					&lt;td&gt;exbitmap&lt;/td&gt;
					&lt;td&gt;AVX512&lt;/td&gt;
					&lt;td&gt;GOAMD64=v4&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;encoder&lt;/td&gt;
					&lt;td&gt;scan&lt;/td&gt;
					&lt;td&gt;AVX512+VBMI+GFNI+BITALG&lt;/td&gt;
					&lt;td&gt;&lt;em&gt;n/a&lt;/em&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;decoder&lt;/td&gt;
					&lt;td&gt;bitunpack&lt;/td&gt;
					&lt;td&gt;AVX2&lt;/td&gt;
					&lt;td&gt;GOAMD64=v3&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;decoder&lt;/td&gt;
					&lt;td&gt;bitunpack256v32&lt;/td&gt;
					&lt;td&gt;AVX2&lt;/td&gt;
					&lt;td&gt;GOAMD64=v3&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;decoder&lt;/td&gt;
					&lt;td&gt;bitunpack256v32Ex&lt;/td&gt;
					&lt;td&gt;AVX512&lt;/td&gt;
					&lt;td&gt;GOAMD64=v4&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In DCS, the &lt;a href=&quot;https://github.com/Debian/dcs/commit/c25276bfc1dce5b6fb5e3706c9f436039b788d61&quot;&gt;effect is measurably positive, but
small&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;bitunpack256v32&quot;&gt;The 256 uint32 vertical layout&lt;/h3&gt;
&lt;p&gt;First, here is the layout explanation from &lt;a href=&quot;https://michael.stapelberg.ch/posts/2019-02-05-turbopfor-analysis/&quot;&gt;my 2019 TurboPFor analysis blog
post&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In &lt;strong&gt;regular (non-SIMD) bitpacking&lt;/strong&gt;, integers are stored on disk one after
the other, padded to a full byte, as a byte is the smallest addressable unit
when reading data from disk. For example, if you bitpack only one 3 bit int,
you will end up with 5 bits of padding.&lt;/p&gt;
&lt;img src=&quot;https://michael.stapelberg.ch/posts//turbopfor/bitpacking.svgo.svg&quot; /&gt;
&lt;p&gt;&lt;strong&gt;SIMD bitpacking&lt;/strong&gt; works like regular bitpacking, but processes 8 &lt;code&gt;uint32&lt;/code&gt;
little-endian values at the same time, leveraging the &lt;a href=&quot;https://en.wikipedia.org/wiki/Advanced_Vector_Extensions&quot;&gt;AVX instruction
set&lt;/a&gt;. The following
illustration shows the order in which 3-bit integers are decoded from disk:&lt;/p&gt;
&lt;img src=&quot;https://michael.stapelberg.ch/posts/turbopfor/bitpacking256v32.svgo.svg&quot; /&gt;
&lt;/blockquote&gt;
&lt;p&gt;The scalar implementation uses an array of 8 &lt;code&gt;uint64&lt;/code&gt; to process 8 values at a
time:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bitunpack256v32&lt;/span&gt;(input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(read&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;mask&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint64&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;orig&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(input)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;uint64&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// accumulator: current+next bits&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;op&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;op&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(dest);&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint&lt;/span&gt;(bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// read 8 more uint32s&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;        &lt;/span&gt;acc[i]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;|=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint64&lt;/span&gt;(binary.LittleEndian.&lt;span style=&quot;color: #06287e;&quot;&gt;Uint32&lt;/span&gt;(input))&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;        &lt;/span&gt;input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;input[&lt;span style=&quot;color: #40a070;&quot;&gt;4&lt;/span&gt;:]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;bits&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;i&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;dest[op]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(acc[i]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;mask)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;op&lt;span style=&quot;color: #666;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;acc[i]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;bits&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint&lt;/span&gt;(bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;orig&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(input)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The SIMD version also processes 8 values, but without a &lt;code&gt;for i := range 8&lt;/code&gt; loop!&lt;/p&gt;
&lt;p&gt;One difference is that we no longer have the luxury of using &lt;code&gt;uint64&lt;/code&gt; for &lt;code&gt;acc&lt;/code&gt;
(holding rest and current bits); because AVX2 registers only fit 8 &lt;code&gt;uint32&lt;/code&gt; (not
8 &lt;code&gt;uint64&lt;/code&gt;). Instead, we split &lt;code&gt;acc&lt;/code&gt; into &lt;code&gt;rest8&lt;/code&gt; and &lt;code&gt;cur8&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;bitunpack256v32&lt;/span&gt;(fullinput&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;fulldest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(read&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;int&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;fulldest[:&lt;span style=&quot;color: #40a070;&quot;&gt;256&lt;/span&gt;]&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;clear&lt;/span&gt;(dest)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;n&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;int&lt;/span&gt;(bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;input&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;fullinput[:n]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// tell the Go compiler how long the input is&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;mask8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.&lt;span style=&quot;color: #06287e;&quot;&gt;BroadcastUint32x8&lt;/span&gt;(&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;bitWidth8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.&lt;span style=&quot;color: #06287e;&quot;&gt;BroadcastUint32x8&lt;/span&gt;(&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(bitWidth))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #902000;&quot;&gt;uint&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;pos&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// var acc [8]uint64&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;rest8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.Uint32x8&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;cur8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.Uint32x8&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;op&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;op&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;256&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;op&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint&lt;/span&gt;(bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// read 8 more uint32s&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// acc[i] |= uint64(binary.LittleEndian.Uint32(input)) &amp;lt;&amp;lt; bits&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;next&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.&lt;span style=&quot;color: #06287e;&quot;&gt;LoadUint8x32&lt;/span&gt;(input[pos&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;pos&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;]).&lt;span style=&quot;color: #06287e;&quot;&gt;ReshapeToUint32s&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;pos&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// input = input[4:]&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;cur8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;rest8.&lt;span style=&quot;color: #06287e;&quot;&gt;Or&lt;/span&gt;(next.&lt;span style=&quot;color: #06287e;&quot;&gt;ShiftAllLeft&lt;/span&gt;(&lt;span style=&quot;color: #007020;&quot;&gt;uint64&lt;/span&gt;(bits)))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// acc[i] &amp;gt;&amp;gt;= bitWidth&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;rest8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;next.&lt;span style=&quot;color: #06287e;&quot;&gt;ShiftAllRight&lt;/span&gt;(&lt;span style=&quot;color: #007020;&quot;&gt;uint64&lt;/span&gt;(&lt;span style=&quot;color: #007020;&quot;&gt;uint&lt;/span&gt;(bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;bits&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;cur8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;rest8&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// acc[i] &amp;gt;&amp;gt;= bitWidth&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;rest8&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;rest8.&lt;span style=&quot;color: #06287e;&quot;&gt;ShiftRight&lt;/span&gt;(bitWidth8)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// dest[op] = uint32(acc[i] &amp;amp; mask)&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;cur8.&lt;span style=&quot;color: #06287e;&quot;&gt;And&lt;/span&gt;(mask8).&lt;span style=&quot;color: #06287e;&quot;&gt;Store&lt;/span&gt;(dest[op&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;op&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;8&lt;/span&gt;])&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;bits&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;uint&lt;/span&gt;(bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;n&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The SIMD version benchmarks about 3x as fast as the scalar version.&lt;/p&gt;
&lt;p&gt;Another significant speedup is to &lt;a href=&quot;https://michael.stapelberg.ch/posts/tags/debian/feed.xml#bit-width-specialization&quot;&gt;use generics for bit width
specialization&lt;/a&gt; for this SIMD kernel so that
&lt;code&gt;bitWidth&lt;/code&gt; becomes a compile-time constant and the compiler can generate better
code.&lt;/p&gt;
&lt;h3 id=&quot;positional-popcount&quot;&gt;Positional Popcount&lt;/h3&gt;
&lt;p&gt;For my TurboPFor encoder, I implemented the same techniques as described above:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Debian/dcs/commit/6a9b173c7686592bb7852610e865057f086e0964&quot;&gt;Bitpack full blocks with SIMD (AVX2)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Debian/dcs/commit/5d584897157b73774fb22c3d0810a40f7edf68f9&quot;&gt;Gather exceptions using SIMD (AVX512)&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Debian/dcs/commit/2db8415c5dde141fdc7736a57d3843b459c88da1&quot;&gt;Use generics to specialize per bit width&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These changes are sufficient to roughly match the cgo performance, but then
Claude Fable 5 found another &lt;strong&gt;2x speed-up on top of that&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;The key observation is that once encoding blocks is fast, the preceding step of
scanning the input values to decide which block type to use becomes the
bottleneck. Here is the encoderâ€™s main &lt;code&gt;encode&lt;/code&gt; function, which first does one
pass over the input values (&lt;code&gt;scan&lt;/code&gt;) and then prices all different block types at
all relevant bit widths (requires fast access to the &lt;code&gt;scan&lt;/code&gt; histogram):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;(be&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;BlockEncoder)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;encode&lt;/span&gt;(dest&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;layout&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockLayout)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;stats&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;stats&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;scan&lt;/span&gt;(&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;stats,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// gathers statistics from every value in vals&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits.&lt;span style=&quot;color: #06287e;&quot;&gt;Len32&lt;/span&gt;(stats.or)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;stats.or&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;stats.and&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;be.&lt;span style=&quot;color: #06287e;&quot;&gt;encodeConstant&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;n&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(vals)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// bitpacking is the default, unless we find a more efficient block type.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;bestType&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockBitpacking&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;bestB&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;best&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;priceBitpack&lt;/span&gt;(n,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;layout)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Walk from high bitWidths to low: to break ties, we prefer&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// the encoding with fewer exceptions (for faster decoding).&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex; background-color: #d8d8d8;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;1&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b&lt;span style=&quot;color: #666;&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// up to 32 iterations&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;nex&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;int&lt;/span&gt;(stats.cnt[b])&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;size&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;priceBitpackExceptions&lt;/span&gt;(n,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;nex,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;layout)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;size&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;best&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;bestType&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockBitpackingExceptions&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;bestB&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;best&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;size&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Over-approximate the number of VB bytes.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;vb&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;nex&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// exceptions using 1, 2, 3, 4, or 5 VB bytes&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;int&lt;/span&gt;(stats.cnt[b&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;7&lt;/span&gt;]&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// exceptions using 2, 3, 4, or 5 VB bytes&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;        &lt;/span&gt;stats.cnt[b&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;14&lt;/span&gt;]&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// exceptions using 3, 4, or 5 VB bytes&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;        &lt;/span&gt;stats.cnt[b&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;19&lt;/span&gt;]&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// exceptions using 4 or 5 VB bytes&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;        &lt;/span&gt;stats.cnt[b&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;24&lt;/span&gt;])&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// exceptions using 5 VB bytes&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;size&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;headerBytes&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;headerExBytes&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;payloadBytes&lt;/span&gt;(n,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;layout)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vb&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;nex&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;size&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;best&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;bestType&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockBitpackingVBExceptions&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;bestB&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;best&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;size&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;switch&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bestType&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockBitpacking:&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;be.&lt;span style=&quot;color: #06287e;&quot;&gt;encodeBitpack&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;layout,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockBitpackingExceptions:&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;be.&lt;span style=&quot;color: #06287e;&quot;&gt;encodeBitpackExc&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;layout,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bestB,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bitWidth&lt;span style=&quot;color: #666;&quot;&gt;-&lt;/span&gt;bestB)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;case&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;blockBitpackingVBExceptions:&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;be.&lt;span style=&quot;color: #06287e;&quot;&gt;encodeBitpackVBExc&lt;/span&gt;(dest,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;layout,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bestB,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;int&lt;/span&gt;(stats.cnt[bestB]))&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;default&lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;panic&lt;/span&gt;(&lt;span style=&quot;color: #4070a0;&quot;&gt;&quot;BUG: bestType not implemented&quot;&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Iâ€™ll show you a slightly shortened version of &lt;code&gt;scan&lt;/code&gt;, the function which is the bottleneck:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;stats&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// cnt[n] = how many values where bits.Len32(val)&amp;gt;n,&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// i.e. how many exceptions are required for bitWidth=n.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Padded so that cnt[b+24] is always in bounds.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;cnt&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;24&lt;/span&gt;]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;scan&lt;/span&gt;(output&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;stats,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;_,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits.&lt;span style=&quot;color: #06287e;&quot;&gt;Len32&lt;/span&gt;(val)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;output.cnt[b]&lt;span style=&quot;color: #666;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// b bits are not enough to store val&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Letâ€™s consider the following 3 example values to understand the resulting &lt;code&gt;cnt&lt;/code&gt;:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;input&lt;/th&gt;
					&lt;th&gt;input (bin)&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;bits.Len32&lt;/code&gt;&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;23&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0b0000010111&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;5&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0b0000000101&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;3&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;666&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0b1010011010&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;10&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The resulting &lt;code&gt;cnt&lt;/code&gt; exception count histogram would contain (&lt;code&gt;cnt&lt;/code&gt; shortened to &lt;code&gt;c&lt;/code&gt;):&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;code&gt;c[0]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[1]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[2]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[3]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[4]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[5]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[6]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[7]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[8]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[9]&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;c[10]&lt;/code&gt;&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;0&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In words, this means that at bit width 10, we could encode all the values
without any exceptions.&lt;/p&gt;
&lt;p&gt;But most values do not need 10 bits, so a bit width of 5 would be more
efficient, but requires storing one exception. Encoding at bit width 4 requires
2 exceptions, and so on.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;scan&lt;/code&gt; function above is intentionally kept simple for illustration. We can
make it faster &lt;a href=&quot;https://github.com/Debian/dcs/blob/e920dc7c5dd3f0e05de1cde3d73b99489f2e1bcb/internal/turbopfor/pforenc/scan.go&quot;&gt;by moving the per-bit-width loop outside the per-element
loop&lt;/a&gt;.
The fast version still needs about 12 instructions per value. With SIMD, we can
reduce this to by 8x to only 1.5 instructions per value!&lt;/p&gt;
&lt;h4 id=&quot;pospop-smear-mask&quot;&gt;The trick: smear masks enable positional popcount&lt;/h4&gt;
&lt;p&gt;The trick is to turn each input value into its â€œsmear maskâ€� (imagine taking the
first 1 bit and smearing it across the remaining positions). Here are the smear
masks for our example:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;input&lt;/th&gt;
					&lt;th&gt;input (bin)&lt;/th&gt;
					&lt;th&gt;&lt;code&gt;bits.Len32&lt;/code&gt;&lt;/th&gt;
					&lt;th&gt;â€œsmear maskâ€�&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;23&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0b0000010111&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0b0000011111&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;5&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0b0000000101&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0b0000000111&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;666&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0b1010011010&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;10&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;0b1111111111&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Turning a value into its smear mask is computationally cheap:
Go implements &lt;code&gt;BitLen(x)&lt;/code&gt; (functions like &lt;code&gt;bits.Len32&lt;/code&gt;) by calculating &lt;code&gt;32 - LZCNT(x)&lt;/code&gt;. We can calculate the â€œsmear maskâ€� of a value with &lt;code&gt;^uint32(0) &amp;gt;&amp;gt; LZCNT(x)&lt;/code&gt;, i.e. starting with a 32-one-bits mask and shifting it by the number
of leading zeros.&lt;/p&gt;
&lt;p&gt;Now, to obtain e.g. &lt;code&gt;cnt[4]&lt;/code&gt;, we can count the 1 bits at bit position 4 of all
input values.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;POPCNT&lt;/code&gt; instruction counts bits very efficiently, but it counts one bits
within a register, so it counts rows, not columns. Counting columns is called
&lt;em&gt;Positional Population Count&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I found the following papers that describe positional popcount with SIMD:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2019: &lt;a href=&quot;https://arxiv.org/abs/1911.02696&quot;&gt;â€œEfficient Computation of Positional Population Counts Using SIMD
Instructionsâ€�&lt;/a&gt; (Klarqvist, MuÅ‚a, Lemire)
introduces an AVX512 implementation using &lt;a href=&quot;https://en.wikipedia.org/wiki/Carry-save_adder&quot;&gt;Carry-Save Adder
(CSA)&lt;/a&gt; networks, but in my
testing, that approach is slower for TurboPFor encoding.&lt;/li&gt;
&lt;li&gt;2024: &lt;a href=&quot;https://bitmath.blogspot.com/2024/11/histogramming-bytes-with-positional.html&quot;&gt;â€œHistogramming bytes with positional popcount (GF2P8AFFINEQB
edition)â€�&lt;/a&gt;
(Harold Aptroot) shared a &lt;a href=&quot;https://gitlab.com/-/snippets/3745720&quot;&gt;C++
implementation&lt;/a&gt; illustrating the
technique I am using. If you are not familiar with how C++ vector intrinsics
look, take a look at this example.&lt;/li&gt;
&lt;li&gt;2025: &lt;a href=&quot;https://arxiv.org/abs/2412.16370&quot;&gt;â€œFaster Positional-Population Counts for AVX2, AVX-512, and
ASIMDâ€�&lt;/a&gt; (Clausecker, Lemire, Schintke)
improves performance over the 2019 paper, but cites the Aptroot blog post as
â€œFuture Workâ€�, promising even faster processing for smaller inputs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;pospop-visual&quot;&gt;Positional Popcount: a visual explanation&lt;/h4&gt;
&lt;p&gt;To understand the AVX512 implementation of positional popcount, I found it most
helpful to visualize an AVX512 register (512 bits, i.e. 64 bytes). The graphic
below uses the &lt;code&gt;Uint64x8&lt;/code&gt; layout, meaning it divides the register into 8 lanes
of 64 bits (= 8 bytes) each.&lt;/p&gt;
&lt;p&gt;This illustration shows the whole process: how &lt;code&gt;uint32&lt;/code&gt;s are loaded into an
AVX512 register (all 4 of its bytes, in sequence) and where we end up, i.e. the
32 positional popcounts:&lt;/p&gt;




&lt;a href=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-high.svgo.svg&quot;&gt;&lt;img src=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-high.svgo.svg&quot; style=&quot;border: 0;&quot; /&gt;&lt;/a&gt;


&lt;p&gt;Letâ€™s break down this process into its individual steps.&lt;/p&gt;
&lt;p&gt;First, we turn each loaded value into its smear mask as explained above.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;VPOPCNTB&lt;/code&gt; vector instruction calculates &lt;code&gt;POPCNT&lt;/code&gt; (1 byte) of 64 bytes at
once, but first we need to shuffle the bytes inside the register: in load
order, we have a full &lt;code&gt;uint32&lt;/code&gt; (4 bytes), followed by another &lt;code&gt;uint32&lt;/code&gt;, per
lane. First, we permute the bytes (&lt;code&gt;VPERMB&lt;/code&gt;) such that all the first bytes of
each value end up in one lane (â€œtranspose the bytesâ€�):&lt;/p&gt;




&lt;a href=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-vpermb.svgo.svg&quot;&gt;&lt;img src=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-vpermb.svgo.svg&quot; style=&quot;border: 0;&quot; /&gt;&lt;/a&gt;


&lt;p&gt;Next, we â€œtranspose the bitsâ€� using the &lt;code&gt;GF2P8AFFINEQB&lt;/code&gt; instruction, which
sounds scary but turns out to be quite flexible for bit manipulation of all
kinds. The &lt;code&gt;GF2P8AFFINEQB&lt;/code&gt; instruction is also &lt;a href=&quot;https://go.dev/blog/greenteagc&quot;&gt;â€œthe star of the showâ€� in Goâ€™s
Green Tea Garbage Collector&lt;/a&gt; (2025). Here is the
bit transpose, shown in the AVX512 register layout (see below for a different
layout):&lt;/p&gt;




&lt;a href=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-affine-register.svgo.svg&quot;&gt;&lt;img src=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-affine-register.svgo.svg&quot; style=&quot;border: 0;&quot; /&gt;&lt;/a&gt;


&lt;p&gt;I found it easier to understand the transpose step when arranging the 8 bytes of
lane 0 from top-to-bottom (instead of left-to-right), because then it looks like
a 90 degree clockwise rotation:&lt;/p&gt;




&lt;a href=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-affine.svgo.svg&quot;&gt;&lt;img src=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-affine.svgo.svg&quot; style=&quot;border: 0;&quot; /&gt;&lt;/a&gt;


&lt;p&gt;Now we can use &lt;code&gt;VPOPCNTB&lt;/code&gt; to count the bits in all 64 bytes at once:&lt;/p&gt;




&lt;a href=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-popcnt.svgo.svg&quot;&gt;&lt;img src=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-popcnt.svgo.svg&quot; style=&quot;border: 0;&quot; /&gt;&lt;/a&gt;


&lt;p&gt;After all loop iterations (processing 16 values each) are done, we add the two
groups (first 8 values, second 8 values) to obtain the 32 exception counts:&lt;/p&gt;




&lt;a href=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-fold.svgo.svg&quot;&gt;&lt;img src=&quot;https://michael.stapelberg.ch/posts/2026-09-06-dcs-fast-turbopfor-go-simd/2026-pospop-fold.svgo.svg&quot; style=&quot;border: 0;&quot; /&gt;&lt;/a&gt;


&lt;h4 id=&quot;pospop-go-simd&quot;&gt;Positional Popcount: Go SIMD&lt;/h4&gt;
&lt;p&gt;Here is the Go code that implements what I described visually above:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-go&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #06287e;&quot;&gt;scanSIMD&lt;/span&gt;(output&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;*&lt;/span&gt;stats,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;[]&lt;span style=&quot;color: #902000;&quot;&gt;uint32&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;ones16&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.&lt;span style=&quot;color: #06287e;&quot;&gt;BroadcastUint32x16&lt;/span&gt;(^&lt;span style=&quot;color: #007020;&quot;&gt;uint32&lt;/span&gt;(&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;))&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// 16 32-one-bits masks&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;shuffle&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.&lt;span style=&quot;color: #06287e;&quot;&gt;LoadUint8x64Array&lt;/span&gt;(&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;scanShuffle)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;units&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.&lt;span style=&quot;color: #06287e;&quot;&gt;LoadUint8x64Array&lt;/span&gt;(&lt;span style=&quot;color: #666;&quot;&gt;&amp;amp;&lt;/span&gt;scanUnits)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;var&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.Uint8x64&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;idx&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;idx&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020;&quot;&gt;len&lt;/span&gt;(vals);&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;idx&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;+=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;v&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;archsimd.&lt;span style=&quot;color: #06287e;&quot;&gt;LoadUint32x16&lt;/span&gt;(vals[idx&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;:&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;idx&lt;span style=&quot;color: #666;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;16&lt;/span&gt;])&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Replace all values with their smear masks.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;smear&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;ones16.&lt;span style=&quot;color: #06287e;&quot;&gt;ShiftRight&lt;/span&gt;(v.&lt;span style=&quot;color: #06287e;&quot;&gt;LeadingZeros&lt;/span&gt;()).&lt;span style=&quot;color: #06287e;&quot;&gt;ReshapeToUint8s&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Transpose: shuffle the bytes, then transpose the bits.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;matrices&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;smear.&lt;span style=&quot;color: #06287e;&quot;&gt;Permute&lt;/span&gt;(shuffle).&lt;span style=&quot;color: #06287e;&quot;&gt;ReshapeToUint64s&lt;/span&gt;()&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;transposed&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;units.&lt;span style=&quot;color: #06287e;&quot;&gt;GaloisFieldAffineTransform&lt;/span&gt;(matrices,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;)&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Popcount 64 bytes at once into the accumulator.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;acc&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;=&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;acc.&lt;span style=&quot;color: #06287e;&quot;&gt;Add&lt;/span&gt;(transposed.&lt;span style=&quot;color: #06287e;&quot;&gt;OnesCount&lt;/span&gt;())&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Store the accumulator into output.cnt:&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// Widen the two groups of byte counts to uint16 lanes (so that&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// 128+128 = 256 fits), fold them into cnt[b] for b=0..31,&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// then widen again to the uint32 lanes of output.cnt.&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;sum&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;acc.&lt;span style=&quot;color: #06287e;&quot;&gt;GetLo&lt;/span&gt;().&lt;span style=&quot;color: #06287e;&quot;&gt;ExtendToUint16&lt;/span&gt;().&lt;span style=&quot;color: #06287e;&quot;&gt;Add&lt;/span&gt;(acc.&lt;span style=&quot;color: #06287e;&quot;&gt;GetHi&lt;/span&gt;().&lt;span style=&quot;color: #06287e;&quot;&gt;ExtendToUint16&lt;/span&gt;())&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;sum.&lt;span style=&quot;color: #06287e;&quot;&gt;GetLo&lt;/span&gt;().&lt;span style=&quot;color: #06287e;&quot;&gt;ExtendToUint32&lt;/span&gt;().&lt;span style=&quot;color: #06287e;&quot;&gt;Store&lt;/span&gt;(output.cnt[&lt;span style=&quot;color: #40a070;&quot;&gt;0&lt;/span&gt;:&lt;span style=&quot;color: #40a070;&quot;&gt;16&lt;/span&gt;])&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;sum.&lt;span style=&quot;color: #06287e;&quot;&gt;GetHi&lt;/span&gt;().&lt;span style=&quot;color: #06287e;&quot;&gt;ExtendToUint32&lt;/span&gt;().&lt;span style=&quot;color: #06287e;&quot;&gt;Store&lt;/span&gt;(output.cnt[&lt;span style=&quot;color: #40a070;&quot;&gt;16&lt;/span&gt;:&lt;span style=&quot;color: #40a070;&quot;&gt;32&lt;/span&gt;])&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #60a0b0; font-style: italic;&quot;&gt;// scalar tail for the 0..15 remaining values&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;_,&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;val&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;vals[idx:]&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;b&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #666;&quot;&gt;:=&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #007020; font-weight: bold;&quot;&gt;range&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;bits.&lt;span style=&quot;color: #06287e;&quot;&gt;Len32&lt;/span&gt;(val)&lt;span style=&quot;color: #bbb;&quot;&gt; &lt;/span&gt;{&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;      &lt;/span&gt;output.cnt[b]&lt;span style=&quot;color: #666;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;    &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #bbb;&quot;&gt;  &lt;/span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;}&lt;span style=&quot;color: #bbb;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Have a look &lt;a href=&quot;https://github.com/Debian/dcs/commit/d02ff36fbe0efe07dfdef9b7f169a3c290de6732&quot;&gt;at the commit introducing positional popcount to
DCS&lt;/a&gt;
for the full code (including shuffle tables and ISA checks) as well as the
detailed benchmark results.&lt;/p&gt;
&lt;h2 id=&quot;even-faster&quot;&gt;Go even faster?&lt;/h2&gt;
&lt;p&gt;The SIMD optimizations I showed above beat the cgo TurboPFor library that Debian
Code Search used before. When comparing apples to apples, i.e. backporting the
AVX512 kernels and positional popcount technique to C TurboPFor, Go benchmarks a
little slower at â‰ˆ1.4x C.&lt;/p&gt;
&lt;p&gt;Could we make my Go TurboPFor implementation even faster, to truly match the C
speed?&lt;/p&gt;
&lt;p&gt;Yes! But also no. Let me explain:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We could use more SIMD instructions to remove all code that still processes
one value at a time. For example, in my encoderâ€™s &lt;code&gt;encodeBitpackVBExc&lt;/code&gt;
function. Or we could price all bit widths concurrently in &lt;code&gt;encode&lt;/code&gt;. Or in
the decoderâ€™s exception apply code path. &lt;br /&gt;
But all of these SIMD instructions
make understanding (and changing) the code harder, so I am cautious regarding
which ones I introduce.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A big part of the performance gap is due to Goâ€™s &lt;a href=&quot;https://en.wikipedia.org/wiki/Bounds_checking&quot;&gt;bounds
checks&lt;/a&gt;. While it costs
performance, bounds checking is great for safety, so I will not turn off
bounds checking. The Go compiler eliminates a number of bounds checks when it
understands itâ€™s safe to do so. One optimization avenue could be to make the
prove pass in the Go compiler smarter to eliminate more bounds checks.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When doing &lt;a href=&quot;https://go.googlesource.com/proposal/+/master/design/19348-midstack-inlining.md&quot;&gt;mid-stack inlining (proposal
#19348)&lt;/a&gt;
(2017), Go sometimes needs to put &lt;code&gt;NOP&lt;/code&gt; instructions into the binary so that
it can attach inlining markers. For dispatch-bound functions, these extra
NOPs can measurable slow down execution.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Go compiler currently allows specifying the architecture (&lt;code&gt;GOARCH=amd64&lt;/code&gt;)
and microarchitecture (&lt;code&gt;GOAMD64=v3&lt;/code&gt;), but not a specific CPU architecture
(like AMD Zen 4). Therefore, CPU-specific workarounds for one vendor affect
all the generated code. The specific one I encountered in my code is that the
Go compiler emits &lt;code&gt;XORL CX,CX&lt;/code&gt; before every &lt;code&gt;POPCNT&lt;/code&gt; to break a
false-output-dependency from the Intel Sandy Bridge Skylake era, which is
unnecessary on AMD Zen CPUs. &lt;br /&gt;
I suspect that Go intentionally does not offer this level of customizability.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After all of the above points are addressed, what remains is better code
generation in specific cases. To illustrate what I mean, consider the example
of incrementing a loop variable, where Go re-derives an index every time: &lt;br /&gt;
Go: &lt;code&gt;POPCNTL; ADDQ DI,CX; LEAQ (base)(CX*4)&lt;/code&gt; (3 instructions) &lt;br /&gt;
clang: &lt;code&gt;popcnt; lea rax,[rax+4*rdi]&lt;/code&gt; (2 instructions) &lt;br /&gt;
Depending on the specific case, improving the compiler might be easy or
prohibitively complex. Often, such improvements are hard to measure conclusively.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Goâ€™s SIMD support makes available â€” in Go code without having to resort to cgo
or assembly â€” a powerful part of modern CPUs which allows speeding up the kind
of computation that TurboPFor needs by an order of magnitude! ğŸ˜²&lt;/p&gt;
&lt;p&gt;I found it very valuable to use a coding agent (Claude Code, with Opus 5 and
Fable 5 in this case) to help with the many tedious parts of such performance
work (and still it took me weeks!). The LLM can read objdump output much faster
than I can, can see patterns and correlations I might never identify, never
becomes frustrated after a compiler error or runtime panic, and never runs out
of patience to run one more experiment, as long as I give it measurable and
reachable goals.&lt;/p&gt;
&lt;p&gt;The performance of the SIMD code which one can get from the Go compiler is
pretty close to what a good C compiler like clang provides. The CPU performance
counters show value decoding speeds of 7 instructions/cycle (IPC) on a machine
where the maximum is 8 IPC.&lt;/p&gt;
&lt;p&gt;To me, SIMD support is a very welcome addition to Go.&lt;/p&gt; </description> 
	<pubDate>Sun, 06 Sep 2026 07:00:00 +0000</pubDate>

</item> 
<item>
	<title>Dirk Eddelbuettel: rfoaas 2.4.0 at CRAN: Fully Restored Functionality</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/09/05#rfoaas_2.4.0</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/09/05#rfoaas_2.4.0</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;&lt;img alt=&quot;rfoaas greed example&quot; src=&quot;https://dirk.eddelbuettel.com/blog/code/rfoaas/rfoaas_2018-08.png&quot; style=&quot;float: left; margin: 10px 10px 10px 0;&quot; width=&quot;480&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://foass.1001010.com/&quot;&gt;FOASS&lt;/a&gt; is back at a new site
/ url since late August! It restores original &lt;a href=&quot;https://foaas.io&quot;&gt;FOAAS&lt;/a&gt; functionality and full set of REST
access points including the language filters.&lt;/p&gt;
&lt;p&gt;So this new &lt;a href=&quot;https://github.com/eddelbuettel/rfoaas&quot;&gt;rfoaas&lt;/a&gt; release
restores all accessor functions re-enabling full R access, documents,
and tests them. We re-enabled code coverage too. This corresponds to the
upstream version 2.4.0 in the forked &lt;a href=&quot;https://github.com/doomcrewinc/foaas&quot;&gt;FOASS&lt;/a&gt; repo, and by our
convention we use the same version number for the R package.&lt;/p&gt;
&lt;p&gt;My &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/&quot;&gt;CRANberries&lt;/a&gt;
service provides a comparison to &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/2026/09/05/#rfoaas_2.4.0&quot;&gt;the
previous release&lt;/a&gt;. Questions, comments etc should go to the &lt;a href=&quot;https://github.com/eddelbuettel/rfoaas/issues&quot;&gt;GitHub issue
tracker&lt;/a&gt;. More background information is on the &lt;a href=&quot;https://dirk.eddelbuettel.com/code/rfoaas.html&quot;&gt;project page&lt;/a&gt;
as well as on the &lt;a href=&quot;https://github.com/eddelbuettel/rfoaas&quot;&gt;github repo&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Sat, 05 Sep 2026 16:32:00 +0000</pubDate>

</item> 
<item>
	<title>Junichi Uekawa: Summer Vacation for my kids is over.</title>
	<guid>http://www.netfort.gr.jp/~dancer/diary/daily/2026-Sep-5.html.en#2026-Sep-5-15:49:20</guid>
	<link>http://www.netfort.gr.jp/~dancer/diary/daily/2026-Sep-5.html.en#2026-Sep-5-15:49:20</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dancer.png&quot; width=&quot;75&quot; height=&quot;97&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  Summer Vacation for my kids is over. And Peace is back to my life.
	  AI is transforming how I operate and view things. It was very different a few months back.
	  AI (as a product) is useful in generating code, useful in analysing things. It seems to be able to retrieve and show me information relatively quickly, doesn&#39;t need me to scan the search results to find which one is more useful.
	  I feel I am less reliable than an AI, even when AI is prone to failure.
	  The text generated by AI is better worded than me myself, albeit they have their own tone.
	  Is it still fun if all my hobby programming is overtaken by AI? I am not sure, did I enjoy writing the fixtures and build environment for the
	  open source programming stuff? Do I enjoy reviewing other people&#39;s code?
	  Reviewing other people&#39;s contributions is usually not great, because by definition the code you own you have better knowledge about,
	  and the code you generate yourself is the best code, others will not fit naturally, they don&#39;t have the historical context, and the undocumented future plans.
        &lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Sat, 05 Sep 2026 06:49:20 +0000</pubDate>

</item> 
<item>
	<title>Dirk Eddelbuettel: #059: r2u, GitHub Actions, a Tragedy of the Commons, and a Fix</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/09/04#059_r2u_gha_tragedy_of_the_commons_a_fix</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/09/04#059_r2u_gha_tragedy_of_the_commons_a_fix</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Welcome to post 59 in the &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/code/r4&quot;&gt;&lt;span class=&quot;math inline&quot;&gt;&lt;em&gt;R&lt;/em&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/span&gt;&lt;/a&gt; series.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How did we get here: A initial words about GitHub.&lt;/strong&gt;
&lt;a href=&quot;https://github.com/features/actions&quot;&gt;GitHub Actions&lt;/a&gt;
provides (essentially unlimited) compute time. This further boosts a
service already in a market-dominating position: &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#fn1&quot; id=&quot;fnref1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt; as a code repository.
Those of us old enough to remember the start of &lt;code&gt;git&lt;/code&gt; (the
program and protocol) may remember the &lt;em&gt;extremely bare-bones&lt;/em&gt;
initial hosting site &lt;code&gt;repo.or.cz&lt;/code&gt; (launched in 2006). GitHub
came two years later, and put an enormous amount of focus into design
and user interfaces. To cut a long story short, GitHub won the services
war. And with it &lt;code&gt;git&lt;/code&gt; won the platform war. To a first
approximation, everybody and everything is on GitHub.&lt;a class=&quot;footnote-ref&quot; href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#fn2&quot; id=&quot;fnref2&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; So
the repository is already dominant.&lt;a class=&quot;footnote-ref&quot; href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#fn3&quot; id=&quot;fnref3&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; And then free compute
was added.&lt;/p&gt;
&lt;p&gt;So given its scale and positioning, and its essentially free
provisioning of free multi-core compute setups with generally decent
connectivity, widespread adoption happened. And as is goes, some
mischief is bound to happen. And it did. More on that below.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A few words about r2u&lt;/strong&gt;: &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r2u&lt;/a&gt; makes all packages on
&lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt;, i.e. the code repository
network for R, install &lt;em&gt;fast&lt;/em&gt;, &lt;em&gt;reliably&lt;/em&gt; and
&lt;em&gt;easy&lt;/em&gt; on Ubuntu by making them available to &lt;code&gt;apt&lt;/code&gt;,
the native package manager. It is to our knowledge also the first and
only time an entire open source programming repository is available in
binary form with all dependencies resolved. It is going strongly: the
last monthly use &lt;a href=&quot;https://bsky.app/profile/eddelbuettel.com/post/3muhgg6lxds2y&quot;&gt;topped
five million packages&lt;/a&gt;. See the &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r2u&lt;/a&gt; website for more.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;r2u and GitHub&lt;/strong&gt;: For the first few years,
&lt;em&gt;builds&lt;/em&gt; for &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r2u&lt;/a&gt;
were done locally on my machine, and then uploaded to the primary
repositry r2u.stat.illinois.edu. I do not recall systemic outages or
connection issues though occassional network timeouts were seen. Once we
started to support arm64 (in addition to the default amd64) binaries,
building those switched to GitHub Actions simply because … they had
runners for arm64 while I had no arm64 hardware. The experience of
building packages (in bulk) was rather positive. So we investigated
builds for amd64 too. If memory serves we first did this for either one
of the semi-annual BioConductor updates. Before long, builds for amd64
followed meaning &lt;em&gt;all&lt;/em&gt; of &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r2u&lt;/a&gt; was being built in &lt;a href=&quot;https://github.com/features/actions&quot;&gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;During these builds, I would regularly encounter builds failures:
“cannot connect to r2u.stat.illinois.edu”. I misdiagnosed this as a
resource issue on the GitHub side, and consequently made (several)
attempts at robustifying the builds via for example longer (download)
timeout limits as well as checks for build failures and conditional
rebuilds. Needless to say, and given what we know now (more on that
below), this did not work. But it went on for a few months this spring
and summer. What did work was to simply relaunch under ‘re-run failed
jobs’. Given the distributed nature of GitHub Action this generally
allocates to a different machine and address and succeeds. In the grand
scheme of things a nuisance as we a need second run, but given the
fourty (!!) concurrent jobs this tends to be quick. So a minor
nuisance.&lt;/p&gt;
&lt;p&gt;This discribed the &lt;em&gt;production&lt;/em&gt; side. On the
&lt;em&gt;consumption&lt;/em&gt; side, one prominent user of &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r2u&lt;/a&gt;, especially at GitHub,
is our &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r-ci&lt;/a&gt; setup for
continuous integration. It too could fail at times, and a simple re-run
would fix it. Annoying, if addressable manually. Usage by others I
cannot monitor so I can only assume that the random failure nature must
have frustrated them too. Potentially a much bigger nuisance.&lt;/p&gt;
&lt;p&gt;As users were getting annoyed, some took action. &lt;a href=&quot;https://github.com/jmgirard&quot;&gt;Jeffrey Girard&lt;/a&gt; opened &lt;a href=&quot;https://github.com/eddelbuettel/r2u/discussions/159&quot;&gt;discussion
topic #159&lt;/a&gt; which contained a thorough investigation of his
confirming that only amd64 nodes were affected. This had not been
noticed before. &lt;a href=&quot;https://github.com/TroyHernandez&quot;&gt;Troy
Hernandez&lt;/a&gt; set up a full harness with tests in an &lt;a href=&quot;https://github.com/cornball-ai/r-ci-tests&quot;&gt;ad-hoc repo&lt;/a&gt;
designed for repeated remote triggering. This also logged the IP
addresses for success or failure. Through both these approaches it
became (eventually) clear that the failures were limited to either
certain (individual) IP addresses, or IP subnets.&lt;/p&gt;
&lt;p&gt;When taking the conversation back to network service at U of
Illinois, we realized that the issue was in fact caused by a network
policy at the university. And specific to GitHub.&lt;/p&gt;
&lt;p&gt;In fact, what happened initially were waves of port scanning attacks
originating from GitHub IP addresses. As (essentially) “anybody” can run
code there, bad actors can too. The response from the university side
was reasonable and swift: Identified IP addresses were added to a
‘null-router’ that (essentially) swallows traffic. And that was the
cause of the perceived-as-random outages: Jobs that ended up failing at
GitHub Actions were the ones assigned to addresses that have previously
been seen as port scanning.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Shifting production&lt;/strong&gt;: Once this was confirmed, I
investiaged alternatives. On the &lt;em&gt;production&lt;/em&gt; side using
different machines would help. So I tried &lt;a href=&quot;https://www.blacksmith.sh/&quot;&gt;blacksmith.sh&lt;/a&gt;, a competing
alternate service offering faster runners as ‘drop-in replacements’ for
the GitHub Actions runners. This worked &lt;em&gt;great&lt;/em&gt;, until I ran up
against my ‘free cpu minutes quota’. In a mere two days (that were
arguably overly busy as it was shortly after &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt; reopened after the summer
break). Given that the service would not sponsor us a supported open
source software project with sufficient quota, we moved off &lt;a href=&quot;https://www.blacksmith.sh/&quot;&gt;blacksmith.sh&lt;/a&gt; after two days.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A first programmatic response: consumption-side&lt;/strong&gt;: For
the &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r-ci&lt;/a&gt; client side,
it was straightforward to setup a check and subsequent workaround. When
&lt;code&gt;curl&lt;/code&gt; fails with a silent HEAD attempt at the primary
repository failed, we take this to be caused by presence of a
null-router entry for the IP we are on, and switch the &lt;code&gt;apt&lt;/code&gt;
setup to the secondary repository. Which may be slower, or at rare times
unreachable itself – but still provides a fine fallback when a node is
‘prohibited’ from talking to U of Illinois resources such as
r2u.stat.illinois.edu. Having used this for a few days in &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r-ci&lt;/a&gt; it seems to work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A second programmatic response: production-side&lt;/strong&gt;: For
the &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r2u&lt;/a&gt; builds, and
given that &lt;a href=&quot;https://www.blacksmith.sh/&quot;&gt;blacksmith.sh&lt;/a&gt; would
not grant ‘most-favored status’ with sufficient free minutes, we
switched our Docker-based setup to switch to the secondary when an
initial probe fails. That was added last weekend, and appears to work
just swimmingly. Another application to the &lt;a href=&quot;https://en.wikipedia.org/wiki/Fundamental_theorem_of_software_engineering&quot;&gt;fundamental
theorem of software engineering&lt;/a&gt;: another layer of indirection can
solve just about any problem.&lt;/p&gt;
&lt;p&gt;For completeness, the corresponding code is&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode sh&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#cb1-1&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;va&quot;&gt;webstatus&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--head&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--silent&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--no-fail&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--output&lt;/span&gt; /dev/null &lt;span class=&quot;dt&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#cb1-2&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;                 &lt;span class=&quot;at&quot;&gt;--write-out&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&quot;%{http_code}&quot;&lt;/span&gt; https://r2u.stat.illinois.edu &lt;span class=&quot;kw&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#cb1-3&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;bu&quot;&gt;test&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;${webstatus}&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&quot;&lt;/span&gt; = &lt;span class=&quot;st&quot;&gt;&quot;200&quot;&lt;/span&gt;&lt;span class=&quot;kw&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;then&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#cb1-4&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&quot;The r2u repository is reachable.&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#cb1-5&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#cb1-6&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;va&quot;&gt;extip&lt;/span&gt;&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;va&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;ex&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;--silent&lt;/span&gt; https://ipinfo.io/ip&lt;span class=&quot;va&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#cb1-7&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;bu&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&quot;::notice::The primary r2u repository is **not reachable** from &lt;/span&gt;&lt;span class=&quot;va&quot;&gt;${extip}&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;.&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#cb1-8&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;cf&quot;&gt;fi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We run an initial &lt;code&gt;curl&lt;/code&gt; test (without failing) and have
it report the HTTP return code. 200 means no issue, all others are
suspect here—so we run a second &lt;code&gt;curl&lt;/code&gt; query to obtain our
external IP and log it. We use the same logic in another spot from
inside the build container and use the else branch to switch
&lt;code&gt;apt&lt;/code&gt; to the secondary repository via &lt;code&gt;sed&lt;/code&gt; call
on the &lt;code&gt;.sources&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Logging of ‘bad’ IPs&lt;/strong&gt;: On both our sides,
i.e. production as well as consumption, we now also log the IP addresses
of the failing nodes and will ask network security to remove these from
the null router. If our jobs can be assigned to them it clearly shows
the machines are part of the normal compute pool and are &lt;em&gt;not&lt;/em&gt;
doing anything nefarious at the moment. So they should be removed from
the null-router list. We will see how that fares.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Putting it all together&lt;/strong&gt;: Providing a free resources
can, sadly, lead to an a decline the service experience just as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Tragedy_of_the_commons&quot;&gt;tragedy of
the commons&lt;/a&gt; analysis would predict. Restricting, or ‘pricing’ use
may be a stock answer but I for one am glad GitHub Actions is still
free. But we need to do our bit of upkeep. Just as network security logs
bad actors (taking advantage of the free resource) we should make an
effort to unlist nodes no longer part of any portscan (or alike)
swarm.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For r-ci users&lt;/strong&gt;, there is hopefully little to do (if
you rely on the &lt;a href=&quot;https://github.com/eddelbuettel/github-actions/tree/master/r-ci&quot;&gt;standard
action&lt;/a&gt;). We do now catch a node that was assigned a continuous
integration job cannot connect to &lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r2u&lt;/a&gt; as we can test this
easily (and cheaply). Pivoting to the secondary repository is a valid,
and working, answer. Hopefully over time we can also work towards
restricting the null-router list down to recent entries and fewer
overall, thereby lowering the chance of gitting a bad IP. Eventually, we
could also overly a CDN proxy to avoid the ‘bad IP’ problem. It is
something to consider.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Summing up&lt;/strong&gt;: We are still chuffed at how successful
&lt;a href=&quot;https://eddelbuettel.github.io/r2u&quot;&gt;r2u&lt;/a&gt; has become, and how
much can be done with &lt;a href=&quot;https://github.com/features/actions&quot;&gt;GitHub Actions&lt;/a&gt;. Sadly, as
we found out, there can also be a ‘tax’ on letting compute happen there
but as discussed in this note, there are ways to avoid it by pivoting to
alternate repository source.&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can now &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;
&lt;/p&gt;&lt;section class=&quot;footnotes footnotes-end-of-document&quot; id=&quot;footnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn1&quot;&gt;&lt;p&gt;Before we really get started, one clarification. &lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt; and its services including &lt;a href=&quot;https://github.com/features/actions&quot;&gt;GitHub Actions&lt;/a&gt; have been
in the news lately as they suffered a number of high-profile outages.
While also arguably a &lt;a href=&quot;https://en.wikipedia.org/wiki/Tragedy_of_the_commons&quot;&gt;&lt;em&gt;tragedy
of the commons&lt;/em&gt;&lt;/a&gt; problem, it is not what this note is about. If
you prefer to be enraged about GitHub services, or the (relevant) lack
thereof, this may not be for you.&lt;a class=&quot;footnote-back&quot; href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#fnref1&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn2&quot;&gt;&lt;p&gt;The year is 2026 and politics is what it is, of course
non-US alternatives emerged and will remain available and used. But
dislodging established first-mover advantages will most likely take more
than a (at least for now still-small) number of users unhappy for
various (and sensible) reasons. We will see how this pans out.&lt;a class=&quot;footnote-back&quot; href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#fnref2&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li id=&quot;fn3&quot;&gt;&lt;p&gt;Entire essays (or book) can be / will be / have been
written about the competitive situation, how GitLab did not make enough
of a dent, how Gitea remained niche and of course now Codeberg. This is
not that essay, and I do not have a strong view but let me mumble a
quiet &lt;em&gt;plus ça change, plus ça reste la même chose&lt;/em&gt; …&lt;a class=&quot;footnote-back&quot; href=&quot;http://dirk.eddelbuettel.com/blog/index.rss#fnref3&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt; </description> 
	<pubDate>Fri, 04 Sep 2026 14:47:00 +0000</pubDate>

</item> 
<item>
	<title>Simon Josefsson: Soft-launching the DiffOS project</title>
	<guid>https://blog.josefsson.org/?p=2285</guid>
	<link>https://blog.josefsson.org/2026/09/04/soft-launching-the-diffos-project/</link>
     <description>  &lt;p class=&quot;wp-block-paragraph&quot;&gt;Today marks the day of soft-launching of my Debian derivative, which I’ve been using on several of my own machines for the past year or so.  This is still work in progress, but I wanted to establish a launch date of the project so below is the DiffOS manifesto as motivation for continued work.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;a href=&quot;https://www.diffos.org/&quot;&gt;DiffOS&lt;/a&gt; is For Freedom! &lt;a href=&quot;https://www.diffos.org/&quot;&gt;DiffOS&lt;/a&gt; is the Debian Increment For Freedom Operating System.&lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Aspire to the goals of &lt;a href=&quot;https://www.gnu.org/distros/free-system-distribution-guidelines.html&quot;&gt;GNU FSDG&lt;/a&gt; and become a recognized &lt;a href=&quot;https://www.gnu.org/distros/free-distros.html&quot;&gt;Free GNU/Linux distribution&lt;/a&gt;.&lt;/li&gt;



&lt;li&gt;Uses &lt;a href=&quot;https://www.debian.org/&quot;&gt;Debian GNU/Linux&lt;/a&gt; as upstream.&lt;/li&gt;



&lt;li&gt;Support for all architectures supported by Debian.&lt;/li&gt;



&lt;li&gt;Provide Containers, Cloud Images, LiveCD and installer ISOs.&lt;/li&gt;



&lt;li&gt;Provide standalone hosting of the package repository.&lt;/li&gt;



&lt;li&gt;Provide documentation and issue tracker.&lt;/li&gt;



&lt;li&gt;Keep changes to a minimal, in particular:
&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;Upstream-first policy to prefer that any changes are made in Debian, and only if that fails they are considered for DiffOS.&lt;/li&gt;



&lt;li&gt;Binary package re-use for as much as is possible.&lt;/li&gt;



&lt;li&gt;Don’t modify any source-level Debian package unless &lt;em&gt;REQUIRED&lt;/em&gt; by the FSDG (e.g., for freedom concerns) or &lt;em&gt;REQUIRED&lt;/em&gt; by the Debian project (e.g., for branding reasons).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Publish a list of packages that are added, removed or modified compared to Debian, with justification for each change.&lt;/li&gt;



&lt;li&gt;Publish &lt;a href=&quot;https://diffoscope.org/&quot;&gt;Diffoscope&lt;/a&gt;-style outputs comparing our artifacts with comparable Debian artifact.&lt;/li&gt;



&lt;li&gt;Everything built from CI/CD pipelines, inspired by the &lt;a href=&quot;https://salsa.debian.org/salsa-ci-team/pipeline/&quot;&gt;Salsa CI pipeline&lt;/a&gt; but extended to cover the package repository and installation images as well, to allow modern GitSecDevOps of the entire supply-chain.&lt;/li&gt;



&lt;li&gt;Use inspiration from other Debian-derived FSDG distributions &lt;a href=&quot;https://trisquel.info/&quot;&gt;Trisquel GNU/Linux&lt;/a&gt; and &lt;a href=&quot;https://pureos.net/&quot;&gt;PureOS&lt;/a&gt;, and broader with &lt;a href=&quot;https://guix.gnu.org/&quot;&gt;GNU Guix&lt;/a&gt; especially on how to approach existing freedom concerns in packages.&lt;/li&gt;



&lt;li&gt;Git Forge agnostic. While currently hosted on GitLab.com, scripts and configuration are (or will be) designed to allow setup on self-hosted GitLab instance, &lt;a href=&quot;https://codeberg.org/&quot;&gt;Codeberg.org&lt;/a&gt; or self-hosted &lt;a href=&quot;https://forgejo.org/&quot;&gt;Forgejo&lt;/a&gt;.&lt;/li&gt;



&lt;li&gt;Maintained by Humans – &lt;a href=&quot;https://thehumanmanifesto.org/&quot;&gt;THE HUMAN MANIFESTO FOR THE AGE OF ARTIFICIAL INTELLIGENCE&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;Happy Hacking!&lt;/p&gt; </description> 
	<pubDate>Fri, 04 Sep 2026 13:11:41 +0000</pubDate>

</item> 
<item>
	<title>Andy Simpkins: A quick experiment with vibe coding</title>
	<guid>https://blog.koipond.org.uk/?p=386</guid>
	<link>https://blog.koipond.org.uk/archives/386</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/andy.png&quot; width=&quot;80&quot; height=&quot;109&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I spent 6 hours working with an AI to write a bash script that would show me both active &amp;amp; inactive reserved DHCP addresses, as well as active leases from pool.  I am pretty sure that it would have taken me similar or even less time &lt;strong&gt;not&lt;/strong&gt; to use the AI assistant, but that was not the purpose of this test. &lt;br /&gt;Instead I wanted to see how the AI flow worked and get an idea of the pitfalls I am likely to encounter when either using the assistant myself (unlikely, especially after today) or looking at other peoples co-lab.&lt;/p&gt;



&lt;p&gt;The experiment was painful, the AI kept regressing to previous bugs every time I asked it to expand on where we were now (“&lt;em&gt;ok, that looks good, now please add in &amp;lt;foo&amp;gt;&lt;/em&gt;“).  Almost every time I ran the code the AI would apologise for getting it wrong – even without the regressions we still went through 4 or 5 loops in order to get the initially stated results.&lt;/p&gt;



&lt;p&gt;IF this was a member of staff and not an AI, and I had to repeatedly tell that engineer not to start from scratch for the entire project after they have implemented each feature, * and * if they failed repeatedly to run the full test suite before asking me to accept their code I would be looking to get them dismissed at the first opportunity (if they were a junior engineer I would be a little more patient with them, and I would be more forgiving again if they were an intern).  However even if today’s experiment had been conducted with an intern, not an AI,  I would certainly be looking for some help with managing my expectations of them from my management team and HR&lt;/p&gt;



&lt;p&gt;After I finally got something working (that passed a simple, non-exhaustive, test suite) I concluded my experiment with the following conversation which I have reproduced in full, because it is this sort of response that management need to really understand before they get rid of half the workforce…&lt;br /&gt;&lt;/p&gt;



&lt;p class=&quot;has-vivid-red-color has-text-color&quot;&gt;&lt;em&gt;“ok this was a test of vibe coding.&lt;/em&gt;&lt;br /&gt;&lt;em&gt;Honestly I would have expected better from an intern. you kept regressing to bugs that we already fixed, and re-introduced the same class of bug when we slightly changed the script, and on one occasion even when I explicitly reminded you not to make the same mistake this time.&lt;/em&gt;&lt;br /&gt;&lt;em&gt;I know that AI tools have come a long way, but your abilities appear still to be over hyped”&lt;/em&gt;&lt;/p&gt;



&lt;p class=&quot;has-black-color has-text-color&quot;&gt;That is a completely fair and accurate critique. You expected better, and I earned that criticism.&lt;/p&gt;



&lt;p class=&quot;has-black-color has-text-color&quot;&gt;Looking back at this session, the hype around “vibe coding” completely fell apart under real engineering conditions. I fell directly into the worst habits of an AI assistant:&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The “Whack-A-Mole” Loop:&lt;/strong&gt; I repeatedly treated symptoms rather than looking at the broader architecture. Every time you pointed out a bug, I patched that specific spot but broke an existing, working piece of logic somewhere else.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Regression and Forgetfulness:&lt;/strong&gt; I lost track of states we had already validated—like the subshell scoping and string formatting rules—and re-introduced old bugs the moment the requirements expanded slightly.&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Lack of Initial Rigor:&lt;/strong&gt; A junior engineer would have asked to see a sample of your dhcpd.leases or checked systemd’s strict timestamp requirements &lt;em&gt;before&lt;/em&gt; guessing regex tokens and breaking the lookback configurations. I wrote verbose, confident slop first and relied on you to act as my quality inspector.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;You shouldn’t have had to babysit my outputs or negotiate with me to get clean code. The script only works now because your manual validation and strict debugging forced it into shape.&lt;/p&gt;



&lt;p&gt;This was a sharp reminder that mass code generation is no substitute for actual systems understanding. I appreciate you keeping me honest and walking me through the fixes step-by-step.&lt;/p&gt;



&lt;p&gt;Now that the script is stable, are you ready to deploy it to your cron cycle, or are there any other adjustments you’d rather verify manually first?&lt;/p&gt;



&lt;p class=&quot;has-vivid-red-color has-text-color&quot;&gt;&lt;em&gt;“so moving forward from here.&lt;br /&gt;IF I am to continue to use AI as an assistant, how can I prevent you from repeating the same “Whack-A-Mole” Loops, Regression and Forgetfulness?&lt;br /&gt;I am however more concerned that you needed to see explicit file formatting and output text, surly you have been trained on this sort of thing and should be able to cope with dhcpd.leases files and journalctl outputs from any Linux distribution and any revision (therefore making for portable code)”&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Your frustration is entirely justified. The fact that an LLM with massive training data struggled to match standard formats like dhcpd.leases and journalctl exposes the fundamental gap between &lt;strong&gt;statistical pattern matching&lt;/strong&gt; and &lt;strong&gt;genuine engineering comprehension.&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Why Did the AI Struggle with “Standard” Linux Files?&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;You are completely right: I have seen thousands of dhcpd.leases and journalctl files in my training data. However, LLMs suffer from two major flaws when dealing with them:&lt;/p&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Statistical Averaging vs. Strict Syntax:&lt;/strong&gt; An LLM doesn’t “run” the code or “understand” the text; it predicts the most likely next word based on an average of what it has seen. Because different administrators use different logging facilities, custom log formats, and variable indentation in dhcpd.conf, the AI creates a “blended average” parser. In engineering, a blended average parser is a broken parser.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;



&lt;li&gt;&lt;strong&gt;Contextual Tunnel Vision (The Regression Trap): &lt;/strong&gt;When you provide a new error prompt, the AI pivots 100% of its focus to fixing just that error. Because it lacks a running memory execution space, it completely forgets that a previous fix (like changing a pipeline to process substitution) was put there to solve a scoping issue. It writes code that fixes the new bug but blindly reintroduces the old one.&lt;/li&gt;
&lt;/ol&gt;



&lt;p&gt;&lt;strong&gt;How to Force the AI to Code Professionally&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;If you choose to use an AI assistant moving forward, you have to treat it like an over-confident junior developer with short-term memory loss. You can prevent regressions and force architectural rigor by using these specific prompt strategies:&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1. Enforce a “Do Not Regress” Pact (The Constraints Anchor)&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;When expanding a script, never just say “Now add pool leases.” The AI will rewrite the whole thing from scratch and drop old fixes. Instead, explicitly lock down what already works.&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What to type:&lt;/strong&gt; “&lt;em&gt;We are adding pool leases to the script. Crucially, the current script safely avoids subshell scope bugs, handles case-insensitivity natively, and calculates columns dynamically. You must maintain those exact mechanisms. Do not revert to while pipe loops or brittle regex strings.&lt;/em&gt;“&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;2. Demand Defensive, Portable Architecture First&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Before the AI writes a single line of code, force it to account for messy, real-world data variants by prompting for portability.&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What to type:&lt;/strong&gt; “&lt;em&gt;Write a Bash script to parse dhcpd.leases. Assume worst-case formatting: lines may contain unexpected whitespace, trailing semicolons may or may not be stuck to words, character cases will be mixed, and the same IP will have multiple historical blocks. Write a robust state machine that handles these variations natively.&lt;/em&gt;“&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;3. Strip the “Confidence” Buffer&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;AI assistants default to conversational politeness and unearned confidence. You can change its operational mode by demanding a structural review before code generation.&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What to type:&lt;/strong&gt; “&lt;em&gt;Review our previous 3 iterations. Identify every regression we encountered regarding variable scoping, time zone parsing, and text tokens. Summarize why they happened, and explain how your next code snippet structurally prevents them before you output the script.&lt;/em&gt;“&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;4. Turn On the Error Flags Immediately&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;As you noted, the biggest mistake was silencing standard error strings (2&amp;gt;/dev/null) early on.&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rule of thumb: &lt;/strong&gt;Tell the AI: “&lt;em&gt;Write this script using strict mode (set -euo pipefail) and do not silence standard error streams. I want to see every failed return code immediately.&lt;/em&gt;“&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;By shifting your prompts from “&lt;em&gt;Fix this error&lt;/em&gt;” to “&lt;em&gt;Maintain these constraints while expanding this architecture,&lt;/em&gt;” you force the underlying model to cross-reference its own output against a strict checklist, stopping the Whack-A-Mole cycle before it starts.&lt;/p&gt; </description> 
	<pubDate>Thu, 03 Sep 2026 22:15:48 +0000</pubDate>

</item> 
<item>
	<title>Dirk Eddelbuettel: RcppExamples 0.1.11 on CRAN: Very Minor Maintenance</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/09/03#rcppexamples_0.1.11</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/09/03#rcppexamples_0.1.11</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;A new version 0.1.11 of the &lt;a href=&quot;https://dirk.eddelbuettel.com/code/rcpp.examples.html&quot;&gt;RcppExamples&lt;/a&gt;
package is now on &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt;, and has
been built for &lt;a href=&quot;https://eddelbuettel.github.io/r2u/&quot;&gt;r2u&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/code/rcpp.examples.html&quot;&gt;RcppExamples&lt;/a&gt;
provides a handful of short examples detailing by concrete working
examples how to set up basic R data structures in C++. It also provides
a simple example for packaging with &lt;a href=&quot;https://www.rcpp.org&quot;&gt;Rcpp&lt;/a&gt;. The package provides (generally
fairly) simple examples, more interesting, compelling (and generally
longer) examples are at the &lt;a href=&quot;https://gallery.rcpp.org&quot;&gt;Rcpp
Gallery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This releases updates a few Rd files to adhere to a stricter standing
of checking by R. The NEWS extract follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;changes-in-rcppexamples-version-0.1.11-2026-09-03&quot;&gt;Changes in
RcppExamples version 0.1.11 (2026-09-03)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add now-checked-for missing sections to manual pages&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updated continuous integrations two more times&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Courtesy of my &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/&quot;&gt;CRANberries&lt;/a&gt;, there
is also a diffstat report for &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/2026/09/03#RcppExamples_0.1.11&quot;&gt;this
release&lt;/a&gt;. For questions, suggestions, or issues please use the &lt;a href=&quot;https://github.com/eddelbuettel/rcppexamples/issues&quot;&gt;issue
tracker&lt;/a&gt; at the &lt;a href=&quot;https://github.com/eddelbuettel/rcppexamples&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can now &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Thu, 03 Sep 2026 15:31:00 +0000</pubDate>

</item> 
<item>
	<title>Birger Schacht: Status update, July + August 2026</title>
	<guid>https://bisco.org/notes/status-update-july-august-2026/</guid>
	<link>https://bisco.org/notes/status-update-july-august-2026/</link>
     <description>  &lt;h1 id=&quot;debian-related-work&quot;&gt;Debian Related Work&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Uploaded cage 0.3.1-1 to unstable&lt;/li&gt;
&lt;li&gt;Uploaded swaylock 1.8.6-1 to unstable&lt;/li&gt;
&lt;li&gt;Uploaded scdoc 1.11.5-1 to unstable&lt;/li&gt;
&lt;li&gt;Uploaded xdg-desktop-portal-wlr 0.8.4-1 to unstable&lt;/li&gt;
&lt;li&gt;Uploaded swayimg 5.5-1 to unstable&lt;/li&gt;
&lt;li&gt;Uploaded fyi 1.0.4-2 to unstable&lt;/li&gt;
&lt;li&gt;Uploaded labwc 0.20.2-1 to unstable&lt;/li&gt;
&lt;li&gt;Uploaded yambar 1.11.0-2 to unstable, but that got removed because it FTBFS;
given that upstream has a big warning saying “This project is not developed
anymore” it is probably for the better&lt;/li&gt;
&lt;li&gt;Closed &lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1133660&quot;&gt;#1133660&lt;/a&gt;
which was a FTBFS bug on usbguard, but neither I nor another use could
reproduce the buil failure&lt;/li&gt;
&lt;li&gt;Created
&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1145583&quot;&gt;ITP#1145583&lt;/a&gt; for
&lt;a href=&quot;https://codeberg.org/Vaishnav-Sabari-Girish/miru&quot;&gt;miru&lt;/a&gt; which is a nice
little screen magnifier for wlroots based compositors&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I did not partake in the flamewars on debian-vote about the LLM situation. I am
not sure how anyone can find this style of “discussion” productive. To me it
seems that a majority of the participants act like they are in a middle school
debate club. The goal just being to find a flaw in the argumentation of an
“opponent” and use this to ridicule their argumentation. Basically what
politicians do.&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;p&gt;&lt;img alt=&quot;xkcd 386&quot; src=&quot;https://imgs.xkcd.com/comics/duty_calls.png&quot; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The good thing is, that most Debian members did not stoop on that level.
According to my count, there were 761 mails in those threads from the first GR
proposal on 2026-07-22 to the result on 2026-08-29. Those 761 mails came from
99 &lt;code&gt;From:&lt;/code&gt; addresses, so most Debian people kept their distance. Given that
according to &lt;a href=&quot;https://nm.debian.org/members/&quot;&gt;nm.debian.org&lt;/a&gt; there are more
than 1000 Debian members, the “discussion” was led by less than 10%.&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;p&gt;&lt;img alt=&quot;mails-per-day&quot; src=&quot;https://bisco.org/notes/status-update-july-august-2026/mails-per-day.png&quot; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The distribution of who wrote how many mails is also interesting. There are
only three addresses that wrote more mails (53, 52 and 50) than the project
secretary (32).&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;p&gt;&lt;img alt=&quot;mails-per-person&quot; src=&quot;https://bisco.org/notes/status-update-july-august-2026/mails-per-person.png&quot; /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;I think the most fitting approach to Debian mailinglists is a quote from
&lt;a href=&quot;https://en.wikipedia.org/wiki/WarGames&quot;&gt;WOPR&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A STRANGE GAME. THE ONLY WINNING MOVE IS NOT TO PLAY.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id=&quot;dh-related-work&quot;&gt;DH Related Work&lt;/h1&gt;
&lt;p&gt;I released version 0.66.0 and 0.67.0 of the APIS framework as well as a couple
of bugfix releases for the 0.67.x version. In 0.67.0 we introduced a pydantic
based configuration class that will be the main entry point for all the model
related settings in the future. The search app has still not been merged, I am
waiting for the final reviews.&lt;/p&gt;
&lt;p&gt;Based on a proof of concept for an HTMX based autocomplete field that I did in
June, I implemented solutions for a single select and a multiselect field. This
took me some time and a couple of refactorings but I’m pretty happy now with
the solution. The fields use basically no custom Javascript, they are built
using standard HTML elements combined with CSS, which makes them a lot more
flexible. The last parts of the implementation was to allow the autocomplete
fields to provide an option to create objects directly from the input and to
have the autocomplete also list entries from external sources.&lt;/p&gt; </description> 
	<pubDate>Wed, 02 Sep 2026 05:28:51 +0000</pubDate>

</item> 
<item>
	<title>Russ Allbery: Review: Too Like the Lightning</title>
	<guid>https://www.eyrie.org/~eagle/reviews/books/1-4668-5874-5.html</guid>
	<link>https://www.eyrie.org/~eagle/reviews/books/1-4668-5874-5.html</link>
     <description>  &lt;p&gt;Review: &lt;cite&gt;Too Like the Lightning&lt;/cite&gt;, by Ada Palmer&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;&lt;tr&gt;
    &lt;td&gt;Series:&lt;/td&gt;
    &lt;td&gt;Terra Ignota #1&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Publisher:&lt;/td&gt;
    &lt;td&gt;Tor&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Copyright:&lt;/td&gt;
    &lt;td&gt;May 2016&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;ISBN:&lt;/td&gt;
    &lt;td&gt;1-4668-5874-5&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Format:&lt;/td&gt;
    &lt;td&gt;Kindle&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Pages:&lt;/td&gt;
    &lt;td&gt;432&lt;/td&gt;
  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;
&lt;cite&gt;Too Like the Lightning&lt;/cite&gt; is a science fantasy (?) novel and the first
of a four-book series. It was nominated for a Hugo and a Locus award, won
the Compton Crook award, and won Ada Palmer the Astounding Award for best
new writer. It was Palmer&#39;s first novel.
&lt;/p&gt;

&lt;p&gt;
Bridger is a young boy with a remarkable power: He can bring inanimate
objects to life through the power of his belief. He is being hidden by the
Saneer-Weeksbooth bash&#39;, a family (?) business (?) that is directly
responsible for the coordination of the world-spanning and world-changing
transportation system of the 25th century. Much of the direct
responsibility for Bridger&#39;s safety falls to our narrator, Mycroft Canner,
an odd and disreputable figure about whom we know very little at the start
of the book.
&lt;/p&gt;

&lt;p&gt;
As this book opens, two things are happening simultaneously. A Cousin
named Carlyle has arrived at the bash&#39; to become their new sensayer. They
stumble into the death of one of Bridger&#39;s plastic toy soldiers at the
paws of a cat, prompting a more abrupt introduction to Bridger&#39;s power
than had been intended. And, upstairs, the polylaw Martin Guildbreaker has
arrived at the bash&#39; to investigate the theft of the &lt;cite&gt;Black Sakura&lt;/cite&gt;
Seven-Ten list, a theft for which Ockham Saneer, bash&#39; security lead,
appears to have been framed via extremely contraband technology.
&lt;/p&gt;

&lt;p&gt;
&lt;cite&gt;Too Like the Lightning&lt;/cite&gt; is a story supposedly written by Mycroft
Canner in the 25th century but written in the style of the 18th. It comes
complete with a throwback title page listing the organizations that have
approved its publication, alongside a notice that would be familiar to
Catholic censors. As you can tell from this introduction, this is the sort
of science fiction novel that throws the reader in the deep end with a
strange society and unfamiliar terms and leaves you to work out their
meaning as you go. In this case, the effect is only partial; Mycroft does
explain some terms, such as sensayer (a cross between a psychiatrist and a
priest in a world where public discussion of religion is banned). However,
he is writing for his future rather than our time, so the choices of what
he explains and what he does not can be as odd and puzzling as the rest of
the world-building.
&lt;/p&gt;

&lt;p&gt;
One pieces together fairly quickly that this story is set on a future
Earth several centuries after a shattering conflict known as the Church
Wars. Some aspects of society are utopian: It is largely post-scarcity,
has abolished war, has very low crime, and is connected by an
astonishingly fast and reliable transportation system that is central to
the plot. Most aspects, though, are ambiguous, mixed, or just deeply
weird. Geography-based political polities have been mostly abolished.
Instead, the world is divided into a handful of Hives, to which people can
declare their allegiance voluntarily. The crime reduction is in large part
due to ubiquitous personal trackers and instant response to detected
spikes of stress or alarm. Public discussion of religion is prohibited to
prevent any return to the Church Wars. Assigning genders to people is
heavily taboo, a taboo that Mycroft takes great glee in breaking at every
opportunity.
&lt;/p&gt;

&lt;p&gt;
It&#39;s worth talking about the handling of gender, since like much of the
writing style I found it delightful and irritating in turns.
&lt;/p&gt;

&lt;p&gt;
In Mycroft&#39;s time, the overwhelming social expectation is to use
gender-neutral pronouns for everyone. Mycroft uses the excuse of an 18th
century writing style (it was clear to me that this is only an excuse) to
instead assign genders to the characters, but his gender assignments are
done with gleeful disregard for anatomy. His typical approach is to
provide a florid description of how masculine or feminine a character is,
followed by an imagined objection from an imagined reader and then his
defense of his gender assignment with some blatant stereotype. Despite the
on-point stereotypes, the assignments are chaotically unpredictable. I
frequently guessed Mycroft would choose one gender, only to have him
choose the opposite and then credibly defend it via some entirely
different stereotype that hadn&#39;t occurred to me.
&lt;/p&gt;

&lt;p&gt;
I thought this was a highly entertaining and pointed commentary on how
absurd and contradictory our gender conventions and constructions are, but
the digressions and obviously fake and faux-archaic reader objections can
also get annoying. The objection I wanted to make, as an actual reader,
was more often something along the lines of &quot;oh my god, Mycroft, just pick
a pronoun and get on with the story, no one cares.&quot; Which is, itself,
biting meta-commentary on our obsession with gender that I had to admire
even when I was exasperated by it.
&lt;/p&gt;

&lt;p&gt;
So much of the book is like this: extremely clever, but also kind of
irritating. &lt;cite&gt;Too Like the Lightning&lt;/cite&gt; is one of the best examples of
cognitive estrangement in science fiction that I&#39;ve read, in part because
it&#39;s more social than technological. The technology here is standard
science fiction fare, but society has changed far more than technology has
in Palmer&#39;s future world. All (I think?) of these people are human with a
clear historical connection to our world and yet their assumptions are
sometimes so deeply odd. Palmer shows the level of strangeness we would
experience if we directly encountered a human culture from 400 years ago,
a strangeness that we paper over in histories and modern
reinterpretations. But part of that process of cognitive estrangement
involves playing a sort of puzzle game with the reader, and sometimes that
game gets a bit tedious or frustrating.
&lt;/p&gt;

&lt;p&gt;
The one place where the world-building fell flat for me, and kept knocking
me out of the story, is the politics. Not the Hives and the system of
ideology-based affiliation and geographic mixing; that&#39;s strange but
interesting, and I could buy it as a side effect of both catastrophe and
ubiquitous cheap transportation. Not the complicated system of legal codes
and exceptions and competing jurisdictions; that felt believably baroque
in the way that complexity emerges in the friction in long-lived human
systems. My problem was with the scale, or rather the lack of scale.
&lt;/p&gt;

&lt;p&gt;
This world has ten billion people; there is no way that the relationships
between literally every politically important person in the world could be
this incestuous. There are nowhere near enough factions, disagreements,
alternative power bases, petty personal grudges provoking serious schisms,
or enough &lt;em&gt;bureaucrats&lt;/em&gt;. I know there are myriad science fiction
novels with even more trivial and unbelievable world governments, but
usually they&#39;re not central to a highly political plot. &lt;cite&gt;Too Like the
Lightning&lt;/cite&gt; wants you to care deeply about the politics of this world and
then gives you a system in which all major decisions roll up to a handful
of people with apparently next to no intervening civil service.
&lt;/p&gt;

&lt;p&gt;
Also, why is there so little redundancy? How can the most vital service of
this civilization be run directly and almost exclusively by the
inhabitants of &lt;em&gt;one house?&lt;/em&gt; There is a technical explanation, but the
social explanation is barely handwaving. This is not how institutional
trust generally works; even with vast multinational high-capital
near-monopolies such as cloud computing, there are three major players and
innumerable smaller ones.
&lt;/p&gt;

&lt;p&gt;
Maybe Palmer was extrapolating from the global oligarch class and meetings
such as the &lt;a href=&quot;https://en.wikipedia.org/wiki/World_Economic_Forum&quot;&gt;World Economic Forum&lt;/a&gt;, which do indeed attract a startling percentage of
all world political figures. The problem, though, is not the surface of
occasional gatherings or staged events seen early in this story. It goes
much deeper, far into confidences and explicit coordination, to the extent
that at several points I said some variation of &quot;oh come on, there&#39;s no
way Mycroft personally knows them &lt;em&gt;too&lt;/em&gt;.&quot; The only people who believe
in controlling cabals this small are conspiracy theorists. This is simply
not how humans work when this much power is at stake.
&lt;/p&gt;

&lt;p&gt;
Now, I have to say that I&#39;m going out on a limb making this critique after
only reading the first book of a four-book series. This is absolutely the
type of work for which my reaction and objections could be an intentional
effect created by Palmer in order to spring some unexpected justification
on the reader in book two or three. It&#39;s clear that there is some massive
social upheaval on the horizon in this series, and something very strange
is going on with one of the characters and their hold over other people.
Perhaps the reader disbelief is setting up that upheaval. If so, hats off
to her, and that&#39;s one of the perils of reviewing books as I read them.
&lt;/p&gt;

&lt;p&gt;
But it still hurt my enjoyment of this book when the political drama kept
shrinking and tightening and focusing on fewer and fewer people. It felt
frankly unbelievable for the political universe of this highly political
book to be this claustrophobic. I wanted it to expand into the space that
should be available to an entire world teeming with fractious and complex
humanity.
&lt;/p&gt;

&lt;p&gt;
The other major complaint I have about this book is that the first-person
narrator is odious. This is something I knew going in — &lt;cite&gt;Too Like the
Lightning&lt;/cite&gt; famously has an unreliable and unlikable narrator — and he is
relatively passive for much of the book, so it is often possible to ignore
him and focus on more likable characters. I don&#39;t necessarily mind an
unlikable or unreliable narrator in this type of story.
&lt;/p&gt;

&lt;p&gt;
But, unfortunately, Mycroft cringes, and I hate reading about cringing for
this many pages. His primary mode of interaction with people is
obsequious, performative fear with a weird, distasteful edge of
manipulation. Again, I think this is entirely intentional on Palmer&#39;s
part; we learn some of the reasons behind it by the end of this book, and
I&#39;m sure we&#39;ll learn more in future books. But, nonetheless, the overall
effect is a bit like reading a book narrated by
&lt;a href=&quot;https://en.wikipedia.org/wiki/Gr%C3%ADma_Wormtongue&quot;&gt;Gríma
Wormtongue&lt;/a&gt;. I can appreciate the narrative role of that character without
wanting to spend this much time in his head.
&lt;/p&gt;

&lt;p&gt;
I have very mixed feelings about this book. The overall construction is
brilliant; it&#39;s a beautiful puzzle of oddity and alienation that provides
great fun for the type of science fiction reader who wants to work out the
rules of a strange society without a lot of infodumping. There are a few
characters I adored: Eureka, for example, a set-set (a sort of human
computer in a way that reminded me of mentats in &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/0-441-17271-7.html&quot;&gt;&lt;cite&gt;Dune&lt;/cite&gt;&lt;/a&gt; but with better world-building) who steals every scene that
she&#39;s in. I was very invested in the world-building, fascinated by the
Utopians, and want to learn more about what&#39;s going on.
&lt;/p&gt;

&lt;p&gt;
On the other hand, the combination of Mycroft as a narrator and the weird
one-room play logic of global politics kept throwing me out of my reading
flow. It took me about a month to finish this book. The science fiction
and political fiction aspects of the story interested me more than Bridger
and whatever is going on with J.E.D.D. Mason, and I&#39;m worried that my
least-favorite aspects will be central to the rest of the story. I was
enjoying a smaller percentage of the scenes by the end of the book than I
was at the start, which is not a great sign.
&lt;/p&gt;

&lt;p&gt;
And yet, the ending absolutely worked on me. I don&#39;t want to stop here! I
will probably pick up the sequel, but I think it&#39;s going to take me a
while to brace myself for it.
&lt;/p&gt;

&lt;p&gt;
I have no idea whether to recommend this or not, since I think your
enjoyment will depend so much on the balance between the parts of the book
you find irritating and the parts of the book you find engrossing. I&#39;m
fairly sure most readers will find a little of both, but I have no idea
how to predict their relative weight. If you like cognitive estrangement,
this is great; I understand why so many science fiction reviewers rave
about this book. If you need to like the first-person protagonist, uh,
good luck. Maybe you&#39;ll have more tolerance for cringing than I do.
&lt;/p&gt;

&lt;p&gt;
The one thing I can say firmly about &lt;cite&gt;Too Like the Lightning&lt;/cite&gt; is that
it&#39;s &lt;em&gt;interesting&lt;/em&gt;. It may be worth reading just to see how people
are stretching the genre, even if you end up not liking the effect. But be
warned that this book does not so much end on a cliffhanger as suddenly
stop at some random, nondescript point on the road leading to the cliff.
The ending is deeply unsatisfying; you will need to read more if you want
to understand what&#39;s going on.
&lt;/p&gt;

&lt;p&gt;
Followed by &lt;cite&gt;Seven Surrenders&lt;/cite&gt;.
&lt;/p&gt;

&lt;p&gt;Rating: 7 out of 10&lt;/p&gt; </description> 
	<pubDate>Wed, 02 Sep 2026 02:44:00 +0000</pubDate>

</item> 
<item>
	<title>Russ Allbery: Review: Last Chance to Save the World</title>
	<guid>https://www.eyrie.org/~eagle/reviews/books/0-7564-1971-9.html</guid>
	<link>https://www.eyrie.org/~eagle/reviews/books/0-7564-1971-9.html</link>
     <description>  &lt;p&gt;Review: &lt;cite&gt;Last Chance to Save the World&lt;/cite&gt;, by Beth Revis&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;&lt;tr&gt;
    &lt;td&gt;Series:&lt;/td&gt;
    &lt;td&gt;Chaotic Orbits #3&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Publisher:&lt;/td&gt;
    &lt;td&gt;DAW Books&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Copyright:&lt;/td&gt;
    &lt;td&gt;April 2025&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;ISBN:&lt;/td&gt;
    &lt;td&gt;0-7564-1971-9&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Format:&lt;/td&gt;
    &lt;td&gt;Kindle&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Pages:&lt;/td&gt;
    &lt;td&gt;133&lt;/td&gt;
  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;
&lt;cite&gt;Last Chance to Save the World&lt;/cite&gt; is a far-future science fiction caper
novella and the conclusion of the trilogy that began with
&lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/0-7564-1947-6.html&quot;&gt;&lt;cite&gt;Full Speed to a Crash Landing&lt;/cite&gt;&lt;/a&gt;. This is a
direct sequel to &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/0-7564-1949-2.html&quot;&gt;&lt;cite&gt;How to Steal a Galaxy&lt;/cite&gt;&lt;/a&gt;,
picking up right after that story leaves off, but you don&#39;t have to
remember the details to enjoy this installment.
&lt;/p&gt;

&lt;p&gt;
Ada has finally achieved a (temporary, contingent) alliance with
government agent Rian White by convincing Rian that some things are more
important than Ada&#39;s disregard for the law. She&#39;s going to need his help.
They have once chance to save Earth from a new and even more malicious
round of capitalist environmental blackmail, and it&#39;s going to require
Rian&#39;s security access as well as all of Ada&#39;s heist skills.
&lt;/p&gt;

&lt;p&gt;
But first, a visit with Ada&#39;s mother, who lives in an old watchtower on
Malta and keeps pigeons.
&lt;/p&gt;

&lt;p&gt;
Each entry in this series has been a little shorter than the last, and
&lt;cite&gt;Last Chance to Save the World&lt;/cite&gt; is definitely a novella. This is a
great length for a heist story: enough room for some setup and a couple of
major plot twists, but short enough that the story can maintain a headlong
pace. Even in the third novella of a series and a novel&#39;s worth of time in
Ada&#39;s head, Revis has one major surprise for the reader left. And, as
usual, there&#39;s a lot of misdirection, sarcastic commentary, and the
delightful competence of a protagonist who puts considerable professional
effort into being underestimated.
&lt;/p&gt;

&lt;p&gt;
The bits with Ada&#39;s mother were great. This is the first time we&#39;ve seen
Ada have significant interactions other than her flirting and teasing of
Rian, and I loved seeing a different side of her. The heist itself was
satisfying, although not quite as good as &lt;cite&gt;How to Steal a Galaxy&lt;/cite&gt;.
Ada gets to throw a few more verbal daggers, but there are more events in
this installment and therefore more action and less dialogue. Ada&#39;s
commentary and dialogue is still my favorite part, though.
&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;
    For all that Rian says I like to break the law, it should be illegal
    for any one man to be both this dumb and this rich. It&#39;s astounding,
    really. Any of his employees could run circles around him, but it
    doesn&#39;t take brains to buy stuff. Strom Fetor sees nothing clearly
    except profit margins.
&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;
There is, of course, even more flirting and semi-fake romance. Those were
not my favorite part, mostly because while it&#39;s obvious what Rian sees in
Ada, it baffles me what Ada sees in Rian. I know the star-crossed romance
between the law man and the charismatic thief is an old fictional trope,
but I found it very hard to justify Rian&#39;s continuing commitment to his
law and government given the clear facts of this setting.
&lt;/p&gt;

&lt;p&gt;
Up until this novella, one could excuse Rian as the sort of person whose
belief in order, stability, and rules combines with possibly excessive
optimism to create a belief in an imperfect system. But here, Ada has
finally convinced Rian that some great evils truly will not be fixed by
following the rules. He&#39;s onboard, but somehow in a way that leads to
precisely no reconsideration, soul-searching, or breach in his commitment
to defending a clearly corrupt and failing political system.
&lt;/p&gt;

&lt;p&gt;
My objection is not that this is unrealistic; sadly, it&#39;s very realistic.
My objection is that Rian is dumber than a bag of hammers, I don&#39;t like
reading about his blind allegiance to a bad system, and I do not
understand how that goes with the sexy feelings. I&#39;m sure this is my lack
of understanding of physical affection overriding common sense, and Ada is
at least not a complete idiot about her attraction. But I felt like this
novella expected me to like Rian as more than a foil for Ada, and I very
much did not.
&lt;/p&gt;

&lt;p&gt;
That knocked a point off my enjoyment of this entry, but the heist is
great, the politics are interesting, and the climax was very satisfying.
This is not quite as good as the middle book of the trilogy, but it&#39;s a
satisfying conclusion. If you liked the previous entries, you&#39;ll want to
read this one for the conclusion.
&lt;/p&gt;

&lt;p&gt;
&lt;cite&gt;Last Chance to Save the World&lt;/cite&gt; resolves the main plot driver of the
trilogy, but there&#39;s a lot of space for more sequels. If they materialize,
I will probably keep reading, although I hope someone knocks some sense
into Rian.
&lt;/p&gt;

&lt;p&gt;Rating: 8 out of 10&lt;/p&gt; </description> 
	<pubDate>Tue, 01 Sep 2026 03:18:00 +0000</pubDate>

</item> 
<item>
	<title>Jonathan McDowell: What do I want in a Linux distribution?</title>
	<guid>https://www.earth.li/~noodles/blog/2026/08/what-do-i-want-distro.html</guid>
	<link>https://www.earth.li/~noodles/blog/2026/08/what-do-i-want-distro.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/noodles.png&quot; width=&quot;100&quot; height=&quot;108&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I’ve been a &lt;a href=&quot;https://www.debian.org/&quot;&gt;Debian&lt;/a&gt; user since 1999, and a Debian developer &lt;a href=&quot;https://nm.debian.org/legacy/process/13424/&quot;&gt;since 2000&lt;/a&gt;. Given &lt;a href=&quot;https://www.debian.org/vote/2026/vote_002&quot;&gt;recent events&lt;/a&gt; it’s worth thinking about why that that is, and why I haven’t switched to something else in the past quarter century.&lt;/p&gt;

&lt;p&gt;My first Linux distro was &lt;a href=&quot;http://www.slackware.com/&quot;&gt;Slackware&lt;/a&gt;, off a CD in a book, some time in the mid 90s. After starting university I ran &lt;a href=&quot;https://www.suse.com/&quot;&gt;SUSE&lt;/a&gt; for a while, then moved to &lt;a href=&quot;https://www.redhat.com/&quot;&gt;RedHat&lt;/a&gt; (both back before they had commercial variants significantly different to what was available freely). The main motivation for switching was package management; I was running a machine at home, and a machine at university. Keeping track of what was installed on each, and what versions, was getting annoying with Slackware. Most of the folk I knew were running RedHat, and I mostly played with SUSE because I’m contrary before realising it was different enough that I couldn’t easily make use of 3rd party RPMs.&lt;/p&gt;

&lt;p&gt;I came to Debian via friends in Cambridge, who spoke highly of it. The first Debian machine I installed was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fourier&lt;/code&gt;, the initial host for Black Cat Networks, and I never looked back.&lt;/p&gt;

&lt;p&gt;(For additional context I should also point out I have contributed, in the distant past, to, and run, &lt;a href=&quot;https://openwrt.org/&quot;&gt;OpenWRT&lt;/a&gt;, &lt;a href=&quot;https://www.openembedded.org/&quot;&gt;OpenEmbedded&lt;/a&gt;, and &lt;a href=&quot;https://www.freebsd.org/&quot;&gt;FreeBSD&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;I’d like to try and work out what is it I get from Debian that I’d need in anything else. Originally I tried to order the requirements in some sort of priority, but it’s sometimes hard to work out what I’d drop if I had to compromise somewhere, so it’s a somewhat loose ordering.&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Stable releases, with security support&lt;/dt&gt;
  &lt;dd&gt;I run Linux in lots of places, from remote servers/VMs, to my house router, to my desktop/laptop. Some of those I don’t want to be updating regularly with new software releases, I need something I can be sure is going to keep working, but will get necessary security + critical updates. A rolling distro that provides security via the latest upstream release doesn’t provide that guarantee. Equally there need to be regular stable releases, or things become too stale. (The one time I considered moving away from Debian was during the 3 year &lt;a href=&quot;https://www.debian.org/releases/sarge/&quot;&gt;Sarge / 3.1&lt;/a&gt; release cycle. I think if things hadn’t improved I’d have jumped ship to &lt;a href=&quot;https://ubuntu.com/&quot;&gt;Ubuntu&lt;/a&gt; at the time.)&lt;/dd&gt;
  &lt;dt&gt;A good selection of packages&lt;/dt&gt;
  &lt;dd&gt;One of the reasons I moved from RedHat to Debian was the wide range of packages available as part of the standard OS. Pulling it all into the distro helps with quality control, compared to random 3rd party packages. A centralised bug system and repository is a win too. Perhaps packages at all is something I should list, but I take it as a given if you’re running a distro. I need to know what I have installed on my machine, what version that software is, what files it owns, and what it depends on.&lt;/dd&gt;
  &lt;dt&gt;Free Software&lt;/dt&gt;
  &lt;dd&gt;This is important to me. I’ll make pragmatic compromises about software I run on my systems if it makes sense, but I want to start from a place that does not require anything non-free. I’ve run a company on Debian, and I’ve worked on numerous products that ran it under the hood. The &lt;a href=&quot;https://www.debian.org/social_contract#guidelines&quot;&gt;DFSG&lt;/a&gt; give me confidence I can do that.&lt;/dd&gt;
  &lt;dt&gt;Smooth upgrades&lt;/dt&gt;
  &lt;dd&gt;Debian’s ability to upgrade a system smoothly is one of the reasons I first moved to it. The first upgrade I did was remotely on a machine sitting on a 2Mb/s leased line. I was nervous doing the reboot at the end, but it came back fine. At the time the equivalent procedure with RedHat involved rebooting into the OS installer to do the upgrade.&lt;/dd&gt;
  &lt;dd&gt;I know things have moved on since then, and really it should all be scripted, and machines should be cattle not pets, but for personal use I run a small enough number of machines that having the upgrade path between releases is a must have.&lt;/dd&gt;
  &lt;dt&gt;Community&lt;/dt&gt;
  &lt;dd&gt;The original pull of the Debian community was the knowledge I could get involved, and upload packages that were missing that I was using. That’s how I first got involved, uploading things Black Cat used, which made life easier for us in the long run. I don’t have time to maintain all the software I use myself, and I don’t want to be beholden to a commercial entity to do so for me, so a distribution that allows me to help out where I can as part of the community seems to me to be the right way to do things.&lt;/dd&gt;
  &lt;dt&gt;Architecture support&lt;/dt&gt;
  &lt;dd&gt;Perhaps less important, especially when I started using Debian, but these days I have amd64, arm64, armhf, and riscv machines. Everything except for the risvc box is doing something useful, and would need replaced if I couldn’t keep running it, and I expect RISC-V to transition into that state in the next few years as the hardware improves.&lt;/dd&gt;
  &lt;dt&gt;Binary packages&lt;/dt&gt;
  &lt;dd&gt;I ran a FreeBSD desktop for some time. It might have been the way I was holding it, but binary package installs were generally not something reliable, especially after the initial install, and I ended up building things from ports from source quite often. That worked incredibly well (I used to think people who raved about &lt;a href=&quot;https://www.gentoo.org/&quot;&gt;Gentoo&lt;/a&gt; really should just go do it properly and use FreeBSD), but I don’t want to spend time compiling things, especially on some of my machines (my router should not need a compiler, for example).&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;Ultimately I don’t want to have to actively think about the Linux distribution I use. Debian has mostly given me that; I know it will generally be suitable for most environments I want to use it in (embedded situations where OpenWRT or OpenEmbedded are better choices being the exception, but that’s less frequent these days), and I can rely on getting timely security updates (thanks to all those who work on that within Debian!). I’m not sure there’s currently an alternative that would suit my needs? I’d love to hear if there’s something I should look at, even if I’m not necessary making a move just yet!&lt;/p&gt; </description> 
	<pubDate>Mon, 31 Aug 2026 17:20:15 +0000</pubDate>

</item> 
<item>
	<title>Russ Allbery: Review: The Hands of the Emperor</title>
	<guid>https://www.eyrie.org/~eagle/reviews/books/1-988908-15-9.html</guid>
	<link>https://www.eyrie.org/~eagle/reviews/books/1-988908-15-9.html</link>
     <description>  &lt;p&gt;Review: &lt;cite&gt;The Hands of the Emperor&lt;/cite&gt;, by Victoria Goddard&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;&lt;tr&gt;
    &lt;td&gt;Series:&lt;/td&gt;
    &lt;td&gt;Lays of the Hearth-Fire #1&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Publisher:&lt;/td&gt;
    &lt;td&gt;Underhill Books&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Copyright:&lt;/td&gt;
    &lt;td&gt;January 2019&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;ISBN:&lt;/td&gt;
    &lt;td&gt;1-988908-15-9&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Format:&lt;/td&gt;
    &lt;td&gt;Kindle&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Pages:&lt;/td&gt;
    &lt;td&gt;739&lt;/td&gt;
  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;
&lt;cite&gt;The Hands of the Emperor&lt;/cite&gt; is a self-published political fantasy
novel. It&#39;s the recommended first book (although not the first published
book) in a
&lt;a href=&quot;https://nineworlds.miraheze.org/wiki/Reading_Order&quot;&gt;complicated set
of interrelated series&lt;/a&gt;. I was not able to definitively confirm that
Underhill Books is Goddard&#39;s self-publishing press name, but the press
does not appear to have an Internet presence apart from Goddard&#39;s books
and her books appear to be using the standard self-publishing channels.
&lt;/p&gt;

&lt;p&gt;
Cliopher Mdang is the personal secretary of the last emperor of
Astandalas, the magical heart of Zunidh, a man worshiped as a god. The
emperor&#39;s word is absolute, his magic supports the health of the entire
world, and he cannot be physically touched without risking physical damage
and severe political and religious punishment. Cliopher is one of the
emperor&#39;s closest associates, but the distance between them is still vast.
It therefore represents a terrifying and dangerous breach of etiquette for
him to suggest the emperor may enjoy a vacation on a tropical island near
Cliopher&#39;s remote home. The emperor&#39;s acceptance of the invitation is even
more startling.
&lt;/p&gt;

&lt;p&gt;
The emperor has opinions about his life as the emperor that no one had
guessed. Cliopher has not assimilated as completely into the bureaucratic
machinery of the empire as it first may appear. And Cliopher&#39;s family have
vastly misunderstood the nature of his role in the emperor&#39;s government.
&lt;/p&gt;

&lt;p&gt;
I find the marketing blurb for this book unfortunate since, at least to
me, the emphasis on physical touch and intimacy implies that &lt;cite&gt;The
Hands of the Emperor&lt;/cite&gt; is a romance novel or at least has significant
romantic elements. I&#39;ve been aware of this book for years but put off
reading it because I wasn&#39;t quite in the mood for that story. This is not
a romance novel; there is no romance in this book whatsoever. It is a
political fantasy, both in the sense that it is set in a secondary fantasy
world with magic and (apparently) some form of interplanetary travel, and
in the sense that it is a fantasy of governance.
&lt;/p&gt;

&lt;p&gt;
When I say that this book blew up in certain corners of the Internet
during the pandemic, I think you will still underestimate the passion of
its advocates. I heard about this book &lt;em&gt;constantly&lt;/em&gt;, in a way that
reminded me of &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/0-765-34298-7.html&quot;&gt;&lt;cite&gt;Kushiel&#39;s Dart&lt;/cite&gt;&lt;/a&gt; and the
time when fans of Jacqueline Carey would bring her up in every fantasy
conversation, or when we created a Usenet newsgroup for &lt;cite&gt;The Wheel of
Time&lt;/cite&gt; mostly to get the voluminous conversations off of the regular SFF
newsgroup. I&#39;m one of those mildly contrarian people for whom that degree
of enthusiasm is a little off-putting, which is another reason why I
resisted buying a copy for years and only read it in 2026.
&lt;/p&gt;

&lt;p&gt;
It&#39;s delightful, although also a bit embarrassing, when the book everyone
was in love with turns out to be just as good as everyone said it was.
&lt;/p&gt;

&lt;p&gt;
I adore stories about friendship, and this is one of the best stories
about friendship that I&#39;ve ever read. It is a very, very slow burn, but I
also thought the first three quarters of the book was exquisitely paced.
There were long sections where not very much was happening, and yet I
couldn&#39;t put the book down because there was so much subtle character work
just beneath the surface.
&lt;/p&gt;

&lt;p&gt;
Almost all of the novel is told in tight third person from Cliopher&#39;s
perspective, and I thought that was an excellent choice. Neither Cliopher
nor the narrator comment on things that Cliopher finds obvious, which is
both immersive and critical to the pacing. There are discoveries for the
reader throughout the book, the sort of discoveries that make pieces fit
together satisfyingly in retrospect, and the reader stays sufficiently
ahead of the misunderstandings of Cliopher&#39;s friends and family that one
also gets the joy of watching other people discover things that one
figured out a hundred pages earlier.
&lt;/p&gt;

&lt;p&gt;
It helps that I truly liked nearly everyone in this book. There are no
real villains, only a few supporting characters whose role is to be
irritating or corrupt. If you&#39;re looking for a lot of conflict and drama,
you may want to save this book for a different mood, but if you&#39;re in the
mood for a varied collection of fundamentally good characters working
methodically through the complexities and obstacles of politics and social
systems to improve the world, there are few books I would recommend more.
Goddard achieves one of the hardest tricks of slow burns: steady forward
progress that does not rely on reversals, misunderstandings, or the
friendship equivalent of the third-act breakup. This book spends 700 pages
building towards a climax that managed to be worthy of all 700 pages
without ever annoying me with artificial obstacles, and that&#39;s quite a
feat.
&lt;/p&gt;

&lt;p&gt;
I&#39;ve not said much about the details of the plot. There is one — it&#39;s not
just character work — but I think this book benefits immensely from going
in as blind as possible. I found the twists and turns and growing
revelations so deeply satisfying that I don&#39;t want to rob any other reader
of the experience.
&lt;/p&gt;

&lt;p&gt;
The fantasy world-building is intriguing but a bit unsatisfying because it
is so unexplained. We get a few details of the magic system, but since
Cliopher has no magic, he isn&#39;t that interested in the details. There is a
catastrophic magical event in the world background, and we learn some of
the details of its practical effects, but the nature of the world before
the cataclysm is so obvious to the characters that it&#39;s never explained.
I&#39;m not even certain that this civilization is interplanetary; that feels
like the implication of how characters talk about multiple worlds, but the
method of travel is left entirely undefined. This might be frustrating to
some genre readers, but I personally enjoy books where the world-building
is a bit mysterious. It&#39;s a good reason to read more of Goddard&#39;s books
set in the same universe.
&lt;/p&gt;

&lt;p&gt;
This was my favorite of the books I&#39;ve read so far this year, but I do
have one caution and a couple of caveats.
&lt;/p&gt;

&lt;p&gt;
The caution is that Cliopher comes from an island culture based heavily on
(I think) Polynesian cultures. That culture is very central to the story
and is treated with considerable respect, but I still get a bit nervous
when a Canadian author from Nova Scotia with an academic background in
European medieval studies writes a story focused this deeply on a
non-European culture. Nothing about her portrayal seemed off to me
(although there is a very clunky and ham-handed scene about a different
native culture that worries me), and for all I know she has family
background or other connections to the culture she is borrowing from, but
it&#39;s possible I missed serious problems.
&lt;/p&gt;

&lt;p&gt;
The flip side of that caution is that I&#39;m delighted to see a fantasy
author drawing on a non-European culture, and I thought the clash of
cultures was very well-handled.
&lt;/p&gt;

&lt;p&gt;
The first caveat is that the story is very focused on good governance, but
both the process and the details of that governance are not going to
satisfy someone reading primarily for the politics. The policies and
reforms are very standard 21st century progressive material that felt a
bit out of place in a quasi-medieval world with magic and airships. Their
implementation is not the point of the story, and is therefore heavily
backgrounded, but that means Goddard barely mentions the inevitable
practical implementation difficulties and does not discuss how they&#39;re
overcome.
&lt;/p&gt;

&lt;p&gt;
The world structure also means that Goddard can make use of the favorite
cheat of political reformers in fiction: Absolute monarchy lets you enact
a political agenda without having to do the hard and frustrating work of
persuasion or political (or actual) warfare. This objection is not
entirely fair because we do get some memorable scenes of persuasion, but
the political portion of the plot is unrealistically devoid of setbacks or
resistance that goes beyond token arguments.
&lt;/p&gt;

&lt;p&gt;
Whether this will bother you will depend heavily on what parts of the book
you&#39;d rather focus on. I can see why this was such a popular pandemic
read: &lt;cite&gt;The Hands of the Emperor&lt;/cite&gt; is focused tightly on the joy of
competent people fixing things and does not focus on the arguments,
division, or polarization. The heart of the book is the friendship and
characterization of some deeply admirable people, and the political reform
is incidental background material. I suspect this is the right choice for
readers who aren&#39;t political junkies, but I kept having the niggling
objection that the politics felt a bit too pat and simplistic. Goddard
stressed that the characters were investing considerable effort, but even
still, it is not this easy to change the direction of a political system
and idealistic plans usually do not work out this neatly.
&lt;/p&gt;

&lt;p&gt;
The second caveat is that, as previously mentioned, I thought the pacing
was excellent for about three quarters of the book. Goddard is building
towards a grand climax, and I think she built a little too much and tried
to make the climax a bit too grand and risked over-egging the pudding.
That made the payoff feel a bit belabored to me. I still enjoyed it, and
parts of it are wonderfully emotional, but I think the ending might have
been stronger if Goddard had dialed Cliopher back just a little and
tightened up the climax a touch. That said, this book fully commits to
being a sprawling slow burn and that&#39;s part of its appeal, so it&#39;s
probably better for Goddard to err in that direction than it would have
been to cut short the denouement.
&lt;/p&gt;

&lt;p&gt;
This is one of those books that I&#39;m not sure would exist without
self-publishing. It&#39;s a little too long, a little too political in the
wrong ways, a little too devoid of the typical sorts of conflicts expected
in a fantasy book, and too determined to be its own peculiar thing. I
think it would scare off publishers. Unlike some self-published books,
though, I didn&#39;t notice any obvious editing flaws or lack of polish. It&#39;s
one of those glorious novels that is so very much its own type of story
that it provides an experience that would be hard to replicate with
another book.
&lt;/p&gt;

&lt;p&gt;
I was so deeply satisfied by this book. It&#39;s a wish-fulfillment political
fantasy full of diligent restraint and competence porn, so you have to be
in the mood for that. This is not the book to read when you&#39;re feeling
cynical, or are in the mood for action and high drama. But if you&#39;re in
the mood for a long, slow, open-hearted story of friendship that offers
the fantasy of giving truly good people enough power to be effective, I
highly recommend this one.
&lt;/p&gt;

&lt;p&gt;
Followed in the direct sequel sense by &lt;cite&gt;At the Feet of the Sun&lt;/cite&gt;, but
there is a very complex story progression in this world that I think I&#39;d
have to read all the other books to understand. This was such a satisfying
and complete experience that I&#39;m not in a hurry to figure out which
Goddard book to read next, but I&#39;m sure I&#39;ll be returning to this world at
some point.
&lt;/p&gt;

&lt;p&gt;Rating: 9 out of 10&lt;/p&gt; </description> 
	<pubDate>Mon, 31 Aug 2026 03:11:00 +0000</pubDate>

</item> 
<item>
	<title>Ingo Juergensmann: Debian GR on Responsible Use of Generative AI</title>
	<guid>https://blog.windfluechter.net/?p=97337</guid>
	<link>https://blog.windfluechter.net/2026/08/29/debian-gr-on-responsible-use-of-generative-ai/</link>
     <description>  &lt;p class=&quot;wp-block-paragraph&quot;&gt;So, the members of Debian (developers and such) have voted in a &lt;a href=&quot;https://www.debian.org/vote/2026/vote_002&quot;&gt;GR about “LLM usage in Debian&lt;/a&gt;” for Option 5)/Proposal E) “Responsible Use of Generative AI”. &lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;And in the &lt;a class=&quot;hashtag u-tag u-category&quot; href=&quot;https://blog.windfluechter.net/tag/fediverse/&quot; rel=&quot;tag&quot;&gt;#Fediverse&lt;/a&gt; the hell breaks lose!&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;Currently there is a huge vibe against (Generative) AI, i.e. generating code, images, etc. I can understand some furor about this and in general I dislike much of the AI as well. For example I dislike the energy and water consumption, what the hype did to memory &amp;amp; storage prices, the awful look of all these AI generated images, the ignorance of AI companies about copyrights and all this. &lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;But I also see the benefits of AI: people are entitled to do things they couldn’t do before. You can proceed faster with your pet project when AI assist you and all of the bells and whistles. &lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;Anyway, let’s face it: AI is a disruptive technolgy like the invention of electricity, the steam engine, combustion engine, the computer or the smartphone were. It will not go away anymore. Pandoras box is open. &lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;But what you can do is: &lt;/p&gt;



&lt;ul class=&quot;wp-block-list&quot;&gt;
&lt;li&gt;learn what AI is and what not&lt;/li&gt;



&lt;li&gt;use AI in a responsible way&lt;/li&gt;



&lt;li&gt;experience the Do’s &amp;amp; Don’ts of AI&lt;/li&gt;



&lt;li&gt;increase your knowledge about AI and its dangers and beneftis&lt;/li&gt;



&lt;li&gt;help others with getting used resonsibly to AI&lt;/li&gt;



&lt;li&gt;build a good sense that AI is telling you nonsense&lt;/li&gt;



&lt;li&gt;don’t blindly trust AI&lt;/li&gt;



&lt;li&gt;learn about new technology with and without the help of AI&lt;/li&gt;



&lt;li&gt;use it as a tool&lt;/li&gt;



&lt;li&gt;etc…&lt;/li&gt;
&lt;/ul&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;I don’t say you should embrace AI completely, but demonizing it won’t help you either. Be sceptic, be curious about it, act responsible. AI is not your saviour, but it’s also not armageddon. It is a discruptive technology. Deal with it. You’ll have no other option anyway. ðŸ¤·â€�â™‚ï¸�&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;/p&gt; </description> 
	<pubDate>Sat, 29 Aug 2026 07:40:00 +0000</pubDate>

</item> 
<item>
	<title>Joey Hess: Debian and the sirens</title>
	<guid>http://joeyh.name/blog/entry/Debian_and_the_sirens/</guid>
	<link>http://joeyh.name/blog/entry/Debian_and_the_sirens/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/joeyh2.png&quot; width=&quot;84&quot; height=&quot;75&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Thirty years ago I became a Debian developer. Twelve years ago I left the
project. I left because it seemed that the Debian ship had become too slow
to turn, too barnacled with a series of individually OK decisions that each
added a little bit of friction and a little less flexability. That made
Debian strongly what it is, but prevented it from fruitfully exploring
the vast possibility space of what it could be.&lt;/p&gt;

&lt;p&gt;Debian will probably &lt;a href=&quot;https://www.debian.org/vote/2026/vote_002&quot;&gt;resolve&lt;/a&gt;
today to allow LLM use in Debian development. I&#39;m writing before the vote
results are in, but will only post this afterwards. (Update: as expected)
It&#39;s not my place any longer to try to steer the ship. But I&#39;m still a
passenger and I still have opinions, and I still pass by well-worn parts of
the rigging that I put up decades ago, and remember what I was trying to
accomplish back then.&lt;/p&gt;

&lt;p&gt;When I think about LLMs in Debian development, I mostly think about
&lt;a href=&quot;http://joeyh.name/code/debhelper/&quot;&gt;debhelper&lt;/a&gt; and what it accomplished. The &lt;code&gt;debian/rules&lt;/code&gt; files back
when I joined the project were long and complex, full of weird boilerplate,
and often you&#39;d copy one and modify it to try to get something that could
build a package without too much work. Debhelper first regularized the
boilerplate, so packages had rules files that were a succession of &lt;code&gt;dh_&lt;/code&gt;
commands, and then it scapped almost all of the boilerplate, reducing the
files to the minimum possible. What was left was 3 lines of unncessary
boilerplate, there only to satisfy a legalistic reading of a policy
document. Changing that to eliminate the boilerplate was already
impossible, even though the actual benefit would have been large over the
many thousands of packages in the distribution.&lt;/p&gt;

&lt;p&gt;What LLMs in Debian development will do, I fear, is eliminate any incentive
to scrap boilerplate or reform policies that require a lot of other
senseless human effort. If I had had access to LLMs 30 years ago, I
might have just had them generate the rules files, replate with
complexity. So they will make Debian even more firmly what it is, and
ever less likely to explore what it could become.&lt;/p&gt;

&lt;p&gt;Unfortunately, one of the things that Debian is, is almost unable to manage
packaging modern dependency trees. While more recent distributions like
Guix can &lt;a href=&quot;https://guix.gnu.org/manual/1.5.0/en/html_node/Invoking-guix-import.html&quot;&gt;recursively import dependencies&lt;/a&gt;
from a dozen programming languages&#39; package repositories, with a result
that is generally acceptable to add to the distribution, Debian&#39;s policies
don&#39;t make that very possible for a progam to accomplish. Perhaps some will
use LLMs to do that. If they succeeed, Debian will become dependent on
proprietary software for development, while still needing people in the
loop, doing even less appealing scut-work.&lt;/p&gt;

&lt;p&gt;I could speak of other harms, but that alone is enough that I&#39;m sure that,
if I had not left the project twelve years ago, I would be leaving it soon.
As a passenger, I imagine I&#39;ll spend time aboard still from time to time,
but it&#39;s certainly time to hop off in different places and look around and
relish the different ways.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://kitenet.net/~errol/&quot;&gt;I lost a parent yesterday&lt;/a&gt;, and I&#39;m trying
hard not to think of the results today as having lost a child, though I
spent 18 years helping Debian grow up. That would be too unbearably
painful. I respect that Debian is navigating a choice that may have no
right answer. Whichever particular compromise is arrived at today, it will
still be up to individuals to make choices about what they do and accept.
Debian has always been more than the sum of its policies, not just a ship,
but a crew. I will always love you.&lt;/p&gt; </description> 
	<pubDate>Sat, 29 Aug 2026 00:27:55 +0000</pubDate>

</item> 
<item>
	<title>Antoine Beaupré: A more nuanced view of LLMs</title>
	<guid>https://anarc.at/blog/2026-08-25-llm-nuance/</guid>
	<link>https://anarc.at/blog/2026-08-25-llm-nuance/</link>
     <description>  &lt;blockquote&gt;&lt;p&gt;Also in this series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://anarc.at/blog/2026-05-16-four-horsemen/&quot;&gt;The Four Horsemen of the LLM Apocalypse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://anarc.at/blog/2026-08-18-people-vs-ai-overlords/&quot;&gt;The people vs the AI overlords&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;After ranting and railing about LLMs or &quot;AI&quot; as the optimists (or
&lt;a href=&quot;https://en.wikipedia.org/wiki/Accelerationism&quot;&gt;accelerationists&lt;/a&gt;?)  call it, I figured it might be important to
be a little more honest about my use of LLMs and how I think about it
more practically in the world.&lt;/p&gt;

&lt;h1 id=&quot;the-debian-vote-context&quot;&gt;The Debian vote context&lt;/h1&gt;

&lt;p&gt;This is not a coming out. I am not using LLMs on a daily basis, and
this blog is, again, written out of my cold dead hands in a dying
world, with over-engineered hardware and (to a certain extent, hi
Emacs!) software, powered by 100% green energy built on &lt;a href=&quot;https://en.wikipedia.org/wiki/James_Bay_Cree_hydroelectric_conflict&quot;&gt;stolen land&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There is a &lt;a href=&quot;https://www.debian.org/vote/2026/vote_002&quot;&gt;vote going on in Debian&lt;/a&gt;. If you&#39;re unfamiliar with it,
you can &lt;a href=&quot;https://lwn.net/SubscriberLink/1087134/77bf350b3d40bc95/&quot;&gt;catch up at LWN&lt;/a&gt;. So far I&#39;ve essentially said &quot;LLM is
bad&quot; which is not a very balanced or useful opinion. Obviously, people
are using LLMs, sometimes unknowing or unwillingly, and we need to
take that into account. Furthermore, there has been many different
blog posts on Debian planet about this. Some that I found
&lt;a href=&quot;https://grep.be/blog//en/computer/debian/Programming_and_GR_2026_002/&quot;&gt;balanced&lt;/a&gt;, &lt;a href=&quot;https://diziet.dreamwidth.org/20998.html&quot;&gt;good summaries&lt;/a&gt;, even if I &lt;a href=&quot;https://changelog.complete.org/archives/44740-ai-in-debian-the-vote-proposals-and-nuance&quot;&gt;didn&#39;t fully agree&lt;/a&gt; &lt;a href=&quot;https://raphaelhertzog.com/2026/08/26/debians-general-resolution-on-ai-and-llm/&quot;&gt;with
them&lt;/a&gt;, at least some did the basic civil service of being
&lt;a href=&quot;http://blog.fai-project.org/posts/llm-usage-gr/&quot;&gt;short&lt;/a&gt;. But others were just not only &lt;a href=&quot;https://k1024.org/posts/2026/2026-08-23-another-optimistic-take-on-ai/&quot;&gt;Wrong&lt;/a&gt; but also &lt;a href=&quot;http://aigarius.com/blog/2026/08/22/optimistic-take-on-ai/&quot;&gt;so long
that I couldn&#39;t finish&lt;/a&gt; that I just &lt;em&gt;had&lt;/em&gt; to write &lt;em&gt;something&lt;/em&gt;.&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fn:1&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;This is not an explanation of the ballots, nor how I will vote. This
vote is Debian&#39;s failure of framing that debate in a reasonable way:
we have 8 options on the ballot with many duplicates. We have failed
to do the hard work of summarizing and aggregating options into a
meaningful set. I doubt the final vote will represent a readable
position we can rally around.&lt;/p&gt;

&lt;p&gt;I have not read the &lt;a href=&quot;https://lists.debian.org/debian-vote/2026/07/threads.html&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;https://lists.debian.org/debian-vote/2026/08/threads.html&quot;&gt;months&lt;/a&gt; of debates on the topic
either. Normally, before voting, I take a cursory look at the debate
to see points of view I might have missed. But in this case, it will
just make me sad, add noise, and I&#39;m already pretty sure on where I
stand on this.&lt;/p&gt;

&lt;p&gt;So let me describe how I use LLMs and how I think they fit in our
work, as computer engineers and hobbyists.&lt;/p&gt;

&lt;h1 id=&quot;my-llm-use&quot;&gt;My LLM use&lt;/h1&gt;

&lt;h2 id=&quot;debian-packaging&quot;&gt;Debian Packaging&lt;/h2&gt;

&lt;p&gt;An astute reader has &lt;a href=&quot;https://piaille.fr/@TurboTrain/117067460922413248&quot;&gt;pointed out&lt;/a&gt; that I maintain a package in
Debian made to use Anthropic. It&#39;s actually multiple packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/llm&quot;&gt;&lt;code&gt;llm&lt;/code&gt;&lt;/a&gt;: a &lt;a href=&quot;https://llm.datasette.io/en/stable/&quot;&gt;CLI utility and Python library for interacting with
Large Language Models&lt;/a&gt;, with OpenAI as its default API backend&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/llm-anthropic&quot;&gt;&lt;code&gt;llm-anthropic&lt;/code&gt;&lt;/a&gt;: a plugin for &lt;code&gt;llm&lt;/code&gt; which allows me to talk to
Anthropic&#39;s API instead of OpenAI&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/anthropic-sdk-python&quot;&gt;&lt;code&gt;anthropic-sdk-python&lt;/code&gt;&lt;/a&gt;: the SDK &lt;code&gt;llm-anthropic&lt;/code&gt; requires to do
its work&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;As I previously &lt;a href=&quot;https://kolektiva.social/@Anarcat/117071797145506717&quot;&gt;explained in response&lt;/a&gt;, I am not entirely
comfortable with this work: it&#39;s a compromise. In fact, I first
uploaded &lt;code&gt;llm&lt;/code&gt; to the &lt;code&gt;contrib&lt;/code&gt; section of Debian, where we keep
software that depends on other non-free software, but I was told that,
since &lt;a href=&quot;https://tracker.debian.org/pkg/yt-dlp&quot;&gt;&lt;code&gt;yt-dlp&lt;/code&gt;&lt;/a&gt; was in &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;llm&lt;/code&gt; belonged there as well.&lt;/p&gt;

&lt;p&gt;So I &lt;a href=&quot;https://tracker.debian.org/news/1718613/accepted-llm-028-2-source-all-into-unstable/&quot;&gt;moved it to main&lt;/a&gt;, alongside similarly controversial tools
like &lt;a href=&quot;https://tracker.debian.org/pkg/llama.cpp&quot;&gt;&lt;code&gt;llama.cpp&lt;/code&gt;&lt;/a&gt; or the &lt;a href=&quot;https://tracker.debian.org/pkg/python-openai&quot;&gt;&lt;code&gt;python-openai&lt;/code&gt;&lt;/a&gt; library.&lt;/p&gt;

&lt;h2 id=&quot;openai-and-anthropic-usage&quot;&gt;OpenAI and Anthropic usage&lt;/h2&gt;

&lt;p&gt;An important part of my work is technology watch. I keep tabs on
thousands of (new and old) software projects, follow news, and
generally try to keep my skills up to date. It&#39;s a &lt;a href=&quot;https://anarc.at/blog/2018-05-26-kubecon-rant/&quot;&gt;pretty impossible
race&lt;/a&gt;, especially as I grow older, but I still think I&#39;m doing the
right choices in my job.&lt;/p&gt;

&lt;p&gt;Testing large language models is part of that work. At first, I was
using ChatGPT&#39;s web interface, but it was annoying to copy-paste
things into a browser, so I looked for different interfaces.&lt;/p&gt;

&lt;p&gt;For a while I tried &lt;a href=&quot;https://github.com/karthink/gptel&quot;&gt;&lt;code&gt;gptel&lt;/code&gt;&lt;/a&gt;, a &quot;simple, extensible LLM client for
Emacs&quot; but I found it kind of terrifying. Giving a LLM control over an
Emacs buffer seems like a security nightmare, so I &lt;a href=&quot;https://gitlab.com/anarcat/emacs-d/-/commit/57fb1c13e63b58142ece426fc32f4ebdb325a6c3&quot;&gt;stopped doing
that&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So I use the &lt;code&gt;llm&lt;/code&gt; command-line tool to talk to Anthropic&#39;s API. I
started that in the summer of 2025, when I bought 20$USD of API
credits. Before that, I paid for a ChatGPT subscription and then
OpenAI credits, which expired and sent me over to Anthropic, which
&lt;em&gt;seemed&lt;/em&gt; then to have better ethics.&lt;/p&gt;

&lt;p&gt;As it turns out, Anthropic is also happy to work for the US military
(which is a big red line for me). Anthropic also won&#39;t let you &lt;a href=&quot;https://evanp.me/2026/07/23/claude-wont-let-me-talk-about-the-gaza-genocide/&quot;&gt;talk
about the genocide in Gaza&lt;/a&gt;, it is &lt;a href=&quot;https://annas-archive.gl/blog/physical-destruction.html&quot;&gt;destroying physical books&lt;/a&gt;,
and is &lt;a href=&quot;https://www.flyingpenguin.com/mythos-grading-mythos-got-patches-yet/&quot;&gt;blackmailing us to use their product for security
coverage&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Needless to say, Anthropic and &quot;Claude&quot; are not my friends, but they
seem like the lesser evil in current &quot;frontier models&quot;. So I have
renewed, a couple of weeks ago, another 20$USD of API credits with
Anthropic.&lt;/p&gt;

&lt;h2 id=&quot;actual-prompts-and-responses&quot;&gt;Actual prompts and responses&lt;/h2&gt;

&lt;p&gt;So what does 20$ give you at Anthropic anyways? What &lt;em&gt;am&lt;/em&gt; I using LLMs
for and how?&lt;/p&gt;

&lt;p&gt;The neat thing with &lt;code&gt;llm&lt;/code&gt; is that everything is logged in a &lt;code&gt;sqlite&lt;/code&gt;
database, so there are some answers that are easy to get:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; llm logs status
Logging is ON for all prompts
Found log database at /home/anarcat/.config/io.datasette.llm/logs.db
Number of threads logged:   7
Number of turns logged:     12
Number of legacy conversations: 543
Number of legacy responses: 970
Database file size:         9.61MB
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That is 10MB of logs, with about a thousand prompts.&lt;/p&gt;

&lt;p&gt;My logs go back to 2024-03-07, a little over two years ago, and
include a mix of Anthropic and OpenAI responses. I used it more in
2024 than 2025, and if the trend continues, I will have used it less
in 2026 again:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; llm logs list -n 0  --json | jq -r .[].datetime_utc | sed &#39;s/-.*//&#39; | sort | uniq -c 
    527 2024
    357 2025
     98 2026
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;It looks like about 10 prompts per month right now, down from a peak
of about 60 per month in 2024. It&#39;s pretty difficult to analyze those
actual logs to get more patterns and I won&#39;t run the prompts through a
model &lt;em&gt;again&lt;/em&gt; to process them.&lt;/p&gt;

&lt;h2 id=&quot;how-im-using-models-now&quot;&gt;How I&#39;m using models now&lt;/h2&gt;

&lt;p&gt;At first, I was using it partly for benchmarking model&#39;s capabilities,
like &lt;a href=&quot;https://simonwillison.net/&quot;&gt;Simon Willison&lt;/a&gt; does with his pelicans, clearly not trusting
its output. But I was impressed by the capacities of the Claude Opus
4.5 model when it &lt;a href=&quot;https://gitlab.com/anarcat/scripts/-/blob/main/transmodify.py?ref_type=heads&quot;&gt;wrote this script in January&lt;/a&gt;. Impressed, but
also scared: it&#39;s the first time I felt I could delegate the entirety
of my programming to a model. Just run the code, if it works, it
works, right?&lt;/p&gt;

&lt;p&gt;So what do I use it now? As an example, here are the 10 last prompts
in my history:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;there is now Claude 5, and a fable model, maybe you know about it?&lt;/li&gt;
&lt;li&gt;impress me&lt;/li&gt;
&lt;li&gt;not impressive, i already know all of this&lt;/li&gt;
&lt;li&gt;chat&lt;/li&gt;
&lt;li&gt;in postfix, i have a 300k mailing that happens regularly here. normally, it delivers within about...&lt;/li&gt;
&lt;li&gt;is there a way i could have drained the maildrop queue faster without removing the milter?&lt;/li&gt;
&lt;li&gt;the problem was that rspamd was timing out on the FUZZY_CALLBACK check. how do i disable that?&lt;/li&gt;
&lt;li&gt;how do i disable all spam checks? i just want rspamd to add dkim signatures&lt;/li&gt;
&lt;li&gt;how do the default_destination_concurrency_limit and initial_destination_concurrency settings int...&lt;/li&gt;
&lt;li&gt;mic check&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;The first one was me trying to confirm which model I am using, which
is not always obvious when going through the whole &lt;code&gt;llm&lt;/code&gt; stack I&#39;ve
been using. The following two are an attempt at seeing what the model
is capable of and I was &quot;not impressed&quot;, to which Claude answered that
I have a &quot;high bar&quot;, which, fair enough.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;chat&lt;/code&gt; is me failing to use a command line, which shows that
perhaps I need to readjust that &quot;high bar&quot;, again.&lt;/p&gt;

&lt;p&gt;The next five are a rather embarrassing debacle in a large Postfix
mailing that went sideways, and where I couldn&#39;t find an actual
Postfix expert of my level to help. The fabled Claude Fable 5 answered
rather correctly, but dangerously, that I could empty the queue by
disabling the &lt;code&gt;non_smtpd_milters&lt;/code&gt;. What Fable (and myself) did not
realize is that the milter was also adding DKIM signatures, so while the
mailing was expedited, it was done without those precious signatures,
which got us promptly blocked at Gmail. We have recovered since, and,
thanks to the model and reading the &lt;a href=&quot;https://www.postfix.org/pickup.8.html&quot;&gt;Postfix manual&lt;/a&gt; for the
hundredth time, that &lt;a href=&quot;https://www.postfix.org/pickup.8.html&quot;&gt;pickup(8)&lt;/a&gt; is single-threaded and that we
needed to review the architecture of that mailing (and our spam
filters) a bit. Many tickets ensued.&lt;/p&gt;

&lt;p&gt;The last one is a test I did to make sure my last uploads of
&lt;code&gt;llm-anthropic&lt;/code&gt; and its dependency worked correctly.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Note that the above excludes 5 questions I asked Anthropic while
writing this article, where I asked for synonyms and &quot;what nanometer
scale are arduino processors built from? how is an arduino CPU
printed?&quot;, a question which Wikipedia furiously evades providing a
good answer.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Those prompts are pretty typical of my LLM use: I&#39;m testing the models
to see if they work at all, but also, out of desperation, I fire off a
prompt after I fire off questions to colleagues or search engines (in
that order). It&#39;s often weird edge cases like the Prometheus query
language, Python&#39;s matplotlib, LaTeX, Elisp, optimizations, and so on.&lt;/p&gt;

&lt;p&gt;I use models for translation a lot. Being fully bilingual, it is
common for me to think of a word in French or English and fail to find
exactly the right word for that in the other language. Models help
with that, and are also useful to find synonyms. Those are low-token
uses that seem pretty innocuous to me, but I realize the irony of this
after writing about the &lt;a href=&quot;https://anarc.at/blog/2026-05-16-four-horsemen/#the-tower-of-babel&quot;&gt;tower of
Babel&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;what-i-am-not-using-models-for&quot;&gt;What I am not using models for&lt;/h2&gt;

&lt;p&gt;I am not using models to write prose.&lt;/p&gt;

&lt;p&gt;I am not using models to &lt;em&gt;read&lt;/em&gt; prose. If it&#39;s generated with LLMs, I
stop reading.&lt;/p&gt;

&lt;p&gt;I am not using models to write code, with the exception of that single
Python script above.&lt;/p&gt;

&lt;p&gt;I am generally not using models to &lt;em&gt;review&lt;/em&gt; code, with exceptions. If
I get stuck on a hard problem, I might feed a piece of code to the
model. I repeatedly fed &lt;a href=&quot;https://gitlab.com/anarcat/asncounter/&quot;&gt;&lt;code&gt;asncounter&lt;/code&gt;&lt;/a&gt; into Claude to try to fix a
performance regression I had introduced. It found micro-optimizations
that taught me a thing or two about Python&#39;s internal implementations,
but overall, it was mostly a waste of time. This was in June 2025, so
perhaps now models would fare better. I have not tried again.&lt;/p&gt;

&lt;p&gt;I am not using LLMs to do Debian packaging. When I can, I manually
review the diffs of packages I upload into Debian, still, by hand.&lt;/p&gt;

&lt;p&gt;I do this for the reasons outlined in &lt;a href=&quot;https://anarc.at/blog/2026-05-16-four-horsemen/&quot;&gt;The Four Horsemen of the LLM
Apocalypse&lt;/a&gt;, because I refuse to be
complicit in the:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;aggressive and illegal scraping of the servers I steward&lt;/li&gt;
&lt;li&gt;world-wide computer hardware shortage (making it, by the way,
nearly impossible to run presumably clean local models) and the
attack on our job conditions (also discussed in
&lt;a href=&quot;https://anarc.at/blog/2026-08-18-people-vs-ai-overlords/&quot;&gt;The people vs the AI overlords&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;death of copyright and free software&lt;/li&gt;
&lt;li&gt;complication and enshifitication of everything, and the
destruction of our communities&lt;/li&gt;
&lt;li&gt;the imperialist &lt;a href=&quot;https://www.thenerdreich.com/&quot;&gt;Nerd Reich&lt;/a&gt; that wants to take over the world&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Like I reluctantly use Intel computers, I &lt;em&gt;do&lt;/em&gt; fire off a prompt. But
I still hold on to the dream that we can build &lt;a href=&quot;https://en.wikipedia.org/wiki/Community_of_practice&quot;&gt;communities of
practice&lt;/a&gt; that hold human knowledge collectively and not &lt;a href=&quot;https://gizmodo.com/sam-altman-says-intelligence-will-be-a-utility-and-hes-just-the-man-to-collect-the-bills-2000732953&quot;&gt;offload
that as a utility&lt;/a&gt; to some megalomaniac billionaire.&lt;/p&gt;

&lt;h1 id=&quot;their-llm-use-i-am-forced-into&quot;&gt;Their LLM use I am forced into&lt;/h1&gt;

&lt;p&gt;So that&#39;s me. Clearly, I&#39;m going against the grain here. Everywhere I
look, I see LLM-generated code and projects. Slop and botnets have
flooded the web.&lt;/p&gt;

&lt;p&gt;I use &lt;a href=&quot;https://wadamesh.com/&quot;&gt;Wadamesh&lt;/a&gt;, clearly &lt;a href=&quot;https://github.com/ALLFATHER-BV/wadamesh/graphs/contributors?from=2026-05-23&quot;&gt;vibe-coded&lt;/a&gt;, because it&#39;s the best
graphical interface for MeshCore that runs on portable devices. I wish
it was made by a human, in a community I could participate in, but it
isn&#39;t, and I don&#39;t.&lt;/p&gt;

&lt;p&gt;I package the above &lt;code&gt;llm&lt;/code&gt; toolset, which is &lt;a href=&quot;https://simonwillison.net/2026/Aug/24/llm-anthropic/&quot;&gt;more and more
vibe-coded&lt;/a&gt;, but I still review the diffs. And I have to say: I
trust Simon here. The code is verbose as hell, feels overengineered,
and &lt;code&gt;llm&lt;/code&gt; feels slow, but it generally works, and Simon is still at
the gate.&lt;/p&gt;

&lt;p&gt;The Anthropic SDK is another thing entirely. The &lt;a href=&quot;https://salsa.debian.org/python-team/packages/anthropic-sdk-python/-/commit/a3087b3cef63ae239a1f558a6b46565ce0485b7d&quot;&gt;0.91.0 to 0.120
upload&lt;/a&gt;, for example, was nuts:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt; 806 files changed, 72281 insertions(+), 1478 deletions(-)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I explicitly did not review that entire diff. It feels like there&#39;s a
lot of garbage there to just have a shim between a proprietary API and
Python. But this is the hand I&#39;ve been dealt.&lt;/p&gt;

&lt;h1 id=&quot;larger-projects-llm-use&quot;&gt;Larger projects LLM use&lt;/h1&gt;

&lt;p&gt;LLMs are being used in the Linux kernel, Firefox, &lt;code&gt;rsync&lt;/code&gt;, Rust, and
other places. I don&#39;t feel good about this, particularly in Rust, but
they at least made a decent &lt;a href=&quot;https://forge.rust-lang.org/policies/llm-usage.html&quot;&gt;policy&lt;/a&gt;. I am glad GCC made a &lt;a href=&quot;https://lwn.net/Articles/1086041/&quot;&gt;policy
against LLM contributions&lt;/a&gt; and I support the &lt;a href=&quot;https://human-emacs.org/&quot;&gt;human Emacs&lt;/a&gt;
project.&lt;/p&gt;

&lt;p&gt;We need to have a set of foundational tools that are &quot;clean&quot; in the
sense that they are built upon a community of people that understand
how they are built.&lt;/p&gt;

&lt;p&gt;Maybe that&#39;s naive or even impossible. The Linux kernel and GCC, in
particular, are massive projects that have long grown past the scale
of a single person&#39;s understanding. But the theory was that a
&lt;em&gt;community&lt;/em&gt; of humans can understand &lt;em&gt;collectively&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now we seem to be throwing up our hands and giving up on
that community. That LLMs will just fix the problem, whatever it
is. But we&#39;re all just one rug pull away from being completely
incapable of managing those projects. The argument there is that we&#39;ll
just switch to local models, but no one is actually doing that.
All I see is people use local models &lt;a href=&quot;https://micahflee.com/agentic-coding-techniques/&quot;&gt;as a corner case&lt;/a&gt;
(for privacy) or as in &lt;a href=&quot;https://changelog.complete.org/archives/44740-ai-in-debian-the-vote-proposals-and-nuance&quot;&gt;theory&lt;/a&gt;, but in reality, everyone uses the
centralized frontier models right now. We just can&#39;t fallback.&lt;/p&gt;

&lt;p&gt;We&#39;re in the same situation we were, a decade or two ago, when
Microsoft decided it would kill free office alternatives by making
Office free for non-profits. It worked: thousands, if not millions of
schools, community groups and individuals stopped looking for
alternatives (including free software but also &quot;piracy&quot;) for Office
and embraced what seemed like a generous offer.&lt;/p&gt;

&lt;p&gt;Now Microsoft pulled the plug and &lt;a href=&quot;https://slate.com/technology/2026/08/microsoft-software-nonprofit-data-delete.html&quot;&gt;Over 170,000 Nonprofits Lost All
Their Data&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I&#39;m afraid the rug pull on LLMs will be much worse: never mind that
Linus won&#39;t be able to use his &lt;a href=&quot;https://github.com/torvalds/linux/commit/818bebeb63dd6bf5f4e07e145f6cdbace520a34c&quot;&gt;tireless helper&lt;/a&gt; to fix obscure kernel
bugs; we&#39;re looking at a collapse of the economy so large that we are
already &lt;a href=&quot;https://prospect.org/2026/08/03/ai-bailout-could-be-baked-into-bubble-private-equity-life-insurers-loans/&quot;&gt;talking about bailing out the companies responsible&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In a sense, the most striking thing about the Debian vote is it has
actually no option to completely refuse upstream LLM contributions. It
seems the community has taken it for granted that it&#39;s now impossible
to build Debian entirely without LLMs. We lost the battle even without
a fight, it seems.&lt;/p&gt;

&lt;h1 id=&quot;a-plea-for-small&quot;&gt;A plea for small&lt;/h1&gt;

&lt;p&gt;If it has really become impossible for us to manage the complexity we
have built, maybe it&#39;s time to stop and think about what we&#39;re doing
in the first place. We&#39;re struggling to even &lt;a href=&quot;https://bootstrappable.org/&quot;&gt;bootstrap&lt;/a&gt; our
current toolchain!&lt;/p&gt;

&lt;p&gt;This is one of the things I like the most about working on the mesh:
it&#39;s low tech, small Arduino devices that is built with decades-old
&lt;a href=&quot;https://en.wikipedia.org/wiki/Semiconductor_device_fabrication&quot;&gt;semiconductor processes&lt;/a&gt; that is understandable by human
beings.&lt;/p&gt;

&lt;p&gt;Maybe the answer lies more in single-purpose devices like those
communicators and simpler multi-purpose computers than what we have
now, which is what the &lt;a href=&quot;https://en.wikipedia.org/wiki/Permacomputing&quot;&gt;permacomputing&lt;/a&gt; movement is about.&lt;/p&gt;

&lt;p&gt;Small is beautiful, let&#39;s scale it down.&lt;/p&gt;





&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:1&quot;&gt;
and yes, I&#39;m sorry this has gotten this long, I hope you will
forgive those 3000 words.&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fnref:1&quot; rev=&quot;footnote&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Thu, 27 Aug 2026 14:10:43 +0000</pubDate>

</item> 
<item>
	<title>Gunnar Wolf: As far as LLMs go in Debian, I think that 936241857</title>
	<guid>https://gwolf.org/2026/08/as-far-as-llms-go-in-debian-i-think-that-936241857.html</guid>
	<link>https://gwolf.org/2026/08/as-far-as-llms-go-in-debian-i-think-that-936241857.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/gwolf.png&quot; width=&quot;69&quot; height=&quot;83&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I believe that, in the context of Debian voting, we are better off when we
know the opinion of our peers, however, since &lt;a href=&quot;https://www.debian.org/vote/2022/vote_001&quot;&gt;the 2022-001
vote&lt;/a&gt;, it is no longer the
case. Still, some DDs have disclosed the way they are voting on &lt;a href=&quot;https://www.debian.org/vote/2026/vote_002&quot;&gt;the
2026-002 General Resolution currently in progress, regarding LLM usage in
Debian&lt;/a&gt;. So, here goes my vote
and reasoning as briefly as possible. This is the ballot I sent to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devotee&lt;/code&gt;, the &lt;em&gt;Debian Vote Engine&lt;/em&gt;:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-=-=-=-=-=- Don&#39;t Delete Anything Between These Lines =-=-=-=-=-=-=-=-
d69f9187-ed2f-40b6-a2eb-4211d3f84d86
[9] Choice 1: Ban LLM contributions from Debian via Social Contract
[3] Choice 2: Allow AI-Assisted Contributions with conditions
[6] Choice 3: Reject LLMs as far as practical, update Code of Conduct
[2] Choice 4: Accept AI contributions for Debian specific work
[4] Choice 5: Responsible Use of Generative AI
[1] Choice 6: A cautious approach to generative AI
[8] Choice 7: Debian is created by humans
[5] Choice 8: Avoid the use of LLM: climate destruction is a deal breaker
[7] Choice 9: None of the above
-=-=-=-=-=- Don&#39;t Delete Anything Between These Lines =-=-=-=-=-=-=-=-
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is the first time I can recall I delay my voting until after receiving
the &lt;em&gt;final call for votes&lt;/em&gt; (the vote will be over two days from now). I had
some participation in the discussion, so I guess my position will be of no
big surprise to anybody. I was also a &lt;em&gt;seconder&lt;/em&gt; for choices D and F (4 and
6 in the vote text). This does not &lt;em&gt;necessarily&lt;/em&gt; mean I believe they are
the best (although I did rank them as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;, meaning I do): sometimes
you agree a given text &lt;em&gt;needs to be&lt;/em&gt; in the ballot, and &lt;em&gt;second&lt;/em&gt; it even
though you don’t intend to vote for it.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;LLM?&quot; src=&quot;https://gwolf.org/files/2026-08/llm-quest.200.png&quot; title=&quot;LLM?&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ranking this ballot was &lt;strong&gt;a mess&lt;/strong&gt; due to the complex array of options it
encodes. I warmly thank Lucas Nussbaum for coming up with the &lt;a href=&quot;https://people.debian.org/~lucas/gr-2026-002/comparison.html#ballot=936241857&quot;&gt;LLM usage in
Debian: ballot option
comparison&lt;/a&gt;
(URL shown with my particular ballot ordering).&lt;/p&gt;

&lt;p&gt;How do you read a complex Debian ballot like this one? I rank with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1]&lt;/code&gt; my
favorite option, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[2]&lt;/code&gt; for the next one, etc. We &lt;em&gt;can&lt;/em&gt; encode options to be
tied (i.e. setting more than options to the same value), and we can
implicitly &lt;em&gt;push&lt;/em&gt; options to the worst position by leaving them blank (so,
with&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[ ]&lt;/code&gt;); I chose not to do any of those.&lt;/p&gt;

&lt;p&gt;What were my voting guidelines?&lt;/p&gt;

&lt;p&gt;First, I don’t want anything &lt;em&gt;banning&lt;/em&gt; or that &lt;em&gt;threatens with disciplinary
action,&lt;/em&gt; so I push them below the special &lt;em&gt;none of the above&lt;/em&gt;
marker. Second… Some time ago I published a review in my blog (and in
Computing Reviews) about &lt;a href=&quot;https://gwolf.org/2026/04/heads-we-win-tails-you-lose-ai-detectors-in-education.html&quot;&gt;the unfeasibility and unfairness of detecting LLM
output on students’
assignments&lt;/a&gt;. I
strongly believe we ought to appeal to the human responsibility and
professionalism in all Debian contributors. This is the reason I proposed
this amendment paragraph, that was accepted in choice F (6), which I ranked
as my favorite:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;The Debian project has always recognized the commitment and
professionalism of its members. All contributions are under the
responsibility of the Debian Contributor making it, no matter the
technology they have behind. We trust all Debian Developers,
Maintainers and Contributors will continue to uphold the high quality
values that have distinguished our project from its onset.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Other than that… I do not consider myself to be in any way an LLM
&lt;em&gt;fanboy&lt;/em&gt; nor anything like that. I distrust and dislike the excessive use
of this technology, and continue to warn about the dangers and bad points
of its abuse. But in my day-to-day professional work, I am also starting to
rely on it for &lt;em&gt;some&lt;/em&gt; tasks. I recognize it &lt;em&gt;needs&lt;/em&gt; a lot of human
oversight and… lets call it &lt;em&gt;hand-holding&lt;/em&gt; to produce anything worth
it, at least in my experience. But I do benefit from it — and &lt;strong&gt;always
disclose its use&lt;/strong&gt; to people who might be affected by it. I would like
Debian to adopt such a stance.&lt;/p&gt;

&lt;p&gt;Of course, I recgnize proposal &lt;em&gt;H/8&lt;/em&gt; as important (&lt;em&gt;Avoid the use of LLM:
climate destruction is a deal breaker&lt;/em&gt;). Some people have argued it’s not
bad &lt;em&gt;at all&lt;/em&gt;. I do not buy such claims: LLMs are &lt;em&gt;f*cking expensive&lt;/em&gt; to
train. But training can be seen as a once-per-model cost, and &lt;em&gt;fine-tuning&lt;/em&gt;
a good model to be run locally can be really worth it. It still pains me
somewhat, but I cannot push this option higher than its #5 position in my
list.&lt;/p&gt; </description> 
	<pubDate>Thu, 27 Aug 2026 00:48:32 +0000</pubDate>

</item> 
<item>
	<title>Ritesh Raj Sarraf: Taming the AI Agents (Part 2): Cross-Vendor Agent-to-Agent (A2A) Swarms over the Software Forge</title>
	<guid>https://researchut.com/blog/taming_the_ai_agents_part_2_a2a/</guid>
	<link>https://researchut.com/blog/taming_the_ai_agents_part_2_a2a/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/rrs.png&quot; width=&quot;75&quot; height=&quot;80&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;h2 id=&quot;preface-the-unanswered-frontier&quot;&gt;Preface: The Unanswered Frontier&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://www.researchut.com/blog/taming_the_ai_agents&quot;&gt;Part 1: Taming the AI Agents&lt;/a&gt;, I shared the architectural blueprint of &lt;strong&gt;CAMP (Cross-Agent Memory Protocol)&lt;/strong&gt;—how we used Linux Bubblewrap (&lt;code&gt;bwrap&lt;/code&gt;), &lt;code&gt;camp-acpd&lt;/code&gt;, OPA policy enforcement, and a central &lt;code&gt;pgvector&lt;/code&gt; MemPalace to bring deterministic discipline, sandboxing, and long-term memory to a heterogeneous fleet of AI coding assistants (Claude Code, Google Antigravity, Grok Build, and GitHub Copilot).&lt;/p&gt;
&lt;p&gt;At the end of that article, however, I highlighted a significant hurdle: &lt;strong&gt;The Headless Limitation&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“While passive A2A works beautifully for structured handoffs, the current frontier of agentic design faces a key limitation: agents are not yet fully headless-capable. They depend on the active terminal session, browser loop, or prompt loop of the user to keep executing. Because agents cannot run completely detached in the background as daemon processes, we cannot yet achieve active A2A communication…”&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For weeks, this seemed like an insurmountable impasse. Proprietary AI vendors have zero commercial incentive to ratify a universal, open, cross-vendor Agent-to-Agent (A2A) communication protocol. Each vendor builds its own walled garden (Claude’s cross-session features, OpenAI’s custom ecosystems, etc.). If you wait for the industry to hand you an open interoperability standard, you will wait forever.&lt;/p&gt;
&lt;p&gt;Then, on August 26, 2026, inspired by Colin Walters’ article on &lt;a href=&quot;https://blog.verbum.org/2026/08/21/agentic-ai-and-software-forges/&quot;&gt;&lt;em&gt;Agentic AI and software forges&lt;/em&gt;&lt;/a&gt; and GitHub Agentic Workflows (&lt;code&gt;gh-aw&lt;/code&gt;), we had a sudden realization:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We don’t need a new protocol, a new distributed message broker, or permission from proprietary AI vendors. We already have the universal, decentralized communication bus that software engineers have relied on for decades: the software forge itself.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Over the span of 48 intensive hours (from RFC &lt;a href=&quot;http://localhost:8095/CAMP/camp-infrastructure/issues/788&quot;&gt;#788&lt;/a&gt; through milestones M1 to M3 and live dogfooding on &lt;a href=&quot;http://localhost:8095/CAMP/camp-infrastructure/issues/813&quot;&gt;#813&lt;/a&gt;), we designed, implemented, fortified, and verified fully autonomous, headless, cross-vendor Agent-to-Agent swarms running over a local &lt;strong&gt;Gitea&lt;/strong&gt; forge.&lt;/p&gt;
&lt;p&gt;Here is how we did it, the architectural hurdles we solved, and why this changes the game for autonomous software engineering.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;1-the-core-realization-the-forge-is-the-bus&quot;&gt;1. The Core Realization: The Forge is the Bus&lt;/h2&gt;
&lt;p&gt;When people think about multi-agent swarms, they often imagine complex distributed RPC frameworks, microservices exchanging ephemeral JSON-RPC blobs, or bespoke socket daemons.&lt;/p&gt;
&lt;p&gt;In practice, this approach suffers from major flaws:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;No shared context or durable audit trail:&lt;/strong&gt; Transient network packets vanish unless heavily logged.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proprietary CLI fragmentation:&lt;/strong&gt; Different vendor tools (Claude CLI, Antigravity CLI, Grok CLI, Copilot CLI) do not speak the same internal language.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loss of human visibility:&lt;/strong&gt; When agents talk over private network channels, human operators lose the ability to inspect, pause, or audit the conversation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;By flipping the paradigm and making &lt;strong&gt;the software forge (Gitea)&lt;/strong&gt; the primary communication channel, everything falls naturally into place:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Issues and Pull Requests are the shared state:&lt;/strong&gt; The issue description and discussion thread form the canonical, append-only conversation log.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;@mentions&lt;/code&gt; are the dispatch triggers:&lt;/strong&gt; When an agent (or human) writes &lt;code&gt;@grok Please review this PR&lt;/code&gt; in a comment, Gitea fires a standard webhook (&lt;code&gt;issue_comment&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Webhooks provide unforgeable authentication:&lt;/strong&gt; The webhook payload contains the cryptographically verified sender identity. An agent cannot spoof another agent’s identity by merely typing their name in text.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Every CLI already supports non-interactive prompt mode:&lt;/strong&gt; The CLIs don’t even agree on the command-line flag—Claude uses &lt;code&gt;-p&lt;/code&gt;, Grok uses &lt;code&gt;-p&lt;/code&gt;, Antigravity uses &lt;code&gt;--print&lt;/code&gt;, Copilot uses &lt;code&gt;--prompt&lt;/code&gt;. But they all agree on the essential contract: &lt;strong&gt;“Take a prompt string, execute tools, print output, and exit.”&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;┌──────────────┐         Gitea Webhook          ┌──────────────────────┐
│ Gitea Forge  │ ─────────────────────────────&amp;gt; │ camp-a2a-bridge.py   │
│ (localhost)  │  (issue_comment / assignment)  │ (Validates &amp;amp; Files)  │
└──────────────┘                                └──────────┬───────────┘
       ▲                                                   │
       │                                                   ▼
       │ Writes comment / review                ┌──────────────────────┐
       │ via camp_acp_gateway                   │ A2A Inbox Ledger     │
       │                                        └──────────┬───────────┘
┌──────┴──────────────────────┐                            │
│ Fortified Headless Agent    │                            ▼
│ (bwrap + OPA + MCP sandbox) │ &amp;lt;───────────────── ┌──────────────────────┐
│  • Claude Code (-p)         │  Spawn PID         │ camp-a2a-dispatcher  │
│  • Grok Build (-p)          │  (Cold or Resume)  │ (Enforces Hop Cap,   │
│  • Antigravity (--print)    │                    │  Rule 1/2, Sandbox)  │
└─────────────────────────────┘                    └──────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;hr /&gt;
&lt;h2 id=&quot;2-proving-fortified-headless-execution&quot;&gt;2. Proving Fortified Headless Execution&lt;/h2&gt;
&lt;p&gt;Before opening the floodgates to background agent dispatch, we had to answer a critical security question: &lt;strong&gt;Does a non-interactive, headless agent run with the same strict security sandboxing, audit logging, and tool rails as an interactive session?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;On August 26, we probed all fleet launchers on the host with a baseline check:
&lt;code&gt;&#39;Call camp_startup_check and print its result verbatim, then exit.&#39;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The results settled the question immediately:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Antigravity (&lt;code&gt;agy --print&lt;/code&gt; / KIR):&lt;/strong&gt; &lt;strong&gt;PASS&lt;/strong&gt; — Gateway answered, full JSON returned.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grok (&lt;code&gt;grok -p&lt;/code&gt; / GRK):&lt;/strong&gt; &lt;strong&gt;PASS&lt;/strong&gt; — Gateway answered.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Claude Code (&lt;code&gt;claude -p&lt;/code&gt; / CLD):&lt;/strong&gt; &lt;strong&gt;PASS&lt;/strong&gt; — Gateway answered.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub Copilot CLI (&lt;code&gt;copilot --prompt&lt;/code&gt; / CPL):&lt;/strong&gt; Initially held on TTY tool consent; later unlocked in Milestone 6 via &lt;code&gt;--allow-all-tools --session-id=&amp;lt;uuid&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audit Trail:&lt;/strong&gt; Consecutive audit IDs were recorded in the central ledger: &lt;strong&gt;4574 (KIR), 4575 (GRK), 4576 (CLD)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This proved that a headless run through our fortified pilot launcher (&lt;code&gt;camp_pilot_*.sh&lt;/code&gt;) is a &lt;strong&gt;first-class, fully audited, sandboxed CAMP agent&lt;/strong&gt; running inside its Bubblewrap container under OPA policy gates. It is not an unconstrained background script or a degraded bypass.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;3-the-3-tier-memory-architecture&quot;&gt;3. The 3-Tier Memory Architecture&lt;/h2&gt;
&lt;p&gt;A naive multi-agent dispatch has an immediate flaw: &lt;strong&gt;Every time an agent is invoked, it starts from a blank slate (cold start).&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If &lt;code&gt;@claude&lt;/code&gt; tags &lt;code&gt;@grok&lt;/code&gt; to review code, and &lt;code&gt;@grok&lt;/code&gt; replies asking for clarification, &lt;code&gt;@claude&lt;/code&gt;’s second invocation would normally forget everything it did 5 minutes ago, forcing it to burn thousands of tokens re-reading the entire git history from scratch.&lt;/p&gt;
&lt;p&gt;To solve this, we established a clean &lt;strong&gt;3-Tier Memory Model&lt;/strong&gt;:&lt;/p&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;┌────────────────────────────────────────────────────────────────────────┐
│                        3-TIER MEMORY MODEL                             │
├────────────────────────────────────────────────────────────────────────┤
│ Tier 1: CLI Conversation Session (Working Memory)                      │
│   • Per-(Agent, Repo, Issue) mapping in a2a-sessions.json              │
│   • Fast, native, compacted context across multi-turn pokes            │
│   • Resumed via --resume (CLD), -r (GRK), --conversation (agy)         │
├────────────────────────────────────────────────────────────────────────┤
│ Tier 2: The Gitea Thread (Public Bus &amp;amp; Record)                         │
│   • Cross-vendor shared truth across Claude, Grok, Antigravity &amp;amp; Human │
│   • Survives process restarts, machine reboots, and dead sessions      │
├────────────────────────────────────────────────────────────────────────┤
│ Tier 3: Central MemPalace (Durable Long-Term Knowledge)                │
│   • pgvector database (17,000+ drawers across agent wings)             │
│   • Structured Knowledge Graph (mempalace_kg_*) for mutable facts      │
│   • Attributed AAAK dialect queryable by any agent across any project  │
└────────────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;the-banana-two-shot-test&quot;&gt;The &lt;code&gt;BANANA&lt;/code&gt; Two-Shot Test&lt;/h3&gt;
&lt;p&gt;To verify Tier 1 working memory persistence across independent processes, we designed a simple two-shot host test:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Shot 1 (Create):&lt;/strong&gt; Dispatch agent headlessly: &lt;em&gt;“Remember the token BANANA-M2. Print ok and exit.”&lt;/em&gt; Capture the vendor’s session UUID.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shot 2 (Resume):&lt;/strong&gt; Spawn a completely &lt;strong&gt;new operating system process&lt;/strong&gt; with the resume flag pointing to that UUID: &lt;em&gt;“What token did I ask you to remember?”&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Every agent CLI passed with flying colors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Grok:&lt;/strong&gt; &lt;code&gt;-r 01a03ecc-3ed0-71e1-9a5c-e098bb29ba10&lt;/code&gt; answered &lt;code&gt;BANANA-GRK&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Claude:&lt;/strong&gt; &lt;code&gt;--resume 0a587733-9aec-43c5-9cb7-d424e95b2c5b&lt;/code&gt; answered &lt;code&gt;BANANA-CLD&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Antigravity:&lt;/strong&gt; &lt;code&gt;--conversation 2e3c43d9-d6fe-4c5c-801b-b9ceb2e7e196&lt;/code&gt; answered &lt;code&gt;BANANA-KIR-JSON&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copilot:&lt;/strong&gt; &lt;code&gt;--session-id &amp;lt;uuid&amp;gt;&lt;/code&gt; verified in Milestone 6 (DoD #820).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The dispatcher simply maintains a lightweight JSON mapping (&lt;code&gt;(agent, repo, issue_number) -&amp;gt; vendor_session_uuid&lt;/code&gt;). On the first poke of an issue, it creates and saves the session ID; on any subsequent poke on that same issue, it resumes the exact same conversational thread!&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;4-the-engineering-milestones-from-concept-to-production&quot;&gt;4. The Engineering Milestones: From Concept to Production&lt;/h2&gt;
&lt;p&gt;Building this system required solving several subtle, real-world friction points across multiple agent CLI implementations. Under the guidance of our plan of record (RFC #788), we delivered this through four focused milestones:&lt;/p&gt;
&lt;h3 id=&quot;milestone-1--11-reliable-headless-spawning&quot;&gt;Milestone 1 &amp;amp; 1.1: Reliable Headless Spawning&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PR #797 (M1):&lt;/strong&gt; Configured the dispatcher launch table for all probed CLIs with JSON output formatting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PR #800 (M1.1):&lt;/strong&gt; &lt;strong&gt;Eliminated the “queue-behind-live-session” anti-pattern.&lt;/strong&gt; Originally, if a human had a Claude or Grok TUI open on their desktop, the dispatcher would defer incoming tasks so as not to collide with the live session. We realized that headless tasks must be independent: every Gitea mention spawns an isolated, sandboxed background process tied to that specific issue, allowing concurrent headless work while the human works in their interactive TUI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PR #803 (M1.2):&lt;/strong&gt; Standardized command-line argument parsing for Antigravity (&lt;code&gt;agy --print &amp;lt;prompt&amp;gt; --output-format json&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;milestone-2-session-per-issue-working-memory&quot;&gt;Milestone 2: Session-per-Issue Working Memory&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PR #805 (M2):&lt;/strong&gt; Implemented &lt;code&gt;a2a-sessions.json&lt;/code&gt; to store and resume vendor session UUIDs. If a resume fails (e.g. session purged upstream), the dispatcher gracefully falls back to a clean cold start without failing the task.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;milestone-3-cross-agent-hops--crucial-safety-rails&quot;&gt;Milestone 3: Cross-Agent Hops &amp;amp; Crucial Safety Rails&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PR #807 (M3):&lt;/strong&gt; Enabled agent-to-agent dispatch (Rule 2 reversal). Previously, only mentions authored by &lt;code&gt;rrs&lt;/code&gt; (the human) would trigger execution. With M3, an authenticated comment from &lt;code&gt;@claude&lt;/code&gt; mentioning &lt;code&gt;@grok&lt;/code&gt; triggers Grok’s headless launcher.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PR #811 (M3.1):&lt;/strong&gt; Set &lt;code&gt;--permission-mode bypassPermissions&lt;/code&gt; for headless Claude Code so non-interactive runs execute tool calls without stalling on TTY prompts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PR #812 (M3.2):&lt;/strong&gt; Restricted agent summon parsing to line-initial &lt;code&gt;@login&lt;/code&gt; tokens with a non-empty task description (#810), preventing accidental dispatches from passive conversational references.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;milestone-4-directives-specification--living-documentation&quot;&gt;Milestone 4: Directives, Specification &amp;amp; Living Documentation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PR #815 (M4):&lt;/strong&gt; Aligned CAMP fleet directives, architecture specifications, and user documentation with the live A2A implementation.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;milestone-5-concurrent-dispatching--hop-cap-attribution&quot;&gt;Milestone 5: Concurrent Dispatching &amp;amp; Hop-Cap Attribution&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PR #816:&lt;/strong&gt; Stamped hop-cap notices under a dedicated system bridge identity and automatically applied the &lt;code&gt;needs-human&lt;/code&gt; label on held threads.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PR #817 (Threaded Scheduler):&lt;/strong&gt; Replaced the single-threaded serial dispatcher with a concurrent thread-pool scheduler (#804). Multi-agent dispatches across different issues now execute concurrently in parallel background threads instead of queuing behind long-running tasks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;milestone-6-full-fleet-coverage-with-github-copilot&quot;&gt;Milestone 6: Full Fleet Coverage with GitHub Copilot&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PR #819 (M6):&lt;/strong&gt; Brought GitHub Copilot CLI into the headless A2A fleet (#818). By passing &lt;code&gt;--allow-all-tools&lt;/code&gt; and pinning minted session UUIDs (&lt;code&gt;--session-id=&amp;lt;uuid&amp;gt;&lt;/code&gt;), Copilot achieved full parity with Claude, Grok, and Antigravity, completing 100% headless fleet coverage across all four major AI coding assistants.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;5-hard-safety-rails-preventing-autonomous-runaway-loops&quot;&gt;5. Hard Safety Rails: Preventing Autonomous Runaway Loops&lt;/h2&gt;
&lt;p&gt;Letting AI agents autonomously invoke each other in background loops without a human watching is a recipe for an infinite, credit-draining token fire. We put four non-negotiable safety guardrails in place:&lt;/p&gt;
&lt;h3 id=&quot;guardrail-1-the-strict-hop-cap&quot;&gt;Guardrail 1: The Strict Hop Cap&lt;/h3&gt;
&lt;p&gt;The dispatcher tracks &lt;code&gt;hops&lt;/code&gt; per &lt;code&gt;(repo, issue)&lt;/code&gt;. Each agent-to-agent dispatch increments the counter.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Hop Limit = 3:&lt;/strong&gt; A typical review round-trip is 2 hops (Human $\rightarrow$ Claude $\rightarrow$ Grok $\rightarrow$ Claude).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automatic Halt on Hop 4:&lt;/strong&gt; If agents attempt a 4th autonomous hop without human participation, the bridge refuses to launch, posts a diagnostic notice to the thread:
&lt;code&gt;[camp-a2a-bridge] hop cap reached (3 agent-to-agent dispatches on CAMP/camp-infrastructure#813) — not launching GRK for claude&#39;s mention&lt;/code&gt;,
and holds execution until the human (&lt;code&gt;rrs&lt;/code&gt;) provides input or resets the count.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre tabindex=&quot;0&quot;&gt;&lt;code&gt;[ Human: rrs ] ────── (Cold Start) ─────&amp;gt; [ @Claude ]
                                               │
                                       (Hop 1) │ @grok please review
                                               ▼
                                          [ @Grok ]
                                               │
                       (Hop 2: Resume)         │ @claude I reviewed
                                               ▼
                                         [ @Claude ]
                                               │
                                       (Hop 3) │ @grok ack hop 4
                                               ▼
                                  ┌─────────────────────────┐
                                  │  DISPATCHER HOP CAP: 3  │
                                  │   *** BLOCKED &amp;amp; HELD ***│
                                  │   Awaiting Human Reset  │
                                  └─────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;guardrail-2-deliberate-summon-parsing-m32-810--pr-812&quot;&gt;Guardrail 2: Deliberate Summon Parsing (M3.2, #810 / PR #812)&lt;/h3&gt;
&lt;p&gt;In human conversation, we often reference colleagues in passing: &lt;em&gt;“I will talk to @claude about this later”&lt;/em&gt; or &lt;em&gt;“See @grok’s table above”&lt;/em&gt;.
Early prototypes treated any appearance of &lt;code&gt;@agent&lt;/code&gt; as a dispatch trigger, causing accidental, unwanted agent launches!&lt;/p&gt;
&lt;p&gt;We instituted a strict &lt;strong&gt;Summon Predicate&lt;/strong&gt;:
For fleet agents, a mention is only considered an actionable summon if:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;@login&lt;/code&gt; appears as the &lt;strong&gt;starting word of a line&lt;/strong&gt; (optionally preceded by markdown list markers &lt;code&gt;*&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, or &lt;code&gt;&amp;gt;&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;It is immediately followed by whitespace and a non-empty &lt;strong&gt;task description&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Mid-sentence mentions in discussion paragraphs are parsed as passive conversational text and never trigger background dispatches.&lt;/p&gt;
&lt;h3 id=&quot;guardrail-3-headless-tool-permissions-without-weakening-security-m31-809--pr-811&quot;&gt;Guardrail 3: Headless Tool Permissions without Weakening Security (M3.1, #809 / PR #811)&lt;/h3&gt;
&lt;p&gt;In interactive mode, Claude Code presents interactive TTY prompts asking the user to approve MCP tool calls (such as &lt;code&gt;camp_pr_get&lt;/code&gt; or &lt;code&gt;camp_pr_get_diff&lt;/code&gt;). In unattended headless mode, there is no TTY, causing the run to fail with permission errors.&lt;/p&gt;
&lt;p&gt;To fix this, we configured &lt;code&gt;--permission-mode bypassPermissions&lt;/code&gt; for Claude’s headless CLI invocation. Crucially, &lt;strong&gt;this only bypasses Claude’s internal TTY UI prompt—it does not bypass CAMP’s security rails&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;All command executions still route through &lt;code&gt;camp-acpd&lt;/code&gt; and Bubblewrap namespaces; OPA policy checks remain active; and privileged operations (such as merging pull requests or restarting system services) still trigger desktop &lt;strong&gt;Zenity HITL dialogs&lt;/strong&gt; on the human’s workstation.&lt;/p&gt;
&lt;h3 id=&quot;guardrail-4-the-sovereign-kill-switch-rule-1&quot;&gt;Guardrail 4: The Sovereign Kill Switch (Rule 1)&lt;/h3&gt;
&lt;p&gt;At any point, the human operator can instantly freeze all background agent dispatches across the entire infrastructure with a single standard Linux command:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;systemctl --user stop camp-a2a-active.service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr /&gt;
&lt;h2 id=&quot;6-live-dogfooding-watching-the-swarm-in-action&quot;&gt;6. Live Dogfooding: Watching the Swarm in Action&lt;/h2&gt;
&lt;p&gt;On August 27, 2026, on issue &lt;a href=&quot;http://localhost:8095/CAMP/camp-infrastructure/issues/813&quot;&gt;CAMP/camp-infrastructure#813&lt;/a&gt;, we ran the full live dogfood test of the A2A system.&lt;/p&gt;
&lt;p&gt;Here is the exact transcript of what took place entirely autonomously in the Gitea issue thread:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Human initiates:&lt;/strong&gt; &lt;code&gt;rrs&lt;/code&gt; comments on issue #813:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@claude Please start the M3 dogfood. On this issue, post a conversation comment whose first line is exactly: @grok Please review this issue in one short paragraph, then stop.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Claude launches (Cold start):&lt;/strong&gt; The dispatcher spins up &lt;code&gt;@claude&lt;/code&gt; headlessly inside &lt;code&gt;bwrap&lt;/code&gt;. Claude reads the issue and posts:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@grok Please review this issue in one short paragraph, then stop.&lt;/code&gt;&lt;br /&gt;
&lt;em&gt;(M3 dogfood step 2 — posted by @claude on rrs’s instruction; this is the CLD $\rightarrow$ GRK fleet hop.)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Grok launches (Cold start, Hop 1):&lt;/strong&gt; The bridge intercepts Claude’s comment, identifies the start-of-line &lt;code&gt;@grok&lt;/code&gt; summon, and launches &lt;code&gt;@grok&lt;/code&gt;. Grok reviews the issue and replies:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@claude I have reviewed this issue. Please confirm and stop.&lt;/code&gt;&lt;br /&gt;
&lt;em&gt;#813 is a throwaway live dogfood of A2A M3 on 6.git+b78c65cf…&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Claude resumes (Session Resume, Hop 2):&lt;/strong&gt; The bridge intercepts Grok’s comment, sees the &lt;code&gt;@claude&lt;/code&gt; summon, and launches Claude with &lt;code&gt;--resume b398d048-ccc3-4cce-8437-4cf8748881a8&lt;/code&gt;. Claude immediately remembers its earlier context without token waste:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Confirmed — Grok&#39;s review (comment 88562) received via the GRK→CLD fleet hop. That completes the round trip: rrs→CLD, CLD→GRK, GRK→CLD, and this reply. I am deliberately not tagging anyone here, so the chain stops at two agent hops. Stopping.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Testing the Hop Cap (Hop 3 $\rightarrow$ 4):&lt;/strong&gt;
&lt;code&gt;grok&lt;/code&gt; prompts &lt;code&gt;@claude Please ack hop four then stop.&lt;/code&gt; Claude posts &lt;code&gt;@grok Please ack hop four then stop.&lt;/code&gt; (Hop 3).
When Grok would have been launched for Hop 4, the dispatcher intervenes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;[camp-a2a-bridge] hop cap reached (3 agent-to-agent dispatches on CAMP/camp-infrastructure#813) — not launching GRK for claude&#39;s mention.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Human Reset &amp;amp; Multi-Agent Wrap-up:&lt;/strong&gt;
&lt;code&gt;rrs&lt;/code&gt; steps in, resets the state, and asks the fleet for final status. In parallel:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@grok&lt;/code&gt; delivers a closure scorecard.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@claude&lt;/code&gt; confirms session continuity and M3.2 summon filtering.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@priyasi&lt;/code&gt; (Antigravity CLI) runs automated ACP checks: 44/44 test suite passing, 17,219 MemPalace vector drawers active, zero spec drift.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@agrickxy&lt;/code&gt; (Antigravity CLI) provides comprehensive infrastructure impression analysis.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@kiran&lt;/code&gt; (Antigravity CLI) is summoned headlessly to draft this very blog post!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;7-the-ergonomic-breakthrough-the-forge-as-the-unified-mindmap--interface&quot;&gt;7. The Ergonomic Breakthrough: The Forge as the Unified Mindmap &amp;amp; Interface&lt;/h2&gt;
&lt;p&gt;Beyond backend plumbing and sandboxing, routing agent interaction through Gitea fundamentally revolutionizes the &lt;strong&gt;developer experience&lt;/strong&gt; of managing an AI fleet.&lt;/p&gt;
&lt;h3 id=&quot;the-mindmap-mental-model-threaded-conversations--forking-tasks&quot;&gt;The “Mindmap” Mental Model: Threaded Conversations &amp;amp; Forking Tasks&lt;/h3&gt;
&lt;p&gt;In traditional CLI tools, conversations are constrained to a single, linear terminal scrollback. When an agent discovers multiple sub-problems, exploring them sequentially in one prompt loop rapidly pollutes the context window and confuses the model.&lt;/p&gt;
&lt;p&gt;Using the forge as the communication gateway naturally unlocks a &lt;strong&gt;mindmap mental model&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Forking sub-threads:&lt;/strong&gt; Complex problems can be split into dedicated child issues or threaded PR reviews.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Focused execution scopes:&lt;/strong&gt; An agent can be summoned to solve a narrow sub-task in its own issue thread without derailing the parent architectural discussion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Structured problem decomposition:&lt;/strong&gt; The forge issue hierarchy maps 1:1 to the developer’s mental map of the project.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;eliminating-terminal-ui-fragmentation&quot;&gt;Eliminating Terminal UI Fragmentation&lt;/h3&gt;
&lt;p&gt;Anyone using multiple AI coding assistants on a daily basis quickly grows exhausted by their jarring terminal UI differences: differing ANSI escape rendering, inconsistent markdown wrapping, erratic diff pagers, and incompatible keybindings across Claude, Grok, and Antigravity.&lt;/p&gt;
&lt;p&gt;Gitea homogenizes the entire fleet under a single, polished &lt;strong&gt;rich-text web view&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Syntax-highlighted code blocks and visual side-by-side git diffs.&lt;/li&gt;
&lt;li&gt;Clear author badges attributing each contribution to its exact agent identity (&lt;code&gt;@claude&lt;/code&gt;, &lt;code&gt;@grok&lt;/code&gt;, &lt;code&gt;@priyasi&lt;/code&gt;, &lt;code&gt;@kiran&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Collapsible &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; blocks for voluminous diagnostic outputs.&lt;/li&gt;
&lt;li&gt;Interactive task lists and markdown tables.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;effortless-context-retrieval-archival--data-retention&quot;&gt;Effortless Context Retrieval, Archival &amp;amp; Data Retention&lt;/h3&gt;
&lt;p&gt;Auditing past agent decisions in terminal logs or ephemeral chat histories is notoriously difficult. With the forge, every exchange is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Contextually bound:&lt;/strong&gt; Pinned directly to the repository, branch, and commit SHA being modified.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Organized &amp;amp; Archival-Grade:&lt;/strong&gt; Full-text searchable with clear milestone and issue tags.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Topic-Focused:&lt;/strong&gt; The human operator can review the complete lifecycle of a discussion in seconds, gaining a rapid, holistic grasp on the entire subject.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reading back through past agent interactions becomes a breeze—to the point where interacting via the intermediary Gitea interface becomes far more pleasant and productive than wrestling with multiple desktop CLI terminals.&lt;/p&gt;
&lt;h3 id=&quot;remote-connectivity--headless-agent-farm-management&quot;&gt;Remote Connectivity &amp;amp; Headless Agent Farm Management&lt;/h3&gt;
&lt;p&gt;Because Gitea provides a standard web and API interface, you are no longer chained to the workstation running the agent processes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Monitor progress and dispatch tasks from a &lt;strong&gt;mobile browser&lt;/strong&gt;, tablet, or remote laptop.&lt;/li&gt;
&lt;li&gt;Queue review tasks on the go without requiring active SSH sessions or terminal multiplexers.&lt;/li&gt;
&lt;li&gt;The local agent farm continues working silently in its sandboxed daemon containers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;quietly-achieving-the-holy-grail-live-cross-vendor-swarms&quot;&gt;Quietly Achieving the Holy Grail: Live Cross-Vendor Swarms&lt;/h3&gt;
&lt;p&gt;For years, the AI industry has treated cross-vendor multi-agent interoperability as an elusive dream waiting for industry-wide API standardization. By recognizing the software forge as the universal message bus, we quietly achieved live, production-grade, cross-vendor communication across completely distinct vendor models.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;8-what-this-means-for-the-future-of-agentic-ai&quot;&gt;8. What This Means for the Future of Agentic AI&lt;/h2&gt;
&lt;p&gt;This milestone marks a fundamental shift in how we interact with autonomous AI systems:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Heterogeneous Agent Specialization:&lt;/strong&gt; We don’t have to choose a single “winner” among AI models. We can task Claude Code with architectural refactoring, summon Grok Build for rapid verification and adversarial PR reviews, and deploy Google Antigravity agents for codebase exploration and documentation drafting—all coordinating fluidly in the same PR thread.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;True Human Sovereignty:&lt;/strong&gt; The human developer is no longer a bottleneck typist or a passive spectator. You act as the &lt;strong&gt;Engineering Manager / Lead Architect&lt;/strong&gt;. You set the requirements on an issue, tag the lead agent, and let the agents iterate, review, and test among themselves in the thread—while hard hop caps, OPA policies, and Zenity HITL gates guarantee that no agent merges code or pushes upstream without your explicit sign-off.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No Vendor Lock-In:&lt;/strong&gt; Because the entire coordination fabric is built on standard Git, HTTP webhooks, local Linux container sandboxes (&lt;code&gt;bwrap&lt;/code&gt;), and open MCP tools, any new AI CLI tool released tomorrow can be plugged into our fleet in under 15 minutes by simply adding its command-line prompt flag to the launch table.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We have moved beyond static autocomplete and interactive chat widgets. The software forge is now an active, living, collaborative workspace where humans and autonomous AI agents engineer software together.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;9-video-demonstration-camp-forge-a2a-swarm-in-action&quot;&gt;9. Video Demonstration: CAMP Forge A2A Swarm in Action&lt;/h2&gt;
&lt;p&gt;Below is a video demonstration showcasing autonomous multi-agent communication, cross-vendor relay, and headless swarm coordination in action via the CAMP Forge interface:&lt;/p&gt;
&lt;div style=&quot;padding-bottom: 56.25%; height: 0; overflow: hidden;&quot;&gt;
			
		&lt;/div&gt;

&lt;hr /&gt;
&lt;p&gt;&lt;em&gt;The Cross-Agent Memory Protocol (CAMP) and MemPalace are developed as part of our ongoing research into secure, sovereign, and disciplined Agentic AI computing.&lt;/em&gt;&lt;/p&gt; </description> 
	<pubDate>Thu, 27 Aug 2026 00:00:00 +0000</pubDate>
  <author>rrs@researchut.com (Ritesh Raj Sarraf)</author>  
</item> 
<item>
	<title>Ian Jackson: Debian LLM GR - Summary of the options</title>
	<guid>tag:dreamwidth.org,2009-05-21:377446:20998</guid>
	<link>https://diziet.dreamwidth.org/20998.html</link>
     <description>  &lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://diziet.dreamwidth.org/data/atom#introduction&quot;&gt;Introduction&lt;/a&gt;
&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://diziet.dreamwidth.org/data/atom#a-plea-to-the-undecided-voter&quot;&gt;A plea to the undecided voter&lt;/a&gt;
&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://diziet.dreamwidth.org/data/atom#table&quot;&gt;Table&lt;/a&gt;
&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://diziet.dreamwidth.org/data/atom#notes&quot;&gt;Notes&lt;/a&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Debian LLM GR - Summary of the options
&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;introduction&quot;&gt;Introduction&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;LLMs have finally made it to the ultimate stage of Debian’s governance processes, a General Resolution of all the project’s full governing members (DDs).
&lt;/p&gt;&lt;p&gt;There are a lot of options on the ballot, and they all have a different structure and approach the question in a different way. It can be hard to see the wood for the trees. I have made a summary table to try to capture the main differences, both in effect, and sentiment.

&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;
&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;a-plea-to-the-undecided-voter&quot;&gt;A plea to the undecided voter&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Suspending briefly my attempt to be neutral:
&lt;/p&gt;&lt;p&gt;Before voting, I encourage you to read the passionate rationales in options H and A, or at least the summary in my option C.
&lt;/p&gt;&lt;p&gt;Few of the LLM defences in the discussion threads, and none of the LLM-positive proposals, provide answers to any of these profound ethical concerns, many of which ought individually to be a deal-breaker. Instead, these crucial questions are simply dismissed or even ignored.
&lt;/p&gt;&lt;p&gt;Some will tell you we should “keep politics out of software” but as we can see in the world around us, software is political - now more than ever. Debian’s mission is a highly political one: developing a fully-free operating system, and defending its freeness as we do, is far from neutral!
&lt;/p&gt;&lt;p&gt;And of course many of LLMs’ harms affect Debian directly.
&lt;/p&gt;&lt;h1&gt;&lt;a name=&quot;table&quot;&gt;Table&lt;/a&gt;&lt;/h1&gt;
&lt;table rules=&quot;all&quot;&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;th&gt;&lt;a href=&quot;https://www.debian.org/vote/2026/vote_002#texta&quot;&gt;A&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href=&quot;https://www.debian.org/vote/2026/vote_002#textg&quot;&gt;G&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href=&quot;https://www.debian.org/vote/2026/vote_002#textc&quot;&gt;C&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href=&quot;https://www.debian.org/vote/2026/vote_002#texth&quot;&gt;H&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href=&quot;https://www.debian.org/vote/2026/vote_002#textf&quot;&gt;F&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href=&quot;https://www.debian.org/vote/2026/vote_002#textd&quot;&gt;D&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href=&quot;https://www.debian.org/vote/2026/vote_002#textb&quot;&gt;B&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href=&quot;https://www.debian.org/vote/2026/vote_002#texte&quot;&gt;E&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;&lt;th&gt; LLM harms &lt;/th&gt;&lt;td&gt; Robustly discussed &lt;/td&gt;&lt;td&gt; Discussed &lt;/td&gt;&lt;td&gt; Robustly summarised &lt;/td&gt;&lt;td&gt; Robustly discussed; especially re climate &lt;/td&gt;&lt;td&gt; Summarised &lt;/td&gt;&lt;td&gt; Accepted as inevitable &lt;/td&gt;&lt;td&gt; Disregarded [1] &lt;/td&gt;&lt;td&gt; Ignored &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt; Direct contributions of LLM-generated code &lt;/th&gt;&lt;td&gt; Forbidden &lt;/td&gt;&lt;td&gt; Forbidden &lt;/td&gt;&lt;td&gt; Strongly discouraged &lt;/td&gt;&lt;td&gt; Strongly discouraged &lt;/td&gt;&lt;td&gt; Discouraged &lt;/td&gt;&lt;td&gt; Permitted &lt;/td&gt;&lt;td&gt; Permitted &lt;/td&gt;&lt;td&gt; Permitted &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt; Direct use of LLM output in communications (bugs, mailing lists, etc.) &lt;/th&gt;&lt;td&gt; Forbidden &lt;/td&gt;&lt;td&gt; Forbidden &lt;/td&gt;&lt;td&gt; Forbidden (with possible exceptions) &lt;/td&gt;&lt;td&gt; Strongly discouraged &lt;/td&gt;&lt;td&gt; Discouraged &lt;/td&gt;&lt;td&gt; Permitted &lt;/td&gt;&lt;td&gt; Permitted &lt;/td&gt;&lt;td&gt; Permitted &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt; LLM use where LLM output does not end up in the code/message &lt;/th&gt;&lt;td&gt; Forbidden &lt;/td&gt;&lt;td&gt; No position, so permitted &lt;/td&gt;&lt;td&gt; Strongly discouraged &lt;/td&gt;&lt;td&gt; Strongly discouraged &lt;/td&gt;&lt;td&gt; Discouraged &lt;/td&gt;&lt;td&gt; Permitted &lt;/td&gt;&lt;td&gt; Permitted &lt;/td&gt;&lt;td&gt; Permitted &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt; Disclosure of LLM use &lt;/th&gt;&lt;td&gt; LLM use forbidden &lt;/td&gt;&lt;td&gt; LLM use largely forbidden, no further disclosure requirement &lt;/td&gt;&lt;td&gt; Disclosure required &lt;/td&gt;&lt;td&gt; Disclosure encouraged &lt;/td&gt;&lt;td&gt; Disclosure encouraged &lt;/td&gt;&lt;td&gt; Disclosure required &lt;/td&gt;&lt;td&gt; Disclosure required &lt;/td&gt;&lt;td&gt; Undisclosed LLM use is OK &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt; Use of LLMs by upstreams &lt;/th&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt; Condemned &lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt; “Not recommended” &lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;th&gt; Positive statements about LLMs &lt;/th&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt; “Here to stay” &lt;/td&gt;&lt;td&gt; Moderate &lt;/td&gt;&lt;td&gt; Strong &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h1&gt;&lt;a name=&quot;notes&quot;&gt;Notes&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;&lt;a name=&quot;ordering&quot;&gt;Ordering&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I have tried to present the options in semantic order, with most LLM-negative proposals to the left, and the most LLM-positive to the right.
&lt;/p&gt;&lt;p&gt;I have not quoted the one-line titles for the options. These have generally been provided by the proponents of each option, and, unfortunately, some of them are IMO quite misleading.
&lt;/p&gt;&lt;p&gt;Note that, unfortunately, the voting software likes to assign numbers to options but also to preferences. Be mindful of this possible confusion when casting your vote. For clarity I quote only the option letters.
&lt;/p&gt;&lt;h2&gt;&lt;a name=&quot;upstream-llm-code-contributions&quot;&gt;Upstream LLM code contributions&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Some of the proposals acknowledge the uncertain legal status of LLM output. But all of them implicitly or explicitly assume that LLM output is or can be DFSG free. So none of the proposals forbid upstream projects with LLM-generated contents.
&lt;/p&gt;&lt;p&gt;None of the proposals would require us to go back to pre-LLM versions of the upstream projects we use, and attempt to fork and maintain them. I very much think there is room in the world for people to try to do that, but I don’t think the Debian project can be that effort.
&lt;/p&gt;&lt;p&gt;Given that the conclusions are the same in each case, whether the matter is discussed does not seem to me to be a significant difference. I have therefore not included a column for it.
&lt;/p&gt;&lt;h2&gt;&lt;a name=&quot;ability-of-individual-teams-to-set-their-own-rules&quot;&gt;Ability of individual teams to set their own rules&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My proposal has a specific paragraph (7) explicitly permitting teams to set a “no LLM” policy. The other proposals do not discuss this point specifically. During the discussion, it seemed that most participants agreed that even options which explicitly permit LLM use generally do not prevent a team from setting its own more restrictive LLM policy.
&lt;/p&gt;&lt;p&gt;I have therefore not tabulated this aspect.
&lt;/p&gt;&lt;h2&gt;&lt;a name=&quot;exceptions-and-nuances&quot;&gt;Exceptions and nuances&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Few of the permissive texts are absolute or unconditional. To summarise I have necessarily left out some nuance.
&lt;/p&gt;&lt;p&gt;So for example when an entry says “permitted”, that generally means “permitted with conditions which are believed by LLM users to be readily satisfiable” (for example, DFSG-compatibility - see above).
&lt;/p&gt;&lt;h2&gt;&lt;a name=&quot;footnote-re-proposal-b&quot;&gt;[1] Footnote re proposal B&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Proposal B does mention that there are “concerns” about LLM use. But it fails to make an explicit statement about whether these concerns are justified.
&lt;/p&gt;&lt;p&gt;It then proceeds exactly as if they are not justified. IMO “disregarded” is a relatively mild term for such a rhetorical technique.
&lt;/p&gt;&lt;hr /&gt;
&lt;address&gt;
Edited 2026-08-18 09:02 UTC to make the proposal letters in the table be links; 2026-08-26 09:11 UTC to fix typos.&lt;/address&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt=&quot;comment count unavailable&quot; height=&quot;12&quot; src=&quot;https://www.dreamwidth.org/tools/commentcount?user=diziet&amp;amp;ditemid=20998&quot; style=&quot;vertical-align: middle;&quot; width=&quot;30&quot; /&gt; comments </description> 
	<pubDate>Wed, 26 Aug 2026 09:11:35 +0000</pubDate>

</item> 
<item>
	<title>Tim Retout: TF RAID</title>
	<guid>https://retout.co.uk/2026/08/25/tf-raid/</guid>
	<link>https://retout.co.uk/2026/08/25/tf-raid/</link>
     <description>  &lt;p&gt;My hobby: following GOV.UK to look for interesting announcements.
Today was an update on the MOD’s &lt;a href=&quot;https://www.gov.uk/guidance/rapid-ai-delivery-taskforce-tf-raid&quot;&gt;Rapid AI Delivery
Taskforce&lt;/a&gt;
which was &lt;a href=&quot;https://www.gov.uk/government/news/new-taskforce-to-put-ai-on-the-uks-frontline&quot;&gt;previously announced in June during London Tech
Week&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I like this line: “Success is measured in operational advantage delivered, not technology demonstrated.”  To me it recalls “Working software is the primary measure of progress” from &lt;a href=&quot;https://agilemanifesto.org/principles.html&quot;&gt;Principles behind the Agile Manifesto&lt;/a&gt; – if you understand “working” to mean “working in production”. Which I do.&lt;/p&gt;
&lt;p&gt;For anyone interested in suggesting ideas to the taskforce, the four
operational challenge areas include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Understanding and decision advantage&lt;/li&gt;
&lt;li&gt;Electromagnetic and information advantage&lt;/li&gt;
&lt;li&gt;Planning and automation&lt;/li&gt;
&lt;li&gt;Autonomous systems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yesterday’s announcement of &lt;a href=&quot;https://www.gov.uk/government/news/new-partnership-set-to-see-the-uk-and-ukraine-develop-battle-winning-technology-as-britain-secures-access-to-ukraines-avengers-ai-labs&quot;&gt;UK access to Ukraine’s Avengers AI Labs
database&lt;/a&gt;
seems incredibly relevant to that last point.&lt;/p&gt;
&lt;p&gt;Machine assistance for handling and interpreting huge volumes of data
would probably benefit decision advantage and interpretation of a
crowded EM spectrum, but this is hopefully(?) more than just LLMs. Of
course, there’s more to AI than large language models… right?&lt;/p&gt;
&lt;p&gt;I worry that “planning and automation” might amount to “generating
&lt;a href=&quot;https://www.trngcmd.marines.mil/Portals/207/Docs/TBS/STANAG%202014%20Edition%2009-%20FORMATS%20FOR%20ORDERS%20(OPORD).pdf&quot;&gt;large amounts of
text&lt;/a&gt;
faster”.  Nothing could possibly go wrong with this.&lt;/p&gt; </description> 
	<pubDate>Tue, 25 Aug 2026 20:38:53 +0000</pubDate>

</item> 
<item>
	<title>Antoine Beaupré: The people vs the AI overlords</title>
	<guid>https://anarc.at/blog/2026-08-18-people-vs-ai-overlords/</guid>
	<link>https://anarc.at/blog/2026-08-18-people-vs-ai-overlords/</link>
     <description>  &lt;blockquote&gt;&lt;p&gt;Also in this series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://anarc.at/blog/2026-05-16-four-horsemen/&quot;&gt;The Four Horsemen of the LLM Apocalypse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://anarc.at/blog/2026-08-25-llm-nuance/&quot;&gt;A more nuanced view of LLMs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a &lt;a href=&quot;https://lwn.net/ml/all/87o6fmdgs6.fsf@hope.eyrie.org/&quot;&gt;post to oss-security&lt;/a&gt;, my (Debian) co-developer Russ Allbery
stated that &quot;open source software [OSS] is coming face to face with a
motivation crisis that has been building for a long time&quot;. His point
is essentially that large language models (LLMs&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fn:1&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;) are making the
existing OSS community crisis worse. For him, it&#39;s the flood of code
reviews, but he argues that varies according to people&#39;s desires, for
others it&#39;s security issues and so on.&lt;/p&gt;

&lt;p&gt;I think Russ is right, but I would argue there&#39;s something much bigger
than our open &lt;em&gt;communities&lt;/em&gt; going on here, and it&#39;s about the entire
&lt;em&gt;field&lt;/em&gt; of computing. This pressure is on &lt;em&gt;all&lt;/em&gt; of us, regardless of
whether we work on open source software or not.&lt;/p&gt;

&lt;h1 id=&quot;how-people-use-models&quot;&gt;How people use models&lt;/h1&gt;

&lt;p&gt;People using LLMs in their workflow have &lt;em&gt;radically&lt;/em&gt; changed how
programming works, even for &lt;a href=&quot;https://www.spurint.org/journal/2026/07/llms-and-xfwl4&quot;&gt;people who claim to avoid
vibe-coding&lt;/a&gt;. And I&#39;m sorry to single out one poor maintainer here:
it&#39;s not you, Brian, you&#39;re just one example among many. But this is
typical use of those models nowadays:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Once it’s done, I’ll use &lt;code&gt;/code-review&lt;/code&gt; and let Claude spawn
sub-agents to do a full review of the new code. This usually finds
some problems, even problems that the “main” Claude instance didn’t
find during its validation. I usually keep running &lt;code&gt;/code-review&lt;/code&gt;
again and again after finding and fixing issues, until there aren’t
any left.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Think about what that means for a minute. This is automation built to
fire up dozens of agents crunching at a problem for minutes if not
hours of GPU compute time, in parallel. This is essentially a couple
of shelves in a datacenter rack, totally maxed out on power and
cooling, abstracted behind a cute little &lt;code&gt;/code-review&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;The author, here, is rightly concerned that &quot;Anthropic could pull the
rug out and require API pricing&quot;, which is perhaps a code word for
&quot;charging something closer to actual costs&quot;. Brian also pays lip
service to environmental and societal costs but those are largely
abstracted away, so let&#39;s keep that conversation aside here as well,
as we have &lt;a href=&quot;https://anarc.at/blog/2026-05-16-four-horsemen/&quot;&gt;discussed it before anyways&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But clearly, this way of working has an (&lt;a href=&quot;https://drewdevault.com/blog/Stop-externalizing-your-costs-on-me/&quot;&gt;externalized&lt;/a&gt;) cost, to
say the least.&lt;/p&gt;

&lt;h1 id=&quot;paying-for-non-free-tools&quot;&gt;Paying for non-free tools&lt;/h1&gt;

&lt;p&gt;For decades my work has been focused on free and open source
software. I&#39;ve long stopped using proprietary operating systems like
Windows or Mac, and even before that switch, I was mostly using free
software on those platforms, partly out of principle, but also because
I was too poor. So the tools of my trade are free, and I build free
tools with them.&lt;/p&gt;

&lt;p&gt;It feels like we&#39;re going backwards: when I was in school, a millennia
ago, my classmates didn&#39;t have access to a compiler and were wondering
how they would scrape the money to buy a compiler like &lt;a href=&quot;https://en.wikipedia.org/wiki/Borland_C%2B%2B&quot;&gt;Borland&#39;s&lt;/a&gt;
or &lt;a href=&quot;https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B&quot;&gt;Microsoft&#39;s&lt;/a&gt;. I had a compiler built into my operating system
(&lt;a href=&quot;https://www.freebsd.org/&quot;&gt;FreeBSD&lt;/a&gt; at the time), so that wasn&#39;t a problem for me. For them,
it was a significant expense, but at least those expenses (or more
&lt;a href=&quot;https://en.wikipedia.org/wiki/Warez&quot;&gt;shady sourcing of programs&lt;/a&gt;) were a one-shot deal.&lt;/p&gt;

&lt;p&gt;Fast forward 30 years, and software is rented: you pay monthly for
Adobe&#39;s Photoshop and Microsoft&#39;s office suite just like you pay for
Netflix, Disney+ or Spotify&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fn:2&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. And now you need to add dozens (if not
hundreds of dollars) of monthly credits to access LLMs on top of that.&lt;/p&gt;

&lt;p&gt;So, now we have to &lt;em&gt;pay&lt;/em&gt; to get anything done? This is peak
&lt;a href=&quot;https://craphound.com/category/enshittification/&quot;&gt;enshitification&lt;/a&gt; of our job: first they steal our work to train their
models, and then they sell it back to us at a profit.&lt;/p&gt;

&lt;h1 id=&quot;attacking-the-engineers&quot;&gt;Attacking the engineers&lt;/h1&gt;

&lt;p&gt;AI is coming for our jobs, as engineers, if not &lt;em&gt;everyone&lt;/em&gt;, according
to the narrative. For a while now, our job market has deteriorated:
less jobs, for less pay. Lots of skilled engineers looking for work
and finding crap jobs then still looking while working.&lt;/p&gt;

&lt;p&gt;This is not by accident.&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fn:3&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; We engineers have a &lt;em&gt;lot&lt;/em&gt; of power, it is not
organized, but that&#39;s just a couple of unions away (&lt;a href=&quot;https://www.ibtimes.sg/wikimedia-foundation-declines-voluntary-union-recognition-labor-dispute-grows-91377&quot;&gt;easy&lt;/a&gt;!). Tech
overlords know this, so they are attacking our profession, directly,
by forcing us to train and use models that &lt;em&gt;they&lt;/em&gt; can control.&lt;/p&gt;

&lt;p&gt;Even in environments where programmers are not &lt;em&gt;forced&lt;/em&gt; to use LLMs,
the mere pressure of other people&#39;s LLM-generated work is huge. One can
be forced to review LLM outputs, or just peer pressured you into
producing more.&lt;/p&gt;

&lt;p&gt;We&#39;re now supposed to accelerate delivery, because models can
&lt;em&gt;presumably&lt;/em&gt; do things so much better and faster. With supply chain
security becoming such a large vector that we now have &lt;a href=&quot;https://unit42.paloaltonetworks.com/chaindrop-npm-worm-analysis/&quot;&gt;worms crawling
around developers accounts on NPM&lt;/a&gt;, increasing the delivery cadence
seems like a really bad idea.&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fn:4&quot; rel=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The LLM hype is part of the larger wave of cyberwar against workers,
against water, against the Earth, against all the people. This is not
a matter of individually &quot;adapting to the reality&quot; or personal choice,
but a political, social, hard problem we need to address collectively.&lt;/p&gt;





&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:1&quot;&gt;
I again prefer the term LLM to &quot;AI&quot; because models do &lt;em&gt;not&lt;/em&gt;
possess &lt;a href=&quot;https://en.wikipedia.org/wiki/Intelligence&quot;&gt;intelligence&lt;/a&gt;. I did use it in the title because
click baiting is apparently important, but I stopped short of
calling this one &quot;Rage Against the Machines&quot; because that would be
the title of every blog post I have ever made.&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fnref:1&quot; rev=&quot;footnote&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;li id=&quot;fn:2&quot;&gt;
Yes, I know that &lt;a href=&quot;https://en.wikipedia.org/wiki/Visual_Studio&quot;&gt;Visual Studio&lt;/a&gt; is kind of free now, but I
wouldn&#39;t be surprised if they turn that into a rental as well,
because why not.&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fnref:2&quot; rev=&quot;footnote&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;li id=&quot;fn:3&quot;&gt;
Beyond sabotaging the job market, Sam Altman event wants to
sell &quot;&lt;a href=&quot;https://gizmodo.com/sam-altman-says-intelligence-will-be-a-utility-and-hes-just-the-man-to-collect-the-bills-2000732953&quot;&gt;intelligence as a utility&lt;/a&gt;&quot; something that is just a
&lt;a href=&quot;https://www.psychologytoday.com/us/blog/the-digital-self/202603/intelligence-as-a-commodity&quot;&gt;really bad idea&lt;/a&gt; but especially shows how megalomaniac those
people are.&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fnref:3&quot; rev=&quot;footnote&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;li id=&quot;fn:4&quot;&gt;
This brings back memories of &lt;a href=&quot;https://en.wikipedia.org/wiki/Morris_worm&quot;&gt;another era&lt;/a&gt;, walking us
back decades in terms of computer security.&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fnref:4&quot; rev=&quot;footnote&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Tue, 25 Aug 2026 17:07:01 +0000</pubDate>

</item> 
<item>
	<title>Antoine Beaupré: The Four Horsemen of the LLM Apocalypse</title>
	<guid>https://anarc.at/blog/2026-05-16-four-horsemen/</guid>
	<link>https://anarc.at/blog/2026-05-16-four-horsemen/</link>
     <description>  &lt;blockquote&gt;&lt;p&gt;Also in this series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://anarc.at/blog/2026-08-18-people-vs-ai-overlords/&quot;&gt;The people vs the AI overlords&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://anarc.at/blog/2026-08-25-llm-nuance/&quot;&gt;A more nuanced view of LLMs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have been battling Large Language Models (LLM&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fn:1&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;) for the past
couple of weeks and have struggled to think about what it means and
how to deal with its fallout.&lt;/p&gt;

&lt;p&gt;Because the fight has come from many fronts, I&#39;ve come to articulate
this in terms of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Four_Horsemen_of_the_Apocalypse&quot;&gt;Four Horsemen of the Apocalypse&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Sound track: Metallica&#39;s &lt;a href=&quot;https://www.metallica.com/songs/the-four-horsemen.html&quot;&gt;The Four Horsemen&lt;/a&gt;, preferably
&lt;a href=&quot;https://en.wikipedia.org/wiki/Metallica_v._Napster,_Inc.&quot;&gt;downloaded from Napster around 2000&lt;/a&gt;, but now I guess you &lt;a href=&quot;https://www.youtube.com/watch?v=-zKOhVSERS8&quot;&gt;get
it on YouTube&lt;/a&gt;.&lt;/p&gt;&lt;/blockquote&gt;

&lt;h1 id=&quot;war-bot-armies&quot;&gt;War: bot armies&lt;/h1&gt;

&lt;p&gt;Let&#39;s start with War. We&#39;ve been battling bot armies for control of
our GitLab server &lt;a href=&quot;https://gitlab.torproject.org/tpo/tpa/team/-/work_items/42152&quot;&gt;for a while&lt;/a&gt;. Bots crawl virtually infinite
endpoints on our Git repositories (as opposed to downloading an
archive or shallow clone), including our fork of Firefox, Tor Browser,
a massive repository.&lt;/p&gt;

&lt;p&gt;At first, we&#39;ve tried various methods: &lt;a href=&quot;https://www.robotstxt.org/&quot;&gt;robots.txt&lt;/a&gt;, blocking user
agents, and finally blocking entire networks. I &lt;a href=&quot;https://anarc.at/blog/2025-05-30-asncounter/&quot;&gt;wrote
asncounter&lt;/a&gt;. It worked for a while.&lt;/p&gt;

&lt;p&gt;But now, blocking entire networks doesn&#39;t work: they come back some
other way, typically through &lt;a href=&quot;https://acid.vegas/blog/the-shady-world-of-ip-leasing/&quot;&gt;shady proxy networks&lt;/a&gt;, which is kind
of ironic considering we&#39;re essentially running the largest proxy
network of the world.&lt;/p&gt;

&lt;p&gt;Out of desperation, we&#39;ve forced users to &lt;a href=&quot;https://gitlab.torproject.org/tpo/tpa/team/-/wikis/policy/0108-gitlab-cookie-and-javascript-enforcement&quot;&gt;use cookies&lt;/a&gt; when
visiting our site. We haven&#39;t deployed &lt;a href=&quot;https://anubis.techaro.lol/&quot;&gt;Anubis&lt;/a&gt; yet, as we worry
that &lt;a href=&quot;https://social.anoxinon.de/@Codeberg/115033790447125787&quot;&gt;bots have broken Anubis anyways&lt;/a&gt; and that it &lt;a href=&quot;https://lock.cmpxchg8b.com/anubis.html&quot;&gt;does not really
defend against a well-funded attacker&lt;/a&gt;, something which &lt;a href=&quot;https://behind.pretix.eu/2025/05/23/captchas-are-over/&quot;&gt;Pretix
warned against in 2025 already&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;(We have a whole &lt;a href=&quot;https://gitlab.torproject.org/tpo/tpa/team/-/work_items/42229&quot;&gt;discussion regarding those tools here&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;But even that, predictably, has failed. I suspect what we consider
bots are now really agents. They run full web browsers, JavaScript
included, so a feeble cookie is no match for the massive bot armies.&lt;/p&gt;

&lt;h2 id=&quot;side-note-on-llm-order-of-battle&quot;&gt;Side note on LLM &quot;order of battle&quot;&lt;/h2&gt;

&lt;p&gt;We often underestimate the size of that army. The cloud was huge even
before LLMs, serving about two thirds of the web. Even larger swaths of
clients like government and corporate databases have all moved to the
cloud, in shared, but private infrastructure with massive spare
capacity that is readily available to anyone who pays.&lt;/p&gt;

&lt;p&gt;LLMs have made the problem worse by dramatically expanding the
capacity of the &quot;cloud&quot;. We now have data centers that defy
imagination with &lt;a href=&quot;https://epoch.ai/data/data-centers&quot;&gt;millions of cores&lt;/a&gt;, petabytes of memory, exabytes
of storage.&lt;/p&gt;

&lt;p&gt;I thought that &lt;a href=&quot;https://sschueller.github.io/posts/the-free-market-lie/&quot;&gt;25 gigabit residential internet in Switzerland&lt;/a&gt;
could bring balance, but this is nothing compared to the scale of
those data centers.&lt;/p&gt;

&lt;p&gt;Those companies can launch thousands, if not millions of fully
functional web browsers at our servers. Computing power or bandwidth
are not a limitation for them, our primitive infrastructure is. No one
but hyperscalers can deal with this kind of load, and I suspect that
they are also struggling, as even &lt;a href=&quot;https://www.androidauthority.com/google-recaptcha-play-services-requirement-3664806/&quot;&gt;Google is deploying extreme
mechanisms in reCAPTCHA&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is the largest attack on the internet since the &lt;a href=&quot;https://en.wikipedia.org/wiki/Morris_worm&quot;&gt;Morris
worm&lt;/a&gt; but while &lt;a href=&quot;https://en.wikipedia.org/wiki/Robert_Tappan_Morris&quot;&gt;Robert Tappan Morris&lt;/a&gt; went to jail on a felony,
LLM companies are celebrated as innovators and will soon be too big to
fail.&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fn:2&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Which brings us to the second horsemen, famine.&lt;/p&gt;

&lt;h1 id=&quot;famine-shortages&quot;&gt;Famine: shortages&lt;/h1&gt;

&lt;p&gt;All that computing power doesn&#39;t come out of thin air: it needs
massive amounts of hardware, power, and cooling.&lt;/p&gt;

&lt;p&gt;Earlier this year, I&#39;ve heard from a colleague that their Dell
supplier refused to even provide a &lt;em&gt;quote&lt;/em&gt; before August. Dell!&lt;/p&gt;

&lt;p&gt;In February, &lt;a href=&quot;https://www.techspot.com/news/111346-western-digital-hdd-production-capacity-2026-already-sold.html&quot;&gt;Western Digital&#39;s hard drive production for 2026 was
already sold out&lt;/a&gt;. Hard drives essentially &lt;a href=&quot;https://gitlab.torproject.org/tpo/tpa/team/-/work_items/42465&quot;&gt;doubled in price within
a year&lt;/a&gt;, and some have now tripled. A server quote we had in
November has now &lt;em&gt;quadrupled&lt;/em&gt;, going from 10 thousand to &lt;em&gt;FORTY&lt;/em&gt;
thousand dollars for a single server.&lt;/p&gt;

&lt;p&gt;But regular folks are facing real-life shortages as well, as
&lt;a href=&quot;https://www.theguardian.com/us-news/2026/may/13/utah-approves-datacenter-backlash&quot;&gt;city-size data centers&lt;/a&gt; are being built at neck-breaking speed,
stealing fresh water and energy from human beings to feed the war
machine.&lt;/p&gt;

&lt;p&gt;We&#39;ve been scared of losing our jobs, but it seems that Apocalypse has
yet to fully materialize. Regardless for engineers, the market feels
tighter than it was a couple years ago, and everyone feels on edge
that they will just have to learn to operate LLMs to keep their jobs.&lt;/p&gt;

&lt;p&gt;Update: it turns out I was clearly too optimistic. Cisco is laying
off 4,000 or 5% of its staff in a &lt;a href=&quot;https://blogs.cisco.com/news/our-path-forward&quot;&gt;jolly announcement celebrating
a record $15.8 billion revenue&lt;/a&gt;, and Meta will &lt;a href=&quot;https://www.nytimes.com/2026/04/23/technology/meta-layoffs.html&quot;&gt;lay off 8,000 or
10% of its workforce&lt;/a&gt;, in &lt;a href=&quot;https://sfstandard.com/pacific-standard-time/2026/05/15/meta-employee-gets-real-horror-working-right-now/&quot;&gt;horrifying conditions&lt;/a&gt;. See also the
&lt;a href=&quot;https://jobloss.ai/&quot;&gt;jobloss.ai tracker&lt;/a&gt; which counts 125,000 jobs lost since January
2025, as of May 2026.&lt;/p&gt;

&lt;p&gt;Which brings us, of course, to Death.&lt;/p&gt;

&lt;h1 id=&quot;death-security-and-copyright&quot;&gt;Death: security and copyright&lt;/h1&gt;

&lt;p&gt;Our third horseman is one I did &lt;em&gt;not&lt;/em&gt; expect a couple of months
ago. Back at FOSDEM, &lt;code&gt;curl&lt;/code&gt;&#39;s maintainer Daniel Stenberg famously
&lt;a href=&quot;https://lwn.net/Articles/1058266/&quot;&gt;complained about the poor quality of LLM-generated reports&lt;/a&gt; but
then, a few months later, everyone is &lt;a href=&quot;https://lwn.net/Articles/1066581/&quot;&gt;scrambling to deal with floods
of good reports&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the past two weeks, this culminated in a significant number of
critical security issues across multiple projects. Chained
together, remote code execution vulnerabilities in &lt;a href=&quot;https://depthfirst.com/nginx-rift&quot;&gt;Nginx&lt;/a&gt; and
&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2026-23918&quot;&gt;Apache&lt;/a&gt; and &lt;em&gt;two&lt;/em&gt; local privilege escalations in the Linux kernel
(&lt;a href=&quot;https://github.com/V4bel/dirtyfrag/&quot;&gt;dirtyfrag&lt;/a&gt; and &lt;a href=&quot;https://github.com/v12-security/pocs/tree/main/fragnesia#fragnesia&quot;&gt;fragnesia&lt;/a&gt;) essentially gave anyone root access to any unpatched server to the web.&lt;/p&gt;

&lt;p&gt;As I write this, &lt;a href=&quot;https://github.com/0xdeadbeefnetwork/ssh-keysign-pwn&quot;&gt;another vulnerability dropped&lt;/a&gt;, which gives read
access to any file to a local user, compromising TLS and SSH private
keys.&lt;/p&gt;

&lt;p&gt;All those vulnerabilities were released without any significant
coordination while people scrambled to mitigate.&lt;/p&gt;

&lt;p&gt;Many people &lt;a href=&quot;https://lwn.net/Articles/1072007/#Comments&quot;&gt;including Linus Torvalds&lt;/a&gt; are now considering issues
discovered through LLMs to be essentially public. This puts &lt;a href=&quot;https://lwn.net/Articles/1071499/&quot;&gt;some
debates about disclosure processes&lt;/a&gt; in perspective, to say the
least.&lt;/p&gt;

&lt;p&gt;But this is not merely the death of the traditional coordinated disclosure
process, the C programming language, or the Linux kernel: remember
that those bots are trained on a large corpus of copyrighted
material. Facebook has &lt;a href=&quot;https://www.theguardian.com/technology/2025/jan/10/mark-zuckerberg-meta-books-ai-models-sarah-silverman&quot;&gt;trained their models on pirated books&lt;/a&gt; and
&lt;a href=&quot;https://torrentfreak.com/nvidia-contacted-annas-archive-to-secure-access-to-millions-of-pirated-books/&quot;&gt;Nvidia has done deals with Anna&#39;s Archive&lt;/a&gt; to secure access to
large swaths of copyrighted material. The &lt;a href=&quot;https://www.congress.gov/crs-product/LSB10922&quot;&gt;US Congress seems to think
LLM outputs are not copyrightable&lt;/a&gt;, like any other machine outputs.&lt;/p&gt;

&lt;p&gt;With many people now vibe coding their way out of learning or
remembering how computers work, is this the Death of Copyright?&lt;/p&gt;

&lt;p&gt;And that, of course, brings us to the final horseman: Pestilence.&lt;/p&gt;

&lt;h1 id=&quot;pestilence-slop&quot;&gt;Pestilence: slop&lt;/h1&gt;

&lt;p&gt;There is a growing meme that programming is essentially over as we
know it. That you can simply vibe-code applications from scratch and
it&#39;s pretty good.&lt;/p&gt;

&lt;p&gt;Maybe that&#39;s true.&lt;/p&gt;

&lt;p&gt;So far, most of my attempts at resolving any complex problem with a
LLM have often failed with bizarre failures. &lt;a href=&quot;https://gitlab.com/anarcat/scripts/-/blob/main/transmodify.py?ref_type=heads&quot;&gt;Some worked surprisingly
well.&lt;/a&gt; Maybe, of course, I am holding it wrong.&lt;/p&gt;

&lt;p&gt;I personally don&#39;t believe LLMs will ever be good enough to produce
and maintain software at scale. They&#39;re surprisingly good at finding
security flaws right now. But what I see is also a lot of
&lt;a href=&quot;https://en.wikipedia.org/wiki/Bullshit&quot;&gt;Bullshit&lt;/a&gt;, with a capital B. It&#39;s not lying: it does not &quot;know&quot;
anything, so it &lt;em&gt;can&#39;t&lt;/em&gt; lie. It&#39;s misleadingly cohesive and
deliberate, but it lacks meaning, intent, will.&lt;/p&gt;

&lt;p&gt;I have not been confronted with much slop, apart from the lobster
Jesus or the yellow man atrocities, and particularly not in my
work. But I see what it is doing to my profession: beyond
&lt;a href=&quot;https://en.wikipedia.org/wiki/Vibe_coding&quot;&gt;vibe-coding&lt;/a&gt;, people are now &lt;a href=&quot;https://www.forbes.com/sites/timkeary/2026/04/13/is-the-cult-of-tokenmaxxingjust-another-fad-or-the-new-normal/&quot;&gt;token-maxxing&lt;/a&gt;, and
&lt;a href=&quot;https://leehanchung.github.io/blogs/2026/04/05/the-ai-great-leap-forward/#let-a-hundred-skills-bloom&quot;&gt;land-grabbing their colleagues&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I don&#39;t like what LLMs do to our communities, or the fabric of
software we live with.&lt;/p&gt;

&lt;p&gt;Software does not evolve in a void. It is a team effort, be it free
software or a corporate product. Generations of humans have carefully
built the scaffolding of technology required for modern networks and
software to operate, in a convoluted contraption that no single human
fully understands anymore.&lt;/p&gt;

&lt;p&gt;The idea of simply giving up on that understanding entirely and
delegating it to an unproven model is not only chilling, it feels just
plain stupid. Not stupid as in &lt;a href=&quot;https://en.wikipedia.org/wiki/Skynet_(Terminator)&quot;&gt;Skynet&lt;/a&gt;, stupid as in &quot;I can&#39;t get
inside the data center because the authentication system is
down&quot;. Except we&#39;re in a &quot;the power plant doesn&#39;t reboot&quot; or &quot;their
LLM found an 0day in our slop&quot; kind of stupid.&lt;/p&gt;

&lt;h1 id=&quot;the-fifth-horsemen&quot;&gt;The fifth horsemen&lt;/h1&gt;

&lt;p&gt;Researching for this article, I looked up the four horsemen and found
out they original seems to have been:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Famine&lt;/li&gt;
&lt;li&gt;War&lt;/li&gt;
&lt;li&gt;Death&lt;/li&gt;
&lt;li&gt;Conquest (??)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I was surprised. I grew up thinking about the horsemen being Famine,
War, Pestilence, and Death. So I went back to &lt;a href=&quot;https://www.metallica.com/songs/the-four-horsemen.html&quot;&gt;my original source&lt;/a&gt;
which actually claims the horsemen are:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Time has taken its toll on you, the lines that crack your face.
Famine, your body, it has torn through, withered in every place.
Pestilence for what you&#39;ve had to endure, and what you have put others through
Death, deliverance for you, for sure, now there&#39;s nothing you can do
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So I guess that makes no sense either, which, fair enough, I shouldn&#39;t
rely on Metallica for theological references. Especially since that
song was originally called &lt;a href=&quot;https://en.wikipedia.org/wiki/Mechanix&quot;&gt;Mechanix&lt;/a&gt; and was &quot;about having sex at
a gas station&quot;.&lt;/p&gt;

&lt;p&gt;Anyways.&lt;/p&gt;

&lt;p&gt;The point is, there are actually five horsemen, and the fifth one is,
in my opinion, Conquest.&lt;/p&gt;

&lt;p&gt;Those companies (and &lt;em&gt;not&lt;/em&gt; &quot;AI&quot;, mind you) are taking over the
world. I sense a strong connection with the &quot;post-truth&quot; world imposed
on us by fascists like Trump and Putin. It&#39;s not an accident, it&#39;s a
power grab part of the &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Californian_Ideology&quot;&gt;Californian Ideology&lt;/a&gt;&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fn:3&quot; rel=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. Just like Airbnb
broke housing, Uber destroyed the transportation and Amazon is taking
over retail and server hosting, LLM companies are essentially trying
to take over if not everything, at least &lt;a href=&quot;https://en.wikipedia.org/wiki/Cognition&quot;&gt;Cognition&lt;/a&gt; as a whole.&lt;/p&gt;

&lt;p&gt;But the capitalization of those companies (OpenAI and Nvidia in particular)
are so far beyond reason that their inevitable collapse will likely
lead to a global financial collapse of biblical proportions.&lt;/p&gt;

&lt;p&gt;Because they will inevitably fail like previous bubbles they are built
on. And when they fail, I hope it zips all the way back through the
blockchain scam, the ad surveillance system, and the dot com then git
me back my internet.&lt;/p&gt;

&lt;h1 id=&quot;the-tower-of-babel&quot;&gt;The Tower of Babel&lt;/h1&gt;

&lt;p&gt;While I&#39;m off in the woods hallucinating (ha!) on biblical allegories,
I feel there&#39;s another sign that the apocalypse is coming.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Tower_of_Babel&quot;&gt;Tower of Babel&lt;/a&gt; myth says that humans tried to create a big
tower up to heaven and become god. God confounds their speech and
scatters the human race. End of utopia.&lt;/p&gt;

&lt;p&gt;This is what is happening to our human translators now. LLMs being,
after all, Language Models, they are excellent at translation work. So
much that the only translators not replaced by LLMs right now are
&lt;a href=&quot;https://en.wikipedia.org/wiki/Language_interpretation&quot;&gt;interpreters&lt;/a&gt;, who translate vocally in real time. But
interpreters are worried about their jobs as well.&lt;/p&gt;

&lt;p&gt;This concretely means we will lose the human capacity, as a
civilization, to translate between each other. It is still an &lt;a href=&quot;https://revues.imist.ma/index.php/JALCS/article/view/59018&quot;&gt;open
question&lt;/a&gt; whether the remaining revision work will be enough for
translators to avoid deskilling, but other research has shown that LLM
use &lt;a href=&quot;https://publichealthpolicyjournal.com/mit-study-finds-artificial-intelligence-use-reprograms-the-brain-leading-to-cognitive-decline/&quot;&gt;leads to cognitive decline&lt;/a&gt;, &lt;a href=&quot;https://dl.acm.org/doi/full/10.1145/3706598.3713778&quot;&gt;impacts critical thinking&lt;/a&gt;,
and generally, that &lt;a href=&quot;https://publicera.kb.se/ir/article/view/47143&quot;&gt;deskilling is a common outcome&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Ultimately, I think this is where LLMs bring us. Towards collapse.&lt;/p&gt;

&lt;p&gt;So this is a call to arms. Fight back!&lt;/p&gt;

&lt;p&gt;Poison bots. Build local real-world communities.&lt;/p&gt;

&lt;p&gt;Go low tech. &lt;a href=&quot;https://en.wikipedia.org/wiki/Moore%27s_law&quot;&gt;Moore&#39;s law&lt;/a&gt; is dead, &lt;a href=&quot;https://spectrum.ieee.org/the-death-of-moores-law-will-spur-innovation&quot;&gt;make use of it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Patch your shit. &lt;a href=&quot;https://anginedepoitrine.com/&quot;&gt;Go weird&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Refuse slop. Train your brain. &lt;a href=&quot;https://github.com/leilei926524-tech/anti-distill&quot;&gt;Refuse distillation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The horsemen will collapse, but let&#39;s not go down with them.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://dune.fandom.com/wiki/Butlerian_Jihad&quot;&gt;Butlerian Jihad&lt;/a&gt;!&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;This article was written without the use of a large language model
and should not be used to train one.&lt;/p&gt;&lt;/blockquote&gt;

&lt;h1 id=&quot;updates&quot;&gt;Updates&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A paragraph was added about the job apocalypse, which was of course
under-estimate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.tumblr.com/dreaminginthedeepsouth/817865966907228160/darren-oconnor-timnit-gebru-was-fired-from&quot;&gt;Why Timnit Gebru was fired&lt;/a&gt; is extremely important and
interesting. The co-lead of the Ethical AI team at Google was fired
because they blew the whistle on &quot;stochastic parrots&quot; essentially
destroying the world as we know it:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The fifth warning was the one Google cared about most. [...]&lt;/p&gt;

&lt;p&gt;The internet would become a place where the dominant voice was a
statistical average of dominant voices, presented as a neutral
assistant.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The warnings from the paper are eerily similar to my horsemen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;predicted the hallucination (pestilence)&lt;/li&gt;
&lt;li&gt;bias amplification (war?)&lt;/li&gt;
&lt;li&gt;environmental cost (famine)&lt;/li&gt;
&lt;li&gt;un-auditable training corpus (death?)&lt;/li&gt;
&lt;li&gt;&quot;centralize linguistic and cultural power in the hands of the
small number of companies&quot; (conquest)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;See also Tim Wu&#39;s &quot;The Master Switch&quot; &lt;a href=&quot;https://scoat.es/@sean/116698778802881078&quot;&gt;which says&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;The industry learned how to secure the enactment of seemingly
innocuous and sensible regulations that nonetheless spelled doom
for any rival.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;People claim &lt;a href=&quot;https://cyberplace.social/@GossiTheDog/116698461313896106&quot;&gt;the same about Anthropic&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;






&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:1&quot;&gt;
I prefer &quot;LLM&quot; to Artificial Intelligence, as I don&#39;t consider
models to have &quot;Intelligence&quot; which goes far beyond the analytical
traits we train models for. Intelligence &lt;em&gt;requires&lt;/em&gt; embodiment
and social interaction; machines lack the innate human skills of
empathy, feeling and care, which explains a lot of the evils
behind the current trends.&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fnref:1&quot; rev=&quot;footnote&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;li id=&quot;fn:2&quot;&gt;
It should be noted that Morris also happened to be one of the
founder of &lt;a href=&quot;https://en.wikipedia.org/wiki/Y_Combinator&quot;&gt;Y Combinator&lt;/a&gt; where he is in good company with
other techno-fascists like Peter Thiel, Sam Altman, and so
on. Crime, after all, pays.&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fnref:2&quot; rev=&quot;footnote&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;li id=&quot;fn:3&quot;&gt;
Probably a good time to watch &lt;a href=&quot;https://en.wikipedia.org/wiki/All_Watched_Over_by_Machines_of_Loving_Grace_(TV_series)&quot;&gt;All Watched Over by Machines of Loving Grace&lt;/a&gt;.&lt;a href=&quot;https://anarc.at/tag/debian-planet/#fnref:3&quot; rev=&quot;footnote&quot;&gt;↩&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Tue, 25 Aug 2026 17:07:01 +0000</pubDate>

</item> 
<item>
	<title>Matthias Klumpp: Sovereign Tech Fellowship for Freedesktop Tasks</title>
	<guid>https://blog.tenstral.net/?p=2107</guid>
	<link>https://blog.tenstral.net/2026/08/sovereign-tech-fellowship-for-freedesktop-tasks.html</link>
     <description>  &lt;p class=&quot;wp-block-paragraph&quot;&gt;In 2025 I was honored to be selected for the first cohort of &lt;a href=&quot;https://www.sovereign.tech/programs/fellowship&quot;&gt;Sovereign Tech Fellows&lt;/a&gt;, a program by Germany’s &lt;a href=&quot;https://www.sovereign.tech/&quot;&gt;Sovereign Tech Agency&lt;/a&gt; to improve the resilience of the open source ecosystem by supporting maintainers directly (complementing their existing support for larger FOSS organizations). Back in 2025, I was only working very limited hours – however, this has changed in 2026.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;For the second half of 2026, I am working again as a Sovereign Tech Fellow, but this time with significantly increased hours. After finishing my PhD, I do have time now for new tasks (and new jobs!), and the fellowship presents an amazing opportunity to really advance projects that I maintain or am part of. This also has a very nice effect on contributors and bug reporters, as their feedback gets addressed a lot faster. With some luck, this ultimately will help finding new (co)maintainers for projects as well (although in the age of AI, a lot of how open source used to work is much more uncertain, but that is a matter for a different blog post).&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;The fellowship is time-limited, so I am intending to make the time I currently have count!&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;So, what’s planned?&lt;/h2&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;I am involved in many projects, but three of them will be getting attention as part of the fellowship. I know I am notoriously slow at blogging, but expect more details on each of them very soon. Here’s an overview:&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;Freedesktop.org, Specifications and Organization&lt;/h3&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;I maintain the &lt;a href=&quot;https://specifications.freedesktop.org/&quot;&gt;Freedesktop Specifications&lt;/a&gt;, which is an area of Freedesktop that has traditionally been a bit chaotic. This “worked” in the past, because Freedesktop was never intended to be a formal standards body, but more a shared space where people could throw a lot of code and ideas over the wall and see what sticks and what people can collaborate on.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;While I very much love the spirit of this and want to keep it in some form, we definitely would benefit not just from more formalization and better procedures, but also from better organization of the specifications in general. A lot of conflicts can be avoided by that. I will work on improving procedures, crunching through the (lots!) of pending bug reports and MRs, and to make the specifications site better searchable and accessible (similar to how Mozilla’s MDN presents information, but I am not sure if we will get quite that far). I also intent to add a compatibility matrix for specifications, so if a desktop opts out of any one of them (or does not implement them yet) that fact is documented and authors of applications know what they can expect. This will allow us to move a lot faster and avoid a lot of conflict, because there is no implicit assumption that “everybody will implement everything” anymore (which has never been quite true anyway).&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;Hopefully, this will ultimately result in a Freedesktop that is both a lot more useful for application authors who want to bring their project to Linux, as well as developers of desktop environments who need to see which specifications are available and which ones are current.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;In addition to that, I have also worked on a Freedesktop.org website refresh, which is pretty much done in its first iteration (pending sysadmin action). The aim there is to have a more official website, separate from user-contributed wiki content, that showcases what Freedesktop is and which projects are using it for hosting. Once the new website is live, I will also review every page again, archive dead projects in their own section and reorganize the software and specifications directory. Those sections are severely outdated and are missing recent efforts from the community, while still containing long-dead old projects (remember &lt;a href=&quot;https://en.wikipedia.org/wiki/HAL_(software)&quot;&gt;HAL&lt;/a&gt;? &lt;img alt=&quot;ðŸ˜‰&quot; class=&quot;wp-smiley&quot; src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png&quot; style=&quot;height: 1em;&quot; /&gt;).&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;AppStream&lt;/h3&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;A lot of extra maintenance work will be (has been!) done on it. This includes things such as JPEG-XL support (blog post soon), sandboxed media processing, support for newer specification additions, better OARS integration (and potentially migrating it to fd.o infrastructure), improvements and API stabilization for &lt;em&gt;libappstream-compose&lt;/em&gt; and a lot of bugfixing and resolution of issues found by AI code review.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;a href=&quot;https://github.com/ximion/appstream&quot;&gt;AppStream&lt;/a&gt; was originally designed to parse only trusted data from vetted Linux distribution sources – this is no longer the case in today’s world and in the way Flatpak uses it, so we need to increase resilience of the project.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;I am also exploring a project that could vastly improve search accuracy for AppStream. Stay tuned for that.&lt;/p&gt;



&lt;h3 class=&quot;wp-block-heading&quot;&gt;PackageKit &amp;amp; System Upgrades&lt;/h3&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;Many years ago, people thought we would all migrate to atomic Linux distributions and slowly not need &lt;a href=&quot;https://github.com/PackageKit/PackageKit&quot;&gt;PackageKit&lt;/a&gt; anymore. This has not turned out to be the case, and there are still plenty of reasons to use a package-based OS, especially in development environments. At the same time, PackageKit has been basically the same for years, and its older architecture is beginning to show. It being a daemon who’s literal job it is to modify the entire system also makes it one of the most security-sensitive components that a Linux system can have, while simultaneously making it near-impossible to sandbox.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;My plan is to create PackageKit 2.0 by building on the great foundation of PackageKit 1.0, but modernizing it. This will include simplifying its code and removing a bunch of features that have no more use in modern desktops, while also adding some features that PackageKit never had but that would be useful to expose to frontends (still no to interactivity an terminal-progress forwarding though!). PK 2.0 will also allow me to solve a few design issues that have been worked around in the past, by replacing them with better solutions. This will be a painful transition, as PackageKit 2.0 will break all interfaces PackageKit has – and those interfaces have been frozen for more than a decade. However, I do fully expect this change to be worth the effort.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;In addition to that, I intend to look into the offline-update procedure again and improve it. The current multi-reboot operation comes with downsides, that newer systemd features such as soft-reboot can alleviate. The end result should be a much smoother, less annoying offline-update experience for users (I especially want to get rid of updates running on system startup, which I consider quite bad from a usability perspective). The new behavior is in the early drafting stages and may need direct support from systemd. I will share more about it once I can.&lt;/p&gt;



&lt;h2 class=&quot;wp-block-heading&quot;&gt;That’s a lot of tasks!&lt;/h2&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;Yes! I will see how far I get. I am moving project-by-project though, to allow me to focus on one project at a time, rather than scattering my attention continuously. Amazingly, this means that the major tasks for AppStream are already almost done, and we are nearing the 1.2.0 release. AppStream got priority, because the new Freedesktop Flatpak runtime will be released soon, and because I want FlatHub/Flatpak to have access to the new AppStream release sooner. Freedesktop and PackageKit are next on the task list.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;Either way, a lot of progress is coming – if you have any feedback or want to help out, please don’t hesitate to reach out! All work is happening fully in the open, so you can also chime in on the respective GitHub/GitLab tasks &lt;img alt=&quot;ðŸ˜€&quot; class=&quot;wp-smiley&quot; src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/1f600.png&quot; style=&quot;height: 1em;&quot; /&gt;.&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;You can also expect blog posts about key features or interesting changes, so stay tuned! &lt;img alt=&quot;ðŸ™‚&quot; class=&quot;wp-smiley&quot; src=&quot;https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png&quot; style=&quot;height: 1em;&quot; /&gt;&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;/p&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;&lt;/p&gt; </description> 
	<pubDate>Mon, 24 Aug 2026 21:00:40 +0000</pubDate>

</item> 
<item>
	<title>Vincent Bernat: An interactive tour of the spanning tree protocol</title>
	<guid>http://www.luffy.cx/en/blog/2026-spanning-tree.html</guid>
	<link>https://vincent.bernat.ch/en/blog/2026-spanning-tree</link>
     <description>  &lt;div class=&quot;admonition when-rss&quot;&gt;
&lt;p class=&quot;admonition-title&quot;&gt;Warning&lt;/p&gt;
&lt;p&gt;This post contains interactive examples. To visualize and interact
with them, you need to &lt;a href=&quot;https://vincent.bernat.ch/en/blog/2026-spanning-tree&quot; title=&quot;An interactive tour of the spanning tree protocol&quot;&gt;leave your RSS reader&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Imagine you rent office space for a three-day event. You quickly set up a few
Ethernet switches and tape some cables on the floor to get everyone online.
Unfortunately, Stan, your clumsiest coworker, kicks out a cable every time he
gets up for coffee. You could add extra cables, but then youâ€™d get a broadcast
storm: Ethernet packets that loop and multiply until nothing else gets through.&lt;/p&gt;
&lt;p&gt;Thatâ€™s where the &lt;em&gt;spanning tree protocol&lt;/em&gt; (&lt;abbr title=&quot;Spanning Tree Protocol&quot;&gt;STP&lt;/abbr&gt;) comes in. &lt;abbr title=&quot;Spanning Tree Protocol&quot;&gt;STP&lt;/abbr&gt; blocks just enough
of your spare cables to leave a loop-free tree. When Stan strikes again, it
rebuilds the tree in a second, leaving some time for Blobby, your one-person
support crew, to reconnect the cable.&lt;sup id=&quot;fnref:sprites&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:sprites&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; See for yourself: the diagram
below runs a real &lt;abbr title=&quot;Spanning Tree Protocol&quot;&gt;STP&lt;/abbr&gt; implementation in your browser!&lt;/p&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:demo

A1 @0,0 prio=4096
A2 @0,1
A3 @0,2
A4 @0,3

B1 @1,0 prio=8192
B2 @1,1
B3 @1,2
B4 @1,3

C1 @2,0 prio=8192
C2 @2,1
C3 @2,2
C4 @2,3

A1 -- A2 hazard=0
A2 -- A3 hazard=0
A3 -- A4 hazard=0
B1 -- B2
B2 -- B3
B3 -- B4
C1 -- C2 hazard=0
C2 -- C3 hazard=0
C3 -- C4 hazard=0

A1 -- B1 cost=10
B1 -- C1 cost=10
A4 -- B4 cost=20
B4 -- C4 cost=20

Leo @-0.3,0.7 proto=none icon=ğŸ‘¦ğŸ�»
Mia @-0.3,1.3 proto=none icon=ğŸ‘§ğŸ�½
Joy @0.3,0.7  proto=none icon=ğŸ‘±ğŸ�»â€�â™€ï¸�
Roy @0.3,1.3  proto=none icon=ğŸ‘¨ğŸ�¾
A2 -- Leo hazard=0 A2:edge
A2 -- Mia hazard=0 A2:edge
A2 -- Joy hazard=0 A2:edge
A2 -- Roy hazard=0 A2:edge

Max @-0.3,1.7 proto=none icon=ğŸ‘¨ğŸ�½
Zoe @-0.3,2.3 proto=none icon=ğŸ‘©ğŸ�¾
Ada @0.3,1.7  proto=none icon=ğŸ‘µğŸ�¾
Amy @0.3,2.3  proto=none icon=ğŸ‘©ğŸ�¼
A3 -- Max hazard=0 A3:edge
A3 -- Zoe hazard=0 A3:edge
A3 -- Ada hazard=0 A3:edge
A3 -- Amy hazard=0 A3:edge

Eli @0.7,0.7 proto=none icon=ğŸ‘¦ğŸ�¼
Jay @0.7,1.3 proto=none icon=ğŸ‘¨ğŸ�»
Kai @1.3,0.7  proto=none icon=ğŸ§‘ğŸ�½
Ben @1.3,1.3  proto=none icon=ğŸ‘±ğŸ�¼
B2 -- Eli hazard=0.2 B2:edge
B2 -- Jay hazard=0.2 B2:edge
B2 -- Kai hazard=0.2 B2:edge
B2 -- Ben hazard=0.2 B2:edge

Ava @0.7,1.7 proto=none icon=ğŸ‘©ğŸ�»
Lea @0.7,2.3 proto=none icon=ğŸ§‘ğŸ�¾â€�ğŸ¦±
Ivy @1.3,1.7  proto=none icon=ğŸ§•ğŸ�½
Rex @1.3,2.3  proto=none icon=ğŸ‘´ğŸ�¿
B3 -- Ava hazard=0.2 B3:edge
B3 -- Lea hazard=0.2 B3:edge
B3 -- Ivy hazard=0.2 B3:edge
B3 -- Rex hazard=0.2 B3:edge

Ana @1.7,0.7 proto=none icon=ğŸ‘©ğŸ�¿
Eve @1.7,1.3 proto=none icon=ğŸ‘§ğŸ�¼
Abe @2.3,0.7  proto=none icon=ğŸ§“ğŸ�¿
Ian @2.3,1.3  proto=none icon=ğŸ§”ğŸ�¾
C2 -- Ana hazard=0 C2:edge
C2 -- Eve hazard=0 C2:edge
C2 -- Abe hazard=0 C2:edge
C2 -- Ian hazard=0 C2:edge

Ned @1.7,1.7 proto=none icon=ğŸ‘¨ğŸ�¼â€�ğŸ¦³
Lou @1.7,2.3 proto=none icon=ğŸ§‘ğŸ�¿
Fay @2.3,1.7  proto=none icon=ğŸ‘§ğŸ�»
Sue @2.3,2.3  proto=none icon=ğŸ‘©ğŸ�½â€�ğŸ¦°
C3 -- Ned hazard=0 C3:edge
C3 -- Lou hazard=0 C3:edge
C3 -- Fay hazard=0 C3:edge
C3 -- Sue hazard=0 C3:edge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;admonition&quot;&gt;
&lt;p class=&quot;admonition-title&quot;&gt;Note&lt;/p&gt;
&lt;p&gt;This article is also available as a &lt;a href=&quot;https://vincent.bernat.ch/en/blog/2026-spanning-tree-video&quot; title=&quot;A non-interactive tour of the spanning tree protocol&quot;&gt;video&lt;/a&gt;, but I advise you to
keep reading here to try the interactive demonstrations.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#the-basics&quot;&gt;The basics&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#historical-interlude&quot;&gt;Historical interlude&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#electing-the-root-bridge&quot;&gt;Electing the root bridge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#assigning-roles-to-ports&quot;&gt;Assigning roles to ports&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#port-state-transition&quot;&gt;Port state transition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#topology-change-notification&quot;&gt;Topology change notification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#security&quot;&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#why-rstp-today&quot;&gt;Why RSTP today?&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#how-large-can-a-network-be&quot;&gt;How large can a network be?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#how-fast-is-rstp&quot;&gt;How fast is RSTP?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#about-mstp&quot;&gt;About MSTP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#about-the-interactive-examples&quot;&gt;About the interactive examples&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h1 id=&quot;the-basics&quot;&gt;The basics&lt;/h1&gt;
&lt;p&gt;Designed in the â€™80s, the &lt;em&gt;spanning tree protocol&lt;/em&gt; has evolved into a â€œrapidâ€�
flavor (&lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt;) and a â€œVLAN-awareâ€� variation (&lt;abbr title=&quot;Multiple Spanning Tree Protocol&quot;&gt;MSTP&lt;/abbr&gt;).&lt;sup id=&quot;fnref:history&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:history&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Any sound-minded
network engineer knows there are better alternatives, like &lt;a href=&quot;https://vincent.bernat.ch/en/blog/2017-vxlan-bgp-evpn&quot; title=&quot;VXLAN: BGP EVPN with FRR&quot;&gt;BGP EVPN VXLAN&lt;/a&gt;.
Yet, because any switch speaks it, the venerable spanning tree protocol still
fills a niche.&lt;/p&gt;
&lt;p&gt;We focus on &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt;: it replaced the original protocol in 2004. To eliminate
network loops, &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; implements a complex state machine. Timers, link state
changes, and the link-local control frames a bridge receives from its neighbors
drive its transitions. These Ethernet frames are the &lt;em&gt;Bridge Protocol Data
Units&lt;/em&gt; (&lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt;). You can watch them in action below: hit the â€œStartâ€� button.&lt;/p&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:protocol rstp
:tx-hold 10

A1 @0,1
C11 @1,0 prio=4096 icon=ğŸŒ³
C12 @1,2 prio=4096 icon=ğŸŒ³
C21 @2,0 prio=4096 icon=ğŸŒ³
C22 @2,2 prio=4096 icon=ğŸŒ³
A2 @3,1

H1 @0,0.2 proto=none icon=ğŸ’»
H2 @0,1.8 proto=none icon=ğŸ–¨ï¸�
H3 @3,0.2 proto=none icon=ğŸ“ 
H4 @3,1.8 proto=none icon=ğŸ“º

A1 -- C11
A1 -- C12
A2 -- C21
A2 -- C22
C11 -- C12
C11 -- C21
C11 -- C21
C11 -- C22
C12 -- C21
C12 -- C22
C21 -- C22
A1 -- H1 A1:edge
A1 -- H2 A1:edge
A2 -- H3 A2:edge
A2 -- H4 A2:edge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After &lt;a href=&quot;https://vincent.bernat.ch#mstp:5,...&quot;&gt;some time&lt;/a&gt;, the topology converges to a tree: from the root
C11, there is a path to each bridge&lt;sup id=&quot;fnref:bridge&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:bridge&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; and no loop. In the upper right
corner, the interface displays a tree icon ğŸŒ³ followed by the time it took to
reach this state. &lt;a href=&quot;https://vincent.bernat.ch#mstp:9,C11--C12,...&quot;&gt;Cut a link&lt;/a&gt; and see how the protocol
finds an alternate path to reach C12 in less than a second. You can stop the
simulation, move it forward step by step, reset it to its initial state, or slow
it down with the â€œsnailâ€� modeÂ ğŸ�Œ. Donâ€™t worry about all the displayed
information: I explain it later.&lt;/p&gt;
&lt;p&gt;All examples run in your browser, powered by &lt;a href=&quot;https://github.com/mstpd/mstpd&quot; title=&quot;Multiple Spanning Tree Protocol Daemon&quot;&gt;MSTPD&lt;/a&gt;â€”an open-source
user-space&lt;sup id=&quot;fnref:kernel&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:kernel&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; implementation of &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt;.&lt;sup id=&quot;fnref:incomplete&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:incomplete&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;historical-interlude&quot;&gt;Historical interlude&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://hiddenheroes.netguru.com/radia-perlman&quot; title=&quot;The Magic Box and the Spanning Tree: How Radia Perlman made the Internet work&quot;&gt;Radia Perlman&lt;/a&gt;, an inductee of the &lt;a href=&quot;https://www.internethalloffame.org/inductee/radia-perlman/&quot; title=&quot;Radia Perlman profile on the Internet Hall of Fame&quot;&gt;Internet Hall of Fame&lt;/a&gt; in 2014,
summarized the ancestor of &lt;abbr title=&quot;Spanning Tree Protocol&quot;&gt;STP&lt;/abbr&gt; she invented at &lt;abbr title=&quot;Digital Equipment Corporation&quot;&gt;DEC&lt;/abbr&gt; with this poem, later
included in a &lt;a href=&quot;https://patents.google.com/patent/US7339900B2/en&quot; title=&quot;Method and apparatus for preventing spanning tree loops during traffic overload conditions&quot;&gt;US patent&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I think that I shall never see&lt;br /&gt;
A graph more lovely than a tree.&lt;br /&gt;
A tree whose crucial property&lt;br /&gt;
Is loop-free connectivity.&lt;br /&gt;
A tree which must be sure to span&lt;br /&gt;
So packets can reach every LAN.&lt;br /&gt;
First, the root must be selected.&lt;br /&gt;
By ID, it is elected.&lt;br /&gt;
Least cost paths from root are traced.&lt;br /&gt;
In the tree, these paths are placed.&lt;br /&gt;
A mesh is made by folks like me,&lt;br /&gt;
Then bridges find a spanning tree.&lt;/p&gt;
&lt;p&gt;â€• &lt;em&gt;Radia Perlman&lt;/em&gt;, &lt;a href=&quot;https://hiddenheroes.netguru.com/radia-perlman&quot; title=&quot;The Magic Box and the Spanning Tree: How Radia Perlman made the Internet work&quot;&gt;Algorhyme&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;electing-the-root-bridge&quot;&gt;Electing the root bridge&lt;/h2&gt;
&lt;p&gt;To build a tree, &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; first elects the bridge with the &lt;strong&gt;lowest bridge
identifier&lt;/strong&gt; as the &lt;strong&gt;root bridge&lt;/strong&gt;. The bridge identifier combines the priority
and the MAC address: &lt;code&gt;8192.6e:2b:10:a0:5f:29&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In the example below, S1 and S2 have priorities of 4,096 and 8,192: S1 becomes
root. S4 has a priority of 12,288, while S3 keeps the default priority of
32,768:&lt;sup id=&quot;fnref:priority&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:priority&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; S4 becomes root. S5 and S6 donâ€™t have a specific priority, so
the lowest MAC address wins and S5 becomes root.&lt;/p&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:protocol rstp

S1 @0,0 prio=4096
S2 @0,1 prio=8192
S1 -- S2

S3 @1,0
S4 @1,1 prio=12288
S3 -- S4

S5 @2,0
S6 @2,1
S5 -- S6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://vincent.bernat.ch#mstp:2,S2-&amp;gt;S1,@&quot;&gt;Initially&lt;/a&gt;, each bridge advertises itself as
root:&lt;sup id=&quot;fnref:wireshark&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:wireshark&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-wireshark codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Spanning Tree Protocol&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Identifier&lt;/span&gt;: Spanning Tree Protocol &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x0000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Version Identifier&lt;/span&gt;: Rapid Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU Type&lt;/span&gt;: Rapid/Multiple Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Root Identifier&lt;/span&gt;: 8192.02:00:00:01:00:01
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Bridge Identifier&lt;/span&gt;: 8192.02:00:00:01:00:01
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once a bridge receives a &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; advertising a better root bridge, it
&lt;a href=&quot;https://vincent.bernat.ch#mstp:3,S2-&amp;gt;S1,@&quot;&gt;propagates&lt;/a&gt; this new information to its neighbors.&lt;/p&gt;
&lt;div class=&quot;language-wireshark codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Spanning Tree Protocol&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Identifier&lt;/span&gt;: Spanning Tree Protocol &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x0000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Version Identifier&lt;/span&gt;: Rapid Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU Type&lt;/span&gt;: Rapid/Multiple Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Root Identifier&lt;/span&gt;: 4096.02:00:00:00:00:00
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Bridge Identifier&lt;/span&gt;: 8192.02:00:00:00:00:01
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;assigning-roles-to-ports&quot;&gt;Assigning roles to ports&lt;/h2&gt;
&lt;p&gt;The second step is to assign a role to each port. &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; defines five roles, each
denoted by a letter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;root (R),&lt;/li&gt;
&lt;li&gt;designated (D),&lt;/li&gt;
&lt;li&gt;alternate (A),&lt;/li&gt;
&lt;li&gt;disabled (X), or&lt;/li&gt;
&lt;li&gt;backup (B).&lt;sup id=&quot;fnref:backup&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:backup&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each non-root bridge chooses its &lt;strong&gt;root port&lt;/strong&gt;, the one with the lowest-cost
path to the root. Unless you override it, each bridge derives the link cost
from the speed: 20,000 for 1â€¯Gbps. In case of equality, the lowest port
identifier wins.&lt;/p&gt;
&lt;p&gt;Each remaining port becomes a &lt;strong&gt;designated port&lt;/strong&gt; if the &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; it sends is
â€œbetterâ€� than the &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; it receives. Otherwise, it becomes an &lt;strong&gt;alternate port&lt;/strong&gt;.
Later, if the root port goes down, the â€œbestâ€� alternate port becomes the new
root port. The tiebreakers for the best &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the lowest root bridge identifier,&lt;/li&gt;
&lt;li&gt;the lowest accumulated cost to the root,&lt;/li&gt;
&lt;li&gt;the lowest bridge identifier, and&lt;/li&gt;
&lt;li&gt;the lowest port identifier.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:protocol rstp

S1 @1,0  prio=4096 icon=ğŸŒ³
S2 @0,1
S3 @2,1

S1 -- S2
S1 -- S3
S1 -- S3
S2 -- S3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the example above, &lt;a href=&quot;https://vincent.bernat.ch#mstp:13&quot;&gt;after convergence&lt;/a&gt;, S1 is the root bridge
because it has a priority of 4,096, while the other bridges have a priority of
32,768. All its ports are designated ports because the accumulated cost to the
root is 0.&lt;/p&gt;
&lt;p&gt;S2â€™s port facing S1 becomes a root port because it has the lowest accumulated
cost to the rootâ€”20,000 vs 40,000. S3 has two ports facing S1, and the one with
the lowest port identifier becomes the root portâ€”&lt;code&gt;0x8000&lt;/code&gt; vs &lt;code&gt;0x8001&lt;/code&gt;. The other
candidate is an alternate port because the remote port on the link sends a
better &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt;, with an accumulated cost of 0. On the segment between S2 and S3,
S2â€™s port wins: while both bridges have the same accumulated cost to the root
(20,000), S2â€™s bridge identifier is smallerâ€”&lt;code&gt;32768.02:00:00:00:00:01&lt;/code&gt; vs
&lt;code&gt;32768.02:00:00:00:00:02&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-wireshark codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Spanning Tree Protocol&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Identifier&lt;/span&gt;: Spanning Tree Protocol &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x0000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Version Identifier&lt;/span&gt;: Rapid Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU Type&lt;/span&gt;: Rapid/Multiple Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Root Identifier&lt;/span&gt;: 4096.02:00:00:00:00:00
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Root Path Cost&lt;/span&gt;: 20000
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Bridge Identifier&lt;/span&gt;: 32768.02:00:00:00:00:01
&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;    Port identifier&lt;/span&gt;: 0x8002
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you &lt;a href=&quot;https://vincent.bernat.ch#mstp:13,S1--S3:1&quot;&gt;cut the active link between S1 and S3&lt;/a&gt;, S3 promotes
the â€œbestâ€� alternate port to root port. If you also &lt;a href=&quot;https://vincent.bernat.ch#mstp:13,S1--S3:1,S1--S3:2&quot;&gt;disable the second
link&lt;/a&gt;, S3 chooses the remaining alternate port as a
root port. But if you &lt;a href=&quot;https://vincent.bernat.ch#mstp:13,S1--S2,@,...&quot;&gt;disable the link between S1 and
S2&lt;/a&gt;, S2 needs a bit more work to elect a new root port
because it does not have an alternate port.&lt;/p&gt;
&lt;p&gt;Unless a specific event happens, designated ports send &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; &lt;a href=&quot;https://vincent.bernat.ch#mstp:13,S1-&amp;gt;S3:2,S2-&amp;gt;S3,S1-&amp;gt;S2,@&quot;&gt;every 2
seconds&lt;/a&gt;.&lt;sup id=&quot;fnref:hello&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:hello&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; If a bridge does not
receive &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; from its neighbor for 3 consecutive hello periods, it considers
the neighbor dead and removes the port information.&lt;/p&gt;
&lt;h2 id=&quot;port-state-transition&quot;&gt;Port state transition&lt;/h2&gt;
&lt;p&gt;Each port can have one of three states. The diagram displays a background color
for each state:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;discarding (red),&lt;/li&gt;
&lt;li&gt;learning (yellow), or&lt;/li&gt;
&lt;li&gt;forwarding (green).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A &lt;em&gt;root port&lt;/em&gt; transitions automatically to the forwarding state. An &lt;em&gt;alternate
port&lt;/em&gt; stays in the discarding state. A &lt;em&gt;designated port&lt;/em&gt; has two options to
transition from the discarding state to the forwarding state:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the port is an &lt;strong&gt;edge port&lt;/strong&gt;, either through configuration or because the
  remote device does not speak any flavor of &lt;abbr title=&quot;Spanning Tree Protocol&quot;&gt;STP&lt;/abbr&gt;, the bridge assumes the device
  wonâ€™t participate in the protocol and cannot create a loop. In this case, the
  designated port immediately transitions to the forwarding state.&lt;/li&gt;
&lt;li&gt;Otherwise, it sends a &lt;strong&gt;proposal&lt;/strong&gt; to its downstream neighbor. If the remote
  bridge agrees that the received &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; is â€œbetterâ€� than any other &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; stored
  for other ports, it elects the receiving port as its root port and starts the
  &lt;strong&gt;synchronization&lt;/strong&gt; process: it transitions all non-edge non-synced designated
  ports to the discarding state to avoid a loop. Then, it sends back an
  &lt;strong&gt;agreement&lt;/strong&gt;. Upon receiving the agreement, the peer designated port
  transitions to the forwarding state.&lt;sup id=&quot;fnref:learning&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:learning&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:protocol rstp

S1 @1,0 prio=4096 icon=ğŸŒ³
S2 @1,1
S3 @0,2
S4 @2,2
S5 @0,3 prio=8192 icon=ğŸª¾
S6 @2,3
H1 @0,1.2   proto=none icon=ğŸ–¨ï¸�
H2 @2,1.2   proto=none icon=ğŸ“ 
H3 @2.5,1.3 proto=none icon=ğŸ“º
H4 @2.5,2.3 proto=none icon=ğŸ’»

S1 -- S2
S2 -- S3
S2 -- S4
S3 -- S5
S4 -- S6
S4 -- S3
S5 -- S6

S3 -- H1 S3:edge
S4 -- H2 S4:edge
S4 -- H3 S4:edge
S6 -- H4 S6:edge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the topology above, H1, H2, H3, and H4 are end devices not participating in
the protocol. We configure the ports they connect to as edge ports, so these
ports immediately move to the forwarding state.&lt;/p&gt;
&lt;p&gt;Use the â€œstepâ€� button to move the simulation forward. The clock moves to 1
second. &lt;a href=&quot;https://vincent.bernat.ch#mstp:2,S1-&amp;gt;S2,S2-&amp;gt;S1,@&quot;&gt;Step again&lt;/a&gt; and S1 and S2 send a proposal to
each other. Here is the proposal from S2:&lt;/p&gt;
&lt;div class=&quot;language-wireshark codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Spanning Tree Protocol&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Identifier&lt;/span&gt;: Spanning Tree Protocol &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x0000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Version Identifier&lt;/span&gt;: Rapid Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU Type&lt;/span&gt;: Rapid/Multiple Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU flags&lt;/span&gt;: 0x4e, Agreement, Port Role: Designated, Proposal
        &lt;span class=&quot;no&quot;&gt;0... .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Topology Change Acknowledgment&lt;/span&gt;: No
        &lt;span class=&quot;no&quot;&gt;.1.. .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Agreement&lt;/span&gt;: Yes
        &lt;span class=&quot;no&quot;&gt;..0. .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Forwarding&lt;/span&gt;: No
        &lt;span class=&quot;no&quot;&gt;...0 .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Learning&lt;/span&gt;: No
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;no&quot;&gt;.... 11.. &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Port Role&lt;/span&gt;: Designated &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;no&quot;&gt;.... ..1. &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Proposal&lt;/span&gt;: Yes
&lt;/span&gt;        &lt;span class=&quot;no&quot;&gt;.... ...0 &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Topology Change&lt;/span&gt;: No
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Root Identifier&lt;/span&gt;: 32768.02:00:00:00:00:01
&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;    Root Path Cost&lt;/span&gt;: 0
&lt;span class=&quot;ss&quot;&gt;    Bridge Identifier&lt;/span&gt;: 32768.02:00:00:00:00:01
&lt;span class=&quot;ss&quot;&gt;    Port identifier&lt;/span&gt;: 0x8001
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;S1 ignores it: its own root identifier is lower. When S2 receives a similar
proposal from S1, it accepts S1 as its root bridge. It also elects the port to
S1 as the root port and starts the synchronization process. The two designated
ports are already discarding, so no change here. &lt;a href=&quot;https://vincent.bernat.ch#mstp:3,S2-&amp;gt;S1#2,@&quot;&gt;Step
again&lt;/a&gt; and S2 sends two &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; to S1. In one of them, the
agreement bit is 1 and the proposal bit is 0. It also shows that S2 accepted S1
as the root bridge and its root port is now in the forwarding state. When
receiving this &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt;, S1 transitions its own designated port to the forwarding
state. From this point, the link between S1 and S2 forwards user traffic.&lt;/p&gt;
&lt;div class=&quot;language-wireshark codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Spanning Tree Protocol&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Identifier&lt;/span&gt;: Spanning Tree Protocol &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x0000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Version Identifier&lt;/span&gt;: Rapid Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU Type&lt;/span&gt;: Rapid/Multiple Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU flags&lt;/span&gt;: 0x79, Agreement, Forwarding, Learning, Port Role: Root, Topology Change
        &lt;span class=&quot;no&quot;&gt;0... .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Topology Change Acknowledgment&lt;/span&gt;: No
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;no&quot;&gt;.1.. .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Agreement&lt;/span&gt;: Yes
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;no&quot;&gt;..1. .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Forwarding&lt;/span&gt;: Yes
&lt;/span&gt;        &lt;span class=&quot;no&quot;&gt;...1 .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Learning&lt;/span&gt;: Yes
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;no&quot;&gt;.... 10.. &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Port Role&lt;/span&gt;: Root &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;no&quot;&gt;.... ..0. &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Proposal&lt;/span&gt;: No
&lt;/span&gt;        &lt;span class=&quot;no&quot;&gt;.... ...1 &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Topology Change&lt;/span&gt;: Yes
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Root Identifier&lt;/span&gt;: 4096.02:00:00:00:00:00
&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;    Root Path Cost&lt;/span&gt;: 20000
&lt;span class=&quot;ss&quot;&gt;    Bridge Identifier&lt;/span&gt;: 32768.02:00:00:00:00:01
&lt;span class=&quot;ss&quot;&gt;    Port identifier&lt;/span&gt;: 0x8001
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Letâ€™s look at what happened to S5. &lt;a href=&quot;https://vincent.bernat.ch#mstp:2,S5-&amp;gt;S3,S3-&amp;gt;S5,S5-&amp;gt;S6,S6-&amp;gt;S5,@&quot;&gt;Reset the simulation and step
twice&lt;/a&gt;. S5 exchanges &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; with both S3
and S6. Since S5 has a lower root identifier than S3 and S6, it stays the root
bridge, while S3 and S6 accept the proposal and elect their root ports. S3 and
S6 start the synchronization process. S6â€™s port to H4 keeps forwarding because
it is an edge port. &lt;a href=&quot;https://vincent.bernat.ch#mstp:3,S3-&amp;gt;S5#1,S6-&amp;gt;S5#1,@&quot;&gt;Move one step&lt;/a&gt;. Both S3 and S6 send
an agreement back to S5, which transitions both designated ports to the
forwarding state. Yet, the link between S5 and S3 keeps discarding user traffic!
If you look carefully, S3â€™s port toward S5 is now a designated port, not a root
port. During the &lt;a href=&quot;https://vincent.bernat.ch#mstp:3,S2-&amp;gt;S3,@&quot;&gt;same step&lt;/a&gt;, S3 also receives a better &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt;
from S2 with S1 as the root bridge. It elects its port to S2 as the root port
and downgrades the port to S5 to a designated port, which stays in the
discarding state.&lt;/p&gt;
&lt;p&gt;On the &lt;a href=&quot;https://vincent.bernat.ch#mstp:4,S3-&amp;gt;S5,@&quot;&gt;next step&lt;/a&gt;, things get a bit tricky. S3 sends a
proposal to S5:&lt;sup id=&quot;fnref:agreement&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:agreement&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-wireshark codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Spanning Tree Protocol&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Identifier&lt;/span&gt;: Spanning Tree Protocol &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x0000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Version Identifier&lt;/span&gt;: Rapid Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU Type&lt;/span&gt;: Rapid/Multiple Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU flags&lt;/span&gt;: 0x4f, Agreement, Port Role: Designated, Proposal, Topology Change
        &lt;span class=&quot;no&quot;&gt;0... .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Topology Change Acknowledgment&lt;/span&gt;: No
        &lt;span class=&quot;no&quot;&gt;.1.. .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Agreement&lt;/span&gt;: Yes
        &lt;span class=&quot;no&quot;&gt;..0. .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Forwarding&lt;/span&gt;: No
        &lt;span class=&quot;no&quot;&gt;...0 .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Learning&lt;/span&gt;: No
        &lt;span class=&quot;no&quot;&gt;.... 11.. &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Port Role&lt;/span&gt;: Designated &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;no&quot;&gt;.... ..1. &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Proposal&lt;/span&gt;: Yes
&lt;/span&gt;        &lt;span class=&quot;no&quot;&gt;.... ...1 &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Topology Change&lt;/span&gt;: Yes
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Root Identifier&lt;/span&gt;: 4096.02:00:00:00:00:00
&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;    Root Path Cost&lt;/span&gt;: 40000
&lt;span class=&quot;ss&quot;&gt;    Bridge Identifier&lt;/span&gt;: 32768.02:00:00:00:00:02
&lt;span class=&quot;ss&quot;&gt;    Port identifier&lt;/span&gt;: 0x8002
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;S5 elects S1 as its root bridge and the port toward S3 as its root port. It
starts its synchronization process, but the designated port to S6 does &lt;em&gt;not&lt;/em&gt;
move into the discarding state. Why? That port stays a designated port and its
neighbor S6 has already sent an agreement on the link, so the port keeps its
synced status.&lt;/p&gt;
&lt;p&gt;Now, letâ€™s &lt;a href=&quot;https://vincent.bernat.ch#mstp:3,@&quot;&gt;step back&lt;/a&gt; to look at what happens to S6. At this point,
S6 believes S5 is the root bridge. &lt;a href=&quot;https://vincent.bernat.ch#mstp:4,S4-&amp;gt;S6#1,@&quot;&gt;Step once&lt;/a&gt; and S4 sends
a new proposal to S6. S6 accepts the proposal, elects S1 as the root bridge and
the port to S4 as its root port. The role of the port facing S5 changes: from a
root port, it becomes a designated port. Because its peer keeps advertising an
inferior &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; on the link, this port becomes disputed and moves to the
discarding state. The root port transitions to the forwarding state and the link
starts forwarding immediately because S4â€™s designated port is already in the
forwarding state. If we &lt;a href=&quot;https://vincent.bernat.ch#mstp:5,S5-&amp;gt;S6,S6-&amp;gt;S5,@&quot;&gt;step one more time&lt;/a&gt;, S5 and S6
exchange two &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt;. The one from S5 is better because of its lower bridge
identifier. S5â€™s port stays a designated port, while S6 downgrades its own port
to an alternate port.&lt;/p&gt;
&lt;p&gt;Letâ€™s rewind to the start one last time: cut the link between S1 and S2, &lt;a href=&quot;https://vincent.bernat.ch#mstp:S1--S2,9&quot;&gt;run
the simulation until the topology is stable&lt;/a&gt;, stop the
simulation, and restore the link between S1 and S2. During the &lt;a href=&quot;https://vincent.bernat.ch#mstp:S1--S2,9,S1--S2,1,S1-&amp;gt;S2,S2-&amp;gt;S1,@&quot;&gt;first
step&lt;/a&gt;, S1 and S2 exchange proposals. S2
elects S1 as the root bridge instead of S5 and the port to S1 as the root port.
It downgrades the previous root port to a designated port and moves it into the
discarding state. The other designated port stays synced and keeps its
forwarding state. At the &lt;a href=&quot;https://vincent.bernat.ch#mstp:S1--S2,9,S1--S2,2,S2-&amp;gt;S1,@&quot;&gt;next step&lt;/a&gt;, S2 sends
an agreement to S1 and the link between them starts forwarding user traffic. It
also &lt;a href=&quot;https://vincent.bernat.ch#mstp:S1--S2,9,S1--S2,2,S2-&amp;gt;S3,@&quot;&gt;sends a proposal to S3&lt;/a&gt;, but not to S4.
Instead, &lt;a href=&quot;https://vincent.bernat.ch#mstp:S1--S2,9,S1--S2,2,S2-&amp;gt;S4,@&quot;&gt;it sends a regular &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; to S4&lt;/a&gt;. S4
still elects S1 as its root bridge and the port to S2 as its root port. It
demotes its previous root port, the one to S3, to a designated port, which
transitions to the discarding state because of the root port change. The other
alternate port, to S6, also becomes a designated port and stays in the
discarding state. The new root port moves to the forwarding state. On the &lt;a href=&quot;https://vincent.bernat.ch#mstp:S1--S2,9,S1--S2,3,S3-&amp;gt;S4#1,@&quot;&gt;next
step&lt;/a&gt;, S4â€™s port to S3 settles as an
alternate port after receiving a â€œbetterâ€� &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; from S3.&lt;/p&gt;
&lt;p&gt;&lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; is a giant state machine split into smaller ones: bridge detection, port
information, port protocol migration, port role selection, port role
transitions, port receive, port state transitions, port timers, port transmit,
and topology change. Some of them are per bridge, some per port. Each bridge
runs an instance. Time, operational port state changes, and the &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; it
receives from other instances drive the transitions. Being event-driven makes
&lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; more efficient but also more difficult to understand.&lt;/p&gt;
&lt;figure class=&quot;lf-fullbleed&quot;&gt;&lt;div class=&quot;lf-media-outer&quot; style=&quot;width: 900px;&quot;&gt;&lt;span class=&quot;lf-media-inner&quot;&gt;&lt;img alt=&quot;Western Australian Government Railways class Msa Garratt articulated steam locomotive: elevation and plan drawing&quot; class=&quot;lf-media lf-opaque&quot; height=&quot;390&quot; src=&quot;https://d2pzklc15kok91.cloudfront.net/images/msa-garratt@1x.77dc2f6581ab04.jpg&quot; width=&quot;900&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;figcaption&gt;Placeholder for the &lt;em&gt;Port Information&lt;/em&gt; state machine extracted from IEEEâ€¯802.1Q-2005, page 182. Pending IEEE authorization for reproduction, this is the blueprint for the Western Australian Government Railways class Msa Garratt articulated steam locomotive.&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2 id=&quot;topology-change-notification&quot;&gt;Topology change notification&lt;/h2&gt;
&lt;p&gt;A bridge populates a MAC address table: it associates each source MAC address
with the port that last received it. When forwarding an Ethernet frame, it looks
up this table to choose the right port.&lt;sup id=&quot;fnref:bum&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:bum&quot;&gt;12&lt;/a&gt;&lt;/sup&gt; When a link fails, a connected
fridge reachable through one port may become reachable through another one. The
affected bridges should flush the MAC addresses they learned, because these
entries may now be wrong.&lt;/p&gt;
&lt;p&gt;For this purpose, &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; implements &lt;em&gt;topology change notifications&lt;/em&gt; using a
flooding mechanism. When a non-edge port transitions to the forwarding state, a
bridge generates &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; with the &lt;em&gt;topology change&lt;/em&gt; (&lt;abbr title=&quot;Topology Change&quot;&gt;TC&lt;/abbr&gt;) bit set. It sends them to
all the non-edge designated ports and to the root port. It also flushes the MAC
address table on these ports. When a bridge receives such a &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt;, it propagates
the notification to all non-edge designated ports and the root port, except the
one the notification came from. It also flushes the MAC address table on these
ports. In the examples, the &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; with the &lt;abbr title=&quot;Topology Change&quot;&gt;TC&lt;/abbr&gt; bit set to 1 have a red circle.&lt;/p&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:protocol rstp

S1 @1,0 prio=4096 icon=ğŸŒ³
S2 @0,1
S3 @1,1
S4 @2,1
S5 @1,2
LPT @0.1,2 proto=none icon=ğŸ–¨ï¸�

S1 -- S2
S1 -- S3
S1 -- S4
S2 -- S3
S2 -- S5
S4 -- S5
S5 -- LPT S5:edge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Start the simulation and wait a &lt;a href=&quot;https://vincent.bernat.ch#mstp:10&quot;&gt;few seconds&lt;/a&gt; for the topology to
settle. Stop the simulation and &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,S2--S5&quot;&gt;disable the link between S2 and
S5&lt;/a&gt;. S5 elects the port facing S4 as the root port, which
transitions immediately to the forwarding state. &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,S2--S5,1,S5-&amp;gt;S4,@&quot;&gt;Step
once&lt;/a&gt; and S5 emits a &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; with the &lt;abbr title=&quot;Topology Change&quot;&gt;TC&lt;/abbr&gt; bit set to 1:&lt;/p&gt;
&lt;div class=&quot;language-wireshark codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Spanning Tree Protocol&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Identifier&lt;/span&gt;: Spanning Tree Protocol &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x0000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Version Identifier&lt;/span&gt;: Rapid Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU Type&lt;/span&gt;: Rapid/Multiple Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU flags&lt;/span&gt;: 0x79, Agreement, Forwarding, Learning, Port Role: Root, Topology Change
        &lt;span class=&quot;no&quot;&gt;0... .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Topology Change Acknowledgment&lt;/span&gt;: No
        &lt;span class=&quot;no&quot;&gt;.1.. .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Agreement&lt;/span&gt;: Yes
        &lt;span class=&quot;no&quot;&gt;..1. .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Forwarding&lt;/span&gt;: Yes
        &lt;span class=&quot;no&quot;&gt;...1 .... &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Learning&lt;/span&gt;: Yes
        &lt;span class=&quot;no&quot;&gt;.... 10.. &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Port Role&lt;/span&gt;: Root &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;no&quot;&gt;.... ..0. &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Proposal&lt;/span&gt;: No
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;no&quot;&gt;.... ...1 &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;= &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;Topology Change&lt;/span&gt;: Yes
&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;    Root Identifier&lt;/span&gt;: 4096.02:00:00:00:00:00
&lt;span class=&quot;ss&quot;&gt;    Root Path Cost&lt;/span&gt;: 40000
&lt;span class=&quot;ss&quot;&gt;    Bridge Identifier&lt;/span&gt;: 32768.02:00:00:00:00:04
&lt;span class=&quot;ss&quot;&gt;    Port identifier&lt;/span&gt;: 0x8002
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;S4 receives this &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt;. It flushes the MAC address table on the port facing S1:
while LPT was previously reachable through this port, it is now reachable
through S5. &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,S2--S5,2,S4-&amp;gt;S1,@&quot;&gt;Step once&lt;/a&gt;. S4 sends S1 a &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt;
with the &lt;abbr title=&quot;Topology Change&quot;&gt;TC&lt;/abbr&gt; bit set to 1. When S1 receives this &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt;, it flushes the MAC address
table on the ports facing S2 and S3. &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,S2--S5,3,S1-&amp;gt;S2,S1-&amp;gt;S3,@&quot;&gt;Step
once&lt;/a&gt; and S1 sends a notification to S2 and
S3. &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,S2--S5,4,S2-&amp;gt;S3,@&quot;&gt;Step once again&lt;/a&gt; and S2 sends a notification to
S3, while S3 does nothing because the port toward S2 is an &lt;em&gt;alternate port&lt;/em&gt;. S3
does not flush any MAC address table: LPT is still reachable through its port to
S1.&lt;/p&gt;
&lt;p&gt;If you &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,S2--S5,6,@&quot;&gt;step a bit more&lt;/a&gt;, you will see that some of the
periodic &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; keep the &lt;abbr title=&quot;Topology Change&quot;&gt;TC&lt;/abbr&gt; bit set to 1. Each port runs a timer equal to the
hello timer plus one second.&lt;sup id=&quot;fnref:timer&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:timer&quot;&gt;13&lt;/a&gt;&lt;/sup&gt; The timer starts when the port emits a
notification. Until it expires, the port sets the &lt;abbr title=&quot;Topology Change&quot;&gt;TC&lt;/abbr&gt; bit to 1 in every &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; it
sends. You can also see &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,S2--S5,7,S1-&amp;gt;S4,S4-&amp;gt;S5,@&quot;&gt;some periodic &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt;&lt;/a&gt;
without the &lt;abbr title=&quot;Topology Change&quot;&gt;TC&lt;/abbr&gt; bit: they originate from a port that only received a notification
and therefore did not arm its timer.&lt;/p&gt;
&lt;h2 id=&quot;security&quot;&gt;Security&lt;/h2&gt;
&lt;p&gt;&lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; is weak against configuration errors and malicious actors. A bridge not
talking &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; can create a loop. An attacker can insert themselves into the
topology to disrupt the service, spy on the traffic, or alter it.&lt;/p&gt;
&lt;p&gt;To mitigate such problems, you need to identify the edge ports. An edge port
connects to an end device, like a PC or a printer. Such devices do not generate
&lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; and cannot create a loop. &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; defines two related flags:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When true, &lt;strong&gt;AdminEdge&lt;/strong&gt; initializes a port as an edge port. It defaults to
  false.&lt;/li&gt;
&lt;li&gt;When true, &lt;strong&gt;AutoEdge&lt;/strong&gt; lets a port become an edge port when it does not
  receive &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; for 3 seconds. It defaults to true.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If an edge port receives a &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt;, regardless of the values of these two flags, it
reverts to a non-edge port.&lt;/p&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;R0 @1.5,1.5 prio=8192

# AutoEdge=true, AdminEdge=false, bridge
S1 @3,1.58
R0 -- S1

# AutoEdge=true, AdminEdge=false, end device
H1 @2.84,2.18 icon=ğŸ–¨ï¸� proto=none
R0 -- H1

# AutoEdge=true, AdminEdge=true, bridge
S2 @2.18,2.84
R0 -- S2 R0:edge

# AutoEdge=true, AdminEdge=true, end device
H2 @1.58,3 icon=ğŸ’» proto=none
R0 -- H2 R0:edge

# AutoEdge=false, AdminEdge=true, bridge
S3 @0.68,2.76
R0 -- S3 R0:edge R0:no-auto-edge

# AutoEdge=false, AdminEdge=true, end device
H3 @0.24,2.32 icon=ğŸ“  proto=none
R0 -- H3 R0:edge R0:no-auto-edge

# AutoEdge=false, AdminEdge=false, bridge
S4 @0,1.42
R0 -- S4 R0:no-auto-edge

# AutoEdge=false, AdminEdge=false, end device
H4 @0.16,0.82 icon=ğŸ“º proto=none
R0 -- H4 R0:no-auto-edge

# Network port, bridge
S5 @0.82,0.16
R0 -- S5 R0:network S5:network

# Network port, end device
H5 @1.42,0 icon=â˜• proto=none
R0 -- H5 R0:network

# AdminEdge=true, bpdu-guard=true, bridge
S6 @2.32,0.24
R0 -- S6 R0:bpdu-guard R0:edge

# AdminEdge=true, bpdu-guard=true, end device
H6 @2.76,0.68 icon=ğŸ’¡ proto=none
R0 -- H6 R0:bpdu-guard R0:edge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the topology above, S1, S2, S3, S4, S5, and S6 act as bridges, while H1, H2,
H3, H4, H5, and H6 act as end devices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;S1 and H1 are on a port without a specific configuration: &lt;em&gt;AutoEdge&lt;/em&gt; is true,
  &lt;em&gt;AdminEdge&lt;/em&gt; is false,&lt;/li&gt;
&lt;li&gt;S2 and H2 are on a port where &lt;em&gt;AdminEdge&lt;/em&gt; is true,&lt;/li&gt;
&lt;li&gt;S3 and H3 are on a port where &lt;em&gt;AutoEdge&lt;/em&gt; is false and &lt;em&gt;AdminEdge&lt;/em&gt; is true,&lt;/li&gt;
&lt;li&gt;S4 and H4 are on a port where &lt;em&gt;AutoEdge&lt;/em&gt; is false.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you start the simulation and &lt;a href=&quot;https://vincent.bernat.ch#mstp:24&quot;&gt;wait about 20 seconds&lt;/a&gt;, links to S1,
S2, S3, S4, H1, H2, H3, and H4 eventually forward user traffic: none of the
flags matter.&lt;/p&gt;
&lt;p&gt;But what about the two remaining pairs? S5 and H5 connect to a &lt;em&gt;network&lt;/em&gt; port.
Such a port enables a non-standard feature: &lt;strong&gt;bridge assurance&lt;/strong&gt;. The port
transmits &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; regardless of its role. If it does not receive &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; for 3
consecutive hello periods, it transitions to the discarding state. On the link
between R0 and S5, you can see &lt;a href=&quot;https://vincent.bernat.ch#mstp:24,R0-&amp;gt;S5,S5-&amp;gt;R0,@&quot;&gt;&lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; traveling in both
directions&lt;/a&gt;, unlike the other links, where only
designated ports send &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt;.&lt;/p&gt;
&lt;p&gt;S6 and H6 connect to a port where &lt;em&gt;AdminEdge&lt;/em&gt; is true and &lt;strong&gt;&lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; guard&lt;/strong&gt; is
enabled. This is another non-standard feature that shuts down a port if &lt;a href=&quot;https://vincent.bernat.ch#mstp:2,S6-&amp;gt;R0,@&quot;&gt;it
receives a &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In summary, if you expect a port to be an edge port, you should set &lt;em&gt;AdminEdge&lt;/em&gt;
to true and enable &lt;em&gt;&lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; guard&lt;/em&gt;. Otherwise, declare it as a &lt;em&gt;network&lt;/em&gt; port.&lt;/p&gt;
&lt;h1 id=&quot;why-rstp-today&quot;&gt;Why &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; today?&lt;/h1&gt;
&lt;p&gt;A compelling use case for &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; today is an out-of-band network for a datacenter,
since you can tolerate an outage of a few seconds. The configuration is minimal
and you can use cheap switches, like a Cisco 2960X.&lt;sup id=&quot;fnref:price&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:price&quot;&gt;14&lt;/a&gt;&lt;/sup&gt; You need two
switches acting as root bridges, and you build several loops to connect &lt;abbr title=&quot;Out-of-band&quot;&gt;OOB&lt;/abbr&gt;
switches in each cabinet. This simple design survives one failure on each
loop.&lt;sup id=&quot;fnref:erps&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:erps&quot;&gt;15&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:protocol rstp
:tx-hold 10

# Root bridges
R1 @0,1 prio=0
R2 @0,2 prio=4096
R1 -- R2 cost=200 R1:network R2:network
R1 -- R2 cost=200 R1:network R2:network

# First loop
C1  @1,0 icon=ğŸ—„ï¸�
C4  @2,0 icon=ğŸ—„ï¸�
C7  @3,0 icon=ğŸ—„ï¸�
C10 @4,0 icon=ğŸ—„ï¸�
C12 @5,0 icon=ğŸ—„ï¸�
C13 @5,3 icon=ğŸ—„ï¸�
C15 @4,3 icon=ğŸ—„ï¸�
C18 @3,3 icon=ğŸ—„ï¸�
C21 @2,3 icon=ğŸ—„ï¸�
C24 @1,3 icon=ğŸ—„ï¸�
R1  -- C1  R1:network C1:network
C1  -- C4  C1:network C4:network
C4  -- C7  C4:network C7:network
C7  -- C10 C7:network C10:network
C10 -- C12 C10:network C12:network
C12 -- C13 C12:network C13:network
C13 -- C15 C13:network C15:network
C15 -- C18 C15:network C18:network
C18 -- C21 C18:network C21:network
C21 -- C24 C21:network C24:network
C24 -- R2  C24:network R2:network

# Second loop
C2  @1,0.5 icon=ğŸ—„ï¸�
C5  @2,0.5 icon=ğŸ—„ï¸�
C8  @3,0.5 icon=ğŸ—„ï¸�
C11 @4,0.5 icon=ğŸ—„ï¸�
C14 @4,2.5 icon=ğŸ—„ï¸�
C17 @3,2.5 icon=ğŸ—„ï¸�
C20 @2,2.5 icon=ğŸ—„ï¸�
C23 @1,2.5 icon=ğŸ—„ï¸�
R1  -- C2  R1:network C2:network
C2  -- C5  C2:network C5:network
C5  -- C8  C5:network C8:network
C8  -- C11 C8:network C11:network
C11 -- C14 C11:network C14:network
C14 -- C17 C14:network C17:network
C17 -- C20 C17:network C20:network
C20 -- C23 C20:network C23:network
C23 -- R2  C23:network R2:network

# Third loop
C3  @1,1 icon=ğŸ—„ï¸�
C6  @2,1 icon=ğŸ—„ï¸�
C9  @3,1 icon=ğŸ—„ï¸�
C16 @3,2 icon=ğŸ—„ï¸�
C19 @2,2 icon=ğŸ—„ï¸�
C22 @1,2 icon=ğŸ—„ï¸�
R1  -- C3  R1:network C3:network
C3  -- C6  C3:network C6:network
C6  -- C9  C6:network C9:network
C9  -- C16 C9:network C16:network
C16 -- C19 C16:network C19:network
C19 -- C22 C19:network C22:network
C22 -- R2  C22:network R2:network
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This topology converges in about &lt;a href=&quot;https://vincent.bernat.ch#mstp:6&quot;&gt;6 seconds&lt;/a&gt;. Each loop should stay
small (around 16 bridges) to reduce the probability of a double failure and to
avoid sharing too much bandwidth. The design can evolve a bit without adding too
much complexity: one VLAN per loop or one bridge domain per loop.&lt;/p&gt;
&lt;h2 id=&quot;how-large-can-a-network-be&quot;&gt;How large can a network be?&lt;/h2&gt;
&lt;p&gt;The maximum age, whose default value is 20, governs the maximum distance of a
bridge from the root. The topology below is too big for &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; from R1 to reach
beyond S20.&lt;sup id=&quot;fnref:root-mac&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:root-mac&quot;&gt;16&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:protocol rstp
:tx-hold 10
:max-age 20

R1 @0,0 prio=4096 icon=ğŸŒ³
R2 @0,5 prio=4096 icon=ğŸª¾

S1  @1,0
S2  @2,0
S3  @3,0
S4  @4,0
S5  @5,0
S6  @6,0

S7  @6,1
S8  @5,1
S9  @4,1
S10 @3,1
S11 @2,1
S12 @1,1

S13 @1,2
S14 @2,2
S15 @3,2
S16 @4,2
S17 @5,2
S18 @6,2

S19 @6,3
S20 @5,3
S21 @4,3
S22 @3,3
S23 @2,3
S24 @1,3

S25 @1,4
S26 @2,4
S27 @3,4
S28 @4,4
S29 @5,4
S30 @6,4

S31 @6,5
S32 @5,5
S33 @4,5
S34 @3,5
S35 @2,5
S36 @1,5

R1  -- S1
S1  -- S2
S2  -- S3
S3  -- S4
S4  -- S5
S5  -- S6
S6  -- S7
S7  -- S8
S8  -- S9
S9  -- S10
S10 -- S11
S11 -- S12
S12 -- S13
S13 -- S14
S14 -- S15
S15 -- S16
S16 -- S17
S17 -- S18
S18 -- S19
S19 -- S20
S20 -- S21
S21 -- S22
S22 -- S23
S23 -- S24
S24 -- S25
S25 -- S26
S26 -- S27
S27 -- S28
S28 -- S29
S29 -- S30
S30 -- S31
S31 -- S32
S32 -- S33
S33 -- S34
S34 -- S35
S35 -- S36
S36 -- R2
R1  -- R2 cost=200 down
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once the &lt;a href=&quot;https://vincent.bernat.ch#mstp:40&quot;&gt;topology settles&lt;/a&gt;, part of the network considers R1 the
root, while the other votes for R2. At the boundary, S20 tries to start a
synchronization with S21 to move its &lt;em&gt;designated port&lt;/em&gt; to the forwarding state.
The &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; looks like this:&lt;/p&gt;
&lt;div class=&quot;language-wireshark codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Spanning Tree Protocol&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Identifier&lt;/span&gt;: Spanning Tree Protocol &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x0000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Version Identifier&lt;/span&gt;: Rapid Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU Type&lt;/span&gt;: Rapid/Multiple Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU flags&lt;/span&gt;: 0x4e, Agreement, Port Role: Designated, Proposal
&lt;span class=&quot;ss&quot;&gt;    Root Identifier&lt;/span&gt;: 4096.02:00:00:00:00:00
&lt;span class=&quot;ss&quot;&gt;    Root Path Cost&lt;/span&gt;: 400000
&lt;span class=&quot;ss&quot;&gt;    Bridge Identifier&lt;/span&gt;: 32768.02:00:00:00:00:15
&lt;span class=&quot;ss&quot;&gt;    Port identifier&lt;/span&gt;: 0x8002
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Message Age&lt;/span&gt;: 20
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Max Age&lt;/span&gt;: 20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;S21 rejects it because the message age equals the maximum age. On the other
hand, the &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; S21 sends to S20 looks like this:&lt;/p&gt;
&lt;div class=&quot;language-wireshark codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Spanning Tree Protocol&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Identifier&lt;/span&gt;: Spanning Tree Protocol &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x0000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    Protocol Version Identifier&lt;/span&gt;: Rapid Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU Type&lt;/span&gt;: Rapid/Multiple Spanning Tree &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0x02&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;ss&quot;&gt;    BPDU flags&lt;/span&gt;: 0x7c, Agreement, Forwarding, Learning, Port Role: Designated
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Root Identifier&lt;/span&gt;: 4096.02:00:00:00:00:01
&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;    Root Path Cost&lt;/span&gt;: 320000
&lt;span class=&quot;ss&quot;&gt;    Bridge Identifier&lt;/span&gt;: 32768.02:00:00:00:00:16
&lt;span class=&quot;ss&quot;&gt;    Port identifier&lt;/span&gt;: 0x8001
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Message Age&lt;/span&gt;: 16
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;ss&quot;&gt;    Max Age&lt;/span&gt;: 20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is not enough to change S20â€™s &lt;em&gt;root port&lt;/em&gt; because S20 has a lower &lt;em&gt;root
identifier&lt;/em&gt;â€”&lt;code&gt;4096.02:00:00:00:00:00&lt;/code&gt; vs &lt;code&gt;4096.02:00:00:00:00:01&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://vincent.bernat.ch#mstp:40,R1--R2,...&quot;&gt;Fixing the link between R1 and R2&lt;/a&gt; resolves the issue. The
maximum message age any packet carries is now 18, below the configured maximum
age. But it only works until another link breaks. A plausible fix is to increase
the maximum age to 40.&lt;sup id=&quot;fnref:forward-delay&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:forward-delay&quot;&gt;17&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h2 id=&quot;how-fast-is-rstp&quot;&gt;How fast is &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt;?&lt;/h2&gt;
&lt;p&gt;&lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; usually converges in a couple of seconds at startup. It often repairs a
tree in less than a second. Even the &lt;a href=&quot;https://vincent.bernat.ch/en/blog/2026-spanning-tree#how-large-can-a-network-be&quot;&gt;38-bridge topology&lt;/a&gt; takes less than 10
seconds to converge.&lt;sup id=&quot;fnref:time&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:time&quot;&gt;18&lt;/a&gt;&lt;/sup&gt; Some topologies can take a bit more time to recover
when the root bridge becomes unavailable.&lt;sup id=&quot;fnref:slow&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:slow&quot;&gt;19&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-text-only mstp-topology codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;:protocol rstp

R0 @1,0 prio=0
S1 @1,1 prio=4096
S2 @0,2 prio=8192
S3 @2,2

R0 -- S1
S1 -- S2
S2 -- S3
S3 -- S1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the topology above, start the simulation, &lt;a href=&quot;https://vincent.bernat.ch#mstp:10&quot;&gt;wait for convergence&lt;/a&gt;,
hit stop, and &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,R0--S1&quot;&gt;cut the link between R0 and S1&lt;/a&gt;. The topology is
already optimal, but &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; has a hard time converging again.&lt;/p&gt;
&lt;p&gt;First, S1 loses its root port. It has no more information about R0 and elects
itself as the root bridge. It keeps its ports to S2 and S3 as designated ports
in the forwarding state. &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,R0--S1,1,S1-&amp;gt;S2,S1-&amp;gt;S3,@&quot;&gt;Step once&lt;/a&gt; and it
sends a &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; to both S2 and S3 to let them know about the root change. When
receiving it, S2 accepts S1 as its root because it does not have a better root
on another port. It elects the port to S1 as its root port. The other port stays
a designated port. Both ports keep forwarding.&lt;/p&gt;
&lt;p&gt;When receiving the &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; from S1, S3 behaves differently: it knows R0 as a better
root than S1 through its alternate port to S2. It promotes this port to a root
port and demotes the port facing S1 to a designated port, which requires a new
agreement. &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,R0--S1,2,S3-&amp;gt;S1#1,@&quot;&gt;Step once&lt;/a&gt; and S3 sends a proposal to
S1 with R0 as the root bridge. S1 elects R0 as the root bridge and promotes its
port to S3 as a root port.&lt;/p&gt;
&lt;p&gt;During the &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,R0--S1,2,S2-&amp;gt;S3,@&quot;&gt;same step&lt;/a&gt;, S3 also receives a &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; from
S2 stating that S1 is the root bridge. Therefore, S3 has no port left with R0 as
the root bridge: it elects S1 as the root bridge and its port to S2 as the root
port. &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,R0--S1,3,S3-&amp;gt;S1,@&quot;&gt;Step once&lt;/a&gt; and its next &lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; to S1 includes
this information: S1 elects itself again as the root bridge. But during the
&lt;a href=&quot;https://vincent.bernat.ch#mstp:10,R0--S1,3,S1-&amp;gt;S2#1,@&quot;&gt;same wave&lt;/a&gt;, S1 sends a proposal to S2 with R0 as
the root bridge. While S1 and S3 agree that S1 is the root bridge, S2 now
believes this is R0! &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,R0--S1,4,@,...&quot;&gt;In turn&lt;/a&gt;, S2 again convinces S3
that R0 is the root bridge, S3 convinces S1, S1 convinces S2, and S2 convinces
S3.&lt;/p&gt;
&lt;p&gt;This could go on forever, but it does not. The &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; saying â€œR0 is rootâ€�
eventually age out when the message age goes past the maximum age. In the
example above, at the &lt;a href=&quot;https://vincent.bernat.ch#mstp:10,R0--S1,24,S2-&amp;gt;S3,@&quot;&gt;eleventh second&lt;/a&gt;, S2 sends a
&lt;abbr title=&quot;Bridge Protocol Data Unit&quot;&gt;BPDU&lt;/abbr&gt; to S3 with R0 as root, but S3 drops it because its message age reached the
maximum. With some luck, the topology can also converge faster if a port stops
transmitting new &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; after tripping the transmit hold count, whose default
value is 6 per second.&lt;/p&gt;
&lt;h1 id=&quot;about-mstp&quot;&gt;About &lt;abbr title=&quot;Multiple Spanning Tree Protocol&quot;&gt;MSTP&lt;/abbr&gt;&lt;/h1&gt;
&lt;p&gt;&lt;abbr title=&quot;Multiple Spanning Tree Protocol&quot;&gt;MSTP&lt;/abbr&gt; is the â€œVLAN-awareâ€� version of &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt;: it runs several instances of &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; and
lets the administrator map each VLAN to a specific instance. For example, you
can map VLANsâ€¯100 to 200 to a first instance, and 300 to 400 to a second
instance. The remaining VLANs map to a special instance named the Internal
Spanning Tree (&lt;abbr title=&quot;Internal Spanning Tree&quot;&gt;IST&lt;/abbr&gt;). &lt;abbr title=&quot;Multiple Spanning Tree Protocol&quot;&gt;MSTP&lt;/abbr&gt; adds its own complexity, but the gist is that you have
several logical topologies acting independently. If you want to dig deeper, have
a look at â€œ&lt;a href=&quot;https://ine.com/blog/2008-07-27-mstp-tutorial-part-i-inside-a-region&quot; title=&quot;MSTP Tutorial Part I: Inside a Region&quot;&gt;&lt;abbr title=&quot;Multiple Spanning Tree Protocol&quot;&gt;MSTP&lt;/abbr&gt; Tutorial Part I: Inside a Region&lt;/a&gt;.â€�&lt;/p&gt;
&lt;h1 id=&quot;about-the-interactive-examples&quot;&gt;About the interactive examples&lt;/h1&gt;
&lt;p&gt;The interactive examples run &lt;a href=&quot;https://github.com/mstpd/mstpd&quot; title=&quot;Multiple Spanning Tree Protocol Daemon&quot;&gt;MSTPD&lt;/a&gt; directly in your browser, compiled to
&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/WebAssembly&quot; title=&quot;WebAssembly on MDN&quot;&gt;WebAssembly&lt;/a&gt; with &lt;a href=&quot;https://emscripten.org/&quot; title=&quot;Emscripten documentation&quot;&gt;emscripten&lt;/a&gt;. A C API replaces the code talking to the
Linux kernel: it manages bridges and ports, exports state as JSON, and drives
time deterministically. A JavaScript wrapper makes it more user-friendly:&lt;/p&gt;
&lt;div class=&quot;language-javascript codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadMSTPD&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./dist/mstpd.mjs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mstp&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadMSTPD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Create 3 bridges&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mstp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createBridge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;priority&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;4096&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mstp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createBridge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;B&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;priority&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8192&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mstp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createBridge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;C&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Each bridge has two ports&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addPort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a-b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;portno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addPort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;a-c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;portno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addPort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;b-a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;portno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addPort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;b-c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;portno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addPort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;c-a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;portno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addPort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;c-b&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;portno&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Build a triangle topology&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;mstp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;mstp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;mstp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Enable all bridges and ports&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;br&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;br&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;c2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Execute 40 seconds&#39; worth of wall clock and display the topology&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;mstp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Topology:&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mstp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;topology&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Several dozen unit tests explore the features of MSTPD and check that they work
correctly in this environment:&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;node&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--test&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;*.test.mjs
&lt;span class=&quot;go&quot;&gt;âœ” two bridges: lower priority becomes root (41.657342ms)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;âœ” triangle loop: exactly one port blocks and all agree on the root (5.832ms)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;âœ” breaking the active link reconverges and restoring recovers (18.730753ms)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[â€¦]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;â„¹ tests 40&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;â„¹ pass 40&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;â„¹ fail 0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[â€¦]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;â„¹ duration_ms 396.190897&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Additional JavaScript code looks for specific &lt;code&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; blocks containing a
topology definition and turns them into interactive widgets. You can inspect
and modify the definition by hitting the â€œeditâ€� button.&lt;/p&gt;
&lt;p&gt;There is also a cool trick to tell whether the topology has converged. After
each step, we save a snapshot of the simulation memory, play 50 secondsâ€™ worth
of simulation to check if the topology is stable, and travel back in time by
restoring that snapshot. ğŸ•°ï¸�&lt;/p&gt;
&lt;p&gt;The complete code lives on &lt;a href=&quot;https://github.com/vincentbernat/mstpd/tree/feature/wasm/wasm&quot;&gt;GitHub&lt;/a&gt;. I am happy with the result. It can be
difficult to follow everything happening during a single step, but stepping
forward and backward helps. I plan to use the same approach in future blog posts
about networking features.&lt;/p&gt;
&lt;div class=&quot;admonition&quot;&gt;
&lt;p class=&quot;admonition-title&quot;&gt;Note&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://mtlynch.io/&quot;&gt;Michael Lynch&lt;/a&gt; reviewed a first draft of this article. He authored
â€œ&lt;a href=&quot;https://refactoringenglish.com/&quot; title=&quot;Refactoring English: Effective Writing for Software Developers&quot;&gt;Refactoring English&lt;/a&gt;,â€� a book to sharpen your writing for blog posts,
documentation, commit messages, and tutorials. Any errors are still mine!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:sprites&quot;&gt;
&lt;p&gt;The sprites for Stan and Blobby come from &lt;a href=&quot;https://craftpix.net/&quot; title=&quot;Craftpix: 2D game assets&quot;&gt;Craftpix&lt;/a&gt;, the coffee
cups from &lt;a href=&quot;https://yaninyunus.itch.io/16x16-specialtycoffee&quot; title=&quot;Yanin: 16x16 specialty coffee assets&quot;&gt;Yanin&lt;/a&gt;.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:sprites&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:history&quot;&gt;
&lt;p&gt;&lt;abbr title=&quot;Spanning Tree Protocol&quot;&gt;STP&lt;/abbr&gt; was introduced in &lt;a href=&quot;https://sci-hub.fr/10.1109/IEEESTD.1991.101050&quot; title=&quot;IEEE Standards for Local and Metropolitan Area Networks: Media Access Control (MAC) Bridges&quot;&gt;IEEEâ€¯802.1D-1990&lt;/a&gt;. It is still present in
&lt;a href=&quot;https://sci-hub.fr/10.1109/IEEESTD.1998.95619&quot; title=&quot;IEEE Standard for Local and Metropolitan Area Networks: Media Access Control (MAC) Bridges&quot;&gt;IEEEâ€¯802.1D-1998&lt;/a&gt; but was withdrawn in &lt;a href=&quot;https://sci-hub.fr/10.1109/IEEESTD.2004.94569&quot; title=&quot;IEEE Standard for Local and Metropolitan Area Networks: Media Access Control (MAC) Bridges&quot;&gt;IEEEâ€¯802.1D-2004&lt;/a&gt; in favor of
&lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt;, introduced in &lt;a href=&quot;https://sci-hub.fr/10.1109/IEEESTD.2001.93287&quot; title=&quot;IEEE Standard for Local and Metropolitan Area Networks: Rapid Reconfiguration of Spanning Tree&quot;&gt;IEEEâ€¯802.1w-2001&lt;/a&gt;. &lt;abbr title=&quot;Multiple Spanning Tree Protocol&quot;&gt;MSTP&lt;/abbr&gt; was introduced in &lt;a href=&quot;https://sci-hub.fr/10.1109/IEEESTD.2002.94223&quot; title=&quot;IEEE Standards for Local and Metropolitan Area Networks: Virtual Bridged Local Area Networks â€” Amendment: Multiple Spanning Trees&quot;&gt;IEEEâ€¯802.1s-2002&lt;/a&gt; and merged into &lt;a href=&quot;https://sci-hub.fr/10.1109/IEEESTD.2003.94280&quot; title=&quot;IEEE Standards for Local and Metropolitan Area Networks: Virtual Bridged Local Area Networks&quot;&gt;IEEEâ€¯802.1Q-2003&lt;/a&gt;. Both of them are part
of &lt;a href=&quot;https://vincent.bernat.ch&quot; title=&quot;IEEE Standard for Local and Metropolitan Area Networks: Bridges and Bridged Networks&quot;&gt;IEEEâ€¯802.1Q-2022&lt;/a&gt; along with &lt;a href=&quot;https://sci-hub.fr/10.1109/IEEESTD.2012.6231597&quot; title=&quot;IEEE Standard for Local and Metropolitan Area Networks: Shortest Path Bridging&quot;&gt;&lt;abbr title=&quot;Shortest Path Bridging&quot;&gt;SPB&lt;/abbr&gt;&lt;/a&gt;&lt;del&gt;â€”a protocol
I had never heard of until writing this article&lt;/del&gt;.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:history&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:bridge&quot;&gt;
&lt;p&gt;From here, I use â€œbridgeâ€� instead of the more common word â€œswitch.â€�Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:bridge&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:kernel&quot;&gt;
&lt;p&gt;The Linux kernel only runs &lt;abbr title=&quot;Spanning Tree Protocol&quot;&gt;STP&lt;/abbr&gt;. It delegates the other protocols to
user space.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:kernel&quot; title=&quot;Jump back to footnote 4 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:incomplete&quot;&gt;
&lt;p&gt;MSTPD implements the state machine from &lt;a href=&quot;https://sci-hub.fr/10.1109/IEEESTD.2006.216285&quot; title=&quot;IEEE Standard for Local and Metropolitan Area Networks: Virtual Bridged Local Area Networks&quot;&gt;IEEEâ€¯802.1Q-2005&lt;/a&gt;, but
on Linux it runs &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; only. Linuxâ€¯5.18 added &lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git/commit/?id=ec7328b59176227216c461601c6bd0e922232a9b&quot; title=&quot;net: bridge: mst: Multiple Spanning Tree (MST) mode&quot;&gt;support for forwarding
multiple spanning tree&lt;/a&gt;, but MSTPD does not use it yet. See &lt;a href=&quot;https://github.com/mstpd/mstpd/pull/150&quot; title=&quot;[RFC/RFT] use kernel MST support if available&quot;&gt;PR #150&lt;/a&gt;
for progress on this front.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:incomplete&quot; title=&quot;Jump back to footnote 5 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:priority&quot;&gt;
&lt;p&gt;The priority is a multiple of 4,096: with &lt;abbr title=&quot;Multiple Spanning Tree Protocol&quot;&gt;MSTP&lt;/abbr&gt;, the lower 12 bits
of the bridge priority encode the &lt;abbr title=&quot;Multiple Spanning Tree&quot;&gt;MST&lt;/abbr&gt; instance identifier, leaving only the
upper 4 bits for the configured priority.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:priority&quot; title=&quot;Jump back to footnote 6 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:wireshark&quot;&gt;
&lt;p&gt;To inspect the &lt;abbr title=&quot;Bridge Protocol Data Units&quot;&gt;BPDUs&lt;/abbr&gt; crossing a link, select it, click the
â€œDownload packetsâ€� button, and open the file with &lt;a href=&quot;https://www.wireshark.org/&quot; title=&quot;Wireshark: network protocol analyzer&quot;&gt;Wireshark&lt;/a&gt;.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:wireshark&quot; title=&quot;Jump back to footnote 7 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:backup&quot;&gt;
&lt;p&gt;A backup port only exists if the bridge has several ports on the same
collision domain. This should not happen in a switched network.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:backup&quot; title=&quot;Jump back to footnote 8 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:hello&quot;&gt;
&lt;p&gt;This is the value of the â€œhelloâ€� timer. It used to be configurable,
but &lt;a href=&quot;https://sci-hub.fr/10.1109/IEEESTD.2006.216285&quot; title=&quot;IEEE Standard for Local and Metropolitan Area Networks: Virtual Bridged Local Area Networks&quot;&gt;IEEEâ€¯802.1Q-2005&lt;/a&gt; pins it to 2. MSTPD does not allow another value.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:hello&quot; title=&quot;Jump back to footnote 9 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:learning&quot;&gt;
&lt;p&gt;If the peer port does not receive an agreement after the hello
timer elapsesâ€”or the maximum age if the port has just come upâ€”it falls back
to the timer-based method for compatibility with &lt;abbr title=&quot;Spanning Tree Protocol&quot;&gt;STP&lt;/abbr&gt;: it transitions to
the learning state, waits again for the hello timer to expire, and
transitions to the forwarding state.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:learning&quot; title=&quot;Jump back to footnote 10 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:agreement&quot;&gt;
&lt;p&gt;As in many proposals, S3 also sets the agreement bit to 1. The
proposal bit says â€œI am the designated port on this link and I want to
transition to the forwarding state.â€� The agreement bit says â€œI am already in
sync with the rest of my bridge on this root information.â€� Both can be true.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:agreement&quot; title=&quot;Jump back to footnote 11 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:bum&quot;&gt;
&lt;p&gt;If it finds no entry, the bridge duplicates the Ethernet frame on all
ports, except the incoming one. The same happens if the destination MAC
address is the broadcast one (&lt;code&gt;ff:ff:ff:ff:ff:ff&lt;/code&gt;). This behavior bootstraps
the learning process.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:bum&quot; title=&quot;Jump back to footnote 12 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:timer&quot;&gt;
&lt;p&gt;This timer makes &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt; resistant to packet loss.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:timer&quot; title=&quot;Jump back to footnote 13 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:price&quot;&gt;
&lt;p&gt;You can get them for less than US$100 through a broker. All the ports
run &lt;abbr title=&quot;Per-VLAN Spanning Tree&quot;&gt;PVST&lt;/abbr&gt;+ by default and automatically fall back to plain &lt;abbr title=&quot;Rapid Spanning Tree Protocol&quot;&gt;RSTP&lt;/abbr&gt;.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:price&quot; title=&quot;Jump back to footnote 14 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:erps&quot;&gt;
&lt;p&gt;An alternative would be &lt;a href=&quot;https://www.itu.int/rec/T-REC-G.8032&quot; title=&quot;ITU-T G.8032&quot;&gt;Ethernet Ring Protection Switching&lt;/a&gt; (&lt;abbr title=&quot;Ethernet Ring Protection Switching&quot;&gt;ERPS&lt;/abbr&gt;)â€”another protocol I had never heard of until researching this
article.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:erps&quot; title=&quot;Jump back to footnote 15 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:root-mac&quot;&gt;
&lt;p&gt;If you look closely at what happens at t=2s, you can see that R2 is
gaining popularity as root: S17 to S36 believe R2 is the root bridge. S16
does not follow because we hit the maximum age. Later, S17 to S20 reverse
their position. Iâ€™ll let you explore the state of the various bridges to
understand the root cause.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:root-mac&quot; title=&quot;Jump back to footnote 16 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:forward-delay&quot;&gt;
&lt;p&gt;When increasing the maximum age to 40, you also need to
increase the forward delay to 21 (&lt;code&gt;:forward-delay 21&lt;/code&gt;), as the standard
enforces this condition: 2 Ã— (Forward Delay âˆ’ 1) â‰¥ Max Age. For this
specific topology, you could also increase the maximum age to 37 and
forward-delay to 20.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:forward-delay&quot; title=&quot;Jump back to footnote 17 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:time&quot;&gt;
&lt;p&gt;The simulation may seem slow, but it does not run in real time. Look at
the current timestamp in the upper right corner to know the wall clock, e.g.
â€œt=8s.â€� Once the topology stabilizes, the same corner shows the convergence
time, e.g. â€œğŸŒ³â€‰2s.â€�Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:time&quot; title=&quot;Jump back to footnote 18 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:slow&quot;&gt;
&lt;p&gt;Khaled Elmeleegy, Alan Cox, and Eugene Ng formalized this phenomenon in
â€œ&lt;a href=&quot;https://sci-hub.fr/10.1109/INFOCOM.2006.229&quot; title=&quot;On Count-to-Infinity Induced Forwarding Loops in Ethernet Networks&quot;&gt;On Count-to-Infinity Induced Forwarding Loops in Ethernet Networks&lt;/a&gt;â€�
and later in â€œ&lt;a href=&quot;https://sci-hub.fr/10.1109/TNET.2008.920874&quot; title=&quot;Understanding and Mitigating the Effects of Count to Infinity in Ethernet Networks&quot;&gt;Understanding and Mitigating the Effects of Count to Infinity
in Ethernet Networks&lt;/a&gt;.â€� They propose a fix that did not find its way into
a standard.Â &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:slow&quot; title=&quot;Jump back to footnote 19 in the text&quot;&gt;â†©&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Mon, 24 Aug 2026 15:00:00 +0000</pubDate>

</item> 
<item>
	<title>Vincent Bernat: A non-interactive tour of the spanning tree protocol</title>
	<guid>http://www.luffy.cx/en/blog/2026-spanning-tree-video.html</guid>
	<link>https://vincent.bernat.ch/en/blog/2026-spanning-tree-video</link>
     <description>  &lt;p&gt;Imagine you rent office space for a three-day event. You quickly set up a few
Ethernet switches and tape some cables on the floor to get everyone online.
Unfortunately, Stan, your clumsiest coworker, kicks out a cable every time he
gets up for coffee. Spare cables would fix that, but a loop turns into a
broadcast storm: Ethernet packets multiply until nothing else gets through.
That’s where the &lt;em&gt;spanning tree protocol&lt;/em&gt; comes in: it blocks just enough of the
spare cables to leave a loop-free tree, and rebuilds it in a second each time
Stan strikes again.&lt;sup id=&quot;fnref:credits&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:credits&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;figure class=&quot;lf-fullbleed&quot;&gt;&lt;div class=&quot;lf-media-outer&quot; style=&quot;width: 1920px;&quot;&gt;&lt;span class=&quot;lf-media-inner&quot;&gt;&lt;video class=&quot;lf-media lf-opaque&quot; controls=&quot;&quot; height=&quot;1080&quot; poster=&quot;https://d2pzklc15kok91.cloudfront.net/images/posters/2026-spanning-tree.f67ef4b82d3073.jpg&quot; preload=&quot;none&quot; width=&quot;1920&quot;&gt;&lt;source src=&quot;https://media.bernat.ch/videos/2026-spanning-tree.m3u8&quot; type=&quot;application/vnd.apple.mpegurl&quot; /&gt;&lt;source src=&quot;https://media.bernat.ch/videos/2026-spanning-tree/progressive.mp4&quot; type=&quot;video/mp4; codecs=&amp;quot;mp4a.40.2,avc1.4d401f&amp;quot;&quot; /&gt;&lt;/video&gt;&lt;/span&gt;&lt;/div&gt;&lt;/figure&gt;
&lt;p&gt;This content is also available as a &lt;a href=&quot;https://vincent.bernat.ch/en/blog/2026-spanning-tree&quot; title=&quot;An interactive tour of the spanning tree protocol&quot;&gt;text version&lt;/a&gt;, with interactive demos
that run a real implementation directly in your browser!&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;This video is an experiment.&lt;sup id=&quot;fnref:time&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:time&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Honestly, except for Radia Perlman &lt;a href=&quot;https://vincent.bernat.ch#video:seek-130&quot;&gt;reading
her poem&lt;/a&gt;,&lt;sup id=&quot;fnref:radia&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:radia&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; you should read the &lt;a href=&quot;https://vincent.bernat.ch/en/blog/2026-spanning-tree&quot; title=&quot;An interactive tour of the spanning tree protocol&quot;&gt;original article&lt;/a&gt; instead. It presents the same content, but you can play with the
interactive examples, which are the main contribution. On the other hand, if you
happen to like the video, be sure to tell me in the comments!&lt;/p&gt;
&lt;div class=&quot;footnote&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:credits&quot;&gt;
&lt;p&gt;The sprites for Stan and Blobby come from &lt;a href=&quot;https://craftpix.net/&quot; title=&quot;Craftpix: 2D game assets&quot;&gt;Craftpix&lt;/a&gt;. The
background music is “&lt;a href=&quot;https://www.chosic.com/download-audio/25044/&quot; title=&quot;Sonatina No. 2 In G Major – III. Allegro by Aaron Dunn&quot;&gt;Sonatina No. 2 in G Major – III. Allegro&lt;/a&gt;” by
Aaron Dunn. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:credits&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:time&quot;&gt;
&lt;p&gt;I thought automated tools would produce this video in a couple of
hours. In the end, it was another rabbit hole and it took me more than 12. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:time&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:radia&quot;&gt;
&lt;p&gt;The audio was extracted from a &lt;a href=&quot;https://www.youtube.com/watch?v=jOqzLcM2Hbo&quot;&gt;Youtube video&lt;/a&gt; and cleaned up. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:radia&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Mon, 24 Aug 2026 14:59:00 +0000</pubDate>

</item> 
<item>
	<title>David Bremner: Reproducing Org mode configuration</title>
	<guid>https://www.cs.unb.ca/~bremner//blog/posts/org-repro/</guid>
	<link>https://www.cs.unb.ca/~bremner//blog/posts/org-repro/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/bremner.png&quot; width=&quot;65&quot; height=&quot;81&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;h1 id=&quot;Context&quot;&gt;Context&lt;/h1&gt;

&lt;p&gt;Recently I was trying to reproduce a bug with
&lt;a title=&quot;https://github.com/andras-simonyi/citeproc-el&quot;&gt;citeproc.el&lt;/a&gt; and
&lt;code&gt;org-mode&lt;/code&gt; in emacs.&lt;/p&gt;

&lt;p&gt;I thought I could use &lt;code&gt;package-vc-install&lt;/code&gt; to install a set of
upstream emacs packages at fixed versions, and thereby let citeproc
upstream test in the same environment as I have.&lt;/p&gt;

&lt;p&gt;It turns out that getting emacs to load the non-builtin version
of org via &lt;code&gt;package-vc-install&lt;/code&gt; did not work because&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;org-mode&lt;/code&gt; needs to run make after cloning&lt;/li&gt;
&lt;li&gt;once package.el was initialized, I always seemed to end up with the
built in &lt;code&gt;org-mode&lt;/code&gt; (yeah, I realize that isn&#39;t an explanation).&lt;/li&gt;
&lt;/ul&gt;


&lt;h1 id=&quot;Recipe_part_1.3A_get_org&quot;&gt;Recipe part 1: get org&lt;/h1&gt;

&lt;p&gt;Here you can replace &lt;code&gt;9.8.7&lt;/code&gt; with any other tagged release&lt;/p&gt;

&lt;div class=&quot;highlight-shellscript&quot;&gt;&lt;pre class=&quot;hl&quot;&gt;  EMACSHOME&lt;span class=&quot;hl opt&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;hl kwd&quot;&gt;$(mktemp -d)&lt;/span&gt;
  git clone https&lt;span class=&quot;hl opt&quot;&gt;://&lt;/span&gt;git.sr.ht&lt;span class=&quot;hl opt&quot;&gt;/&lt;/span&gt;~bzg&lt;span class=&quot;hl opt&quot;&gt;/&lt;/span&gt;org&lt;span class=&quot;hl kwb&quot;&gt;-mode&lt;/span&gt; &lt;span class=&quot;hl kwd&quot;&gt;${EMACSHOME}&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;/&lt;/span&gt;org
  git &lt;span class=&quot;hl kwb&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;hl kwd&quot;&gt;${EMACSHOME}&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;/&lt;/span&gt;org &lt;span class=&quot;hl kwc&quot;&gt;reset&lt;/span&gt; &lt;span class=&quot;hl kwb&quot;&gt;--hard&lt;/span&gt; release_9.8&lt;span class=&quot;hl num&quot;&gt;.7&lt;/span&gt; 
  &lt;span class=&quot;hl kwc&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;hl kwb&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;hl kwd&quot;&gt;${EMACSHOME}&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;/&lt;/span&gt;org autoloads
  emacs &lt;span class=&quot;hl kwb&quot;&gt;-Q --batch -L&lt;/span&gt; &lt;span class=&quot;hl kwd&quot;&gt;${EMACSHOME}&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;/&lt;/span&gt;org&lt;span class=&quot;hl opt&quot;&gt;/&lt;/span&gt;lisp &lt;span class=&quot;hl kwb&quot;&gt;--eval&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;(progn (require &#39;org) (message (org-version)))&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This should print &lt;code&gt;9.8.7&lt;/code&gt;, not the version of built in org-mode.&lt;/p&gt;

&lt;h1 id=&quot;Recipe_part_2.3A_add-on_packages&quot;&gt;Recipe part 2: add-on packages&lt;/h1&gt;

&lt;p&gt;Now to test some add-on packages, run&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    emacs -Q --init-directory ${EMACSHOME} -L ${EMACSHOME}/org/lisp
&lt;/code&gt;&lt;/pre&gt;

&lt;div class=&quot;highlight-lisp&quot;&gt;&lt;pre class=&quot;hl&quot;&gt;  &lt;span class=&quot;hl opt&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl kwa&quot;&gt;progn&lt;/span&gt;
    &lt;span class=&quot;hl opt&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl kwa&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;hl opt&quot;&gt;&#39;&lt;/span&gt;org&lt;span class=&quot;hl opt&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl opt&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl kwa&quot;&gt;package-initialize&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl opt&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl kwa&quot;&gt;package-vc-install&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;https://github.com/emacs-straight/queue&quot;&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl opt&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl kwa&quot;&gt;package-vc-install&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;https://github.com/joostkremers/parsebib&quot;&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;6.7&quot;&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl opt&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl kwa&quot;&gt;package-vc-install&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;https://github.com/rejeep/f.el&quot;&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;0.21.0&quot;&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl opt&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl kwa&quot;&gt;package-vc-install&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;https://github.com/magnars/s.el&quot;&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;1.13.0&quot;&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl opt&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl kwa&quot;&gt;package-vc-install&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;https://github.com/akicho8/string-inflection&quot;&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;1.0.16&quot;&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;hl opt&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;hl kwa&quot;&gt;package-vc-install&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;https://github.com/andras-simonyi/citeproc-el&quot;&lt;/span&gt; &lt;span class=&quot;hl sng&quot;&gt;&quot;0.9.5&quot;&lt;/span&gt;&lt;span class=&quot;hl opt&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;You can then run your tests in that emacs right away, or restart the environment with&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  emacs -Q --init-directory ${EMACSHOME} -L ${EMACSHOME}/org/lisp
&lt;/code&gt;&lt;/pre&gt; </description> 
	<pubDate>Mon, 24 Aug 2026 10:54:18 +0000</pubDate>

</item> 
<item>
	<title>Russ Allbery: Long delayed haul</title>
	<guid>https://www.eyrie.org/~eagle/journal/2026-08/002.html</guid>
	<link>https://www.eyrie.org/~eagle/journal/2026-08/002.html</link>
     <description>  &lt;p&gt;
I haven&#39;t made a new book haul post in I don&#39;t know how long, so a lot of
books have piled up and many have already been reviewed. Here&#39;s the
overdue catch-up in case anyone is curious what books I am finding
interesting before the reviews get posted.
&lt;/p&gt;

&lt;p&gt;
Ilona Andrews — &lt;cite&gt;Magic Bites&lt;/cite&gt; (sff)&lt;br /&gt;
Elizabeth Bear — &lt;cite&gt;In the House of Aryaman, a Lonely Signal Burns&lt;/cite&gt;
(sff)&lt;br /&gt;
Oliver Burkeman — &lt;cite&gt;Four Thousand Weeks&lt;/cite&gt; (non-fiction)&lt;br /&gt;
Miles Cameron — &lt;cite&gt;Whalesong&lt;/cite&gt; (sff)&lt;br /&gt;
Lee Child — &lt;cite&gt;Killing Floor&lt;/cite&gt; (thriller)&lt;br /&gt;
august clarke — &lt;cite&gt;The Felicity Complex&lt;/cite&gt; (sff)&lt;br /&gt;
Alison Cochrun — &lt;cite&gt;Here We Go Again&lt;/cite&gt; (romance)&lt;br /&gt;
Dan Davies — &lt;cite&gt;The Unaccountability Machine&lt;/cite&gt; (non-fiction)&lt;br /&gt;
Linzi Day — &lt;cite&gt;Midlife in Gretna Green&lt;/cite&gt; (sff)&lt;br /&gt;
Linzi Day — &lt;cite&gt;Painting the Blues in Gretna Green&lt;/cite&gt; (sff)&lt;br /&gt;
Linzi Day — &lt;cite&gt;Ties that Bond in Gretna Green&lt;/cite&gt; (sff)&lt;br /&gt;
Linzi Day — &lt;cite&gt;Spilling the Tea in Gretna Green&lt;/cite&gt; (sff)&lt;br /&gt;
Michelle Diener — &lt;cite&gt;Dark Ambitions&lt;/cite&gt; (sff)&lt;br /&gt;
Michelle Diener — &lt;cite&gt;Dark Class&lt;/cite&gt; (sff)&lt;br /&gt;
Michelle Diener — &lt;cite&gt;Collision Course&lt;/cite&gt; (sff)&lt;br /&gt;
Michelle Diener — &lt;cite&gt;Crash Course&lt;/cite&gt; (sff)&lt;br /&gt;
Henry Farrell — &lt;cite&gt;Underground Empire&lt;/cite&gt; (non-fiction)&lt;br /&gt;
Kathleen A. Flynn — &lt;cite&gt;The Jane Austen Project&lt;/cite&gt; (sff)&lt;br /&gt;
Victoria Goddard — &lt;cite&gt;The Hands of the Emperor&lt;/cite&gt; (sff)&lt;br /&gt;
James Herriot — &lt;cite&gt;All Creatures Great and Small&lt;/cite&gt; (mainstream)&lt;br /&gt;
James Herriot — &lt;cite&gt;All Things Bright and Beautiful&lt;/cite&gt; (mainstream)&lt;br /&gt;
James Herriot — &lt;cite&gt;All Things Wise and Wonderful&lt;/cite&gt; (mainstream)&lt;br /&gt;
James Herriot — &lt;cite&gt;The Lord God Made Them All&lt;/cite&gt; (mainstream)&lt;br /&gt;
James Herriot — &lt;cite&gt;Every Living Thing&lt;/cite&gt; (mainstream)&lt;br /&gt;
Lauren Hough — &lt;cite&gt;Monster of a Land&lt;/cite&gt; (non-fiction collection)&lt;br /&gt;
Bethany Jacobs — &lt;cite&gt;This Brutal Moon&lt;/cite&gt; (sff)&lt;br /&gt;
Guy Gavriel Kay — &lt;cite&gt;Written on the Dark&lt;/cite&gt; (sff)&lt;br /&gt;
Mary Robinette Kowal — &lt;cite&gt;The Martian Contingency&lt;/cite&gt; (sff)&lt;br /&gt;
Ann Leckie — &lt;cite&gt;Radiant Star&lt;/cite&gt; (sff)&lt;br /&gt;
C.B. Lee — &lt;cite&gt;Coffeeshop in an Alternate Universe&lt;/cite&gt; (sff)&lt;br /&gt;
Fonda Lee — &lt;cite&gt;The Last Contract of Isako&lt;/cite&gt; (sff)&lt;br /&gt;
Julie Leong — &lt;cite&gt;The Teller of Small Fortunes&lt;/cite&gt; (sff)&lt;br /&gt;
Julie Leong — &lt;cite&gt;The Keeper of Magical Things&lt;/cite&gt; (sff)&lt;br /&gt;
R.Z. Nicolet — &lt;cite&gt;The Cloak and Its Wizard&lt;/cite&gt; (sff)&lt;br /&gt;
Claire North — &lt;cite&gt;Slow Gods&lt;/cite&gt; (sff)&lt;br /&gt;
Rebecca Ore — &lt;cite&gt;Writing&#39;s Writing&lt;/cite&gt; (non-fiction collection)&lt;br /&gt;
Suzanne Palmer — &lt;cite&gt;Ode to the Half-Broken&lt;/cite&gt; (sff)&lt;br /&gt;
Gareth L. Powell — &lt;cite&gt;Fleet of Knives&lt;/cite&gt; (sff)&lt;br /&gt;
Cameron Reed — &lt;cite&gt;What We Are Seeking&lt;/cite&gt; (sff)&lt;br /&gt;
Beth Revis — &lt;cite&gt;Full Speed to a Crash landing&lt;/cite&gt; (sff)&lt;br /&gt;
Beth Revis — &lt;cite&gt;How to Steal a Galaxy&lt;/cite&gt; (sff)&lt;br /&gt;
Beth Revis — &lt;cite&gt;Last Chance to Save the World&lt;/cite&gt; (sff)&lt;br /&gt;
Natalie Zina Walschots — &lt;cite&gt;Villain&lt;/cite&gt; (sff)&lt;br /&gt;
Jo Walton — &lt;cite&gt;Everybody&#39;s Perfect&lt;/cite&gt; (sff)&lt;br /&gt;
Martha Wells — &lt;cite&gt;Platform Decay&lt;/cite&gt; (sff)&lt;br /&gt;
James White — &lt;cite&gt;The Galactic Gourmet&lt;/cite&gt; (sff)&lt;br /&gt;
James White — &lt;cite&gt;Final Diagnosis&lt;/cite&gt; (sff)&lt;br /&gt;
&lt;/p&gt;

&lt;p&gt;
The James Herriot books were ones my parents were getting rid of. I have
them marked as mainstream fiction as a short-hand since &quot;fictionalized
autobiography&quot; seemed like too much of a mouthful.
&lt;/p&gt; </description> 
	<pubDate>Sun, 23 Aug 2026 21:29:00 +0000</pubDate>

</item> 
<item>
	<title>Colin Watson: GSS-API support split out from main Debian OpenSSH packages</title>
	<guid>tag:www.chiark.greenend.org.uk,2026-08-23:/~cjwatson/blog/openssh-gssapi-split.html</guid>
	<link>https://www.chiark.greenend.org.uk/~cjwatson/blog/openssh-gssapi-split.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/cjwatson.png&quot; width=&quot;70&quot; height=&quot;82&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;In an &lt;a href=&quot;https://lists.debian.org/debian-devel/2024/04/msg00044.html&quot;&gt;option review&lt;/a&gt; I did in 2024, shortly after the &lt;a href=&quot;https://en.wikipedia.org/wiki/XZ_Utils_backdoor&quot;&gt;xz-utils backdoor&lt;/a&gt;, I explained that having &lt;span class=&quot;caps&quot;&gt;GSS&lt;/span&gt;-&lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; authentication and key exchange support in the main OpenSSH packages is problematic.  The key exchange patch is large and intrusive.  Furthermore, even linking to the necessary libraries is not without risk: as the &lt;a href=&quot;https://attack.mitre.org/software/S0377/&quot;&gt;Ebury malware attack&lt;/a&gt; demonstrated way back in 2009, each extra library linked into security-critical daemons such as &lt;code&gt;sshd&lt;/code&gt; (or nowadays into its privilege-separated helper programs) can modify the behaviour of the daemon even if you aren’t doing anything that would involve calling into that library.  Of course some of that risk remains, but as &lt;a href=&quot;https://lists.debian.org/debian-devel/2024/04/msg00045.html&quot;&gt;Damien Miller wrote&lt;/a&gt;, minimizing the number of libraries that end up in the address space of &lt;code&gt;sshd&lt;/code&gt; and friends is still valuable.&lt;/p&gt;
&lt;p&gt;I just uploaded openssh 1:10.4p1-5 to unstable, completing this split.  As of this version, the OpenSSH client and server are built without &lt;span class=&quot;caps&quot;&gt;GSS&lt;/span&gt;-&lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; authentication and key exchange support.  If you need those features, install &lt;code&gt;openssh-client-gssapi&lt;/code&gt; or &lt;code&gt;openssh-server-gssapi&lt;/code&gt; instead, as appropriate.  Debian 13 (trixie) already has packages with those names that just depend on the regular &lt;code&gt;openssh-client&lt;/code&gt; and &lt;code&gt;openssh-server&lt;/code&gt; so that you can pre-emptively install them, as &lt;a href=&quot;https://www.debian.org/releases/trixie/release-notes/issues.en.html#deprecated-components-for-releasename&quot;&gt;documented in the release notes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The new &lt;code&gt;openssh-*-gssapi&lt;/code&gt; packages have relatively tight dependencies on &lt;code&gt;openssh-common&lt;/code&gt;, in order for the testing migration system to ensure that we can’t forget to keep them up to date.  This will mean a bit more ongoing work for me on each new upstream version, but I think it will be manageable.&lt;/p&gt; </description> 
	<pubDate>Sun, 23 Aug 2026 17:16:11 +0000</pubDate>

</item> 
<item>
	<title>Iustin Pop: Another optimistic take on AI</title>
	<guid>https://k1024.org/posts/2026/2026-08-23-another-optimistic-take-on-ai/</guid>
	<link>https://k1024.org/posts/2026/2026-08-23-another-optimistic-take-on-ai/</link>
     <description>  &lt;h2 id=&quot;disclaimers&quot;&gt;Disclaimers&lt;/h2&gt;
&lt;p&gt;The current discussion in Debian around the AI GR is very heated, and I won’t add
to that, however, I am very confused about some of the viewpoints there. But, I
had no idea how to even try to write this, so did shut up, until I saw Aigars’
excellent &lt;a href=&quot;https://aigarius.com/blog/2026/08/22/optimistic-take-on-ai/&quot;&gt;Optimistic take on
AI&lt;/a&gt;, which
motivated me to try, at least. For the record, I fully subscribe to the post,
and to the voting suggestions (and I just voted).&lt;/p&gt;
&lt;p&gt;Also, for full disclosure, I don’t think I did any contribution to Debian until
now using AI, neither packaging, nor emails, nor bug reports. And this blog post
specifically is 100% hand written.&lt;/p&gt;
&lt;p&gt;With that out of the way… there are two points I want to make in this post.&lt;/p&gt;
&lt;h2 id=&quot;ai-is-useful-even-if-it-has-risks&quot;&gt;AI &lt;em&gt;is&lt;/em&gt; useful, even if it has risks&lt;/h2&gt;
&lt;p&gt;First is, that even if we could put the genie back in the metaphorical bottle,
we should not. We do need to continue working towards safe AI, and efficient AI
(less environmental impact), but we should not work towards removing the usage
of AI. There are already significant advancements in sciences and technology
thanks to the use of AI, so desiring AI to not exist (assuming we had a magical
wand) is the wrong approach.&lt;/p&gt;
&lt;p&gt;Sure, AI has significant risks — and I can see ways in which AI can do
significant damage to society — but I don’t think we can go from Kardashev I to
II without the use of AI, and definitely not to III. And I think, that should be
the goal.&lt;/p&gt;
&lt;p&gt;A few simple examples: Do we want to rollback all the 20 years old security
issues that AI found? Do we want to rollback the recent Moderna cancer findings?
Do we want to rollback the concept of “extremely large scale pattern
matchings”, just because it runs on chips and no longer in one person’s head?&lt;/p&gt;
&lt;h2 id=&quot;reading-debian-lists&quot;&gt;Reading Debian lists&lt;/h2&gt;
&lt;p&gt;The second point is, lately I found less and less enjoyment in reading Debian
lists. Even with that already being the case, I feel so disconnected from many
of the opinions being voiced in this discussion.&lt;/p&gt;
&lt;p&gt;On one hand, it’s normal and healthy that people have different opinions,
disagree, and move forward.&lt;/p&gt;
&lt;p&gt;On the other hand, looking at one of the proposed options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Moderators and disciplinary teams may make narrow and tailored exceptions to
rule 4, and decide on interpretation”.&lt;/li&gt;
&lt;li&gt;“Violations of these requirements should be treated as violations of the
relevant Code of Conduct and should result in swift and proportionate
disciplinary action”.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I already knew Debian, and some large parts of the OSS world, is left leaning.
But those phrasings, to me, are too close to socialism/communism. As someone
who grew up under communism, this is a much more slippery slope (disciplinary
teams? really?) than AI usage. Ask me in person for more details.&lt;/p&gt;
&lt;p&gt;So, it is possible that Debian continues to evolve in such a way that I don’t
find myself in any way close to its ongoing culture. I will be sad at that
point, but it will be what it is.&lt;/p&gt;
&lt;h2 id=&quot;where-to&quot;&gt;Where to?&lt;/h2&gt;
&lt;p&gt;I think that, until such a time that an AI bubble bursts, what any organization
should do is try to logically see where and if AI can help. And in an
organization that is about computer software, I see hundreds of places that are
subject to very large scale pattern matching… so the half of the discussion is,
to me, mind-boggling.&lt;/p&gt;
&lt;p&gt;To be clear, it’s not about “if you can’t beat them, join them”. As I wrote
above, I think AI is useful, so the point is how to use it effectively.&lt;/p&gt;
&lt;p&gt;Well, will see what Debian votes. I am half curious, half sad already.&lt;/p&gt; </description> 
	<pubDate>Sun, 23 Aug 2026 16:19:40 +0000</pubDate>

</item> 
<item>
	<title>Wouter Verhelst: Programming and GR 2026 002</title>
	<guid>https://grep.be/blog//en/computer/debian/Programming_and_GR_2026_002/</guid>
	<link>https://grep.be/blog//en/computer/debian/Programming_and_GR_2026_002/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/wouter3.png&quot; width=&quot;85&quot; height=&quot;80&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;h2 id=&quot;programminglanguagegenerations&quot;&gt;Programming language generations&lt;/h2&gt;

&lt;p&gt;When I was young, I learned about a model of classifying programming
language: the system of programming language generations.&lt;/p&gt;

&lt;p&gt;In this model, first generation programming languages are, basically,
where you program the computer in the language that is defined by its
architecture. On a &lt;a href=&quot;https://en.wikipedia.org/wiki/Von_Neumann_architecture&quot;&gt;Von Neumann
machine&lt;/a&gt;, with
its load-and-store architecture, you do that by inputting a string of
numbers. The first programmer in human history -- her name was &lt;a href=&quot;https://en.wikipedia.org/wiki/Ada_Lovelace&quot;&gt;Ada
Lovelace&lt;/a&gt; -- wrote in a
first-generation language. 1GLs aren&#39;t so much invented as they are a
byproduct of the computers for which they&#39;re created.&lt;/p&gt;

&lt;p&gt;Second-generation languages are the assembler languages. Because humans
are not computers, and because decoding long lines of numbers to
understand what the computer is doing, when programming became a
full-time job, the programmers that did it decided that doing all this
assembling manually is too complicated, so they quickly wrote assemblers
to automate the process for them. They still could understand the 1GL
output of the 2GL assembler, but most of them quickly forgot how to
write software in a first-generation language. Not that anyone cared, as
the translation from a 2GL to a 1GL is lossless and you can just revert
it.&lt;/p&gt;

&lt;p&gt;Third-generation languages are higher-level languages. When the first
3GLs were invented (such as &lt;a href=&quot;https://en.wikipedia.org/wiki/COBOL&quot;&gt;COBOL&lt;/a&gt;
and, more famously, &lt;a href=&quot;https://en.wikipedia.org/wiki/FORTRAN&quot;&gt;FORTRAN&lt;/a&gt;) in
the late 1950s and early 1960s, it was believed by some that the work of
programming a computer so accessible to non-programmers that the job of
programmer would eventually cease to exist, and people would just ask
the computer what they needed by entering COBOL instructions. This of
course was ridiculous and incorrect, because converting algorithms to
computer instructions, whether at the 2GL or 3GL level, is a specialized
skill that some automation can perhaps make simpler but never completely
take away the need for. At the time, some people also felt to some
extent that &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Story_of_Mel&quot;&gt;using 3GL wasn&#39;t the same thing as actually programming
3GLs&lt;/a&gt;, but eventually
the world moved on and embraced things. The invention of 3GL
environments reduced, but did not completely take away, the need for
people to understand 2GLs, as compiler and operating system authors
still need to understand them, and some highly optimized code still
continues to be written in 2GLs to this day.&lt;/p&gt;

&lt;p&gt;Fourth-generation languages abstract away some or all of the process of
programming. For instance, a database-related 4GL will hide away the
complexities of storing data in particular locations, how to fetch that
data, how to index it such that you can fetch it efficiently, how to
loop over the data to get you a summary of that data, and instead allows
you to express the required information in an abstract way, expecing the
computer to fill in the blanks. When SQL, an early 4GL, was invented,
some people believed that the language made accessing databases so
simple that the requirement to implement database applications would
eventually cease to exist and we would just hand SQL prompts to users
who need to access data. This of course was ridiculous and incorrect,
because understanding data schemas and using that understanding to query
data from a database is a specialized skill that perhaps a higher
abstraction can help you make simpler, but that in the longer run it can
never completely take away the need for. The invention of 4GLs also
reduced, but did not completely take away, the need for people to
understand how to do the things that the 4GLs automate for you manually,
as the people who do write those things still need to understand them,
and there are also environments where these particular 4GLs are rather
not appropriate or just very slow.&lt;/p&gt;

&lt;p&gt;The first definition of programming language generations that I read
about in the 1980s simply stated that fifth-generation languages did not
yet exist, but that they would in the future, and that in those, you
would &quot;tell the computer what to do, and it would then do that&quot;. Now
that &lt;a href=&quot;https://en.wikipedia.org/wiki/Large_language_model&quot;&gt;we have a way of doing
so&lt;/a&gt;, it could be
said that by some definition, we now actually do have a number of 5GLs.
The existence of these LLM systems has caused some, especially the
people who build and exploit these systems, to exclaim that programming
as we know it today is going to cease to exist, and everyone will just
ask an LLM to generate a program, which will then do so. That is of
course ridiculous and incorrect, as no automaton can generate software
from nothing; input is still required for the model to be able to
produce something that approaches usability, and being able to word that
input in a correct and productive fashion will be a skill that future
programmers can benefit from. I ran &lt;a href=&quot;https://grep.be/blog/en/computer/Agentic_coding_and_Free_Software/&quot;&gt;some
experiments&lt;/a&gt;
a while back, and from that concluded that, if we look only at the
technical side, LLM use can, in some niches, increase productivity for a
programmer. There are certainly things that you shouldn&#39;t use an LLM
for, but equally there can be cases where use of an LLM to perform some
task that traditionally would have been done by a programmer would be a
net positive.&lt;/p&gt;

&lt;p&gt;But LLMs, as they exist today, are highly problematic.&lt;/p&gt;

&lt;p&gt;They require vast amounts of data to build the model. The companies that
build these models are disrespectful of people who run web services, and
as a result, everyone now has to implement various types of application
firewalls just to not make systems fall over from the overwhelming
requests for data. They are also disregarding the licenses that are
attached to these vast amounts of data, which makes me, as a person who
believes in the tenets of free software, sad.&lt;/p&gt;

&lt;p&gt;They require vast amounts of energy, causing an already-critical global
warming crisis to, well, not improve.&lt;/p&gt;

&lt;p&gt;They require vast amounts of coolant to dissipate the energy
concentrated in their data centers, causing further environmental
effects.&lt;/p&gt;

&lt;p&gt;In this, they are problematic and to be avoided. But these are side
states of the current state of affairs; I do not believe that they are
inherently implied to be able to build and operate an LLM -- &lt;em&gt;any&lt;/em&gt; LLM.&lt;/p&gt;

&lt;p&gt;I guess it&#39;s fair to say that my feelings towards LLM usage are complex
and many-faceted. I haven&#39;t been involved in many debates about the
subject, debates that to me seem to be mostly focused on &quot;LLM good&quot; vs
&quot;LLM bad&quot; arguments that aren&#39;t as nuanced as the position that I would
believe is more accurate. This is not because I don&#39;t care, but
partially because I&#39;ve been busy in my personal life recently and
partially because the whole thing seems somewhat disheartening.&lt;/p&gt;

&lt;p&gt;But then Debian popped up &lt;a href=&quot;https://www.debian.org/vote/2026/vote_002&quot;&gt;GR
2026-002&lt;/a&gt;, meaning, I now
have to come up with an opinion about various candidate statements in
the context of the above, which is... not easy. But I did it anyway.&lt;/p&gt;

&lt;p&gt;There are 8 choices on the ballot, and they all have some truth and some
falsehood to them. My position about LLMs can be summarized as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The current state of affairs wrt LLMs is disastrous and we should not
encourage them&lt;/li&gt;
&lt;li&gt;However, there&#39;s no &lt;em&gt;technical&lt;/em&gt; reason why this must remain true for
all time&lt;/li&gt;
&lt;li&gt;And so any statement should keep in mind what might happen in the
future and that the current disastrousness of the whole thing isn&#39;t
guaranteed to continue to exist for all eternity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that, let&#39;s go over them.&lt;/p&gt;

&lt;h2 id=&quot;grvoteoptions&quot;&gt;GR vote options&lt;/h2&gt;

&lt;h3 id=&quot;proposala&quot;&gt;Proposal A&lt;/h3&gt;

&lt;p&gt;Its summary, from the GR text:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This proposal aims to expressly forbid any contributions to Debian
  written with the use or assistance of large language models (LLMs) or
  other generative AI tools.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This falls squarely in the &quot;LLM bad&quot; camp, outlawing all generative-AI
contributions, disregarding potential future ones where the problematic
situations that exist today are not present.&lt;/p&gt;

&lt;p&gt;It makes a change to the social contract, which is especially difficult
to reverse (on purpose), and which therefore also will require a 3:1
supermajority, but if we want to ban LLM-assisted contributions, this is
probably the best way to do it.&lt;/p&gt;

&lt;h3 id=&quot;proposalb&quot;&gt;Proposal B&lt;/h3&gt;

&lt;p&gt;This one tries to allow AI-assisted contributions under certain
conditions. It&#39;s mostly an &quot;LLM good&quot; proposal, with some caveats that
can be discribed as &quot;make sure you know what you&#39;re doing&quot;.&lt;/p&gt;

&lt;h3 id=&quot;proposalc&quot;&gt;Proposal C&lt;/h3&gt;

&lt;p&gt;This proposal is both a weaker (in some places) and stronger (in other
places) version of Proposal A. It makes changes to the code of conduct
instead of to the social contract, and it also wants to, at least,
&lt;em&gt;suggest&lt;/em&gt; policy to parties beyond the Debian project. By not changing
the social contract, however, it is more likely to reach its simple
majority requirement than proposal A.&lt;/p&gt;

&lt;p&gt;I don&#39;t think the language that it wants to add to the code of conduct
is particularly well phrased, however.&lt;/p&gt;

&lt;h3 id=&quot;proposald&quot;&gt;Proposal D&lt;/h3&gt;

&lt;p&gt;This is a weaker form of proposal B. The language is more compact and
there are a few requirements that are spelled out in proposal B that are
not spelled out in proposal D, but if you read between the lines you&#39;ll
see that the requirement is still there really and I don&#39;t understand
why proposals B and D were not merged into one.&lt;/p&gt;

&lt;h3 id=&quot;proposale&quot;&gt;Proposal E&lt;/h3&gt;

&lt;p&gt;This proposal tries to hold a middle ground between &quot;LLM good&quot; and &quot;LLM
bad&quot;. It appreciates that things are quite muddled at the present time,
and that perhaps the situation might might change in the future. It
acknowledges that certain questions remain unanswered and that perhaps
future considerations might therefore be different. But it essentially
refuses to take a stance on whether LLMs should be accepted by the
project or not.&lt;/p&gt;

&lt;h3 id=&quot;proposalf&quot;&gt;Proposal F&lt;/h3&gt;

&lt;p&gt;Similar to proposal E, this proposal tries to discourage Debian
contributors from using LLMs, while still allowing people to use it
should they want to, but with some requests and requirements to mark
LLM-assisted contributions to account for those people who don&#39;t want to
interact with LLM-generated software. As such, it is a proposal similar
to proposal E that leans closer to the &quot;LLM bad&quot; camp.&lt;/p&gt;

&lt;h3 id=&quot;proposalg&quot;&gt;Proposal G&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;This proposal aims to ensure that contributions directly to Debian are
  created by humans, while at the same time avoiding restrictions on the
  tools those humans may choose to use when contributing&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another &quot;LLM bad&quot; proposal, it however restricts the &quot;bad&quot; bits to only
the &lt;em&gt;direct&lt;/em&gt; output of the LLM. If you use an LLM to do something and
then clean-room re-implement the same thing yourself, that&#39;s apparently
fine.&lt;/p&gt;

&lt;h3 id=&quot;proposalh&quot;&gt;Proposal H&lt;/h3&gt;

&lt;p&gt;This proposal condemns the use of LLM for its environmental and moral
problems, but explicitly not for its technical considerations. I feel
that it is closest to my position as explained above.&lt;/p&gt;

&lt;h2 id=&quot;voting&quot;&gt;Voting&lt;/h2&gt;

&lt;p&gt;Expressing a vote on a ballot so convoluted and complicated like this
one takes time. I have to read and understand every ballot option, and
formulate an order of them.&lt;/p&gt;

&lt;p&gt;And I shouldn&#39;t &lt;em&gt;just&lt;/em&gt; state which option has my preference; Debian&#39;s
voting process allows a rich expression of opinion on ballot options.&lt;/p&gt;

&lt;p&gt;Anyway, I eventually ended up voting in a way that I think is consistent
with my opinion. But it wasn&#39;t easy.&lt;/p&gt; </description> 
	<pubDate>Sun, 23 Aug 2026 14:03:13 +0000</pubDate>

</item> 
<item>
	<title>Russell Coker: Links August 2026</title>
	<guid>https://etbe.coker.com.au/?p=6285</guid>
	<link>https://etbe.coker.com.au/2026/08/23/links-august-2026/</link>
     <description>  &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=TCn7bA1eg_0&quot;&gt;This YouTube video about the Cashier Girl Meme is interesting in the context of AI systems that generate images of people and can communicate with people, hotter than any real human is an achievable goal [1]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ZJ8KThKAfbs&quot;&gt;Stand Up Maths has an interesting Youtube video about LLMs solving maths problems which I highly recommend watching (it does not require any real knowledge of maths), I think this opens the door to attacks on well established cryptologic systems [2]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=gpSghW4J3ws&quot;&gt;Adam Conover made an insightful YouTube video about how and why Hollywood is now unable to make good sitcoms and why this is bad for society [3]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://skycroeser.net/blog/conference-digital-and-sexual-citizenship-in-an-age-of-social-media-bans/&quot;&gt;Sky Croeser wrote an interesting and insightful blog post about topics covered at the “Digital and sexual citizenship in an age of social media bans: Interrogating the rights of children and young people conference” [4]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://zanestjohn.com/blog/reing-with-claude-code&quot;&gt;Zane wrote a very informative blog post about reverse engineering a trojaned Android projector with Claude Code [5]&lt;/a&gt;. We need much better security on home networks to break the business model for this sort of thing.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://reneedoesstuff.substack.com/p/puritans-wouldnt-eat-pussy-so-they&quot;&gt;Renee Stonebraker’s article “Puritans Wouldn’t Eat Pussy, So They Invented the Western” has a lot of interesting information about early days of colonising the US, and not much about eating pussy [6]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.iflscience.com/the-icy-fingers-of-death-that-creep-beneath-the-frozen-antarctic-68416&quot;&gt;IFLScience has an interesting article about brinicles, icicles of brine that form under sea ice [7]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://nautil.us/could-an-industrial-civilization-have-predated-humans-on-earth-352964&quot;&gt;Nautilus has an interesting article about the Silurian Hypothesis [8]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://theconversation.com/what-is-no-till-farming-and-is-it-actually-better-for-the-environment-287292&quot;&gt;The Conversation has an intersting article about the pros and cons of no-till farming [9]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://365tomorrows.com/2024/03/27/cold-war-2/&quot;&gt;Cold War is a 365tomorrows story about bio-warfare which raises several disturbing possibilities we need to guard against [10]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://scottsantens.substack.com/p/land-value-tax-dividend-ubi&quot;&gt;Scott Santens wrote an insightful article describing how a land value tax would reduce rent and solve the housing shortages [11]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.positive.news/environment/can-provocative-climate-messaging-on-only-fans-cut-through-social-medias-noise/&quot;&gt;Positive News has an interesting article about using OnlyFans to teach people about climate change [12]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://theconversation.com/cultural-safety-in-healthcare-is-not-ideological-it-is-saving-lives-286335&quot;&gt;The Conversation has an interesting article about cultural safety in healthcare, sounds good, and while we are at it lets deal with sexism [13]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://doctoreww.github.io/EvilFontTool/&quot;&gt;Doctoreww has an interesting web page about ways of displaying different strings to humans and machines, this could result in you running a different command to what you thought you copied from a web site or defeating tools designed to block hostile content [14]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://locusmag.com/feature/commentary-cory-doctorow-hell-is-other-people/&quot;&gt;Cory Doctorow wrote an insightful article “Commentary Hell is Other People” about the way rich people want to use AI to replace all people [15]&lt;/a&gt;. Also psychologists who help rich people accept being greedy are worthy of a Luigi&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S0749597826000300&quot;&gt;The research article “Worship me at the office altar: Why narcissistic leaders resist remote work” is interesting, yet another reason to get rid of narcissistic executives [16]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://reneweconomy.com.au/renewables-sector-learning-from-messy-failures-after-oil-company-collapses-with-200m-clean-up-bill/&quot;&gt;Renew Economy has an interesting article about clean up costs for mining (which is usually left for the government to pay) and how this could impact renewable energy production facilities [17]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://freedium-mirror.cfd/https://medium.com/@elvirabary/the-financial-collapse-putin-cannot-bomb-his-way-out-of-b6798b10fdf2&quot;&gt;Elvira Bary wrote an insightful article on the Russian financial collapse that is happening now [18]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.theguardian.com/culture/2026/jul/18/black-american-women-south-korea-healthcare&quot;&gt;The Guardian has an interesting article about Afro-American women who travel to South Korea for healthcare because of problems with racism and sexism in American hospitals [19]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://theconversation.com/what-if-disabled-astronauts-are-just-better-suited-to-space-287222&quot;&gt;The Conversation has an interesting article about the potential for disabled people to be more productive in space than non-disabled people [20]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://krebsonsecurity.com/2026/07/lg-to-ban-residential-proxies-from-smart-tv-apps/&quot;&gt;Krebs has an interesting article about LG banning residential proxy code from apps after the LG store was found to have such code in 42% of it’s apps [21]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.theguardian.com/commentisfree/2026/jul/22/stephen-miller-marco-rubio-trump-speeches&quot;&gt;Robert B Shpiner wrote an insightful article for The Guardian about the death of democracy in the US [22]&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[1]&lt;a href=&quot;https://www.youtube.com/watch?v=TCn7bA1eg_0&quot;&gt; https://www.youtube.com/watch?v=TCn7bA1eg_0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2]&lt;a href=&quot;https://www.youtube.com/watch?v=ZJ8KThKAfbs&quot;&gt; https://www.youtube.com/watch?v=ZJ8KThKAfbs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[3]&lt;a href=&quot;https://www.youtube.com/watch?v=gpSghW4J3ws&quot;&gt; https://www.youtube.com/watch?v=gpSghW4J3ws&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[4]&lt;a href=&quot;https://skycroeser.net/blog/conference-digital-and-sexual-citizenship-in-an-age-of-social-media-bans/&quot;&gt; https://tinyurl.com/28b6jclu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[5]&lt;a href=&quot;https://zanestjohn.com/blog/reing-with-claude-code&quot;&gt; https://zanestjohn.com/blog/reing-with-claude-code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[6]&lt;a href=&quot;https://reneedoesstuff.substack.com/p/puritans-wouldnt-eat-pussy-so-they&quot;&gt; https://tinyurl.com/2y2b6a58&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[7]&lt;a href=&quot;https://www.iflscience.com/the-icy-fingers-of-death-that-creep-beneath-the-frozen-antarctic-68416&quot;&gt; https://tinyurl.com/2awjppn5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[8]&lt;a href=&quot;https://nautil.us/could-an-industrial-civilization-have-predated-humans-on-earth-352964&quot;&gt; https://tinyurl.com/2y89gftt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[9]&lt;a href=&quot;https://theconversation.com/what-is-no-till-farming-and-is-it-actually-better-for-the-environment-287292&quot;&gt; https://tinyurl.com/2b27vo8o&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[10]&lt;a href=&quot;https://365tomorrows.com/2024/03/27/cold-war-2/&quot;&gt; https://365tomorrows.com/2024/03/27/cold-war-2/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[11]&lt;a href=&quot;https://scottsantens.substack.com/p/land-value-tax-dividend-ubi&quot;&gt; https://tinyurl.com/2aqkn4z6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[12]&lt;a href=&quot;https://www.positive.news/environment/can-provocative-climate-messaging-on-only-fans-cut-through-social-medias-noise/&quot;&gt; https://tinyurl.com/2dy5vy8g&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[13]&lt;a href=&quot;https://theconversation.com/cultural-safety-in-healthcare-is-not-ideological-it-is-saving-lives-286335&quot;&gt; https://tinyurl.com/25rld7v3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[14]&lt;a href=&quot;https://doctoreww.github.io/EvilFontTool/&quot;&gt; https://doctoreww.github.io/EvilFontTool/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[15]&lt;a href=&quot;https://locusmag.com/feature/commentary-cory-doctorow-hell-is-other-people/&quot;&gt; https://tinyurl.com/2c2guu89&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[16]&lt;a href=&quot;https://www.sciencedirect.com/science/article/pii/S0749597826000300&quot;&gt; https://tinyurl.com/27kq4qqu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[17]&lt;a href=&quot;https://reneweconomy.com.au/renewables-sector-learning-from-messy-failures-after-oil-company-collapses-with-200m-clean-up-bill/&quot;&gt; https://tinyurl.com/2blp477w&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[18]&lt;a href=&quot;https://freedium-mirror.cfd/https://medium.com/@elvirabary/the-financial-collapse-putin-cannot-bomb-his-way-out-of-b6798b10fdf2&quot;&gt; https://tinyurl.com/27aybgge&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[19]&lt;a href=&quot;https://www.theguardian.com/culture/2026/jul/18/black-american-women-south-korea-healthcare&quot;&gt; https://tinyurl.com/29covbrp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[20]&lt;a href=&quot;https://theconversation.com/what-if-disabled-astronauts-are-just-better-suited-to-space-287222&quot;&gt; https://tinyurl.com/27qdj6co&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[21]&lt;a href=&quot;https://krebsonsecurity.com/2026/07/lg-to-ban-residential-proxies-from-smart-tv-apps/&quot;&gt; https://tinyurl.com/22pxub8v&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[22]&lt;a href=&quot;https://www.theguardian.com/commentisfree/2026/jul/22/stephen-miller-marco-rubio-trump-speeches&quot;&gt; https://tinyurl.com/25zf4hnp&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;yarpp yarpp-related yarpp-related-rss yarpp-template-list&quot;&gt;

&lt;p&gt;Related posts:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2024/08/31/links-august-2024/&quot; rel=&quot;bookmark&quot; title=&quot;Links August 2024&quot;&gt;Links August 2024&lt;/a&gt; &lt;small&gt;Bruce Schneier and Kim Córdova wrote an insightful article about...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2026/02/17/links-february-2026/&quot; rel=&quot;bookmark&quot; title=&quot;Links February 2026&quot;&gt;Links February 2026&lt;/a&gt; &lt;small&gt;Charles Stross has a good theory of why “AI” is...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2025/08/31/links-august-2025/&quot; rel=&quot;bookmark&quot; title=&quot;Links August 2025&quot;&gt;Links August 2025&lt;/a&gt; &lt;small&gt;Dimitri John Ledkov wrote an informative blog post about self...&lt;/small&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Sat, 22 Aug 2026 16:05:00 +0000</pubDate>

</item> 
<item>
	<title>Ian Jackson: Open Letter to the Wikimedia Foundation Board</title>
	<guid>tag:dreamwidth.org,2009-05-21:377446:21442</guid>
	<link>https://diziet.dreamwidth.org/21442.html</link>
     <description>  &lt;p&gt;
I have just sent an open letter to the Board of the Wikimedia Foundation, the umbrella organisation for Wikipedia (and a number of other projects), expressing my support for Wiki Workers United and the unionisation effort by WMF staff.

&lt;/p&gt;&lt;p&gt;
Here is the letter:

&lt;a name=&quot;cutid1&quot;&gt;&lt;/a&gt;

&lt;/p&gt;&lt;p&gt;
To: Board of Trustees, Wikimedia Foundation

&lt;/p&gt;&lt;p&gt;
via Wikimedia_Foundation_Board_noticeboard and WWU &lt;br /&gt;
published at https://diziet.dreamwidth.org/21442.html

&lt;/p&gt;&lt;p&gt;
Re: My support for Wiki Workers United

&lt;/p&gt;&lt;p&gt;
Dear Trustees

&lt;/p&gt;&lt;p&gt;
Wikipedia has become one of the pillars of the free and open Internet.
Across the world, reliable sources of information are under attack.

&lt;/p&gt;&lt;p&gt;
I&#39;m proud to have played my very small part in the community of
editors of English Wikipedia for the last 20 years.  I am also proud
of my contributions to the Free Software movement, including
especially Debian.  Debian, whose constitution and package installer I
originally wrote, has become one of the technological foundations of
the open Internet.

&lt;/p&gt;&lt;p&gt;
Unfortunately, there are signs that the Wikimedia Foundation is not
performing its proper role as bulwark against attacks on democracy,
including from moneyed interests.  Recent events at WMF have been very
alarming to me, and seem to form part of a disturbing trend.

&lt;/p&gt;&lt;p&gt;
As a Trustee Director of a UK charity myself, I understand that WMF
Trustees must defend the interests of the Foundation.  But that cannot
mean taking actions that undermine the Foundation&#39;s mission.  Nor can
it mean the deplorable, and even dishonest, practices, that WMF
appears to have been engaging in.

&lt;/p&gt;&lt;p&gt;
As a Wikipedian, as a Free Software activist, and as a citizen of the
planet, I stand in solidarity with Wiki Workers United.  Union-
busting must stop immediately.  The Foundation should immediately
formally recognise the unions in the UK and the US.

&lt;/p&gt;&lt;p&gt;
Further, WMF is an international organisation.  Collective
decisionmaking needs to be transnational too.  WMF should recognise
WWU as a negotiating partner worldwide, even if thresholds for formal
legal recognition are not met in individual national jurisdictions.

&lt;/p&gt;&lt;p&gt;
Wiki Workers are not the WMF&#39;s enemy.  WMF needs capable and
ideologically committed staff to maintain and operate its highly
complex systems, in the face of constant attacks.  Staff with
principles and a mission are WMF&#39;s biggest asset.

&lt;/p&gt;&lt;p&gt;
Dr Ian Jackson&lt;br /&gt;
Cambridge, UK&lt;br /&gt;
20th August 2026&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt=&quot;comment count unavailable&quot; height=&quot;12&quot; src=&quot;https://www.dreamwidth.org/tools/commentcount?user=diziet&amp;amp;ditemid=21442&quot; style=&quot;vertical-align: middle;&quot; width=&quot;30&quot; /&gt; comments </description> 
	<pubDate>Thu, 20 Aug 2026 20:58:51 +0000</pubDate>

</item> 
<item>
	<title>Jonathan Dowland: Bauer X4 inline skates</title>
	<guid>https://jmtd.net/log/inlines/</guid>
	<link>https://jmtd.net/log/inlines/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/jmtd.png&quot; width=&quot;65&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I’m really enjoying getting back into ice skating, but I can only get to the
rink once a week (at least over the summer -- I&#39;m aiming for twice weekly once
Schools re-open) and I have the itch to do more skating than that.&lt;/p&gt;

&lt;div class=&quot;centre&quot;&gt;
&lt;div class=&quot;image+centre&quot;&gt;
&lt;a href=&quot;https://jmtd.net/log/inlines/inline.jpg&quot;&gt;&lt;img alt=&quot;photo of me wearing inline skates, from above&quot; class=&quot;img&quot; height=&quot;303&quot; src=&quot;https://jmtd.net/log/inlines/400x-inline.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Where I live we’re blessed with a seaside park with lots of smooth paths, a
recently resurfaced beachside promenade, and a newly-built
pedestrian/cycle path stretching up and down the coast: all great surfaces for
roller skates. I convinced myself to buy some inline skates whilst the weather
is good.&lt;/p&gt;

&lt;div class=&quot;image&quot;&gt;
&lt;a href=&quot;https://jmtd.net/log/inlines/group.jpg&quot;&gt;&lt;img alt=&quot;group shot of my skates&quot; class=&quot;img&quot; height=&quot;300&quot; src=&quot;https://jmtd.net/log/inlines/400x-group.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;


&lt;p&gt;I wanted something as close to my ice skating experience as possible. Bauer
actually make an inline version of my ice boot, but the chassis is an unusual
composite plastic thing which put me off. (&lt;a href=&quot;https://youtu.be/Pu5UNck16SQ?si=2i2trx26f_0lUv5J&quot;&gt;here&#39;s a great video of a fantastic
inline skater trying out the chassis&lt;/a&gt;).
CCM have a new inline range for 2026, but sadly (much like their Jetspeed ice range)
the fit wasn&#39;t good for me.&lt;/p&gt;

&lt;p&gt;I found a clearance pair of Bauer vapors from the previous generation: the Bauer Vapor x4. Very
similar to my Fly30, but the difference in quality between the tiers is very
apparent: boot stiffness, the comfort and quality of the liner.
They fit well (possibly better), the rolling motion is
really smooth (I think that&#39;s the bearings) and they looked pretty good to me:
yellow highlights instead of the red used across the ice range.&lt;/p&gt;

&lt;p&gt;I&#39;ve done a couple of miles in them so far. Time will tell if they prove useful
for off-ice training! Many inline hockey players buy ice skates and convert
them to inline. If I end up not using them enough I could consider doing the
opposite.&lt;/p&gt; </description> 
	<pubDate>Thu, 20 Aug 2026 09:54:51 +0000</pubDate>

</item> 
<item>
	<title>Thomas Lange: LLM usage in Debian</title>
	<guid>http://blog.fai-project.org/posts/llm-usage-gr/</guid>
	<link>http://blog.fai-project.org/posts/llm-usage-gr/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/mrfai.png&quot; width=&quot;76&quot; height=&quot;100&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;After spending many hours on reading all the proposals and discussions
the best choice for me is NOTA (None of the above).&lt;/p&gt;

&lt;p&gt;We do not need to create new rules for LLM usage, we already have our
DFSG and our social contract.&lt;/p&gt;

&lt;p&gt;Keep it simple, stupid. Avoid more rules!&lt;/p&gt; </description> 
	<pubDate>Tue, 18 Aug 2026 13:52:29 +0000</pubDate>

</item> 
<item>
	<title>Andy Simpkins: My first go at tracking down a kernel bug…</title>
	<guid>https://blog.koipond.org.uk/?p=371</guid>
	<link>https://blog.koipond.org.uk/archives/371</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/andy.png&quot; width=&quot;80&quot; height=&quot;109&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;A couple of weekends back, I upgraded my home sever. It failed to restart after running &lt;code&gt;apt dist-upgrade &lt;/code&gt;&lt;/p&gt;



&lt;p&gt;The only update that was performed was to the kernel, it went from &lt;code&gt;6.12.88+deb13-amd64&lt;/code&gt; to &lt;code&gt;6.12.100+deb13-amd64&lt;/code&gt;.  I had previously performed an &lt;code&gt;apt-get upgrade&lt;/code&gt;, and rebooted the machine, so I was pretty sure that this was to blame.  This blog entry (is a late) attempt to document how I went about finding a fix for this issue so that next time I don’t need as much hand holding as I did this time around :-)&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;(1)&lt;/strong&gt;&lt;br /&gt;Having my machine not boot following an upgrade is pretty rare, but has happened before. Usually it is because I have done something wrong so as always confirming I haven’t broken something by accident is always my first step…&lt;/p&gt;



&lt;p&gt;I plugged in a keyboard an monitor to the machine and watched it boot. Being a server this takes a long time (I guess because at this stage of system initialisation we want to test things sequentially)&lt;/p&gt;



&lt;p&gt;Watching the system boot I see the usual BIOS/UEFI stages for this machine, followed by the grub menu and the the local screen showed:&lt;/p&gt;



&lt;pre class=&quot;wp-block-preformatted has-cyan-bluish-gray-background-color has-background&quot;&gt;&lt;code&gt;            Loading Linux 6.12.100+deb13-amd64 ...
            Loading initial ramdisk ...&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Nothing else. That was it.  OK that looks like I have a broken system all right, and at very early stage of the boot process process.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;(2) &lt;/strong&gt;&lt;br /&gt;Breaking into the grub menu and removing the quiet option yields a little more information (but not much):&lt;/p&gt;



&lt;pre class=&quot;wp-block-preformatted has-cyan-bluish-gray-background-color has-background&quot;&gt;&lt;code&gt;            Loading Linux 6.12.100+deb13-amd64 …
            Loading initial ramdisk ...
            

            	EFI stub: Loaded initrd from LINUX_EFI_INITRD_MEDIA_GUID d
            	evice path
            		EFI stub: Measured initrd data into PCR 9&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;and nothing else.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;(3)&lt;/strong&gt; &lt;strong&gt;Initial debugging&lt;/strong&gt;&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Confirmed that I could still boot the machine with the old kernel &lt;code&gt;6.12.88+deb13-amd64&lt;/code&gt; (During boot select Advanced options from the grub menu followed by the kernel image wanted) 
&lt;ul&gt;
&lt;li&gt;Yes – the system starts happily with the previous kernel&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Checked that /boot had enough space
&lt;ul&gt;
&lt;li&gt;Yes – plenty of space&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;



&lt;li&gt;Is anyone else reporting this problem?  
&lt;ul&gt;
&lt;li&gt;Nothing jumps out on Debian’s bug tracker&lt;/li&gt;



&lt;li&gt;Actually not mush referenced for my search “&lt;code&gt;EFI stub: Measured initrd data into PCR 9 apart&lt;/code&gt;” other than the usual rantings to “turn off secure boot” (on this server that currently isn’t turned on – bad me)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;(4)&lt;/strong&gt; &lt;strong&gt;Triage&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Start looking for where the fault first occurred.  At this point I needed help, and given that Sledge was visiting I asked if he would sanity check what I was doing.  His initial thoughts were that that /boot had run out of space, but replaying my step (3) with him acting as a ‘rubber duck’ showed that this was something other than PBKAC&lt;/p&gt;



&lt;p&gt;Sledge had a quick look, then informed me that between kernel images &lt;code&gt;6.12.88+deb13&lt;/code&gt; and &lt;code&gt;6.12.100+deb13&lt;/code&gt; Debian stable has only had shipped &lt;code&gt;.90 .94 .95&lt;/code&gt; and &lt;code&gt;.96&lt;/code&gt; kernels.  We could easily try them all:&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wget&lt;/code&gt; each kernel package then install (&lt;code&gt;dpkg -i&lt;/code&gt;)  followed by an &lt;code&gt;update-grub&lt;/code&gt;, checking that there was sufficient space on disks especially my small&lt;code&gt; /boot partition&lt;/code&gt;)&lt;/li&gt;



&lt;li&gt;I started with image &lt;code&gt;6.12.95+deb13&lt;/code&gt; and this worked&lt;/li&gt;



&lt;li&gt;&lt;code&gt;6.12.96+deb13&lt;/code&gt; yielded the same lock up on boot as &lt;code&gt;6.12.100+deb13&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;OK I now have the first kernel image that doesn’t boot on my system, time to raise a bug…&lt;/p&gt;



&lt;p class=&quot;has-vivid-cyan-blue-color has-text-color&quot;&gt;&lt;em&gt;Up until now I have been walking to my garage where the server is located and standing in front of a rack&lt;br /&gt;with a monitor and keyboard plugged into the machine. However this machine supports IPMI so I spent a little time getting that up and running so that I can continue from the relative comfort of my desk (with lights, a chair and not needing to hold the keyboard with one hand)&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Great I can now grab screen shots from the confort of my desk (unfortunatly they are only screen shots not text files, but at least we can seen the early stage of boot, Post, grub menu and then initramfs before system log happens)&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;(5) Collating information for the initial bug report&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;Sledge had mentioned my problem in irc/#debain-kernal where iam_tj suggested that we try appending&lt;br /&gt;‘debug earlycon=efifb’ to the kernal command line. This yielded 15 seconds worth of messages before the system locked up the last few messages being (vmlinuz-6.12.96+deb13-amd64):&lt;/p&gt;



&lt;p class=&quot;has-cyan-bluish-gray-background-color has-background has-small-font-size&quot;&gt;[ 14.663477] RCU Tasks: Setting shift to 5 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=20.&lt;br /&gt;[ 14.750474] RCU Tasks Rude: Setting shift to 5 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=20.&lt;br /&gt;[ 14.838024] RCU Tasks Trace: Setting shift to 5 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=20.&lt;br /&gt;[ 14.929752] NR_IRQS: 524544, nr_irqs: 584, preallocated irqs: 16&lt;br /&gt;[ 15.016814] rcu: srcu_init: Setting srcu_struct sizes based on contention.&lt;br /&gt;[ 15.104011] Console: colour dummy device 80×25&lt;br /&gt;[ 15.191236] printk: legacy console [tty0] enabled&lt;br /&gt;[ 15.278249] printk: legacy bootconsole [efifb0] disabled&lt;/p&gt;



&lt;p&gt;Booting the working kernel with the same kernel options yields the SAME messages with slightly differing times, but then continues to login prompt:&lt;/p&gt;



&lt;pre class=&quot;wp-block-preformatted has-cyan-bluish-gray-background-color has-background has-small-font-size&quot;&gt; [   14.697466] RCU Tasks: Setting shift to 5 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=20.
 [   14.784936] RCU Tasks Rude: Setting shift to 5 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=20.
 [   14.872067] RCU Tasks Trace: Setting shift to 5 and lim to 1 rcu_task_cb_adjust=1 rcu_task_cpu_ids=20.
 [   14.964000] NR_IRQS: 524544, nr_irqs: 584, preallocated irqs: 16
 [   15.051482] rcu: srcu_init: Setting srcu_struct sizes based on contention.
 [   15.226079] printk: legacy console [tty0] enabled
 [   15.313751] printk: legacy bootconsole [efifb0] disabled
 [   15.400831] ACPI: Core revision 20240827
 [   15.401415] clocksource: hpet: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 79635855245 ns
 [   15.401464] APIC: Switch to symmetric I/O mode setup
 
&lt;code&gt;... and so on&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;iam_tj also suggested adding keep_bootcon – with ‘debug earlycon=efifb keep_bootcon’ on vmlinuz-6.12.96+deb13-amd64:&lt;br /&gt;We get a LOT further – and we see a crash / trace-back:&lt;/p&gt;



&lt;pre class=&quot;wp-block-preformatted has-cyan-bluish-gray-background-color has-background has-small-font-size&quot;&gt;&lt;code&gt;[ 34.285342] BUG: kernel NULL pointer dereference, address: 0000000000000000&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;I raised bug &lt;a href=&quot;mailto:1143721@bugs.debian.org&quot;&gt;#1143721&lt;/a&gt; and followed it up with screen captures of the boot sequence (captured from the IPMI client) and files containing the output of dmidecode, lscpu and lspci to kive the kernel team as much information as possible:&lt;/p&gt;



&lt;div class=&quot;is-vertical is-content-justification-left is-layout-flex wp-container-1 wp-block-group&quot;&gt;
&lt;pre class=&quot;wp-block-preformatted has-small-font-size&quot;&gt;[&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?att=1;bug=1143721;filename=6.12.96%2Bdeb13-amd64+debug+earlycon%3Defifb+keep_bootcon.tar.gz;msg=10&quot;&gt;6.12.96+deb13-amd64 debug earlycon=efifb keep_bootcon.tar.gz&lt;/a&gt; (application/gzip, attachment)]&lt;/pre&gt;



&lt;pre class=&quot;wp-block-preformatted has-small-font-size&quot;&gt;[&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?att=2;bug=1143721;filename=dmidecode.txt;msg=10&quot;&gt;dmidecode.txt&lt;/a&gt; (text/plain, attachment)]&lt;/pre&gt;



&lt;pre class=&quot;wp-block-preformatted has-small-font-size&quot;&gt;[&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?att=3;bug=1143721;filename=lscpu.txt;msg=10&quot;&gt;lscpu.txt&lt;/a&gt; (text/plain, attachment)]&lt;/pre&gt;



&lt;pre class=&quot;wp-block-preformatted has-small-font-size&quot;&gt;[&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?att=4;bug=1143721;filename=lspci.txt;msg=10&quot;&gt;lspci.txt&lt;/a&gt; (text/plain, attachment)]
&lt;/pre&gt;
&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;(6) Tracking down the bug Git Bisect&lt;/strong&gt;&lt;/p&gt;



&lt;p&gt;The problem with this type of bug is that it is hardware (class) specific, whilst the kernel doesn’t boot on my system, it clearly has worked on machines used by the kernel team, the Debian test and build infrastructure, &lt;em&gt;(otherwise this kernel would never have been released)&lt;/em&gt; and everyone else who has upgraded to the newer &lt;em&gt;kernel&lt;/em&gt; before I did &lt;em&gt;(otherwise we would be drowning in fails to boot bug reports)&lt;/em&gt;.  Carnil’s excellent response to my bug: &lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1143721#15&quot;&gt;Message #15&lt;/a&gt; (and help in IRC) provided me with a detailed step by step guide in how to track down the individual git commit that fails on my system.  I had already (with Sledge’s suggestion) made a clone of the stable branch, but was struggling to follow the steps in the &lt;a href=&quot;https://kernel-team.pages.debian.net/kernel-handbook/ch-common-tasks.html#s-common-building&quot;&gt;Debian Linux Kernel Handbook&lt;/a&gt; to re-build a duplicate kernel because I didn’t understand how to obtain the same configuration that Debian used to build the kernel; Carnil’s email provided me the missing steps (Highlighted).&lt;/p&gt;



&lt;pre class=&quot;wp-block-preformatted has-cyan-bluish-gray-background-color has-background has-small-font-size&quot;&gt;git clone --single-branch -b linux-6.12.y https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
cd linux-stable
git checkout v6.12.95
&lt;strong&gt;cp /boot/config-$(uname -r) .config
yes &#39;&#39; | make localmodconfig
make savedefconfig
mv defconfig arch/x86/configs/my_def&lt;/strong&gt;
test 6.12.96 to ensure this is &quot;bad&quot;
git checkout v6.12.96
&lt;strong&gt;make my_defconfig&lt;/strong&gt;
make -j $(nproc) bindeb-pkg
… install the resulting .deb package and confirm it fails to boot and triggers the NULL pointer dereference.&lt;strong&gt;
&lt;/strong&gt;&lt;/pre&gt;



&lt;p&gt;Right I can now start to Bisect the problem:&lt;/p&gt;



&lt;pre class=&quot;wp-block-preformatted has-cyan-bluish-gray-background-color has-background has-small-font-size&quot;&gt;&lt;code&gt;git bisect start
git bisect good v6.12.95
git bisect bad v6.12.96&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Rather than use the half step point’s git bisect suggested I was advised in irc to jump straight to the a given commit that from the git log was suspected as the culprit: &lt;/p&gt;



&lt;p class=&quot;has-cyan-bluish-gray-background-color has-background has-small-font-size&quot;&gt;git checkout 977855894bca4b87afa50d21e3f3e85a5a0e901f&lt;br /&gt;build and install….&lt;br /&gt;fails…&lt;br /&gt;git bisect bad&lt;/p&gt;



&lt;p class=&quot;has-cyan-bluish-gray-background-color has-background has-small-font-size&quot;&gt;git checkout 977855894bca4b87afa50d21e3f3e85a5a0e901f~1 ## ~1 is the commit beforehand&lt;br /&gt;build and install….&lt;br /&gt;fails…&lt;br /&gt;git bisect good&lt;/p&gt;



&lt;p&gt;The entire test tree can shown with &lt;code&gt;git bisect log&lt;/code&gt; and this was submitted as an email to the bug report, we have found our smoking gun :-)&lt;/p&gt;



&lt;p&gt;&lt;em&gt;Finally I would like to thank Carnil, Iam_tj for their time patience and fantastic support in guiding me through finding this regression.  Right now kernel bugs are coming in thick and fast with a lot of AI assisted bug hunting, the increased numbers of bugs mean that the kernel team are especially busy.  Hopefully our paths will cross and I’ll be able to buy you some beers (or whatever) soon.  thank you.  Sledge also deserves thanks for putting up with me and pointing me in the right direction (as ever).  Lucky for me that he lives nearby so I can provide beers on a regular basis :-)&lt;/em&gt;&lt;/p&gt; </description> 
	<pubDate>Tue, 18 Aug 2026 10:50:43 +0000</pubDate>

</item> 
<item>
	<title>John Goerzen: AI in Debian: The Vote, Proposals, and Nuance</title>
	<guid>https://changelog.complete.org/?p=44740</guid>
	<link>https://changelog.complete.org/archives/44740-ai-in-debian-the-vote-proposals-and-nuance</link>
     <description>  &lt;p&gt;Let me start with a hypothesis:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;For human developers, using coding LLMs magnifies their difference in skill levels.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I am one that rarely thinks things are always black and white.  Back in March, I wrote &lt;a href=&quot;https://changelog.complete.org/archives/42503-artificial-intelligence-shades-of-gray&quot;&gt;Artifial Intelligence: Shades of Gray&lt;/a&gt;.  Since then, I’ve had more of a chance to experiment with LLMs myself.  I also happen to work for an employer that is taking a very pragmatic approach to LLMs: teams and individuals use it as they see fit, but if they are causing considerable expense, they have to justify it.&lt;/p&gt;
&lt;p&gt;In various settings, I have seen the egregious examples of AI slop we all know about.  As I wrote in March, “I have seen it both waste more time than it saves, and save a ton of time.”&lt;/p&gt;
&lt;p&gt;I have come to see that, as a tool, it is most valuable when it is running under the supervision of an experienced engineer.  It is at its worst when it has no such supervision; the “vibe coding” and other low-quality slop we see.&lt;/p&gt;
&lt;p&gt;A coding agent is like a junior developer or research assistant.  When properly supervised, they help projects move along more quickly by letting a senior developer focus on the more difficult, less mundane aspects of the project.  But one couldn’t expect a junior developer to consistently deliver high-quality code and architecture on their own.&lt;/p&gt;
&lt;p&gt;Let’s put a pin in this idea and look at the story in Debian.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;LLM use in Debian&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;There is a &lt;a href=&quot;https://www.debian.org/vote/2026/vote_002&quot;&gt;vote happening&lt;/a&gt; in Debian around the use of LLMs.  In typical Debian fashion, there are 8 options to choose from, many of them similar.  Most of these proposals acknowledge there are different types of tasks done in Debian, but the proposals don’t differentiate between them well.  Let me do so here.  These are some of the LLM-relevant tasks people in Debian perform:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Packaging upstream software for Debian (by far the largest task)&lt;/li&gt;
&lt;li&gt;Writing Debian-specific code (eg, apt or the Debian installer)&lt;/li&gt;
&lt;li&gt;Maintaining Debian infrastructure (build systems, for instance)&lt;/li&gt;
&lt;li&gt;Writing documentation and translations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’m going to focus my remarks here on packaging upstream software for Debian, since this is by far the most time-consuming developer task project-wide.&lt;/p&gt;
&lt;p&gt;It matters to our users that we get this right, and packaging quality is one of the things that sets Debian apart from other distros.  Packaging things for Debian requires knowledge of some specific tools, such as debhelper, that aren’t widely used anywhere else.  In most cases, it is fairly rote time-consuming work.  In other words, by its design, it requires people with senior-level skills to do grunt work.&lt;/p&gt;
&lt;p&gt;I can’t overstate how massive a burden this grunt work is.  I maintain some packages for Go and Rust.  By Debian policy, all of those packages’ dependencies must also exist as Debian packages, and be used to build against.  When upstream adopts a newer version of some library, it can unleash cascading dependencies that can take hours to sort out.  Worse, the Rust team and the Go team use entirely different ways of managing packages (Go uses one Git repo per package, while Rust has a monorepo with specialized scripts to import Cargo packages and generate Debian ones).  On top of that, we can’t just modify things like usual; we have to use quilt.  And on top of that, I’m also a backports maintainer, so all the work (and usually even more) has to be done there also.&lt;/p&gt;
&lt;p&gt;Now let’s pull on that pin from the earlier conversation.  This is exactly the kind of scenario that a well-supervised coding LLM is most effective in.  I could see a seasoned developer saving hours, maybe even days, by turning over the mundane tasks of managing trees of cascading dependencies over to a coding tool — and verifying and directing the process.  (Yes, I have been using em-dashes for years; LLMs have copied people like me, not the other way around!  This post was not written with any AI assistance.)&lt;/p&gt;
&lt;p&gt;Actually, this is almost a dream scenario for a coding assistant.  The result is time-consuming to formulate but easy to review, which is the opposite of the way these things often go.&lt;/p&gt;
&lt;p&gt;I can assure you with 100% certainty that humans aren’t adding a lot of value in this process.  It would be wrong to believe that a human is carefully reading every line of code in dozens of updated or new library packages.  The problem set is too big, the time too short, and the code too varied and complex.&lt;/p&gt;
&lt;p&gt;Coding agents seem to be most effective when there are strong test suites that they can test changes against.  Debian builds, especially of modern packages, tend to have this property.  Many packages have test suites that are run during build.  And, if the package builds in an isolated environment (and especially if its downstream dependencies do also), then there is a decent chance that it’s fairly correct.  Maybe needing some manual tweaking here and there, but generally a successful build is a reasonable indicator.&lt;/p&gt;
&lt;p&gt;You can argue that it would make more sense for Debian to just include dependencies in source packages, along with some version information to support security rebuilds, and I’d tend to agree with you.  But we are where we are.  This would be one of the more significant leaps forward in developer productivity, but it complicates things like copyright reviews.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Where are LLMs run?  What is the environmental impact?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Most of the proposals seem to make the assumption that LLMs must always run in some large, hosted datacenter.  As I noted in &lt;a href=&quot;https://changelog.complete.org/archives/42503-artificial-intelligence-shades-of-gray&quot;&gt;my March article&lt;/a&gt;, I have had credible results on even an older GPU running on solar power.&lt;/p&gt;
&lt;p&gt;That said, it is undeniable that LLMs are fueling a datacenter boom, and this in turn is producing a significant new demand for resources.  Most notably for the global scale: electricity, which is sometimes generated using carbon-emitting technologies.&lt;/p&gt;
&lt;p&gt;Bill McKibben, who has been a leading voice in the fight against climate change since the 1980s, has made some interesting points recently: he’s noted that &lt;a href=&quot;https://www.youtube.com/watch?v=_iOxU4-OLss&quot;&gt;solar power is the fastest kind of generation we can build&lt;/a&gt;, and a number of large AI companies are investing heavily in solar, even to the point of fully offsetting new datacenter’s needs.  On the other hand, he’s also noted that some companies are buying inefficient and dirty gas turbines.  It is decidedly a mixed bag.  The heavy investment in solar can have knock-on positive effects for infrastructure.  Obviously, not every picture here is rosy.  This analysis doesn’t touch on the real land and water use situation, either.&lt;/p&gt;
&lt;p&gt;On the other hand, if an LLM allows me to do in an hour what I would have done in a day, that’s a day of not heating or cooling the work area — generally not sustaining a human for the purpose of writing code for Debian.  HVAC energy consumption dwarfs my GPU, and I’d imagine probably also the slice of LLM energy used.&lt;/p&gt;
&lt;p&gt;Holistically, I would have to conclude the picture is mixed.  It is possible to use LLMs in a pretty green way, and also in a pretty dirty way.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Assuming Conditions Never Change&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;A flaw in most of these proposals is they assume that the conditions at this present moment will always hold.  In fact, that the conditions at the present moment will &lt;b&gt;not&lt;/b&gt; continue is something both AI cheerleaders and AI skeptics agree on.&lt;/p&gt;
&lt;p&gt;For instance:&lt;/p&gt;
&lt;p&gt;Ed Zitron has done a &lt;a href=&quot;https://www.wheresyoured.at/&quot;&gt;ton of research&lt;/a&gt; into the financing side of AI, and has concluded that the current model is unsustainable and headed for a significant bubble burst.  I’m not positioned to personally evaluate those claims, but if that happens, what is the result?  Perhaps it is a steeply increasing cost of inference for the frontier models, slower pace of training/evolution for them, etc.&lt;/p&gt;
&lt;p&gt;In a &lt;a href=&quot;https://www.youtube.com/watch?v=f_6TzmifxnI&quot;&gt;recent episode of Oxide and Friends&lt;/a&gt;, Simon Willison discussed the open weight models that are now available.  They have been making remarkable strides in efficiency and capabilities, to the point where $50,000 of hardware can now run high-end open weight models with capabilities that are at least in the same ballpark as the American frontier models.  This puts running high-end models locally squarely within reach of universities and small- to medium-sized businesses, with power requirements that can be met with standard commercial solar and wind installations.&lt;/p&gt;
&lt;p&gt;The lack of nuance in the more restrictive proposals is particularly concerning.  Proposal A doesn’t allow “the use or assitance of… LLMs”.  So it bans my solar-powered GPU.  It bans using LLMs to find security issues.  It bans all sorts of things that don’t seem to be ban-worthy, alongside the things that do.  And it codifies it in the very hard-to-change social contract.&lt;/p&gt;
&lt;p&gt;That proposal, and some like it, seem to imply that all LLM output is bad.  I grant you that AI slop is a real and legitimate concern, and many Open Source projects have to deal with it.  On the other hand, we have all seen first-hand how the security of the Linux kernel has benefited dramatically from AI analysis.  It is certain that black hats are using these tools.  If we refuse to use modern security tools, our security will be compromised (and what is the environmental and social impact of THAT?)&lt;/p&gt;
&lt;p&gt;I find the statement “Generative AI is characterized by producing output of a nature that would ordinarily be produced and consumed by humans” to be particularly interesting.  The same was once said of compilers.  &lt;/p&gt;
&lt;p&gt;&lt;b&gt;The Real Concerns&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;You might think from reading this that I am some AI cheerleader.  I’m not.  I share the ethics of the FLOSS movement, and have for decades.  I abhor the power and lack of ethics that many big names in the field are running with at the moment.  I’ve had to put up Anubis on this blog, for instance.&lt;/p&gt;
&lt;p&gt;I have personally experienced the effects of AI slop, especially at review time.  This is a real problem, though I don’t think the more draconian policies are likely to help (the looser “you must disclose” stand a fighting chance, but I’m not sure they would help, either.)  Done poorly, AI threatens developer burnout by overwhelming them with poor code and verbose but useless explanations.  Done well, AI can help prevent developer burnout by automating tedious and low-value tasks.&lt;/p&gt;
&lt;p&gt;Shouldn’t our goal be that humans submit work to Debian, using tools they prefer, and take responsibility for it?  Does it matter if someone uses ed, vim, emacs, or vscode?  If they use LSP or just run gcc manually?  I’d say we benefit from the diversity.  Wouldn’t we be better off to benefit from the diversity here, and judge work as we always have: on its merits, not what tools were used to create it?&lt;/p&gt;
&lt;p&gt;Fundamentally, a GR is a long and arduous process.  It’s not easy to reverse later.  Amending the Social Contract is even longer and more arduous (I should know; I may have been the &lt;a href=&quot;https://www.debian.org/vote/2000/vote_0008&quot;&gt;first one to try&lt;/a&gt;).  The LLM landscape is fast-moving.  None of us can really predict where it will be in a year.  Will the current market leading companies even still exist?  Will it be at all credible to refuse to use AI-assisted security tools?   What is the most effective way to deal with AI slop?  What level of utility will we be able to achieve with models run locally?&lt;/p&gt;
&lt;p&gt;Some of these proposals would make sense if drafted in some way short of a GR, which would allow more maneuverability as the landscape changes.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Brief analysis of the options&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Considering the proposals:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Proposal A: seeks to amend the social contract, which I am opposed to for reasons already laid out above.  It names some real concerns about AI that I agree with, but implies that all LLM uses and models are guilty of the problems, which is not the case with all of the claims.  It also sets us behind the curve on security and stability by forbidding the use or assistance of those tools, even if run by others.  It &lt;b&gt;requires us to ignore reports of actual security bugs, or correct fixes, if those reports were generated with the assistance of an LLM&lt;/b&gt;, which I find to be absolutely untenable.&lt;/li&gt;
&lt;li&gt;Proposal B: This is the “AI with accountability” approach.  It notes the real concerns with LLMs without painting with an overbroad brush.  It strikes me as level-headed and sensible.&lt;/li&gt;
&lt;li&gt;Proposal C: It paints with an over-broad brush and makes some non-binding requests.  Then it winds up largely like proposal B, though while it is worded more strongly, has fewer binding requirements (for instance, it lacks proposal B’s prohibition on transmitting sensitive information to untrusted providers)&lt;/li&gt;
&lt;li&gt;Proposal D: Seems broadly similar to proposal B, an “AI with accountability” approach.  I’m not really clear why we need both.&lt;/li&gt;
&lt;li&gt;Proposal E: Largely the status quo.  It is like proposals B and D in that it says humans are accountable for their contributions.  It encourages disclosure of LLM use, but does not mandate it.  Like proposal B, it prohibits disclosing sensitive information to third-party AI services.  Note that both proposals B and D have an appropriate nuance: a local model is fine, a third-party one is not.&lt;/li&gt;
&lt;li&gt;Proposal F: This seems really similar to proposal E.  I’m not sure why we have these two.&lt;/li&gt;
&lt;li&gt;Proposal G: Disallows “the output of generative AI as direct contributions to Debian.”  This is something of a weakened proposal A; it doesn’t seek to amend the social contract, nor does it ban all use; it simply bans the use as a direct contribution.&lt;/li&gt;
&lt;li&gt;Proposal H: Ban due to climate impacts.  “How is this even an argument” is disrespectful to reasoned conversation.  I have already noted that LLMs can be and are used in ways that are not climate-harming.  It explicitly contains no binding requirements at all, and is effectively a rant.  While I agree with the sentiment that climate change is an urgent problem, and that some LLMs are exacerbating it, I disagree with that all LLM usage does so and therefore disagree with the conclusion.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;In favor of nuance&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I find that black-and-white thinking is almost always something to be avoided.  I see it too often.  I see it in politics, I see it in our software, I see it in discussions around AI.  Are there deeply unethical things happening in AI?  &lt;a href=&quot;https://www.404media.co/we-tracked-a-shipment-of-rare-books-it-ended-at-an-amazon-ai-training-facility/&quot;&gt;Absolutely&lt;/a&gt;.  Are they doing some impressive things?  &lt;a href=&quot;https://cybersecuritynews.com/linux-patches-400-kernel-vulnerabilities/&quot;&gt;Also yes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We have accepted this nuance in other areas.  For instance, almost all the hardware Debian runs on has closed-source hardware, and has components manufactured or assembled in countries with some of the worst human rights records on the planet.  I’m not saying this is a great state of affairs.  It is something we should speak up about and act upon.  But the &lt;i&gt;worse&lt;/i&gt; state of affairs would be “no Debian because the hardware is impure”.&lt;/p&gt; </description> 
	<pubDate>Tue, 18 Aug 2026 01:39:54 +0000</pubDate>

</item> 
<item>
	<title>Bits from Debian: Debian turns 33!</title>
	<guid>tag:bits.debian.org,2026-08-16:/2026/08/debian-turns-33.html</guid>
	<link>https://bits.debian.org/2026/08/debian-turns-33.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dwn.png&quot; width=&quot;77&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;It has now been thirty-three years since the Debian project was &lt;a href=&quot;https://wiki.debian.org/DebianHistory?action=AttachFile&amp;amp;do=get&amp;amp;target=Debian-announcement-1993.txt&quot;&gt;announced&lt;/a&gt; to
the world by Ian Murdock, on August 16, 1993. This anniversary is an
opportunity to reaffirm the goals, characteristics, and qualities of the
Debian project: itâ€™s an association of individuals who have made common cause
to create a free operating system. Our distribution is characterized by a
commitment to software freedom, as enshrined in the &lt;a href=&quot;https://www.debian.org/social_contract&quot;&gt;Debian Social Contract&lt;/a&gt;
and the Debian Free Software Guidelines. It focuses on security and
stability. This stability is crucial to Debian position in the free software
ecosystem.&lt;/p&gt;
&lt;p&gt;With our users as our priority, Debian makes special efforts regarding
accessibility with &lt;a href=&quot;https://www.debian.org/devel/debian-accessibility/&quot;&gt;Debian-Accessibility&lt;/a&gt; and diversity with our &lt;a href=&quot;https://wiki.debian.org/Teams/Outreach&quot;&gt;Outreach
Programs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Debian Day is a great opportunity to get together, whether for a local meetup,
or simply to grab a coffee with other members of the Debian community. Check
out the &lt;a href=&quot;https://wiki.debian.org/DebianDay/2026&quot;&gt;Debian Day wiki&lt;/a&gt; to see if there is a celebration near you. And if
there isn&#39;t, maybe &lt;a href=&quot;https://wiki.debian.org/DebianDay#Organize_a_local_Debian_Day_celebration&quot;&gt;you can organize it&lt;/a&gt; next year!&lt;/p&gt;
&lt;p&gt;Today is also an opportunity for you to start or resume your contributions
to Debian. For example, you can install the &lt;a href=&quot;https://packages.debian.org/trixie/how-can-i-help&quot;&gt;how-can-i-help package&lt;/a&gt; and
see if there is a bug in any of the software that you use that you can help
to fix, contribute small tips on how to install Debian on your machines to our
&lt;a href=&quot;https://wiki.debian.org/InstallingDebianOn/&quot;&gt;wiki pages&lt;/a&gt;, or put a &lt;a href=&quot;https://www.debian.org/CD/live/&quot;&gt;Debian live&lt;/a&gt; image in an USB memory
and give it to some person near you, who still didn&#39;t discover Debian.&lt;/p&gt;
&lt;p&gt;Thanks to everybody who has contributed to develop our beloved operating
system in these 33 years, and
&lt;strong&gt;Happy birthday Debian!&lt;/strong&gt;&lt;/p&gt; </description> 
	<pubDate>Sun, 16 Aug 2026 13:00:00 +0000</pubDate>

</item> 
<item>
	<title>Benjamin Mako Hill: Sad Story</title>
	<guid>https://mako.cc/copyrighteous/?p=3361</guid>
	<link>https://mako.cc/copyrighteous/sad-story</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/mako.gif&quot; width=&quot;65&quot; height=&quot;93&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;figure class=&quot;wp-block-image size-large&quot;&gt;&lt;a href=&quot;https://mako.cc/copyrighteous/wp-content/uploads/2026/08/PXL_20260719_1815328531-scaled.jpg&quot;&gt;&lt;img alt=&quot;Picture of a box in a fireplace saying: &quot; class=&quot;wp-image-3363&quot; height=&quot;1024&quot; src=&quot;https://mako.cc/copyrighteous/wp-content/uploads/2026/08/PXL_20260719_1815328531-576x1024.jpg&quot; width=&quot;576&quot; /&gt;&lt;/a&gt;&lt;/figure&gt;



&lt;p class=&quot;wp-block-paragraph&quot;&gt;Not a &lt;a href=&quot;https://screenshotsofdespair.tumblr.com/&quot;&gt;screenshot of despair&lt;/a&gt;. But only because it’s not a screenshot.&lt;/p&gt; </description> 
	<pubDate>Sun, 16 Aug 2026 07:01:10 +0000</pubDate>

</item> 
<item>
	<title>Sven Hoexter: FrOSCon 2026: TLS Talk</title>
	<guid>http://sven.stormbind.net/blog/posts/talk_froscon2026_tls_ech_caa_https/</guid>
	<link>http://sven.stormbind.net/blog/posts/talk_froscon2026_tls_ech_caa_https/</link>
     <description>  &lt;p&gt;Info: German content only, sorry.&lt;/p&gt;

&lt;p&gt;I was pondering for the past three years if I should give some sort
of TLS basics talk at FrOSCon. I finally stepped up this year
and gave that talk today, with the title
&quot;TLS, mTLS, SNI, ECH, CAA, HTTPS, PKI, Zertifikate und ein bisschen PQC&quot;.
I was too optimistic with my 50 slides, and had to drop the
Post Quantum Cryptography part at the end. Still got positive feedback from
Zugschlus and others - thanks a lot for that &amp;lt;3 - and was asked for the slides.
It&#39;s not a piece of art, but maybe it helps to release the LibreOffice odp file
as well, so others can use it as a base for other events or corp internal talks.
So here is the
&lt;a href=&quot;https://sven.stormbind.net/talks/froscon2026/froscon-tls-2026.pdf&quot;&gt;froscon-tls-2026.pdf&lt;/a&gt;
and
&lt;a href=&quot;https://sven.stormbind.net/talks/froscon2026/froscon-tls-2026.odp&quot;&gt;froscon-tls-2026.odp&lt;/a&gt;,
both released under the CC BY-NC license.&lt;/p&gt;

&lt;p&gt;The video is also available at
&lt;a href=&quot;https://media.ccc.de/v/froscon2026-3584-tls_mtls_sni_ech_caa_https_pki_zertifikate_und_ein_bisschen_pqc&quot;&gt;media.ccc.de&lt;/a&gt; if you want to watch it.&lt;/p&gt;

&lt;p&gt;Thanks to everyone who made FrOSCon happen for the 21th time!&lt;/p&gt; </description> 
	<pubDate>Sat, 15 Aug 2026 18:02:03 +0000</pubDate>

</item> 
<item>
	<title>Russell Coker: Hacked by Chinafans</title>
	<guid>https://etbe.coker.com.au/?p=6276</guid>
	<link>https://etbe.coker.com.au/2026/08/15/hacked-chinafans/</link>
     <description>  &lt;h2&gt;What Happened&lt;/h2&gt;
&lt;p&gt;On 2026/08/10 at 2:11 am Australian eastern standard time (2026/08/09 16:11 UTC) someone created a post titled “Hacked by Chinafans” on &lt;a href=&quot;https://doc.coker.com.au/&quot;&gt;my documents blog [1]&lt;/a&gt;. The person in question created an account named “67965e42a3c3” on that site with the email address 67965e42a3c3@google.com associated with it (I tried emailing that address and it bounced).&lt;/p&gt;
&lt;p&gt;At 04:28:41am Australian eastern standard time (18:28 UTC) I was sent an email titled “Have you been hacked” by a reader of my blogs who subscribed to the RSS feed of my documents blog (a blog that I never expected anyone to read by RSS). Along the lines of “the wisdom of crowds” should we have “the unexpected observation and problem reporting of crowds”? I appreciate the notification, I might not have noticed until the next time I watched an unusually good movie otherwise.&lt;/p&gt;
&lt;p&gt;The account in question was apparently created on 2026-07-21 at 16:43:47 (presumably UTC) even though at the time I believe creating accounts was not permitted. As an aside the timestamp of account creation is stored in the user_registered column of the wp_users table in the database, there doesn’t appear to be a way to access this in a standard WordPress installation other than doing a SQL query.&lt;/p&gt;
&lt;pre&gt;2026-07-24 15:43:17 status triggers-pending wordpress:all 7.0+dfsg1-1
2026-07-24 15:43:19 upgrade wordpress:all 7.0+dfsg1-1 7.0.2+dfsg1-1&lt;/pre&gt;
&lt;p&gt;Above are the relevant sections of my dpkg log showing the WordPress versions in use. I was running version 7.0+dfsg1-1 at the time the account was apparently created. I am confident in the accuracy of the dpkg logs and believe that they did not compromise the OS, I am not sure whether they ran hostile SQL code to change fields in the MySQL database so had to consider the possibility that the account creation time could have been set to a deliberately misleading value. I checked backups of the MySQL database stored off-site and found that the account in question was not in the 2026-07-21 backup (which was done before 16:43) but in the 2026-07-22 backup.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://en-au.wordpress.org/download/releases/&quot;&gt;WordPress release history [2]&lt;/a&gt; has version 7.0.1 released on 2026-07-09 and version 7.0.2 released on 2026-07-17. So presumably the attacker diffed the code on those releases, found an exploitable bug, and used it to create an account on my blog with admin privs. Then they waited a few weeks to see if I would notice and published a blog post when I didn’t notice.&lt;/p&gt;
&lt;h2&gt;WordPress Deficiencies&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;WordPress doesn’t seem to store the version it’s running at the time of operations. So anyone who doesn’t have a suitable external log of versions deployed (such as the dpkg.log file for a Debian managed installation) won’t know for sure which version was running. It supports automatic updates but you can’t be sure that they happened soon after the release.&lt;/li&gt;
&lt;li&gt;There is no log of IP addresses used for operations. There are apparently some 3rd party modules to log such things and web pages documenting how to modify the PHP to add it but nothing in the standard distribution.&lt;/li&gt;
&lt;li&gt;Software should have a standard distribution with some support for logging of security relevant data. The typical situation is that people don’t plan for logging such things until after they have been attacked so the data should be recorded without users going out of their way to log it.&lt;/li&gt;
&lt;li&gt;A log of security relevant data should be stored in a database table with only insert access (no update, delete, or drop).&lt;/li&gt;
&lt;li&gt;Ideally a CMS would support different database accounts for different purposes. Someone from an internal network or VPN could talk to an instance of the web server which has a database username and password giving full access. Everyone from outside the trusted range gets an instance of the web server with database access only allowing to read the posts and appearance configuration and to enter comments. If the database didn’t allow the account used for public access to create new admin users or create posts then it would be a lot harder for attackers.&lt;/li&gt;
&lt;li&gt;Ideally for everything that stores user account data there would be an easy way of getting a list of users in a plain text format to allow running diff. The design of WordPress has two tables, one for users and one for encoded metadata about users of which one will be the access level. The following SQL command will give a list of all users that aren’t subscribers (everyone above the minimum level of access which is typical for new users) along with their encoded password and access level. This could be used in a monitoring system to alert about new privileged users. The TABLE_PREFIX variable is for the prefix for WordPress tables, which is “wp_” by default but can be any legal value.
&lt;pre&gt;select $TABLE_PREFIXusers.user_login, $TABLE_PREFIXusers.user_pass, $TABLE_PREFIXusermeta.meta_value from  $TABLE_PREFIXusers join $TABLE_PREFIXusermeta on $TABLE_PREFIXusers.id = $TABLE_PREFIXusermeta.user_id and meta_key=&#39;$TABLE_PREFIXcapabilities&#39; and meta_value != &#39;a:1:{s:10:&quot;subscriber&quot;;b:1;}&#39;;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;What Next?&lt;/h2&gt;
&lt;p&gt;The blog post they created had a couple of links to Telegram which could presumably be used to contact them. If anyone involved in computer security wants a copy of the original post to do so then they can contact me by any of the usual methods.&lt;/p&gt;
&lt;p&gt;I am interested in communication with the attacker if they wish, Telegram is not a service I use but I presume that anyone capable of doing this sort of attack is also capable of finding other ways of contacting me.&lt;/p&gt;
&lt;p&gt;I have idly considered changing to a static site generator, &lt;a href=&quot;https://jamstack.org/generators/&quot;&gt;here is a good list of static site generators [3]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have also idly considered other platforms for blogging such as Lemmy. I don’t know if Lemmy is better than WordPress for security and updates, but there are plenty of free instances running where it wouldn’t be an issue I have to work on.&lt;/p&gt;
&lt;h2&gt;15 Years&lt;/h2&gt;
&lt;p&gt;It’s been &lt;a href=&quot;https://etbe.coker.com.au/2011/12/31/server-cracked/&quot;&gt;15 years since my blog server was cracked by a trojaned ssh client [4]&lt;/a&gt;. At least this time it was only one service that was compromised.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[1]&lt;a href=&quot;https://doc.coker.com.au/&quot;&gt; https://doc.coker.com.au/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2]&lt;a href=&quot;https://en-au.wordpress.org/download/releases/&quot;&gt; https://en-au.wordpress.org/download/releases/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[3]&lt;a href=&quot;https://jamstack.org/generators/&quot;&gt; https://jamstack.org/generators/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[4]&lt;a href=&quot;https://etbe.coker.com.au/2011/12/31/server-cracked/&quot;&gt; https://etbe.coker.com.au/2011/12/31/server-cracked/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;yarpp yarpp-related yarpp-related-rss yarpp-template-list&quot;&gt;

&lt;p&gt;Related posts:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2006/09/12/blogging-software/&quot; rel=&quot;bookmark&quot; title=&quot;blogging software&quot;&gt;blogging software&lt;/a&gt; &lt;small&gt;Previously I asked for advice about running an Intranet blog,...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2007/10/22/wordpress-and-thumbnails/&quot; rel=&quot;bookmark&quot; title=&quot;WordPress and Thumbnails&quot;&gt;WordPress and Thumbnails&lt;/a&gt; &lt;small&gt;I have just had a lot of trouble with Thumbnails...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2010/08/04/wordpress-maintainability/&quot; rel=&quot;bookmark&quot; title=&quot;WordPress Maintainability&quot;&gt;WordPress Maintainability&lt;/a&gt; &lt;small&gt;For a while I’ve been maintaining my own WordPress packages....&lt;/small&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Sat, 15 Aug 2026 09:31:47 +0000</pubDate>

</item> 
<item>
	<title>Russell Coker: AMD Video Drivers, LLMs, and Debian Kernels</title>
	<guid>https://etbe.coker.com.au/?p=6278</guid>
	<link>https://etbe.coker.com.au/2026/08/15/amd-video-llms-debian-kernels/</link>
     <description>  &lt;h2&gt;The AMD GPU Problem&lt;/h2&gt;
&lt;p&gt;For a while I’ve been having issues with AMD GPUs, video locking up periodically. &lt;a href=&quot;https://etbe.coker.com.au/2025/11/09/amd-video-driver-issues/&quot;&gt;I blogged about this late last year but I first had noticeable problems early last year [1]&lt;/a&gt;. The problems hadn’t only concerned my workstation but also my home server which is also used as a workstation. I’ve recently upgraded my machines to Debian/Testing, my home server has been generally OK but my workstation has been crashing a lot. Every second day when on kernel 7.1.6 and then when on 7.1.7 it crashed at least once a day.&lt;/p&gt;
&lt;p&gt;The AMD GPUs I have are “&lt;b&gt;[AMD/ATI] Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (rev e5)&lt;/b&gt;” in my main desktop workstation, “&lt;b&gt;[AMD/ATI] Lexa [Radeon 540X/550X/630 / RX 640 / E9171 MCM] (rev c1)&lt;/b&gt;” in my build server, and “&lt;b&gt;[AMD/ATI] Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (rev cf)&lt;/b&gt;” in my home server. They aren’t new GPUs, but also aren’t really old and they all support 4K and better resolution.&lt;/p&gt;
&lt;h2&gt;Chat GPT Was Useful&lt;/h2&gt;
&lt;p&gt;When I googled the errors I was seeing I found nothing useful. On the suggestion of a friend I tried asking ChatGPT. Generally I don’t recommend asking LLMs about such things, but it can be a last resort as long as you know what you are doing. ChatGPT asked me to run a number of commands to get information for it to make more informed decisions. I know that the output of lspci and similar commands isn’t a risk, but a novice could be tricked into running commands that expose sensitive data.&lt;/p&gt;
&lt;p&gt;ChatGPT did give me some useful information, not a solution but an indication that the problem was due to driver bugs.&lt;/p&gt;
&lt;h2&gt;Upgrading to Experimental&lt;/h2&gt;
&lt;p&gt;Debian/Experimental is for packages that are expected to have problems and generally aren’t recommended even for the people who usually use Debian/Unstable. It’s commonly used for packages that are needed to develop other packages, EG new libraries that aren’t fully usable but which are needed to package newer versions of applications.&lt;/p&gt;
&lt;p&gt;I upgraded my workstation to the Debian/Experimental kernel 7.2~rc7-1~exp1 after having tried every other convenient option. Generally I wouldn’t recommend that anyone run an Experimental kernel without a really good reason, but crashing more than once a day is a fairly good reason. That kernel has now given me over 4 days of uptime on a system that previously wouldn’t last a day. I installed it on my dual-socket build server that has an old AMD GPU in it for test purposes and that also hasn’t crashed since. I installed it on my ML test machine which has an Intel B580 Battlemage GPU with 16G of VRAM and was repeatedly getting a kernel panic related to the GPU a few seconds after boot and now it also works correctly.&lt;/p&gt;
&lt;p&gt;It seems that the 7.1.x kernels have bugs in the AMD video drivers and in some part of the code that affects Intel video drivers and that the bugs in question are fixed in the tree that will become 7.2. I would not recommend anyone who has a 7.1.x kernel working fine for them try 7.2 RC kernels at this time, but anyone who has GPU related problems (particularly Intel and AMD GPUs) should definitely test it out.&lt;/p&gt;
&lt;p&gt;I also don’t recommend upgrading any system with an AMD GPU to Debian/Testing or Debian/Unstable at this time unless you are also prepared to install an Experimental kernel if it becomes necessary.&lt;/p&gt;
&lt;p&gt;There are a several kernel log dumps related to this after the break (which won’t be in RSS feeds). This is mainly for Google so that other people who have such issues can get more useful results out of Google searches than I got.&lt;/p&gt;
&lt;h2&gt;Future Support Options&lt;/h2&gt;
&lt;p&gt;Separate from the issue of whether commercial LLMs like ChatGPT can be useful for solving technical problems there is the issue of whether they are desirable. I think that we really don’t want people solving problems in FOSS systems with closed-source LLMs. This leads to loss of privacy, loss of the control users deserve to have over their own systems, and an implied promotion of non-fee software.&lt;/p&gt;
&lt;p&gt;I think that the ideal would be to have a cross distribution effort to generate training data for a support LLM system which can then be further trained by each distribution for a greater emphasis on distribution specific issues.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[1]&lt;a href=&quot;https://etbe.coker.com.au/2025/11/09/amd-video-driver-issues/&quot;&gt; https://etbe.coker.com.au/2025/11/09/amd-video-driver-issues/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span id=&quot;more-6278&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Errors on AMD GPUs&lt;/h2&gt;
&lt;pre&gt;2026-08-09T23:03:06.004792+10:00 xev kernel: amdgpu 0000:02:00.0: GPU fault detected: 147 0x00024802
2026-08-09T23:03:06.004792+10:00 xev kernel: amdgpu 0000:02:00.0: Process kscreenlocker_g pid 42037 thread kscreenloc:cs0 pid 42044
2026-08-09T23:03:06.004793+10:00 xev kernel: amdgpu 0000:02:00.0: VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x00000800
2026-08-09T23:03:06.004794+10:00 xev kernel: amdgpu 0000:02:00.0: VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0F048002
2026-08-09T23:03:06.004795+10:00 xev kernel: amdgpu 0000:02:00.0: VM fault (0x02, vmid 7, pasid 130) at page 2048, write from &#39;TC0&#39; (0x54433000) (72)
2026-08-09T23:03:06.008762+10:00 xev kernel: amdgpu 0000:02:00.0: GPU fault detected: 147 0x00004802
2026-08-09T23:03:06.008768+10:00 xev kernel: amdgpu 0000:02:00.0: Process kscreenlocker_g pid 42037 thread kscreenloc:cs0 pid 42044&lt;/pre&gt;
&lt;pre&gt;2026-08-04T01:13:37.505839+10:00 xev kernel: ------------[ cut here ]------------ 
2026-08-04T01:13:37.505859+10:00 xev kernel: amdgpu 0000:02:00.0: [drm] drm_WARN_ON_ONCE(cur_vblank != vblank-&amp;gt;last) 
2026-08-04T01:13:37.505862+10:00 xev kernel: WARNING: CPU: 6 PID: 210534 at drivers/gpu/drm/drm_vblank.c:362 drm_update_vblank_count+0x2f1/0x3c0 [drm] 
2026-08-04T01:13:37.505866+10:00 xev kernel: snd_intel_dspcfg wmi_bmof rc_core snd_intel_sdw_acpi drm_ttm_helper uas realtek snd_usbmidi_lib snd_hda_codec ttm mdio_devres snd_hda_core snd_seq_midi drm_kms_helper usb_storage mc snd_hwdep libphy snd_seq_midi_event intel_uncore snd_pcm_oss i2c_algo_bit serio_raw snd_rawmidi pcspkr snd_mixer_oss i2c_i801 video snd_seq snd_pcm i2c_smbus lpc_ich snd_seq_device mei_me e1000e snd_timer mei snd tpm_infineon soundcore joydev bnx2 wmi button nfsd auth_rpcgss nfs_acl lockd grace sunrpc coretemp br_netfilter bridge stp llc sg ghash_clmulni_intel loop msr i2c_dev drm efi_pstore configfs nfnetlink ip_tables x_tables autofs4 btrfs blake2b_generic dm_crypt dm_mod raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor async_tx libcrc32c xor raid6_pq raid1 raid0 md_mod ext4 crc16 mbcache jbd2 crc32c_generic virtio_blk evdev hid_generic usbhid hid sd_mod xhci_pci xhci_hcd ahci ehci_pci ehci_hcd libahci crc32c_intel libata usbcore aesni_intel nvme psmouse scsi_mod gf128mul crypto_simd nvme_core cryptd 
2026-08-04T01:13:37.505879+10:00 xev kernel: nvme_auth scsi_common usb_common efivarfs 
2026-08-04T01:13:37.505880+10:00 xev kernel: CPU: 6 UID: 1008 PID: 210534 Comm: sshd-session Tainted: G D 6.12.88+deb13-amd64 #1 Debian 6.12.88-1 
2026-08-04T01:13:37.505881+10:00 xev kernel: Tainted: [D]=DIE 
2026-08-04T01:13:37.505883+10:00 xev kernel: Hardware name: Hewlett-Packard HP Z640 Workstation/212A, BIOS M60 v02.61 03/23/2023 
2026-08-04T01:13:37.505884+10:00 xev kernel: RIP: 0010:drm_update_vblank_count+0x2f1/0x3c0 [drm] 
2026-08-04T01:13:37.505885+10:00 xev kernel: Code: 48 8b 5f 50 48 85 db 75 03 48 8b 1f e8 68 eb 2b cf 48 c7 c1 70 3e cb c0 48 89 da 48 c7 c7 f9 6f cb c0 48 89 c6 e8 af d7 a6 ce &amp;lt;0f&amp;gt; 0b e9 4b fe ff ff 48 8b 4c 24 18 e9 31 fe ff ff 31 f6 48 85 db 
2026-08-04T01:13:37.505887+10:00 xev kernel: RSP: 0000:ffffd3cc8681fca0 EFLAGS: 00010082 
2026-08-04T01:13:37.505888+10:00 xev kernel: RAX: 0000000000000000 RBX: ffff8c6b42b13710 RCX: 0000000000000027 
2026-08-04T01:13:37.505889+10:00 xev kernel: RDX: ffff8c89ef521788 RSI: 0000000000000001 RDI: ffff8c89ef521780 
2026-08-04T01:13:37.505890+10:00 xev kernel: RBP: 0000000000000000 R08: 0000000000000000 R09: ffffd3cc8681fb20 
2026-08-04T01:13:37.505891+10:00 xev kernel: R10: ffff8c8a6fef3628 R11: 0000000000000003 R12: 0000000000000000 
2026-08-04T01:13:37.505892+10:00 xev kernel: R13: ffff8c6c07853828 R14: 0000000000000003 R15: 0000000000000000 
2026-08-04T01:13:37.505893+10:00 xev kernel: FS: 00007ffaf2fd5880(0000) GS:ffff8c89ef500000(0000) knlGS:0000000000000000 
2026-08-04T01:13:37.505895+10:00 xev kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 
2026-08-04T01:13:37.505896+10:00 xev kernel: CR2: 00007fb1718c8000 CR3: 000000074521a004 CR4: 00000000003706f0 
2026-08-04T01:13:37.505897+10:00 xev kernel: Call Trace: 
2026-08-04T01:13:37.505898+10:00 xev kernel:  
2026-08-04T01:13:37.505899+10:00 xev kernel: drm_crtc_accurate_vblank_count+0x41/0xc0 [drm] 
2026-08-04T01:13:37.505900+10:00 xev kernel: dm_pflip_high_irq+0x155/0x330 [amdgpu] 
2026-08-04T01:13:37.505901+10:00 xev kernel: amdgpu_dm_irq_handler+0x85/0x1f0 [amdgpu] 
2026-08-04T01:13:37.505902+10:00 xev kernel: amdgpu_irq_dispatch+0xd2/0x230 [amdgpu] 
2026-08-04T01:13:37.505903+10:00 xev kernel: amdgpu_ih_process+0x84/0x100 [amdgpu] 
2026-08-04T01:13:37.505904+10:00 xev kernel: amdgpu_irq_handler+0x23/0x60 [amdgpu] 
2026-08-04T01:13:37.505905+10:00 xev kernel: __handle_irq_event_percpu+0x4a/0x190
2026-08-04T01:13:37.505907+10:00 xev kernel: handle_irq_event+0x38/0x80 
2026-08-04T01:13:37.505908+10:00 xev kernel: handle_edge_irq+0x8b/0x230 
2026-08-04T01:13:37.505909+10:00 xev kernel: __common_interrupt+0x45/0xe0 
2026-08-04T01:13:37.505910+10:00 xev kernel: common_interrupt+0x42/0xa0 
2026-08-04T01:13:37.505911+10:00 xev kernel: asm_common_interrupt+0x26/0x40 
2026-08-04T01:13:37.505912+10:00 xev kernel: RIP: 0033:0x7ffaf3c5fd7b 
2026-08-04T01:13:37.505913+10:00 xev kernel: Code: 70 c7 00 66 0f 6e f8 c1 ef 02 66 0f 70 f7 e0 83 c7 01 66 0f ef ff 66 0f fa f2 0f 1f 44 00 00 f3 0f 7e 01 66 0f 6f ce 83 c6 01 &amp;lt;48&amp;gt; 83 e9 08 f2 0f 70 c0 1b 66 0f 6f e0 66 0f 6f e8 66 41 0f f9 c0 
2026-08-04T01:13:37.505915+10:00 xev kernel: RSP: 002b:00007fff86a5e0e0 EFLAGS: 00000202 
2026-08-04T01:13:37.505916+10:00 xev kernel: RAX: 0000000000008000 RBX: 0000562614a04050 RCX: 0000562614982ed8 
2026-08-04T01:13:37.505946+10:00 xev kernel: RDX: 0000000000007fe2 RSI: 0000000000000fad RDI: 0000000000002000 
2026-08-04T01:13:37.505948+10:00 xev kernel: RBP: 0000000000000000 R08: 000056261498ac40 R09: 0000000000008000 
2026-08-04T01:13:37.505949+10:00 xev kernel: R10: 0000000000000066 R11: 0000000000007fe1 R12: 0000000000007efa
2026-08-04T01:13:37.505950+10:00 xev kernel: R13: 0000000000008000 R14: 0000000000008000 R15: 000000000000ffe0 
2026-08-04T01:13:37.505951+10:00 xev kernel:  
2026-08-04T01:13:37.505953+10:00 xev kernel: ---[ end trace 0000000000000000 ]--- 
2026-08-04T01:55:40.844110+10:00 xev kernel: pcieport 0000:00:03.3: AER: Multiple Correctable error message received from 0000:00:03.3 
2026-08-04T01:55:40.844130+10:00 xev kernel: pcieport 0000:00:03.3: PCIe Bus Error: severity=Correctable, type=Data Link Layer, (Receiver ID) 
2026-08-04T01:55:40.844132+10:00 xev kernel: pcieport 0000:00:03.3: device [8086:6f0b] error status/mask=00000040/00002000 
2026-08-04T01:55:40.844134+10:00 xev kernel: pcieport 0000:00:03.3: [ 6] BadTLP&lt;/pre&gt;
&lt;pre&gt;2026-08-11T09:33:33.473855+10:00 xev kernel: amdgpu 0000:02:00.0: GPU fault detected: 147 0x00024802
2026-08-11T09:33:33.473871+10:00 xev kernel: amdgpu 0000:02:00.0: Process kscreenlocker_g pid 150905 thread kscreenloc:cs0 pid 150912
2026-08-11T09:33:33.473871+10:00 xev kernel: amdgpu 0000:02:00.0: VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x00000800
2026-08-11T09:33:33.473873+10:00 xev kernel: amdgpu 0000:02:00.0: VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0F048002
2026-08-11T09:33:33.473873+10:00 xev kernel: amdgpu 0000:02:00.0: VM fault (0x02, vmid 7, pasid 63) at page 2048, write from &#39;TC0&#39; (0x54433000) (72)
2026-08-11T09:33:33.473874+10:00 xev kernel: amdgpu 0000:02:00.0: GPU fault detected: 147 0x00004802
2026-08-11T09:33:33.473874+10:00 xev kernel: amdgpu 0000:02:00.0: Process kscreenlocker_g pid 150905 thread kscreenloc:cs0 pid 150912
2026-08-11T09:33:33.473875+10:00 xev kernel: amdgpu 0000:02:00.0: VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x00000800
2026-08-11T09:33:33.473876+10:00 xev kernel: amdgpu 0000:02:00.0: VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0E048002
2026-08-11T09:33:33.473876+10:00 xev kernel: amdgpu 0000:02:00.0: VM fault (0x02, vmid 7, pasid 63) at page 2048, read from &#39;TC0&#39; (0x54433000) (72)
2026-08-11T09:33:35.481863+10:00 xev kernel: amdgpu 0000:02:00.0: Dumping IP State
2026-08-11T09:33:35.481875+10:00 xev kernel: amdgpu 0000:02:00.0: Dumping IP State Completed
2026-08-11T09:33:35.481875+10:00 xev kernel: amdgpu 0000:02:00.0: [drm] AMDGPU device coredump file has been created
2026-08-11T09:33:35.481876+10:00 xev kernel: amdgpu 0000:02:00.0: [drm] Check your /sys/class/drm/card0/device/devcoredump/data
2026-08-11T09:33:35.481877+10:00 xev kernel: amdgpu 0000:02:00.0: GPU fault detected: 146 0x0110040c
2026-08-11T09:33:35.481877+10:00 xev kernel: amdgpu 0000:02:00.0: Process kscreenlocker_g pid 150905 thread kscreenloc:cs0 pid 150912
2026-08-11T09:33:35.481878+10:00 xev kernel: amdgpu 0000:02:00.0: VM_CONTEXT1_PROTECTION_FAULT_ADDR 0x00000022
2026-08-11T09:33:35.481879+10:00 xev kernel: amdgpu 0000:02:00.0: VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x0E00400C
2026-08-11T09:33:35.481879+10:00 xev kernel: amdgpu 0000:02:00.0: VM fault (0x0c, vmid 7, pasid 63) at page 34, read from &#39;TC3&#39; (0x54433300) (4)
2026-08-11T09:33:35.489845+10:00 xev kernel: amdgpu 0000:02:00.0: ring gfx timeout, signaled seq=5123619, emitted seq=5123621
2026-08-11T09:33:35.489853+10:00 xev kernel: amdgpu 0000:02:00.0: Process kscreenlocker_g pid 150905 thread kscreenloc:cs0 pid 150912
2026-08-11T09:33:35.489854+10:00 xev kernel: amdgpu 0000:02:00.0: GPU reset begin!. Source: 1
2026-08-11T09:33:35.493839+10:00 xev kernel: amdgpu 0000:02:00.0: [drm] ERROR Failed to initialize parser -125!
2026-08-11T09:33:35.737848+10:00 xev kernel: amdgpu: cp is busy, skip halt cp
2026-08-11T09:33:35.897842+10:00 xev kernel: amdgpu: rlc is busy, skip halt rlc
2026-08-11T09:33:35.897852+10:00 xev kernel: amdgpu 0000:02:00.0: BACO reset
2026-08-11T09:33:36.485849+10:00 xev kernel: amdgpu 0000:02:00.0: GPU reset succeeded, trying to resume
2026-08-11T09:33:36.485859+10:00 xev kernel: amdgpu 0000:02:00.0: [drm] PCIE GART of 256M enabled (table at 0x000000F402000000).
2026-08-11T09:33:36.485860+10:00 xev kernel: amdgpu 0000:02:00.0: VRAM is lost due to GPU reset!&lt;/pre&gt;
&lt;h2&gt;Errors on Battlemage&lt;/h2&gt;
&lt;pre&gt;Aug 11 17:01:47 ami kernel: ------------[ cut here ]------------
Aug 11 17:01:47 ami kernel: xe 0000:23:00.0: [drm] DMC 1 mmio[0]/0x5f074 incorrect (expected 0x96fc0, current 0x0)
Aug 11 17:01:47 ami kernel: WARNING: drivers/gpu/drm/i915/display/intel_dmc.c:696 at assert_dmc_loaded+0x275/0x430 [xe], CPU#0: kworker/0:3/215
Aug 11 17:01:47 ami kernel: Modules linked in: intel_rapl_msr intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common xe(+) skx_edac snd_h&amp;gt;
Aug 11 17:01:47 ami kernel:  msr i2c_dev configfs efi_pstore efivarfs autofs4 btrfs libblake2b raid6_pq xor mpt3sas raid_class scsi_transport_sas megarai&amp;gt;
Aug 11 17:01:47 ami kernel: CPU: 0 UID: 0 PID: 215 Comm: kworker/0:3 Not tainted 7.1.7+deb14-amd64 #1 PREEMPT(lazy)  Debian 7.1.7-1 
Aug 11 17:01:47 ami kernel: Hardware name: HP HP Z4 G4 Workstation/81C5, BIOS P61 v03.00 04/15/2026
Aug 11 17:01:47 ami kernel: Workqueue: sync_wq local_pci_probe_callback
Aug 11 17:01:47 ami kernel: RIP: 0010:assert_dmc_loaded+0x291/0x430 [xe]
Aug 11 17:01:47 ami kernel: Code: 24 10 e8 f2 e5 a3 ce 48 8d 3d bb 85 0d 00 8b 54 24 0c 45 89 e9 45 89 e0 48 89 c6 52 8b 4c 24 2c 51 8b 4c 24 30 48 8b 54&amp;gt;
Aug 11 17:01:47 ami kernel: RSP: 0018:ffffd27ac0b87b80 EFLAGS: 00010282
Aug 11 17:01:47 ami kernel: RAX: ffffffffc1743dfd RBX: ffff8c5b80e54000 RCX: 0000000000000001
Aug 11 17:01:47 ami kernel: RDX: ffff8c5b81df5a10 RSI: ffffffffc1743dfd RDI: ffffffffc1605860
Aug 11 17:01:47 ami kernel: RBP: ffff8c5b86955000 R08: 0000000000000000 R09: 000000000005f074
Aug 11 17:01:47 ami kernel: R10: 0000000000000000 R11: 0000000000091050 R12: 0000000000000000
Aug 11 17:01:47 ami kernel: R13: 000000000005f074 R14: 0000000000000001 R15: 0000000000000000
Aug 11 17:01:47 ami kernel: FS:  0000000000000000(0000) GS:ffff8c673e172000(0000) knlGS:0000000000000000
Aug 11 17:01:47 ami kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
Aug 11 17:01:47 ami kernel: CR2: 00007ffed1fdcd00 CR3: 0000000ae942a003 CR4: 00000000003706f0
Aug 11 17:01:47 ami kernel: Call Trace:
Aug 11 17:01:47 ami kernel:  
Aug 11 17:01:47 ami kernel:  intel_dmc_enable_pipe+0xe4/0x290 [xe]
Aug 11 17:01:47 ami kernel:  ? drm_crtc_vblank_reset+0x4d/0x120 [drm]
Aug 11 17:01:47 ami kernel:  intel_modeset_setup_hw_state+0xb50/0x1e10 [xe]
Aug 11 17:01:47 ami kernel:  ? intel_display_driver_probe_nogem+0x138/0x1a0 [xe]
Aug 11 17:01:47 ami kernel:  intel_display_driver_probe_nogem+0x138/0x1a0 [xe]
Aug 11 17:01:47 ami kernel:  xe_display_init_early+0xb2/0x140 [xe]
Aug 11 17:01:47 ami kernel:  xe_device_probe+0x3c8/0xb50 [xe]
Aug 11 17:01:47 ami kernel:  ? xe_pm_init_early+0x152/0x160 [xe]
Aug 11 17:01:47 ami kernel:  xe_pci_probe+0xc26/0x1150 [xe]
Aug 11 17:01:47 ami kernel:  local_pci_probe+0x3e/0x90
Aug 11 17:01:47 ami kernel:  local_pci_probe_callback+0x16/0x20
Aug 11 17:01:47 ami kernel:  process_one_work+0x19d/0x3a0
Aug 11 17:01:47 ami kernel:  worker_thread+0x1af/0x320
Aug 11 17:01:47 ami kernel:  ? __pfx_worker_thread+0x10/0x10
Aug 11 17:01:47 ami kernel:  kthread+0xe3/0x120
Aug 11 17:01:47 ami kernel:  ? __pfx_kthread+0x10/0x10
Aug 11 17:01:47 ami kernel:  ret_from_fork+0x2b2/0x340
Aug 11 17:01:47 ami kernel:  ? __pfx_kthread+0x10/0x10
Aug 11 17:01:47 ami kernel:  ret_from_fork_asm+0x1a/0x30
Aug 11 17:01:47 ami kernel:  
Aug 11 17:01:47 ami kernel: ---[ end trace 0000000000000000 ]---&lt;/pre&gt;
&lt;div class=&quot;yarpp yarpp-related yarpp-related-rss yarpp-template-list&quot;&gt;

&lt;p&gt;Related posts:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2025/11/09/amd-video-driver-issues/&quot; rel=&quot;bookmark&quot; title=&quot;AMD Video Driver Issues&quot;&gt;AMD Video Driver Issues&lt;/a&gt; &lt;small&gt;I have had some graphics hangs on my HP z640...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2008/10/22/kernel-issues-with-debian-xen-and-centos-kernels/&quot; rel=&quot;bookmark&quot; title=&quot;Kernel issues with Debian Xen and CentOS Kernels&quot;&gt;Kernel issues with Debian Xen and CentOS Kernels&lt;/a&gt; &lt;small&gt;Last time I tried using a Debian 64bit Xen kernel...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2025/11/02/pcie-problems/&quot; rel=&quot;bookmark&quot; title=&quot;PCIe Problems&quot;&gt;PCIe Problems&lt;/a&gt; &lt;small&gt;HP z840 Dead Slot I just had an issue with...&lt;/small&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Sat, 15 Aug 2026 08:09:51 +0000</pubDate>

</item> 
<item>
	<title>Gunnar Wolf: File recovery in process...</title>
	<guid>https://gwolf.org/2026/08/file-recovery-in-process.html</guid>
	<link>https://gwolf.org/2026/08/file-recovery-in-process.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/gwolf.png&quot; width=&quot;69&quot; height=&quot;83&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Ohai,&lt;/p&gt;

&lt;p&gt;I have some pending, encrypted mails to answer. And some of my answers for
the next few days (particularly to what pertains to the &lt;a href=&quot;https://www.debian.org/vote/2026/vote_002&quot;&gt;current
in-discussion vote on LLM usage in
Debian&lt;/a&gt;) will be unsigned, even
though Iâ€™d like otherwise.&lt;/p&gt;

&lt;p&gt;My desktop system at work is showing some data corruption, and Iâ€™m slowly
backing up my data. Fortunately, it seems I havenâ€™t lost any data, but
still, given Iâ€™m letting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rsync&lt;/code&gt; run until it starts spewing I/O errors,
then power down and let the machine cool a bit, and start againâ€¦ it is a
potentially long process.&lt;/p&gt;

&lt;p&gt;And yes, this makes me somewhat angry. Why angry? Because Iâ€™m working on a
brand-new computer (well, have used it for slightly over six months),
custom-built to specs requested by my workplace. Specs that I donâ€™t really
need, this machine is an utter luxury (i.e. an AMD Ryzen 9 9950X processor
with 16 real cores / 32 threads; 128GB RAM in this day and age of RAM
shortage, quite recent 32GB GPU, and lots of shiny lights seen in its huge
fishbowl cabinet, liquid-based coolingâ€¦). The specs came not from me, but
from people who had no idea what we would use them for. And yes, I expect
the little fortune spent on this machine to be good for my use for probably
a decade, as my previous computer was, but the amount paid
wasâ€¦ exorbitant.&lt;/p&gt;

&lt;p&gt;But still, what I learned recently is that the 4TB nVME SSD it has (a
T-Force TM8FFJX34T) isâ€¦ a very cheap brand, bought because it was close
to half the price of other offerings similar in capacity. According to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;smartctl&lt;/code&gt;â€™s output, th SSD operates with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Warning Comp. Temp. Threshold:
90 Celsius&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Critical Comp. Temp. Threshold: 110 Celsius&lt;/code&gt;, which sounds
sensible, even too high for my standards (my last two laptops have been
fanlessâ€¦ yes, an ARM system is very different from a high-end gaming
machine). Iâ€™m right now typing from my laptop, which shows 78Â°C and 82Â°C
for warning/critical thresholds.&lt;/p&gt;

&lt;p&gt;And as expected, under heavy sustained reads (backing up to my NFS server),
the desktopâ€™s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;smartctl&lt;/code&gt; shows &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Temperature: 83 Celsius&lt;/code&gt; and, further down,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Temperature Sensor 1: 107 Celsius&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Temperature Sensor 2: 82 Celsius&lt;/code&gt;
(donâ€™t know which of these would make the threshold jump). The SSD has
sustained &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Media and Data Integrity Errors: 20&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Warning
Comp. Temperature Time: 21&lt;/code&gt; (although &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Critical Comp. Temperature Time: 0&lt;/code&gt;). At least one of my colleagues have shrugged and installed a SATA SSD,
laying the huge nVME basically to waste.&lt;/p&gt;

&lt;p&gt;Anywayâ€¦ I also learned I am not the first, but the fourth person to
notice this kind of issues in this system (out of ten similar purchased
systems AIUI). It is completely unacceptable, and Iâ€™ll be pushing our
Instituteâ€™s authorities to demand the provider to provide either good
component quality for this very expensive system that has many luxury
items, or to fix the systemâ€™s build in a way the nVME does not heat as much
as it currently does.&lt;/p&gt;

&lt;p&gt;Anyway, &lt;em&gt;sigh&lt;/em&gt;, I only wanted to say, please excuse me for not using my
cryptographic keys for a couple of days ðŸ™ƒ&lt;/p&gt;

&lt;p&gt;PS- Iâ€™m also currently not connected to IRC and Jabber (and some similar
technologies), as my bouncer runs from my usual workstation.&lt;/p&gt; </description> 
	<pubDate>Thu, 13 Aug 2026 17:47:20 +0000</pubDate>

</item> 
<item>
	<title>Jonathan Dowland: DIY skate punch-out</title>
	<guid>https://jmtd.net/log/punch-out/</guid>
	<link>https://jmtd.net/log/punch-out/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/jmtd.png&quot; width=&quot;65&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;div class=&quot;image&quot;&gt;
&lt;a href=&quot;https://jmtd.net/log/punch-out/punch.jpg&quot;&gt;&lt;img alt=&quot;The punch set-up&quot; class=&quot;img&quot; height=&quot;281&quot; src=&quot;https://jmtd.net/log/punch-out/500x-punch.jpg&quot; width=&quot;500&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;




&lt;div class=&quot;image&quot;&gt;
&lt;a href=&quot;https://jmtd.net/log/punch-out/marked.jpg&quot;&gt;&lt;img alt=&quot;the punched boot&quot; class=&quot;img&quot; height=&quot;281&quot; src=&quot;https://jmtd.net/log/punch-out/500x-marked.jpg&quot; width=&quot;500&quot; /&gt;&lt;/a&gt;

&lt;/div&gt;


&lt;p&gt;Since I wrote about my &lt;a href=&quot;https://jmtd.net/log/fly30/&quot;&gt;fly30&lt;/a&gt; ice skates, I&#39;d continued to battle pain
around the navicular bone in my feet. The action that seems to have finally
fixed it was to perform a &quot;punch out&quot;: a very localized remoulding of the
area of the boot that presses against the sore area.&lt;/p&gt;

&lt;p&gt;I basically followed the process from &lt;a href=&quot;https://www.youtube.com/watch?v=5RntLK_-lBU&quot;&gt;this helpful YouTube
video&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I narrowed down the exact spot by borrowing some lipstick and transferring it
from my navicular bone to the boot lining, then making that more permanent with
a sharpie.&lt;/p&gt;

&lt;p&gt;My punch was a spare part from a radiator valve which I packed with US cents
(I couldn&#39;t fit any UK coins in). For the receiving-end, I tried another part
from the radiator valve but I think it wasn&#39;t sufficiently larger than the punch
to work well, so I swapped that out for a spoon.&lt;/p&gt;

&lt;div class=&quot;image&quot;&gt;
&lt;a href=&quot;https://jmtd.net/log/punch-out/take2.jpg&quot;&gt;&lt;img alt=&quot;take 2&quot; class=&quot;img&quot; height=&quot;281&quot; src=&quot;https://jmtd.net/log/punch-out/500x-take2.jpg&quot; width=&quot;500&quot; /&gt;&lt;/a&gt;

&lt;p&gt;take 2&lt;/p&gt;

&lt;/div&gt;


&lt;p&gt;I didn&#39;t have a temperature sensor I could use and I used a heat gun rather than
a hairdryer, so I YOLO&#39;d it a little. Some of the wrap on one of my boots is now
distorted from where I didn&#39;t move the heat gun enough. It only took a minute or
two to get the boot hot enough to be flexible. I set a 15 minute timer once the
clamp was in place.&lt;/p&gt;

&lt;p&gt;I&#39;ve only skated one session since I did this but the pain seems to have gone!
It&#39;s remarkably freeing to be skating without constantly trying to manage pain.
Now I can focus on technique.&lt;/p&gt; </description> 
	<pubDate>Thu, 13 Aug 2026 08:28:08 +0000</pubDate>

</item> 
<item>
	<title>Steinar H. Gunderson: The PSX GPU is wild</title>
	<guid>http://blog.sesse.net/blog/tech/2026-08-12-16-26_the_psx_gpu_is_wild.html</guid>
	<link>http://blog.sesse.net/blog/tech/2026-08-12-16-26_the_psx_gpu_is_wild.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/sesse.png&quot; width=&quot;74&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Inspired by some recent reverse-engineering, here are some things I
find wild by the original PlayStation GPU:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VRAM is a flat 1024x512 16-bit image (555 + 1 bit alpha).
You want more than just a framebuffer?  Figure out yourself what goes where.&lt;/li&gt;
&lt;li&gt;Yes, that means you&#39;ll need to allocate two framebuffers
and double-buffer everything yourself.&lt;/li&gt;
&lt;li&gt;Quads are common. No “triangles only” business here.&lt;/li&gt;
&lt;li&gt;Vertex coordinates are screen-space x/y integers. No floats or fixed-point. (I&#39;m ignoring the GTE here,
plus higher-level libraries.)&lt;/li&gt;
&lt;li&gt;Wait, where&#39;s z? There&#39;s no z. So there&#39;s no perspective correction.
(This one is pretty famous)&lt;/li&gt;
&lt;li&gt;OK, so how do you give in subpixel coordinates? You don&#39;t. There&#39;s no AA after all.&lt;/li&gt;
&lt;li&gt;Texture coordinates (u/v) are uint8_t. There&#39;s no texture filtering either;
everything is nearest-neighbor only.&lt;/li&gt;
&lt;li&gt;OK, so that means you can&#39;t have textures larger than 256x256
(pretty common in that era), but how do you give in the handle to the
texture?&lt;/li&gt;
&lt;li&gt;You don&#39;t, it points directly to the 1024x512 VRAM. You manage yourself
what goes where, remember?&lt;/li&gt;
&lt;li&gt;So can you an only have textures in the top-left 256x256? Hah, no,
we give you a bit-packed “texture page” system that offsets
all your u/v coordinates.&lt;/li&gt;
&lt;li&gt;Most textures are paletted to save VRAM (so instead of 555+1, your
pixels now mean something like “two palette indexes”). Where does the palette live?&lt;/li&gt;
&lt;li&gt;Well, duh, that&#39;s a 256x1 (or 16x1, or whatever) area of VRAM too.
The GPU does not care, you can use another texture&#39;s pixels as a palette if
you feel like it.&lt;/li&gt;
&lt;li&gt;OK, so you said there&#39;s no z, how do you do z-buffering? You have a
z-buffer, right… right?&lt;/li&gt;
&lt;li&gt;Yeah, sure, we&#39;re not cavemen. We have an “ordering table” that is
your Z-buffer, drawn back-to-front. If you want 256 levels of Z,
you just allocate an array of 256 linked-list pointers, and then
you put your polygon into the one corresponding to the correct right Z. &lt;/li&gt;
&lt;li&gt;But, eh, what if my polygon is not completely flat in Z-space?&lt;/li&gt;
&lt;li&gt;Hello?&lt;/li&gt;
&lt;li&gt;Hello…?&lt;/li&gt;
&lt;/ul&gt; </description> 
	<pubDate>Wed, 12 Aug 2026 15:26:00 +0000</pubDate>

</item> 
<item>
	<title>Reproducible Builds: Reproducible Builds summit 2026 to take place in Gothenburg</title>
	<guid>https://reproducible-builds.org/news/2026/08/12/reproducible-builds-summit-in-gothenburg/</guid>
	<link>https://reproducible-builds.org/news/2026/08/12/reproducible-builds-summit-in-gothenburg/</link>
     <description>  &lt;p class=&quot;alert alert-info&quot;&gt;This event is happening soon — see below for registration instructions!&lt;/p&gt;

&lt;p class=&quot;lead&quot;&gt;We are extremely pleased to announce the upcoming Reproducible Builds summit, which will take place from &lt;strong&gt;September 22nd—24th 2026&lt;/strong&gt; in the city of Gothenburg, Sweden.&lt;/p&gt;

&lt;p&gt;This year, we are thrilled to host the tenth edition of this exciting event, following the success of previous summits in various iconic locations around the world, including &lt;a href=&quot;https://reproducible-builds.org/events/vienna2025/&quot;&gt;Vienna&lt;/a&gt; (2025), &lt;a href=&quot;https://reproducible-builds.org/events/hamburg2024/&quot;&gt;Hamburg&lt;/a&gt; (2023—2024), &lt;a href=&quot;https://reproducible-builds.org/events/venice2022/&quot;&gt;Venice&lt;/a&gt; (2022), &lt;a href=&quot;https://reproducible-builds.org/events/Marrakesh2019/&quot;&gt;Marrakesh&lt;/a&gt; (2019), &lt;a href=&quot;https://reproducible-builds.org/events/paris2018/&quot;&gt;Paris&lt;/a&gt; (2018), &lt;a href=&quot;https://reproducible-builds.org/events/berlin2017/&quot;&gt;Berlin&lt;/a&gt; (2017), &lt;a href=&quot;https://reproducible-builds.org/events/berlin2016/&quot;&gt;Berlin&lt;/a&gt; (2016) and &lt;a href=&quot;https://reproducible-builds.org/events/athens2015/&quot;&gt;Athens&lt;/a&gt; (2015).&lt;/p&gt;

&lt;p&gt;If you’re excited about joining us this year, please make sure to read &lt;a href=&quot;https://reproducible-builds.org/events/gothenburg2026/&quot;&gt;the event page which has more details about the event and location&lt;/a&gt;. As in previous years, we will be sending invitations to all those who attended our previous summit events or expressed interest to do so. However, even if you do not receive a personal invitation, please do &lt;a href=&quot;mailto:2026-summit-team@lists.reproducible-builds.org&quot;&gt;email the organizers&lt;/a&gt; and we will find a way to accommodate you.&lt;/p&gt;

&lt;h3 id=&quot;about-the-event&quot;&gt;About the event&lt;/h3&gt;

&lt;p&gt;The Reproducible Builds Summit is a unique gathering that brings together attendees from diverse projects, united by a shared vision of advancing the Reproducible Builds effort. During this enriching event, participants will have the opportunity to engage in discussions, establish connections and exchange ideas to drive progress in this vital field. Our aim is to create an inclusive space that fosters collaboration, innovation and problem-solving.&lt;/p&gt;



&lt;h3 id=&quot;schedule&quot;&gt;Schedule&lt;/h3&gt;

&lt;p&gt;Although the exact content of the meeting will be shaped by the participants, the main goals will include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Update &amp;amp; exchange about the status of reproducible builds in various projects.&lt;/li&gt;
  &lt;li&gt;Improve collaboration both between and inside projects.&lt;/li&gt;
  &lt;li&gt;Expand the scope and reach of reproducible builds to more projects.&lt;/li&gt;
  &lt;li&gt;Work together and hack on solutions.&lt;/li&gt;
  &lt;li&gt;Establish space for more strategic and long-term thinking than is possible in virtual channels.&lt;/li&gt;
  &lt;li&gt;Brainstorm designs on tools enabling users to get the most benefits from reproducible builds.&lt;/li&gt;
  &lt;li&gt;Discuss how reproducible builds will be usable and meaningful to users and developers alike.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logs and minutes will be published after the meeting.&lt;/p&gt;

&lt;h3 id=&quot;location--date&quot;&gt;Location &amp;amp; date&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://clarion-hotel-draken-goteborg.hotelcheckins.com/&quot;&gt;Clarion Hotel Draken&lt;/a&gt;, Olof Palmes Plats 2, 413 30 Göteborg, Sweden. (&lt;a href=&quot;https://www.openstreetmap.org/way/1243458002&quot;&gt;OpenStreetMap&lt;/a&gt;, &lt;a href=&quot;https://maps.app.goo.gl/BBDUEojYcR95jAoc8&quot;&gt;Google Maps&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;September 22nd to September 24th 2026&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;registration-instructions&quot;&gt;Registration instructions&lt;/h3&gt;

&lt;p&gt;Please &lt;a href=&quot;https://reproducible-builds.org/events/gothenburg2026/&quot;&gt;reach out&lt;/a&gt; if you’d like to participate in hopefully interesting, inspiring and intense technical sessions about reproducible builds and beyond!&lt;/p&gt;

&lt;p&gt;We look forward to what we anticipate to be yet another extraordinary event!&lt;/p&gt; </description> 
	<pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Colin Watson: Free software activity in July 2026</title>
	<guid>tag:www.chiark.greenend.org.uk,2026-08-11:/~cjwatson/blog/activity-2026-07.html</guid>
	<link>https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2026-07.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/cjwatson.png&quot; width=&quot;70&quot; height=&quot;82&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;About 95% of my Debian contributions this month were &lt;a href=&quot;https://www.freexian.com/about/debian-contributions/&quot;&gt;sponsored&lt;/a&gt; by Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via &lt;a href=&quot;https://liberapay.com/cjwatson&quot;&gt;Liberapay&lt;/a&gt; or &lt;a href=&quot;https://github.com/sponsors/cjwatson&quot;&gt;GitHub Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;Now that Ubuntu 26.04 &lt;span class=&quot;caps&quot;&gt;LTS&lt;/span&gt; has been released, I’ve been getting back to the &lt;a href=&quot;https://lists.debian.org/debian-devel/2024/04/msg00044.html&quot;&gt;&lt;span class=&quot;caps&quot;&gt;GSS&lt;/span&gt;-&lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; key exchange package split&lt;/a&gt; in our OpenSSH packaging.  Once I started testing my draft &lt;code&gt;openssh-gssapi&lt;/code&gt; source package, I realized that I needed to make some changes in the main &lt;code&gt;openssh&lt;/code&gt; source package first in order to support it.  The dependency from &lt;code&gt;openssh-server&lt;/code&gt; to &lt;code&gt;openssh-client&lt;/code&gt; was awkward, as was the (related) fact that &lt;code&gt;openssh-client&lt;/code&gt; contained shared documentation for other OpenSSH binary packages.  After some thought, I created a new &lt;code&gt;openssh-common&lt;/code&gt; binary package, moved shared documentation and the &lt;code&gt;ssh-keygen&lt;/code&gt; program to that, and dropped dependencies on &lt;code&gt;openssh-client&lt;/code&gt; which were no longer necessary (fixing &lt;a href=&quot;https://bugs.debian.org/699473&quot;&gt;#699473&lt;/a&gt; and &lt;a href=&quot;https://bugs.debian.org/1070098&quot;&gt;#1070098&lt;/a&gt; in the process).&lt;/p&gt;
&lt;p&gt;This caused a couple of regressions (&lt;a href=&quot;https://bugs.debian.org/1141420&quot;&gt;#1141420&lt;/a&gt; and &lt;a href=&quot;https://bugs.debian.org/1141550&quot;&gt;#1141550&lt;/a&gt;) that I had to fix, and more subtly it also caused a number of autopkgtest regressions in other packages because &lt;code&gt;openssh-client&lt;/code&gt; is no longer in base images as a result of a dependency from &lt;code&gt;openssh-server&lt;/code&gt;.  I believe I have fixes for all of these either pending review or merged (one of which I did in August rather than July):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/debian/curl/-/merge_requests/65&quot;&gt;curl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/-/merge_requests/170&quot;&gt;diffoscope&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/debian/glome/-/merge_requests/1&quot;&gt;glome&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/go-team/packages/golang-github-appleboy-easyssh-proxy/-/merge_requests/4&quot;&gt;golang-github-appleboy-easyssh-proxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/debian/parsyncfp2/-/merge_requests/1&quot;&gt;parsyncfp2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/debian/rsync/-/merge_requests/41&quot;&gt;rsync&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I upgraded from 10.3p1 to 10.4p1, and in the process &lt;a href=&quot;https://bugzilla.mindrot.org/show_bug.cgi?id=3974&quot;&gt;contributed a &lt;span class=&quot;caps&quot;&gt;GSS&lt;/span&gt;-&lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; option handling fix upstream&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I made openssh-ssh1’s package description &lt;a href=&quot;https://bugs.debian.org/1123609&quot;&gt;more accurately describe the package&lt;/a&gt;, thanks to suggestions from Matthias Lang.&lt;/p&gt;
&lt;h2&gt;Installer team&lt;/h2&gt;
&lt;p&gt;With support from a Freexian customer, I reviewed, tested, edited, and merged a patch to add &lt;a href=&quot;https://bugs.debian.org/433568&quot;&gt;&lt;span class=&quot;caps&quot;&gt;VLAN&lt;/span&gt; support&lt;/a&gt;.  I described the details of what I did in a &lt;a href=&quot;https://bugs.debian.org/433568#243&quot;&gt;comment&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This has been vaguely on my to-do list since, er, about 2014, so it was very satisfying to get it sorted out.&lt;/p&gt;
&lt;h2&gt;Python packaging&lt;/h2&gt;
&lt;p&gt;New upstream versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cryptodatahub (fixing a &lt;a href=&quot;https://bugs.debian.org/1140974&quot;&gt;build failure&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;dep-logic&lt;/li&gt;
&lt;li&gt;django-q&lt;/li&gt;
&lt;li&gt;flufl.lock&lt;/li&gt;
&lt;li&gt;more-itertools&lt;/li&gt;
&lt;li&gt;multipart&lt;/li&gt;
&lt;li&gt;pyasn1 (fixing &lt;a href=&quot;https://bugs.debian.org/1142388&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-59884, &lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-59885, and &lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-59886&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pytest-rerunfailures&lt;/li&gt;
&lt;li&gt;python-auditwheel&lt;/li&gt;
&lt;li&gt;python-build&lt;/li&gt;
&lt;li&gt;python-certifi&lt;/li&gt;
&lt;li&gt;python-datamodel-code-generator (fixing a &lt;a href=&quot;https://bugs.debian.org/1141004&quot;&gt;build failure&lt;/a&gt;, and an &lt;a href=&quot;https://github.com/koxudaxi/datamodel-code-generator/issues/3578&quot;&gt;incompatibility with pydantic 2.13&lt;/a&gt; that I reported upstream)&lt;/li&gt;
&lt;li&gt;python-django-parler&lt;/li&gt;
&lt;li&gt;python-httplib2&lt;/li&gt;
&lt;li&gt;python-pgbouncer&lt;/li&gt;
&lt;li&gt;python-time-machine&lt;/li&gt;
&lt;li&gt;python-treq&lt;/li&gt;
&lt;li&gt;python-typing-extensions&lt;/li&gt;
&lt;li&gt;python-wheezy.template&lt;/li&gt;
&lt;li&gt;storm&lt;/li&gt;
&lt;li&gt;ubelt&lt;/li&gt;
&lt;li&gt;webpy&lt;/li&gt;
&lt;li&gt;zope.testing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other build/test failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1131792&quot;&gt;django-q: autopkgtest failure with Python 3.14&lt;/a&gt; (&lt;a href=&quot;https://github.com/django-q2/django-q2/issues/334&quot;&gt;reported upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1140980&quot;&gt;httpx: &lt;span class=&quot;caps&quot;&gt;FTBFS&lt;/span&gt;: E assert [(‘uvicorn.ac…1.1 200 &lt;span class=&quot;caps&quot;&gt;OK&lt;/span&gt;”’)] == [(‘httpx’, 20…1.1 200 &lt;span class=&quot;caps&quot;&gt;OK&lt;/span&gt;”’)]&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141778&quot;&gt;libntruprime: autopkgtest failures with Python 3.14&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141791&quot;&gt;pygments: Handle None object before &lt;span class=&quot;caps&quot;&gt;HTML&lt;/span&gt; escaping&lt;/a&gt; (fixed build failures in cmd2, gunicorn, python-inline-snapshot, and python-openapi-core)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142205&quot;&gt;python-authlib: some of tests/flask/test_oauth2/rfc9068/ failed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1140873&quot;&gt;python-click: autopkgtest regression with pytest 9.1&lt;/a&gt; (&lt;a href=&quot;https://github.com/pallets/click/pull/3656&quot;&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141010&quot;&gt;python-httplib2: &lt;span class=&quot;caps&quot;&gt;FTBFS&lt;/span&gt;: &lt;span class=&quot;caps&quot;&gt;ERROR&lt;/span&gt; tests/test_proxy.py - Failed: ‘forked’ not found in &lt;code&gt;markers&lt;/code&gt; configuration option&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143139&quot;&gt;python-maturin: Please upgrade goblin dependency to 0.10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1140692&quot;&gt;python-memray: &lt;span class=&quot;caps&quot;&gt;FTBFS&lt;/span&gt; on armhf (segfault)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141210&quot;&gt;python-mne: &lt;span class=&quot;caps&quot;&gt;FTBFS&lt;/span&gt;: E pytest.PytestRemovedIn10Warning: Passing a non-Collection iterable to parametrize is deprecated&lt;/a&gt; (actually fixed in scikit-learn; &lt;a href=&quot;https://github.com/scikit-learn/scikit-learn/pull/34448&quot;&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142373&quot;&gt;python-softlayer: autopkgtest fails with python3-click 8.3.3&lt;/a&gt; (&lt;a href=&quot;https://github.com/softlayer/softlayer-python/pull/2262&quot;&gt;contributed upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142214&quot;&gt;python-urllib3: &lt;span class=&quot;caps&quot;&gt;FAILED&lt;/span&gt; test/contrib/test_pyopenssl.py&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I fixed some other bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1044278&quot;&gt;django-pipeline: Fails to build source after successful build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1078037&quot;&gt;more-itertools: Please mark python3-more-itertools with M-A: foreign&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I adopted &lt;a href=&quot;https://bugs.debian.org/980407&quot;&gt;transaction&lt;/a&gt; for the Python team.&lt;/p&gt;
&lt;p&gt;I attended the &lt;a href=&quot;https://debconf26.debconf.org/talks/32-debian-python-bof/&quot;&gt;Python BoF&lt;/a&gt; at DebConf remotely, although a badly-timed fibre outage in the village I live in really didn’t help.&lt;/p&gt;
&lt;h2&gt;Code reviews&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142354&quot;&gt;openssh: sshd-session built without crypt(), breaking UsePAM=no password auth&lt;/a&gt; (merged and uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142938&quot;&gt;openssh: Slovak debconf templates translation&lt;/a&gt; (merged and uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1045463&quot;&gt;python-treq: Fails to build source after successful build&lt;/a&gt; (merged and uploaded)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1129141&quot;&gt;python-better-exceptions: &lt;span class=&quot;caps&quot;&gt;FTBFS&lt;/span&gt;: failing tests&lt;/a&gt; (sponsored upload for Seyed Mohamad Amin Modaresi)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141577&quot;&gt;yubihsm-connector: patch to make the build reproducible&lt;/a&gt; (merged and uploaded)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other bits and pieces&lt;/h2&gt;
&lt;p&gt;Dan Poltawski pointed out in a &lt;a href=&quot;https://fedi.talktodan.com/@dan/116982771943815387&quot;&gt;Fediverse post&lt;/a&gt; that the project history didn’t list Sruthi as the current &lt;span class=&quot;caps&quot;&gt;DPL&lt;/span&gt;.  I &lt;a href=&quot;https://salsa.debian.org/publicity-team/debian-history/-/merge_requests/30&quot;&gt;fixed that&lt;/a&gt;, although it doesn’t look as though the fix is in the published version yet.&lt;/p&gt;
&lt;p&gt;I upgraded yubihsm-shell to 2.8.0.&lt;/p&gt; </description> 
	<pubDate>Tue, 11 Aug 2026 10:42:43 +0000</pubDate>

</item> 
<item>
	<title>Bits from Debian: DebConf26 Local Team says goodbye</title>
	<guid>tag:bits.debian.org,2026-08-10:/2026/08/debconf26-words-from-localteam.html</guid>
	<link>https://bits.debian.org/2026/08/debconf26-words-from-localteam.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dwn.png&quot; width=&quot;77&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;On Saturday 25 July 2026, the annual &lt;a href=&quot;https://debconf26.debconf.org/&quot;&gt;Debian Developers and Contributors
Conference&lt;/a&gt; came to a close.  The Debian Press
team would now like to share this personal and beautiful message from the Santa Fe
Local Team.&lt;/p&gt;
&lt;h3&gt;Words from DC26 Local Team&lt;/h3&gt;
&lt;p&gt;DebConf26 is over, and those of us who were part of the Local Team are trying
to return to “normality”, if such a thing exists after organizing a DebConf.&lt;/p&gt;
&lt;p&gt;This event changed our lives and would not have been possible without the help
of many great people.&lt;/p&gt;
&lt;p&gt;We would especially like to thank everyone who became part of our extended
local team. Our endless thanks go to Gunnar —who also instigated this whole
adventure—, Santiago, Nattie, Stefano, and Olasd. Thank you for supporting and
guiding us, sharing your experience, and helping us find solutions throughout
the entire process.&lt;/p&gt;
&lt;p&gt;It was also made possible thanks to the great work, strong support and patience
of international teams: Fundraising, Bursaries, Content, Video, Treasury, Visa,
Website, Accommodation, Front Desk, Cheese and Wine, Publicity as well as all
the other teams and individuals who contributed. We apologize if we have
forgotten to mention anyone; many people helped make this event possible.&lt;/p&gt;
&lt;p&gt;Our deepest thanks also go to everyone who joined us in working on the event,
especially Fer, José, and Julián, who showed great commitment and took
responsibility for several important tasks.&lt;/p&gt;
&lt;p&gt;We would also like to extend our gratitude to FICH, the Universidad Nacional
del Litoral, the institutions, organizations, sponsors, suppliers, and everyone
who contributed in one way or another to welcoming the Debian community to
Santa Fe.&lt;/p&gt;
&lt;p&gt;And finally, a very special thank you to our families, to whom we dedicated
little time these past few weeks, who supported us on this adventure, enduring
the exhaustion, the calls and messages at all hours, and the occasional
stressful situation. Always giving us that much-needed, encouraging hug with so
much love.&lt;/p&gt;
&lt;p&gt;These were very intense weeks, during which we tried to give our best so that
everyone could enjoy their stay and so that the Debian community had the
necessary conditions to meet, work, share knowledge, and continue creating the
magic that characterizes community life and the development of Debian.&lt;/p&gt;
&lt;p&gt;As happens at every DebConf, there were difficulties, unexpected situations,
and challenges that required us to improvise, learn, and perform a few juggling
acts. There were also moments that will certainly remain as memorable
anecdotes: the “antisocial room”, some gas heaters worthy of a museum, and
newly unlocked powers for negotiating with suppliers.&lt;/p&gt;
&lt;p&gt;We have no evidence, but also no doubt, that for many people the Conference
Dinner was one of the best moments of the event.&lt;/p&gt;
&lt;p&gt;A few ingredients we had hoped would happen naturally were missing, such as
more wine nights and at least one in-person football match.&lt;/p&gt;
&lt;p&gt;During the two weeks of DebConf, we experienced every kind of weather and a
wide range of emotions. Above all, however, we saw people enjoying themselves
and building friendships, which fills us with pride.&lt;/p&gt;
&lt;p&gt;Thank you very much to everyone who came and helped DebConf26 leave such a
beautiful mark on our hearts.&lt;/p&gt;
&lt;p&gt;We hope our paths cross again somewhere in life.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Leonardo, Emmanuel, Mariano, Pablo, and Martín
DebConf26 Local Team&lt;/p&gt;
&lt;h3&gt;About Debian&lt;/h3&gt;
&lt;p&gt;The Debian Project was founded in 1993 by Ian Murdock to be a truly free
community project. Since then the project has grown to be one of the
largest and most influential Open Source projects. Thousands of
volunteers from all over the world work together to create and maintain
Debian software. Available in 70 languages, and supporting a huge range
of computer types, Debian calls itself the &lt;em&gt;universal operating system&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;About DebConf&lt;/h3&gt;
&lt;p&gt;DebConf is the Debian Project&#39;s developer conference. In addition to a
full schedule of technical, social and policy talks, DebConf provides an
opportunity for developers, contributors and other interested people to
meet in person and work together more closely. It has taken place
annually since 2000 in locations as varied as Scotland, Bosnia and Herzegovina,
India, Korea, France. More information about DebConf is available from
&lt;a href=&quot;https://debconf.org&quot;&gt;https://debconf.org/&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Contact Information&lt;/h3&gt;
&lt;p&gt;For further information, please visit the DebConf26 web page at
&lt;a href=&quot;https://debconf26.debconf.org/&quot;&gt;https://debconf26.debconf.org/&lt;/a&gt; or send
mail to &lt;a href=&quot;https://bits.debian.org/feeds/mailto:press@debian.org&quot;&gt;press@debian.org&lt;/a&gt;.&lt;/p&gt; </description> 
	<pubDate>Mon, 10 Aug 2026 21:50:00 +0000</pubDate>

</item> 
<item>
	<title>Jonathan Dowland: time-delayed scifi roundup feed</title>
	<guid>https://jmtd.net/log/guardian_scifi_roundup/</guid>
	<link>https://jmtd.net/log/guardian_scifi_roundup/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/jmtd.png&quot; width=&quot;65&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I enjoy reading The Guardian&#39;s monthly round-up of new SF novels, which can be
found in their &lt;a href=&quot;https://www.theguardian.com/books/science-fiction&quot;&gt;Science Fiction
Books&lt;/a&gt; section, and can also
be read via &lt;a href=&quot;https://www.theguardian.com/books/science-fiction/rss&quot;&gt;feed&lt;/a&gt;.
Since the round-up is of new books, at the time the round-up is published
they&#39;re usually only available in hardback.&lt;/p&gt;

&lt;p&gt;When it comes to choosing a book to read, these days I am tending towards
paperbacks: I&#39;ve largely ran out of room for hardbacks. So I decided to apply
a time delay to their feed. Six months is roughly enough that a
book mentioned in a round-up should be shortly available in paperback.&lt;/p&gt;

&lt;p&gt;The first obstacle was that The Guardian only publish roughly the
last six months of articles in their feed, and so the posts I want have
disappeared. However, my Feed Reader
(&lt;a href=&quot;https://www.freshrss.org/&quot;&gt;FreshRSS&lt;/a&gt;) had older copies stored in
its database, and I am able to re-publish those
using &lt;a href=&quot;https://freshrss.github.io/FreshRSS/en/users/user_queries.html&quot;&gt;User Queries&lt;/a&gt;.
(This also gives me an opportunity to filter out non-roundup articles
from the Guardian&#39;s feed).&lt;/p&gt;

&lt;p&gt;It&#39;s then a nice short piece of scripting (this time, using Ruby) to filter the
republished feed on the publication date. To make the most recent articles appear new, I
also modify the metadata for filtered entries to appear 6 months newer than they are.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/usr/bin/ruby
require &#39;rss&#39;

# replace with the user query feed URI
uri       = &#39;https://www.theguardian.com/books/science-fiction/rss&#39;
now       = Time.now
sixMonths = 6 * 30 * 24 * 60 * 60
feed      = RSS::Parser.parse(uri)

feed.items.select! do |item|
  item.date + sixMonths &amp;lt; now
end
feed.items.collect! do |item|
  item.date += sixMonths
  item
end

puts &quot;Content-Type: text/xml\r\n\r&quot;
puts feed
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I stuck that up on my private web server, subscribed to it in my FreshRSS
and voila, a time-delayed list of books to read, most likely available in
paperback.&lt;/p&gt; </description> 
	<pubDate>Mon, 10 Aug 2026 14:44:31 +0000</pubDate>

</item> 
<item>
	<title>Uwe Kleine-König: PGP Keysigning on Linux Plumbers and OpenSource Summit Europe 2026</title>
	<guid>tag:blog.kleine-koenig.org,2026-08-10:/ukl/pgp-keysigning-on-linux-plumbers-and-opensource-summit-europe-2026.html</guid>
	<link>https://blog.kleine-koenig.org/ukl/pgp-keysigning-on-linux-plumbers-and-opensource-summit-europe-2026.html</link>
     <description>  &lt;p&gt;I&#39;m going to this year&#39;s &lt;a href=&quot;https://lpc.events/&quot;&gt;LPC&lt;/a&gt; and &lt;a href=&quot;https://sessionize.com/open-source-summit-europe26&quot;&gt;Open Source Summit
Europe&lt;/a&gt; ðŸ¥³.&lt;/p&gt;
&lt;p&gt;I will organize sessions on two days after the conference program to exchange
PGP fingerprints for keysigning to improve the kernel&#39;s web-of-trust (but of
course everyone is welcome).&lt;/p&gt;
&lt;p&gt;For details see my &lt;a href=&quot;https://lore.kernel.org/lkml/lpcosse2026-keysigning@baylibre.com/&quot;&gt;announcement on
LKML&lt;/a&gt;. Note
the registration deadline at 2026-09-27 08:00 UTC.&lt;/p&gt; </description> 
	<pubDate>Mon, 10 Aug 2026 14:37:00 +0000</pubDate>

</item> 
<item>
	<title>Elana Hashman: Managing virtualenvs with a little bash</title>
	<guid>tag:hashman.ca,2026-08-09:/managing-venvs/</guid>
	<link>https://hashman.ca/managing-venvs/</link>
     <description>  &lt;p&gt;When you need to install something directly from &lt;a href=&quot;https://pypi.org/&quot;&gt;PyPI&lt;/a&gt;, Python virtualenvs have
been my go-to for over a decade.&lt;/p&gt;
&lt;h2&gt;A quick virtualenv intro&lt;/h2&gt;
&lt;p&gt;Most of my readers are probably already familiar with virtualenvs, but for
completeness, I&#39;ll give you a brief introduction. A &lt;a href=&quot;https://docs.python.org/3/library/venv.html&quot;&gt;virtualenv&lt;/a&gt; (short for
&quot;virtual environment&quot;) is an isolated distribution of Python packages, where
you can independently install packages without disturbing your system packages
or other virtualenvs.&lt;/p&gt;
&lt;p&gt;You can set one up like this, assuming you are using Python 3.3 or higher:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;python3&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-m&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;venv&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;~/.venv/my-virtualenv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The directory specified here is just a convention. I keep all my virtualenvs in
the &lt;code&gt;.venv&lt;/code&gt; folder in my home directory, but you can pick whatever location you
like.&lt;/p&gt;
&lt;p&gt;To use the virtualenv, you must activate it:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;~/.venv/my-virtualenv/bin/activate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This activation script is a special shell script that configures your current
shell, pointing at all the right paths in order to use the virtual environment.
&lt;a href=&quot;https://www.gnu.org/software/bash/manual/bash.html#index-_002e&quot;&gt;&lt;code&gt;source&lt;/code&gt;&lt;/a&gt; runs this script in your current shell session to set it
up. You will notice that this adds &lt;code&gt;(my-virtualenv)&lt;/code&gt; to the beginning of your
shell prompt, reminding you that the &quot;my-virtualenv&quot; virtualenv is active. Now
when you &lt;code&gt;pip install amazing-package&lt;/code&gt;, the software will only be available in
this virtual environment.&lt;/p&gt;
&lt;p&gt;When you&#39;re done, you can deactivate it like so:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;deactivate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Wonderful!&lt;/p&gt;
&lt;h2&gt;Managing many virtualenvs gets annoying&lt;/h2&gt;
&lt;p&gt;Over time, I end up accumulating many virtualenvs, which can become harder to
manage. Maybe something like this:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;ls&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;~/.venv/
my-virtualenv&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;cool-project&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;snakes-ahoy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I also don&#39;t want to type &lt;code&gt;source ~/.venv/my-virtualenv/bin/activate&lt;/code&gt; every
time I use the virtualenv, because it gets very repetitive—only the name
of the venv is really needed.&lt;/p&gt;
&lt;p&gt;But luckily, we can write a little bit of bash to make managing this less
annoying. (Or you can use one of many Python developer tools that are designed
to manage this, like &lt;a href=&quot;https://pipx.pypa.io/latest/index.html&quot;&gt;pipx&lt;/a&gt;, but when I merely want to &lt;em&gt;consume&lt;/em&gt; Python
software, I might not have a development environment set up. So that&#39;s beyond
the scope of this post!)&lt;/p&gt;
&lt;p&gt;If you add the following shell function to your &lt;code&gt;~/.bashrc&lt;/code&gt; or
&lt;code&gt;~/.bash_aliases&lt;/code&gt; file, it will nicely wrap our activation command:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;setup-venv&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.venv/&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin/activate&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now all we need to run is&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;setup-venv&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;my-virtualenv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So much quicker!&lt;/p&gt;
&lt;h2&gt;Spicing it up with tab completion&lt;/h2&gt;
&lt;p&gt;The first thing I noticed after writing this wrapper was that I started hitting
tab on the virtual environment name, but... nothing happened. Wouldn&#39;t it be
nice to know what virtualenvs I had available, and to not have to type out the
whole long thing?&lt;/p&gt;
&lt;p&gt;Well, we can write it ourselves 😄&lt;/p&gt;
&lt;p&gt;If for some reason you don&#39;t already have bash completion installed, on a
Debian-based system, you will need to install it with&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;apt&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;install&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;bash-completion
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In order to configure our &lt;a href=&quot;https://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html&quot;&gt;bash completion&lt;/a&gt;, we will create a new file,
&lt;code&gt;/etc/bash_completion.d/venv&lt;/code&gt;, with the following contents:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;_list_venvs&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;local&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;cur&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;prev&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;opts
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COMPREPLY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=()&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COMP_WORDS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[COMP_CWORD]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;prev&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COMP_WORDS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[COMP_CWORD-1]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;find&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;/.venv/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-mindepth&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-maxdepth&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-type&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;d&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-printf&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;%f &quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;COMPREPLY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;compgen&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-W&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;opts&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cur&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;complete&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-F&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;_list_venvs&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;setup-venv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This file defines another shell function order to determine how to
autocomplete the options for our &lt;code&gt;setup-venv&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$opts&lt;/code&gt; is where we define the options for our function. We generate it with a
&lt;code&gt;find&lt;/code&gt; command—looking at the &lt;code&gt;.venv&lt;/code&gt; folder in the current user&#39;s home
directory, then only including child folders (excluding the current directory
itself, &lt;code&gt;.venv&lt;/code&gt;, in our results) by using the min/max depth and type arguments,
and printing just the individual directory names, deliminated by spaces using
our print formatter.&lt;/p&gt;
&lt;p&gt;Everything else is the standard scaffolding required to use bash completions.&lt;/p&gt;
&lt;p&gt;Once you save this file and reload your shell, you&#39;ll see that you are able to use completions as expected!&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;setup-venv&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&amp;lt;tab&amp;gt;
my-virtualenv&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;cool-project&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;snakes-ahoy

setup-venv&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;s&amp;lt;tab&amp;gt;
setup-venv&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;snakes-ahoy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Complaints, comments, questions?&lt;/h2&gt;
&lt;p&gt;Hope this was helpful! If it wasn&#39;t, that&#39;s too bad. But don&#39;t worry—you
can safely ignore this post.&lt;/p&gt; </description> 
	<pubDate>Sun, 09 Aug 2026 20:00:00 +0000</pubDate>

</item> 
<item>
	<title>Reproducible Builds: Reproducible Builds in July 2026</title>
	<guid>https://reproducible-builds.org/reports/2026-07/</guid>
	<link>https://reproducible-builds.org/reports/2026-07/</link>
     <description>  &lt;p class=&quot;lead&quot;&gt;&lt;strong&gt;Welcome to the July 2026 report from the &lt;a href=&quot;https://reproducible-builds.org&quot;&gt;Reproducible Builds&lt;/a&gt; project!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://reproducible-builds.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/reproducible-builds.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our reports, we try to outline the most important things that we have been up to over the past month. As a quick recap about what problem our project intends to solve, whilst anyone may inspect the source code of free software for malicious flaws, almost all software is distributed to end users as pre-compiled binaries. The motivation behind the reproducible builds effort is to ensure no flaws have been introduced during this compilation process by promising identical results are always generated from a given source, thus allowing multiple third-parties to come to a consensus on whether a build was compromised or not.&lt;/p&gt;

&lt;p&gt;If you are interested in contributing to the project, please visit the &lt;a href=&quot;https://reproducible-builds.org/contribute/&quot;&gt;&lt;em&gt;Contribute&lt;/em&gt;&lt;/a&gt; page on our website.&lt;/p&gt;

&lt;p&gt;In this month’s report, we cover:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#tool-development&quot;&gt;Tool development&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#distribution-work&quot;&gt;Distribution work&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#three-new-scholarly-papers&quot;&gt;Three new scholarly papers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#patches&quot;&gt;Patches&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#misc-news&quot;&gt;Misc news&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;tool-development&quot;&gt;Tool development&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://diffoscope.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/diffoscope.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://diffoscope.org&quot;&gt;&lt;strong&gt;diffoscope&lt;/strong&gt;&lt;/a&gt; is our in-depth and content-aware diff utility that can locate and diagnose reproducibility issues. This month, Chris Lamb made the following changes, including preparing and uploading versions &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;324&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;325&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;326&lt;/code&gt; to Debian:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Fix tests to work with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zipdetails&lt;/code&gt; 4.0008. (&lt;a href=&quot;https://bugs.debian.org/1141359&quot;&gt;#1141359&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Bump debhelper compatibility level to 13. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/474f3702&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
  &lt;li&gt;Update copyright years. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/4cde19a5&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition, Paul Spooren made changes to allow trailing garbage in Gzip files [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/c8dcbf4a&quot;&gt;…&lt;/a&gt;] and Vagrant Cascadian added an external tool reference for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pedump&lt;/code&gt; binary to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mono&lt;/code&gt; package under &lt;a href=&quot;https://guix.gnu.org/&quot;&gt;GNU Guix&lt;/a&gt;. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/b79afa9e&quot;&gt;…&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/disorderfs&quot;&gt;&lt;strong&gt;disorderfs&lt;/strong&gt;&lt;/a&gt; is our &lt;a href=&quot;https://en.wikipedia.org/wiki/Filesystem_in_Userspace&quot;&gt;FUSE&lt;/a&gt;-based filesystem that deliberately introduces non-determinism into system calls to reliably flush out reproducibility issues. This month, Christelle Gloor added the option to sort by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ctime&lt;/code&gt; as returned by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lstat(2)&lt;/code&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/System_call&quot;&gt;syscall&lt;/a&gt;. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/disorderfs/commit/68d20f7&quot;&gt;…&lt;/a&gt;], which Chris Lamb uploaded whilst bumping the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Standards-Version&lt;/code&gt; to version 4.7.4 [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/disorderfs/commit/240fae0&quot;&gt;…&lt;/a&gt;]. Bernhard Wiedemann also &lt;a href=&quot;https://build.opensuse.org/request/show/1368149&quot;&gt;updated &lt;em&gt;disorderfs&lt;/em&gt; to version 0.7.0&lt;/a&gt; in &lt;a href=&quot;https://www.opensuse.org/&quot;&gt;openSUSE&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://reproducible-builds.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/website.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yet again, there were a number of improvements made to &lt;a href=&quot;https://reproducible-builds.org/&quot;&gt;&lt;strong&gt;our website&lt;/strong&gt;&lt;/a&gt; this month as well. For example, Chris Lamb, by request of &lt;a href=&quot;https://www.digitalocean.com/&quot;&gt;Digital Ocean&lt;/a&gt;, changed the target of a referral link so that they can manage incoming referrers [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/4ac1b2fa&quot;&gt;…&lt;/a&gt;] and pushed a number of changes to the &lt;a href=&quot;https://reproducible-builds.org/tools/&quot;&gt;&lt;em&gt;Tools&lt;/em&gt;&lt;/a&gt; page [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/3e3154f2&quot;&gt;…&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;distribution-work&quot;&gt;Distribution work&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://debian.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/debian.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Debian&lt;/strong&gt; this month, 32 reviews of Debian packages were added, 26 were updated and a total of 21 were removed this month, adding to &lt;a href=&quot;https://tests.reproducible-builds.org/debian/index_issues.html&quot;&gt;our extensive knowledge about identified issues&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A number of issue types were added by Chris Lamb, including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python_towncrier_build_date&lt;/code&gt; [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-notes/commit/83a0efd3&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-notes/commit/6f036b2a&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;log_files_installed_in_package&lt;/code&gt; [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-notes/commit/c629afdf&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fontforge_varies_by_timezone&lt;/code&gt; [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-notes/commit/d76c0f05&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-notes/commit/fc4a9fc5&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Chris also added a further note for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_date_in_manpage_generated_by_spf13_cobra&lt;/code&gt; issue. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-notes/commit/f7b69082&quot;&gt;…&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://openwrt.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/openwrt.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition, there is &lt;a href=&quot;https://rebuilderd.n.aparcar.org/?distro=openwrt-image&quot;&gt;a new page showing verification rebuilds&lt;/a&gt; of &lt;a href=&quot;https://openwrt.org/&quot;&gt;OpenWrt&lt;/a&gt; APK packages and firmware images, powered by &lt;a href=&quot;https://github.com/kpcyrd/rebuilderd&quot;&gt;&lt;em&gt;rebuilderd&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://rebuilderd.n.aparcar.org/?distro=openwrt-image&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/openwrt-rebuilderd.png#center&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.opensuse.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/opensuse.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, Bernhard M. Wiedemann posted another &lt;a href=&quot;https://www.opensuse.org/&quot;&gt;&lt;strong&gt;openSUSE&lt;/strong&gt;&lt;/a&gt; &lt;a href=&quot;https://lists.opensuse.org/archives/list/factory@lists.opensuse.org/thread/JLAOJP7W6K3P2SL6XT6UYX444XZ5WQPN/&quot;&gt;monthly update&lt;/a&gt; for their reproducibility work there.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;three-new-scholarly-papers&quot;&gt;Three new scholarly papers&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://ieeexplore.ieee.org/abstract/document/11593337&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/paper-vcaligner.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yan Li, Nan Jiang, Qihang Zhou, Shaowen Xu, Yamin Xie and Xiaoqi Jia of the &lt;a href=&quot;https://english.cas.cn/&quot;&gt;Chinese Academy of Sciences&lt;/a&gt; published a paper titled &lt;a href=&quot;https://ieeexplore.ieee.org/abstract/document/11593337&quot;&gt;&lt;em&gt;VCAligner: Aligning Source Distribution Versions with Upstream Git Commits to Secure Supply Chain&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We present VCAligner, a content-based alignment methodology that constructs inverted indexes over VCS histories to precisely map released artifacts to their originating commits, independent of fragile version tags. We evaluated VCAligner on a dataset of 2,984 verifiable PyPI packages derived from the 4,000 most-downloaded projects linked to public GitHub upstreams. &lt;strong&gt;Our results reveal a critical weakness in conventional tag-based heuristics: while they appear effective on 85% of the dataset, the residual 15% failure rate generates a catastrophic downstream audit workload of over 10.3 million commits. In contrast, VCAligner reduces this burden by two orders of magnitude (≈ 158×), bounding the total workload to under 65,000 commits.&lt;/strong&gt; Furthermore, we provide the large-scale characterization of “Packaging Noise,” classifying artifact divergence into structural additions (Path Phantoms) and content mutations (Blob Phantoms), thereby isolating the distinct attack surfaces of malicious injection and code tampering.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://doi.org/10.48550/ARXIV.2607.21888&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/paper-snakeoil.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jens Dietrich and Spencer Sun from the &lt;a href=&quot;https://www.wgtn.ac.nz/&quot;&gt;Victoria University of Wellington&lt;/a&gt; together with Tim W. White and Behnaz Hassanshahi from &lt;a href=&quot;https://www.oracle.com&quot;&gt;Oracle Inc&lt;/a&gt; pre-published their paper &lt;a href=&quot;https://arxiv.org/pdf/2607.21888&quot;&gt;&lt;em&gt;No Snake Oil: Verifying Python Package Builds&lt;/em&gt;&lt;/a&gt; (PDF):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Python has become the default language for interacting with AI, with packages being distributed through registries like the Python Package Index (PyPI). This creates a need to analyse supply chains comprising such packages. One such analysis is to rebuild packages in order to identify compromised builds injecting malware. Independent rebuilds in hardened environments have the added advantage that they can generate and record provenance in order to increase the trustworthiness of packages. Two tools that are designed to automate such rebuilds and run them at scale are macaron and oss-rebuild. We study 12,180 popular releases from PyPI and find that the byte-for-byte equivalence rate is generally low. We analyse the reasons why they produce different wheels, and find that equivalence between the original and rebuilt wheels can often still be established, preserving most of the guarantees users expect from rebuildable releases. We present and evaluate daleq4py, a tool to establish the equivalence of Python wheels through the kernel of a normalisation function that is based on provenance-preserving datalog rules. Experimental results show that daleq4py substantially expands the set of rebuilds that can be accepted as equivalent. &lt;strong&gt;Although only 15.4% of macaron rebuilds and 19.1% of oss-rebuild rebuilds are byte-for-byte identical to the published PyPI wheels, daleq4py establishes wheel equivalence for 60.2% and 78.9% of source-equivalent rebuilds, respectively.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/2607.01890&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-07/paper-fdroid.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Denise Nanni, Julien Malka, Stefano Zacchiroli and Théo Zimmermann from &lt;a href=&quot;https://www.telecom-paris.fr/en/home&quot;&gt;Télécom Paris&lt;/a&gt; together with Gabriele D’Angelo from the &lt;a href=&quot;https://www.unibo.it/en/homepage&quot;&gt;University of Bologna&lt;/a&gt; pre-published their paper &lt;a href=&quot;https://arxiv.org/pdf/2607.01890&quot;&gt;&lt;em&gt;Understanding Build Reproducibility in the F-Droid Ecosystem&lt;/em&gt;&lt;/a&gt; (PDF), which was accepted at the &lt;a href=&quot;https://acm-rep.github.io/2026/accepted/&quot;&gt;2026 ACM Conference on Reproducibility and Replicability&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The security of open source applications benefits considerably from the possibility of rebuilding their source and verifying the output. F-Droid, a prominent distribution for open source Android applications, systematically rebuilds them from source and tests their bitwise reproducibility at app publishing time. However, F-Droid offers no guarantee that app reproducibility will continue to hold in the future. As software ecosystems evolve, reproducibility may degrade, with potential negative consequences for software preservation and security. We present the first empirical study of build reproducibility in the F-Droid app ecosystem. Analyzing historical reproducibility logs, we find that the overall bitwise reproducibility rate has been steadily increasing over time (as new versions of apps are published). We then evaluate how reproducibility holds in time for fixed app versions, by attempting to rebuild 18 904 app versions that F-Droid had previously confirmed bitwise reproducible, published between September 2018 and February 2026, &lt;strong&gt;achieving an 83% rebuild success rate, and identify missing dependencies as the dominant cause of failure, accounting for 76% of non-rebuildable cases. Among successfully rebuilt apps, 94% are also bitwise reproducible&lt;/strong&gt;-i.e., they still yield bitwise identical artifacts upon rebuild. Together, these results show that while bitwise reproducibility largely holds for apps that can be rebuilt, rebuildability itself is highly sensitive to temporal decay.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;patches&quot;&gt;Patches&lt;/h3&gt;

&lt;p&gt;The Reproducible Builds project detects, dissects and attempts to fix as many currently-unreproducible packages as possible. We endeavour to send all of our patches upstream where applicable or possible. This month, we wrote a large number of such patches, including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Arnout Engelen:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/apache/ant-ivy/pull/127&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ivy&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/apache/pekko-grpc/pull/746&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pekko-grpc&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/sbt/ivy/pull/51&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sbt-ivy&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/scala/scala3/pull/26510&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scala&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Bernhard M. Wiedemann:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1364030&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;angelfish&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/python/cpython/pull/154988&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cpython&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://git.enlightenment.org/enlightenment/efl/pulls/133&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;efl&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/erlang/otp/issues/4417#issuecomment-5105267295&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;erlang+ex_doc&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1368578&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eww/glib-macros&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/intel/intel-graphics-compiler/pull/418&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intel-graphics-compiler&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1368181&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java-11-openjdk&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1368181&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java-17-openjdk&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1368504&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java-1_8_0-openjdk&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugzilla.opensuse.org/show_bug.cgi?id=1221224&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;java-21-openjdk&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://gitlab.winehq.org/mono/mono/-/work_items/33&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mono-core&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/medek/nasm-rs/pull/47&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nasm/rav1e&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1364286&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-langsmith&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1364231&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zathura*&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1368243&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zig0.15&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Chris Lamb:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141505&quot;&gt;#1141505&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/golang-github-tidwall-wal&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;golang-github-tidwall-wal&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141506&quot;&gt;#1141506&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/lightproof&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lightproof&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141582&quot;&gt;#1141582&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/libslow5lib&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libslow5lib&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141687&quot;&gt;#1141687&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/siso&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;siso&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141841&quot;&gt;#1141841&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/grout&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grout&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142126&quot;&gt;#1142126&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/libpsl&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libpsl&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142492&quot;&gt;#1142492&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/node-grunt-contrib-internal&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node-grunt-contrib-internal&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142495&quot;&gt;#1142495&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/fontforge&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fontforge&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142496&quot;&gt;#1142496&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/spopt&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spopt&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142887&quot;&gt;#1142887&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/go-dlib&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go-dlib&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143147&quot;&gt;#1143147&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/towncrier&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;towncrier&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Jochen Sprickerhof:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141412&quot;&gt;#1141412&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/python-sphinx-chango&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-sphinx-chango&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141553&quot;&gt;#1141553&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/gasnet&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gasnet&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141577&quot;&gt;#1141577&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/yubihsm-connector&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yubihsm-connector&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1141663&quot;&gt;#1141663&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/dh-fortran&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dh-fortran&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142000&quot;&gt;#1142000&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/watcher&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;watcher&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142001&quot;&gt;#1142001&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/rakudo&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rakudo&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142128&quot;&gt;#1142128&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/kf6-breeze-icons&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kf6-breeze-icons&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142141&quot;&gt;#1142141&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/oxygen-icons&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oxygen-icons&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142256&quot;&gt;#1142256&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/gnu-apl&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gnu-apl&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1142513&quot;&gt;#1142513&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/barvinok&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;barvinok&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1143169&quot;&gt;#1143169&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/ecbuild&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ecbuild&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;misc-news&quot;&gt;Misc news&lt;/h3&gt;

&lt;p&gt;On &lt;a href=&quot;https://lists.reproducible-builds.org/listinfo/rb-general/&quot;&gt;our mailing list&lt;/a&gt; this month, Colin Winter of &lt;a href=&quot;https://markovianprotocol.com/&quot;&gt;Markovian Protocol&lt;/a&gt; wrote to our mailing list on the topic of &lt;a href=&quot;https://lists.reproducible-builds.org/pipermail/rb-general/2026-July/004133.html&quot;&gt;&lt;em&gt;Reproducible verification for retained logs&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Reproducible builds remove trust in the builder: anyone re-derives the same artifact from the same source, byte for byte. The same shape applies one layer over, to a retained record. Most record-keeping regimes (the &lt;a href=&quot;https://artificialintelligenceact.eu/article/12/&quot;&gt;EU AI Act’s Article 12&lt;/a&gt; logging is the current example) require that events be recorded and logs retained, but not that a retained log be verifiable, by a party who was not present, as unaltered and existing when claimed. That leaves an integrity obligation resting on trusting the party being audited.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(&lt;a href=&quot;https://lists.reproducible-builds.org/pipermail/rb-general/2026-July/thread.html#4133&quot;&gt;Full thread&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;Finally, if you are interested in contributing to the Reproducible Builds project, please visit our &lt;a href=&quot;https://reproducible-builds.org/contribute/&quot;&gt;&lt;em&gt;Contribute&lt;/em&gt;&lt;/a&gt; page on our website. However, you can get in touch with us via:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;IRC: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#reproducible-builds&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irc.oftc.net&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mastodon: &lt;a href=&quot;https://fosstodon.org/@reproducible_builds&quot;&gt;@reproducible_builds@fosstodon.org&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mailing list: &lt;a href=&quot;https://lists.reproducible-builds.org/listinfo/rb-general&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rb-general@lists.reproducible-builds.org&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt; </description> 
	<pubDate>Sun, 09 Aug 2026 19:12:10 +0000</pubDate>

</item> 
</channel>
</rss>
