<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Arnaud Gourlay&#x27;s blog</title>
    <subtitle>Yet another programming blog</subtitle>
    <link rel="self" type="application/atom+xml" href="https://agourlay.github.io/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://agourlay.github.io"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-09-06T00:00:00+00:00</updated>
    <id>https://agourlay.github.io/atom.xml</id>
    <entry xml:lang="en">
        <title>Pinch Points - a Rust game with crabs</title>
        <published>2026-09-06T00:00:00+00:00</published>
        <updated>2026-09-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/pinch-points-a-rust-game-with-crabs/"/>
        <id>https://agourlay.github.io/pinch-points-a-rust-game-with-crabs/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/pinch-points-a-rust-game-with-crabs/">&lt;p&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;pinch-points&quot;&gt;Pinch Points&lt;&#x2F;a&gt; is a kid-friendly routing game for 1-6 players, built in Rust with Bevy.&lt;&#x2F;p&gt;
&lt;p&gt;In this game, players compete to save the most crabs by routing them to their respective castles.&lt;&#x2F;p&gt;
&lt;p&gt;Check out what it looks like!&lt;&#x2F;p&gt;
&lt;p&gt;
    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2026-09-06&amp;#x2F;menu.png&quot;
         alt=&quot;Game menu&quot;
        
        
    &gt;
    
    &lt;figcaption&gt;&lt;p&gt;A nice home menu&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;


    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2026-09-06&amp;#x2F;versus.png&quot;
         alt=&quot;Versus mode&quot;
        
        
    &gt;
    
    &lt;figcaption&gt;&lt;p&gt;The main versus mode, with multiplayer support&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;


    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2026-09-06&amp;#x2F;puzzles.png&quot;
         alt=&quot;Puzzles&quot;
        
        
    &gt;
    
    &lt;figcaption&gt;&lt;p&gt;And 100 puzzles to solve&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;You can install it from:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;pinch-points&#x2F;releases&quot;&gt;prebuilt binaries&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;crates.io&lt;&#x2F;code&gt; with &lt;code&gt;cargo install --locked pinch-points&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The rest of the post is not the usual technical deep-dive article found on this blog.&lt;&#x2F;p&gt;
&lt;p&gt;Rather, it is my experience using &lt;strong&gt;AI&lt;&#x2F;strong&gt; to create a video game and what I learned in the process.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;a class=&quot;zola-anchor&quot; href=&quot;#motivation&quot; aria-label=&quot;Anchor link for: motivation&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The game is based on the mechanics of &lt;code&gt;ChuChuRocket!&lt;&#x2F;code&gt; developed by Sonic Team and released in 1999 on the Dreamcast.&lt;&#x2F;p&gt;
&lt;p&gt;In this game, up to four players compete to save mice from cats by guiding them into their rockets by placing arrows on a board.&lt;&#x2F;p&gt;
&lt;p&gt;
    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2026-09-06&amp;#x2F;chuchu-cover.jpg&quot;
         alt=&quot;Game Cover&quot;
        
        
    &gt;
    
    &lt;figcaption&gt;&lt;p&gt;An iconic game cover for the Dreamcast&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;


    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2026-09-06&amp;#x2F;chuchu-game.jpg&quot;
         alt=&quot;Game mode&quot;
        
        
    &gt;
    
    &lt;figcaption&gt;&lt;p&gt;The main game mode&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;I was very fond of this game as a teenager; the gameplay is fast and so simple that everyone gets it and has fun.&lt;&#x2F;p&gt;
&lt;p&gt;As a programmer, I always thought that I could try to create something with similar gameplay while adding a few twists to modernize it and spice things up.&lt;&#x2F;p&gt;
&lt;p&gt;First, the theme: no more mice and cats in space. Given how much I like Rust, I wanted to make it about crabs!&lt;&#x2F;p&gt;
&lt;p&gt;I had a clear idea for the theme and the changes I wanted to make. This led me to think that creating this game could be a well-scoped task to gain experience with AI code generation.&lt;&#x2F;p&gt;
&lt;p&gt;After iterating on a specification document, I handed it over to &lt;code&gt;Claude Code&lt;&#x2F;code&gt; with Opus 5 and experienced the magic of generative coding firsthand.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ai-iterations&quot;&gt;AI iterations&lt;a class=&quot;zola-anchor&quot; href=&quot;#ai-iterations&quot; aria-label=&quot;Anchor link for: ai-iterations&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The first iteration took around an hour and was, retrospectively, by far the biggest productivity gain.
All the boilerplate required to bootstrap the project and wire things together. The basic structure of the game was there; at first I was very satisfied.&lt;&#x2F;p&gt;
&lt;p&gt;At this point, however, the game was far from being done, because my specifications were not precise enough.&lt;&#x2F;p&gt;
&lt;p&gt;What followed was a long and somewhat tedious process of going back and forth to implement certain things exactly as I wanted.&lt;&#x2F;p&gt;
&lt;p&gt;As expected, I did not know exactly what I wanted until I started playing the game myself!&lt;&#x2F;p&gt;
&lt;p&gt;Not only were there a &lt;strong&gt;lot&lt;&#x2F;strong&gt; of bugs to fix, but new changes would often break things elsewhere in the game.&lt;&#x2F;p&gt;
&lt;p&gt;While the coding agent was excellent at performing localized tasks, it was simply not good at preserving the global consistency of the game!&lt;&#x2F;p&gt;
&lt;p&gt;For this reason, I started putting constant pressure on the agent to improve code quality.&lt;&#x2F;p&gt;
&lt;p&gt;An easy first step is to look at code coverage to guide the generation of missing unit tests.&lt;&#x2F;p&gt;
&lt;p&gt;This helps prevent regressions but it is not enough to improve code quality.&lt;&#x2F;p&gt;
&lt;p&gt;After checking the code superficially, I would find myself repeatedly asking for:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;splitting large non-cohesive files&lt;&#x2F;li&gt;
&lt;li&gt;splitting large structs&lt;&#x2F;li&gt;
&lt;li&gt;introducing missing enums to replace fragile if&#x2F;else cascades&lt;&#x2F;li&gt;
&lt;li&gt;adding debug assertions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The quality would slowly increase but it required regular attention.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;end-result&quot;&gt;End result&lt;a class=&quot;zola-anchor&quot; href=&quot;#end-result&quot; aria-label=&quot;Anchor link for: end-result&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;To be honest, I have mixed feelings about this experience.&lt;&#x2F;p&gt;
&lt;p&gt;On one hand, I am pretty satisfied with the game, I find it fun, and I&#x27;ve received some good feedback.&lt;&#x2F;p&gt;
&lt;p&gt;On the other hand, I am not satisfied with the creative process and that is not because AI is bad.&lt;&#x2F;p&gt;
&lt;p&gt;Quite the opposite: in many coding tasks, I found it surprisingly capable.&lt;&#x2F;p&gt;
&lt;p&gt;My main issues are related to ownership and mastery.&lt;&#x2F;p&gt;
&lt;p&gt;Although I precisely specified every aspect of the game through &lt;strong&gt;many&lt;&#x2F;strong&gt; playtests, I still feel like I do not own this game.&lt;&#x2F;p&gt;
&lt;p&gt;What I do have is a 50 KLOC codebase whose internals I don&#x27;t fully understand — unlike my other side projects, which I have crafted with care.&lt;&#x2F;p&gt;
&lt;p&gt;You got the thing you asked for, but because you didn&#x27;t build it yourself, you don&#x27;t feel that it is truly yours.&lt;&#x2F;p&gt;
&lt;p&gt;As the saying goes, &quot;Be careful what you wish for!&quot;&lt;&#x2F;p&gt;
&lt;p&gt;In any case, the game exists now, so you might as well enjoy it.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The transmission</title>
        <published>2026-05-03T00:00:00+00:00</published>
        <updated>2026-05-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/the-transmission/"/>
        <id>https://agourlay.github.io/the-transmission/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/the-transmission/">&lt;p&gt;&lt;em&gt;Tractors, beige boxes and what&#x27;s next&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My father was very fond of tractors.&lt;&#x2F;p&gt;
&lt;p&gt;He would never miss an occasion to stop for any tractor we came across on holidays, at a fair or an agricultural museum.&lt;&#x2F;p&gt;
&lt;p&gt;His eyes would light up and he would start commenting on the particular models in front of us.&lt;&#x2F;p&gt;
&lt;p&gt;As a kid I understood to some degree that tractors were special to my father, but it took me much longer to really understand why.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-father&quot;&gt;The father&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-father&quot; aria-label=&quot;Anchor link for: the-father&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;My father was born in the late 1940s in a small village deep in the French countryside.
Farming was the main activity for most people in such villages.&lt;&#x2F;p&gt;
&lt;p&gt;Having access to a tractor was a big deal at the time. The mechanization of work marked the arrival of modernity.&lt;&#x2F;p&gt;
&lt;p&gt;One day your parents are working outside with horses, the next day the animals could be sold off because this new loud machine had arrived to get things done much faster.&lt;&#x2F;p&gt;
&lt;p&gt;My father told stories of driving Massey-Ferguson tractors as a kid and I remember being quite jealous at the time.
I&#x27;d only get to pretend to drive at those agricultural fairs, standing on the clutch and gripping the massive wheel.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2026-05-03&amp;#x2F;massey-ferguson-35.jpg&quot;
         alt=&quot;Massey-Ferguson 35 Deluxe tractor&quot;
        
        
    &gt;
    
    &lt;figcaption&gt;&lt;p&gt;Massey-Ferguson 35 Deluxe. &lt;br&gt; Photo: &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;User:Acroterion&quot;&gt;Acroterion&lt;&#x2F;a&gt;, &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;4.0&#x2F;&quot;&gt;CC BY-SA 4.0&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Comfortable around machines, he enrolled in a trade school in the 1960s where he eventually discovered the world of analog electronics.&lt;&#x2F;p&gt;
&lt;p&gt;He graduated and landed a job repairing large industrial and medical equipment.
Think large expensive objects that customers are definitely not happy to see standing still.&lt;&#x2F;p&gt;
&lt;p&gt;Troubleshooting complex machines all day, he ended up fixing everything at home too.
I remember the scenes: him under the car, the TV cracked open with its tube exposed in the living room, the washing machine sitting drumless on the kitchen floor.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-boy&quot;&gt;The boy&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-boy&quot; aria-label=&quot;Anchor link for: the-boy&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;When I was around 13 years old, my father brought home a large beige box from Hewlett-Packard.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2026-05-03&amp;#x2F;hp-workstation.jpg&quot;
         alt=&quot;HP beige tower workstation&quot;
        
        
    &gt;
    
    &lt;figcaption&gt;&lt;p&gt;Tractor for millennials. &lt;br&gt; Photo: Thomas Schanz, &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;4.0&#x2F;&quot;&gt;CC BY-SA 4.0&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;That Pentium II running at 233 MHz was rather high-end for the time.&lt;&#x2F;p&gt;
&lt;p&gt;In the pre-Internet era, I used it mostly for gaming and homework thanks to educational programs like Encarta.&lt;&#x2F;p&gt;
&lt;p&gt;The first time I looked inside the box was when my father upgraded to a larger hard drive.
I realized a computer was just the sum of its parts.&lt;&#x2F;p&gt;
&lt;p&gt;The family computer got bricked a few times after I messed with DLLs and the Windows registry. To get me off it, my father gave me an old computer he had salvaged from the street.&lt;&#x2F;p&gt;
&lt;p&gt;I got it to work after re-installing Windows 95 — child&#x27;s play.&lt;&#x2F;p&gt;
&lt;p&gt;Computer technology was moving very fast back then. People would leave entire computers on the curb because the new ones were so much better.&lt;&#x2F;p&gt;
&lt;p&gt;My father had noticed my interest early on, so he kept bringing home abandoned desktops to keep me busy.
From those, I would salvage the best parts into my Frankenstein build, swapping components and operating systems.&lt;&#x2F;p&gt;
&lt;p&gt;At some point, I had a plastic bag full of AMD Athlon CPUs that no one seemed to want.&lt;&#x2F;p&gt;
&lt;p&gt;Then the Internet arrived. I got a new computer and turned my Frankenstein build into a multimedia player.&lt;&#x2F;p&gt;
&lt;p&gt;In high school I was that guy burning CDs and fixing my friends&#x27; computers.&lt;&#x2F;p&gt;
&lt;p&gt;Gaming led to tinkering with hardware, and from there to programming.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-son&quot;&gt;The son&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-son&quot; aria-label=&quot;Anchor link for: the-son&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;A few years back, I took my son to a technology museum.&lt;&#x2F;p&gt;
&lt;p&gt;I showed him a beige box under glass and explained how cool it was back in the day.&lt;&#x2F;p&gt;
&lt;p&gt;He was unimpressed and ran off to see the racing cars section.&lt;&#x2F;p&gt;
&lt;p&gt;I can&#x27;t really blame him, the exhibit was underwhelming.&lt;&#x2F;p&gt;
&lt;p&gt;But at that very moment, I caught myself looking at it the way my father had looked at those tractors.&lt;&#x2F;p&gt;
&lt;p&gt;This was the transmission: curiosity passed from one generation to the next.&lt;&#x2F;p&gt;
&lt;p&gt;Beyond the technology itself, it was about tools you could take apart.&lt;&#x2F;p&gt;
&lt;p&gt;But what are the tractors and beige boxes for this generation?&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2026-05-03&amp;#x2F;jojo-builds.jpeg&quot;
         alt=&quot;Child hands building with tools&quot;
        
        
    &gt;
    
    &lt;figcaption&gt;&lt;p&gt;My son building. &lt;br&gt; Photo: me&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;My father&#x27;s passion for repair was a product of his era. That attitude is mostly gone.
Modern appliances aren&#x27;t built to be opened, and when something breaks, you call someone or replace it.&lt;&#x2F;p&gt;
&lt;p&gt;And yet, my son binges educational shows, loves all kinds of building toys and asks unfiltered questions about how the world works.&lt;&#x2F;p&gt;
&lt;p&gt;The curiosity is there. Now I have to figure out what to bring home.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>New Key-Value Store in Rust at Qdrant</title>
        <published>2025-02-10T00:00:00+00:00</published>
        <updated>2025-02-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/qdrant-new-kv-storage/"/>
        <id>https://agourlay.github.io/qdrant-new-kv-storage/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/qdrant-new-kv-storage/">&lt;p&gt;I have been working at &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;qdrant&#x2F;qdrant&quot;&gt;Qdrant&lt;&#x2F;a&gt; for a while now, where I get the opportunity to work on very interesting problems.&lt;&#x2F;p&gt;
&lt;p&gt;This article is an &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;qdrant.tech&#x2F;articles&#x2F;gridstore-key-value-storage&#x2F;&quot;&gt;external publication&lt;&#x2F;a&gt; regarding my latest contributions to a new key-value storage engine specialized for our needs.&lt;&#x2F;p&gt;
&lt;p&gt;The storage is not yet available as a standalone crate for the moment; in the meantime, there are a few pointers to get started reading the code for the curious.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the Gridstore code &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;qdrant&#x2F;qdrant&#x2F;tree&#x2F;dev&#x2F;lib&#x2F;gridstore&quot;&gt;internal crate&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;usage for &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;qdrant&#x2F;qdrant&#x2F;blob&#x2F;dev&#x2F;lib&#x2F;segment&#x2F;src&#x2F;payload_storage&#x2F;mmap_payload_storage.rs&quot;&gt;payload storage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;usage for &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;qdrant&#x2F;qdrant&#x2F;blob&#x2F;dev&#x2F;lib&#x2F;segment&#x2F;src&#x2F;vector_storage&#x2F;sparse&#x2F;mmap_sparse_vector_storage.rs&quot;&gt;sparse vector storage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Playing guitar tablatures in Rust</title>
        <published>2024-07-14T00:00:00+00:00</published>
        <updated>2024-07-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/ruxguitar-tablature-player/"/>
        <id>https://agourlay.github.io/ruxguitar-tablature-player/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/ruxguitar-tablature-player/">&lt;p&gt;If you ever tried to learn guitar, chances are you are familiar with guitar tablatures.&lt;&#x2F;p&gt;
&lt;p&gt;It is a simple way to visualize music for guitar, using ASCII characters to represent strings and frets as an alternative to sheet music.&lt;&#x2F;p&gt;
&lt;p&gt;For instance, here are the first four measures of the song &quot;Smoke on the Water&quot; by Deep Purple:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;e|-----------------|-----------------|-----------------|-----------------|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;B|-----------------|-----------------|-----------------|-----------------|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;G|-----3---5-------|---3---6-5-------|-----3---5-----3-|-----------------|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;D|-5---3---5-----5-|---3---6-5-------|-5---3---5-----3-|---5-------------|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;A|-5-------------5-|-----------------|-5---------------|---5-------------|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;E|-----------------|-----------------|-----------------|-----------------| &amp;lt;- top&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This song is played in standard tuning (EADGBe), which is conveyed by the letters on the left indicating the tuning for each string, while the numbers indicate where to put your fingers on the fretboard.&lt;&#x2F;p&gt;
&lt;p&gt;Beyond the text representation, the de facto standard is the format used by the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.guitar-pro.com&#x2F;&quot;&gt;Guitar Pro&lt;&#x2F;a&gt; software to render and synthesize sound for the tablature.&lt;&#x2F;p&gt;
&lt;p&gt;Those binary files have the &lt;code&gt;.gp3&lt;&#x2F;code&gt;, &lt;code&gt;.gp4&lt;&#x2F;code&gt;, &lt;code&gt;.gp5&lt;&#x2F;code&gt; or &lt;code&gt;.gp6&lt;&#x2F;code&gt; extension depending on the software version used to produce them, and can be easily found on the internet on websites such as &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.ultimate-guitar.com&#x2F;&quot;&gt;Ultimate Guitar&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Although the software to play the tablature is proprietary, some versions of the file format are well documented, and there are even open-source projects that can read them.&lt;&#x2F;p&gt;
&lt;p&gt;The best OSS tablature player is probably &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;sourceforge.net&#x2F;projects&#x2F;tuxguitar&#x2F;&quot;&gt;TuxGuitar&lt;&#x2F;a&gt; which is very feature-rich and a fantastic tool to learn guitar.&lt;&#x2F;p&gt;
&lt;p&gt;Since &lt;code&gt;TuxGuitar&lt;&#x2F;code&gt; appears to be unmaintained and Java-based, I thought it would be a fun challenge to write my own tablature player in Rust.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;introducing-ruxguitar&quot;&gt;Introducing Ruxguitar&lt;a class=&quot;zola-anchor&quot; href=&quot;#introducing-ruxguitar&quot; aria-label=&quot;Anchor link for: introducing-ruxguitar&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;I named my project &lt;code&gt;Ruxguitar&lt;&#x2F;code&gt;, a portmanteau of &lt;code&gt;Rust&lt;&#x2F;code&gt; and &lt;code&gt;Guitar&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The project is still in its early stages, but I believe it is now functional enough to be officially announced to the world - aka this very blog post!&lt;&#x2F;p&gt;
&lt;p&gt;Rather than describing what the project does, have a look at the following video which shows the tablature player in action with a song a bit more complex:&lt;&#x2F;p&gt;
&lt;video id=&quot;myVideo&quot; controls width=&quot;640&quot; height=&quot;480&quot; style=&quot;margin: auto;&quot;&gt;
  &lt;source src=&quot;&#x2F;2024-07-14&#x2F;ruxguitar.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
  Your browser does not support the video tag.
&lt;&#x2F;video&gt;
&lt;p&gt;You can obviously find the source code on &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;ruxguitar&quot;&gt;GitHub&lt;&#x2F;a&gt; with pre-built &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;ruxguitar&#x2F;releases&quot;&gt;binaries&lt;&#x2F;a&gt; available for Linux, macOS and Windows.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to go play with it and come back when you want to read the rest of this post which will detail various aspects of the internals.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;parsing-the-tablature&quot;&gt;Parsing the tablature&lt;a class=&quot;zola-anchor&quot; href=&quot;#parsing-the-tablature&quot; aria-label=&quot;Anchor link for: parsing-the-tablature&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;The first step in building a tablature player is to parse the binary tablature file.&lt;&#x2F;p&gt;
&lt;p&gt;During my research, I found a specification of the &lt;code&gt;.gp4&lt;&#x2F;code&gt; file format on &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;dguitar.sourceforge.net&#x2F;GP4format.html&quot;&gt;dguitar&lt;&#x2F;a&gt; to get started.&lt;&#x2F;p&gt;
&lt;p&gt;The structure of the file is roughly the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;file version to know which version of the file format is used&lt;&#x2F;li&gt;
&lt;li&gt;information about the piece (e.g. title, subtitle, artist, album, etc.)&lt;&#x2F;li&gt;
&lt;li&gt;lyrics&lt;&#x2F;li&gt;
&lt;li&gt;number of measures and number of tracks&lt;&#x2F;li&gt;
&lt;li&gt;measures per track in the following order:
&lt;ul&gt;
&lt;li&gt;measure 1&#x2F;track 1&lt;&#x2F;li&gt;
&lt;li&gt;measure 1&#x2F;track 2&lt;&#x2F;li&gt;
&lt;li&gt;...&lt;&#x2F;li&gt;
&lt;li&gt;measure 1&#x2F;track m&lt;&#x2F;li&gt;
&lt;li&gt;measure 2&#x2F;track 1&lt;&#x2F;li&gt;
&lt;li&gt;measure 2&#x2F;track 2&lt;&#x2F;li&gt;
&lt;li&gt;...&lt;&#x2F;li&gt;
&lt;li&gt;measure 2&#x2F;track m&lt;&#x2F;li&gt;
&lt;li&gt;...&lt;&#x2F;li&gt;
&lt;li&gt;measure n&#x2F;track 1&lt;&#x2F;li&gt;
&lt;li&gt;measure n&#x2F;track 2&lt;&#x2F;li&gt;
&lt;li&gt;...&lt;&#x2F;li&gt;
&lt;li&gt;measure n&#x2F;track m&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;within each measure, we find the number of beats to read&lt;&#x2F;li&gt;
&lt;li&gt;within each beat, we find the beat duration and the number of notes to read&lt;&#x2F;li&gt;
&lt;li&gt;within each note, we find the string, the fret, the duration, the effect, etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I decided to use the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-bakery&#x2F;nom&quot;&gt;nom&lt;&#x2F;a&gt; crate to parse the tablature because I am &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;hprof-slurp&quot;&gt;familiar&lt;&#x2F;a&gt; with it for parsing binary format.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a quick peek at the code driving the parser so you get an idea of how it looks:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; parse_gp_data&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;file_data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Song&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RuxError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;rest&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; base_song&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; flat_map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;parse_gp_version&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            tuple&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                parse_info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;version&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;                                     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                cond&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GpVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;GP5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; parse_bool&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                cond&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GpVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;GP4&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; parse_lyrics&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;           &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                cond&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GpVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;GP5_10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;19&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;       &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                cond&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GpVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;GP5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; parse_page_setup&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;       &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                cond&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GpVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;GP5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; parse_int_sized_string&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                parse_int&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;                                               &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                cond&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GpVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;GP5&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; parse_bool&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;              &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                parse_signed_byte&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;                                       &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                cond&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GpVersion&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;GP3&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; parse_int&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;               &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                parse_midi_channels&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt;                                     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            )&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                song_info&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                triplet_feel&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                lyrics&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                _master_effect&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                page_setup&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                tempo_name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                tempo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                hide_tempo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                key_signature&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                octave&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                midi_channels&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            )&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;                &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; init base song&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;                let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; tempo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Tempo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;tempo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; tempo_name&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                Song&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    version&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    song_info&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    triplet_feel&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    lyrics&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    page_setup&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    tempo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    hide_tempo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    key_signature&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    octave&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    midi_channels&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    measure_headers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;                    tracks&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;file_data&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_err&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        log&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;error!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Failed to parse GP data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        RuxError&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ParsingError&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Failed to parse GP data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; parse tracks &amp;amp; measures&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The heavy lifting required to parse the tracks and the measures is done in a different function that will be skipped for brevity.&lt;&#x2F;p&gt;
&lt;p&gt;At some point it became quite tedious to handle the various versions of the file format and I decided to focus on the &lt;code&gt;.gp5&lt;&#x2F;code&gt; version which is widely used.&lt;&#x2F;p&gt;
&lt;p&gt;To be honest, this part was rather challenging because the file format is quite complex and the documentation is not always clear.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily I was able to inspect the parsers from &lt;code&gt;TuxGuitar&lt;&#x2F;code&gt; and the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;slundi&#x2F;guitarpro&quot;&gt;guitarpro&lt;&#x2F;a&gt; crate to get a better understanding of the file format.&lt;&#x2F;p&gt;
&lt;p&gt;To ensure correctness, I have written a few unit tests for specific tablature files to check that the parser is working as expected.&lt;&#x2F;p&gt;
&lt;p&gt;This approach is useful to get started but not very scalable, so I am also validating some high level invariants of the resulting &lt;code&gt;Song&lt;&#x2F;code&gt; structure over a directory containing several hundred tablatures.&lt;&#x2F;p&gt;
&lt;p&gt;I found a few bugs in the parser this way, and I am confident that the parser is working as expected.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;building-a-ui&quot;&gt;Building a UI&lt;a class=&quot;zola-anchor&quot; href=&quot;#building-a-ui&quot; aria-label=&quot;Anchor link for: building-a-ui&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;At this point, we have an in-memory representation of the tablature but no way to display it.&lt;&#x2F;p&gt;
&lt;p&gt;Not only should the user be able to see the tablature but also be able to interact with it.&lt;&#x2F;p&gt;
&lt;p&gt;I really wanted to use a native GUI library to ensure that the application would look and feel like a native application on all platforms.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;areweguiyet.com&#x2F;&quot;&gt;state&lt;&#x2F;a&gt; of GUI libraries in Rust required me to do some research.&lt;&#x2F;p&gt;
&lt;p&gt;I needed a truly event-based library to handle the synchronization during playback while also being able to draw the tablature in a custom way with some kind of canvas abstraction.&lt;&#x2F;p&gt;
&lt;p&gt;Based on those requirements, I decided to give &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;iced.rs&#x2F;&quot;&gt;Iced&lt;&#x2F;a&gt; a spin as it checked all the boxes.&lt;&#x2F;p&gt;
&lt;p&gt;Spoiler alert: I am very happy with my choice so I did not try other libraries.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iced&quot;&gt;Iced&lt;a class=&quot;zola-anchor&quot; href=&quot;#iced&quot; aria-label=&quot;Anchor link for: iced&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;code&gt;Iced&lt;&#x2F;code&gt; library is very well written but could benefit from a bit more documentation.&lt;&#x2F;p&gt;
&lt;p&gt;I recommend reading the source code of the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iced-rs&#x2F;iced&#x2F;tree&#x2F;master&#x2F;examples&quot;&gt;examples&lt;&#x2F;a&gt; to get a better understanding of how to use the library.&lt;&#x2F;p&gt;
&lt;p&gt;I started with the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iced-rs&#x2F;iced&#x2F;tree&#x2F;master&#x2F;examples&#x2F;editor&quot;&gt;text editor&lt;&#x2F;a&gt; example which I slowly adapted to my needs.&lt;&#x2F;p&gt;
&lt;p&gt;At some point, I ran into a bug in version &lt;code&gt;0.12.0&lt;&#x2F;code&gt; which forced me to upgrade to the &lt;code&gt;0.13.0&lt;&#x2F;code&gt; version which was not released yet.&lt;&#x2F;p&gt;
&lt;p&gt;This means I had to use the &lt;code&gt;main&lt;&#x2F;code&gt; branch of the &lt;code&gt;Iced&lt;&#x2F;code&gt; repository which was a bit scary but it worked out fine.&lt;&#x2F;p&gt;
&lt;p&gt;All the breakages I encountered were due to the &lt;code&gt;Iced&lt;&#x2F;code&gt; library being in active development and I am very grateful to the maintainers for their hard work.&lt;&#x2F;p&gt;
&lt;p&gt;The library is architected around messages and subscriptions that trigger the update of the UI.&lt;&#x2F;p&gt;
&lt;p&gt;For instance, those are my messages:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;derive&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Message&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    OpenFile&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; open file dialog&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    FileOpened&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PickerError&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; file content &amp;amp; file name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    TrackSelected&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;TrackSelection&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; track selection&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    FocusMeasure&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; used when clicking on measure in tablature&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    FocusTick&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; focus on a specific tick in the tablature&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    PlayPause&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; toggle play&#x2F;pause&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    StopPlayer&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; stop playback&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    ToggleSolo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; toggle solo mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this is the simplified application entry point:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; RuxApplication&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; start&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ApplicationArgs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; iced&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        iced&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;application&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            RuxApplication&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;title&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            RuxApplication&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;update&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            RuxApplication&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;view&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;subscription&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;RuxApplication&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;subscription&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;RuxApplication&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;theme&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;font&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;ICONS_FONT&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;centered&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;antialiasing&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;run&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The application is built around functions that are orchestrated by the &lt;code&gt;Iced&lt;&#x2F;code&gt; engine appropriately.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;update&lt;&#x2F;code&gt; function has the signature &lt;code&gt;Fn(&amp;amp;mut State, Message) -&amp;gt; C&lt;&#x2F;code&gt; where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;State&lt;&#x2F;code&gt; is the application state that can be modified (here &lt;code&gt;RuxApplication&lt;&#x2F;code&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Message&lt;&#x2F;code&gt; is the message to process&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;C&lt;&#x2F;code&gt; is an output &lt;code&gt;Task&lt;&#x2F;code&gt; potentially producing a new &lt;code&gt;Message&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The &lt;code&gt;view&lt;&#x2F;code&gt; function has the signature &lt;code&gt;Fn(&amp;amp;&#x27;a State) -&amp;gt; Widget&lt;&#x2F;code&gt; and renders a &lt;code&gt;Widget&lt;&#x2F;code&gt; based on the current &lt;code&gt;&amp;amp;State&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;drawing-the-tablature&quot;&gt;Drawing the tablature&lt;a class=&quot;zola-anchor&quot; href=&quot;#drawing-the-tablature&quot; aria-label=&quot;Anchor link for: drawing-the-tablature&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;I started by crafting the code which carefully draws a single measure on an &lt;code&gt;Iced::Canvas&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;drawing each string&lt;&#x2F;li&gt;
&lt;li&gt;for each beat, drawing the notes on the strings and potential beat effect (e.g. palm mute)&lt;&#x2F;li&gt;
&lt;li&gt;for each note, adding the potential note effect (e.g. slide, hammer-on, bend)&lt;&#x2F;li&gt;
&lt;li&gt;annotate the measure with additional information (e.g. measure number, tempo, part annotation, chord)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It required a bit of trial and error to get the offsets right but I am happy with the result.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2024-07-14&amp;#x2F;measure.png&quot;
         alt=&quot;single measure&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Once I have a collection of canvas measures, they are assembled in a responsive grid layout to display the whole tablature using the &lt;code&gt;wrap&lt;&#x2F;code&gt; widget from the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;iced-rs&#x2F;iced_aw&quot;&gt;iced-aw&lt;&#x2F;a&gt; crate.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2024-07-14&amp;#x2F;grid.png&quot;
         alt=&quot;grid measures&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The measures can have different lengths depending on the number of beats which makes silent measures very small and crazy guitar solo measures long.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;making-sounds&quot;&gt;Making sounds&lt;a class=&quot;zola-anchor&quot; href=&quot;#making-sounds&quot; aria-label=&quot;Anchor link for: making-sounds&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;To recap, we have an in-memory representation of a tablature and we have the UI, now we need to make some sounds!&lt;&#x2F;p&gt;
&lt;p&gt;What we want is a way to turn each note, for each beat, for each measure, for each track into a specific sound at the &lt;strong&gt;right&lt;&#x2F;strong&gt; time.&lt;&#x2F;p&gt;
&lt;p&gt;This can be achieved using a MIDI synthesizer which is software that can produce sounds based on MIDI events.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;synthesizing-midi-events&quot;&gt;Synthesizing MIDI events&lt;a class=&quot;zola-anchor&quot; href=&quot;#synthesizing-midi-events&quot; aria-label=&quot;Anchor link for: synthesizing-midi-events&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;There are different kinds of MIDI events but the most important for us are the &lt;code&gt;NoteOn&lt;&#x2F;code&gt; and &lt;code&gt;NoteOff&lt;&#x2F;code&gt; ones.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Note On: Indicates that a note is being pressed. It includes the note number (pitch) and velocity (how hard the note is pressed).&lt;&#x2F;li&gt;
&lt;li&gt;Note Off: Indicates that a note is being released.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For each note in the tablature, we can generate a pair of MIDI events annotated with:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the timestamp, also referred to as a tick, at which they should be executed.&lt;&#x2F;li&gt;
&lt;li&gt;the track to which they belong.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; MidiEventType&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    NoteOn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i16&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; midi channel, note, velocity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    NoteOff&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; midi channel, note&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; MidiEvent&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; tick&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; MidiEventType&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; track&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All those events are pushed into a single array sorted by the event tick.&lt;&#x2F;p&gt;
&lt;p&gt;This approach provides an efficient way to find the next events to play at any given time via binary search later on.&lt;&#x2F;p&gt;
&lt;p&gt;Those &lt;code&gt;MidiEvents&lt;&#x2F;code&gt; can be transformed into audio waves using a synthesizer before being sent to the audio output.&lt;&#x2F;p&gt;
&lt;p&gt;For the synthesizer I settled on the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sinshu&#x2F;rustysynth&quot;&gt;rustysynth&lt;&#x2F;a&gt; crate which provides a neat MIDI synthesizer.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a simplified version of the code to play a MIDI event:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; synthesizer_settings&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; SynthesizerSettings&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;SAMPLE_RATE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; synthesizer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Synthesizer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;sound_font&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;synthesizer_settings&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; midi_event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; find next event to play&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; midi_event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;event &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    MidiEventType&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;NoteOn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; velocity&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        synthesizer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;note_on&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; velocity&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    MidiEventType&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;NoteOff&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        synthesizer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;note_off&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;                    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is important to note that a synthesizer requires a soundfont file to produce sound.&lt;&#x2F;p&gt;
&lt;p&gt;For the sake of simplicity, I included the &lt;code&gt;TimGM6mb.sf2&lt;&#x2F;code&gt; soundfont file in the binary at compile time.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; TIMIDITY_SOUND_FONT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; include_bytes!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;..&#x2F;resources&#x2F;TimGM6mb.sf2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The trade-off is that the binary is a bit larger but the user does not have to worry about finding the soundfont file.&lt;&#x2F;p&gt;
&lt;p&gt;However, it is possible to provide a larger soundfont file to get better sound quality using the &lt;code&gt;--sound-font-file&lt;&#x2F;code&gt; command line argument.&lt;&#x2F;p&gt;
&lt;p&gt;For instance, I like to use &lt;code&gt;FluidR3_GM.sf2&lt;&#x2F;code&gt; which is present on most systems and easy to find online (&lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;musical-artifacts.com&#x2F;artifacts&#x2F;738&quot;&gt;here&lt;&#x2F;a&gt; or &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;member.keymusician.com&#x2F;Member&#x2F;FluidR3_GM&#x2F;index.html&quot;&gt;there&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;ruxguitar&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-sound-font-file&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;usr&#x2F;share&#x2F;sounds&#x2F;sf2&#x2F;FluidR3_GM.sf2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;audio-loop&quot;&gt;Audio loop&lt;a class=&quot;zola-anchor&quot; href=&quot;#audio-loop&quot; aria-label=&quot;Anchor link for: audio-loop&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The audio output stream is managed by a dedicated thread which will produce sound at a regular interval.&lt;&#x2F;p&gt;
&lt;p&gt;I picked the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RustAudio&#x2F;cpal&quot;&gt;cpal&lt;&#x2F;a&gt; crate which is a cross-platform audio library.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a simplified version of the code to set up an audio loop:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; host&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; cpal&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;default_host&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; host&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;default_output_device&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;default_output_config&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stream_config&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; cpal&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;StreamConfig&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; config&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;into&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; channels_count&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stream_config&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;channels &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;assert_eq!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;channels_count&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 4410 samples at 44100 Hz is 0.1 second&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; mono_sample_count&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4410&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0_&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; mono_sample_count&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0_&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; mono_sample_count&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; build audio loop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stream&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; device&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;build_output_stream&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;stream_config&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;f32&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cpal&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;OutputCallbackInfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; midi_events&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; find events to play&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; midi_events&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; synthesize events&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            synthesizer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;process&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;event&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Split buffer in two channels (left and right)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; channel_len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; channels_count&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Render the waveform.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        synthesizer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;render&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; left&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;channel_len&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; right&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;channel_len&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Interleave the left and right channels into the output buffer.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        for&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; r&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; left&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;right&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;channel_len&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            output&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;l&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            output&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;r&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Start the stream.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stream&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; stream&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;stream&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;play&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For each run of the audio loop, it is possible to compute the next window of time to process by taking into account:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the current timestamp of the audio player&lt;&#x2F;li&gt;
&lt;li&gt;the tempo of the current measure&lt;&#x2F;li&gt;
&lt;li&gt;how much time has passed since the previous interval&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; QUARTER_TIME&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 960&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; 1 quarter note = 960 ticks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; tick_increase&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;tempo_bpm&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; elapsed_seconds&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; tempo_bps&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; tempo_bpm&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 60&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; bump&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; QUARTER_TIME&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; tempo_bps&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; elapsed_seconds&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    bump&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using the resulting tick increase, we can efficiently query our array of MIDI events to find the next events to play using binary search.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; tick_increase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; tick_increase&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;tempo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; elapsed_seconds&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; next_tick&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;current_tick &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; tick_increase&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; assume we already have a cursor for the start of the events (a.k.a. the index of the last event played)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; start_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;current_cursor&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; end_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; sorted_events&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;start_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;binary_search_by_key&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;start_index&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tick&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;next_position&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; start_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; next_position&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;next_position&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; next_position&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; no matching elements&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; return slice until the last event&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        start_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; next_position&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; return slice of events to play&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sorted_events&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;start_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;end_index&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now that we have the audio loop running, we can focus on the integration between the audio player and the UI.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;putting-it-all-together&quot;&gt;Putting it all together&lt;a class=&quot;zola-anchor&quot; href=&quot;#putting-it-all-together&quot; aria-label=&quot;Anchor link for: putting-it-all-together&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;Having a perfect integration is crucial to providing a smooth user experience:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;when clicking on the &quot;Play&quot; button, the tablature cursor should start moving, the notes should be highlighted as they are played.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;when a measure is clicked, the player should jump to the corresponding position in the tablature and the correct notes should be played.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;when clicking on a different track, the whole tablature should be updated to show the new track and the sound should be updated accordingly.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;when clicking on the &quot;Solo&quot; button, all other tracks should be muted.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;when clicking on the &quot;Stop&quot; button, the tablature cursor should be reset to the beginning and the sound should stop.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I think you get the idea.&lt;&#x2F;p&gt;
&lt;p&gt;The critical bridge between the audio player and the UI is implemented using the &lt;code&gt;iced::Subscription&lt;&#x2F;code&gt; mechanism.&lt;&#x2F;p&gt;
&lt;p&gt;Subscriptions are a way to listen to external events and publish them as messages to the application.&lt;&#x2F;p&gt;
&lt;p&gt;For instance, here is how the application reacts to pressing the space bar to toggle the playback:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; keyboard_subscription&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; keyboard&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;on_key_press&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; _modifiers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    keyboard&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Named&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Space&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PlayPause&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; None&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The update function does not care whether the message has been triggered by the keyboard or by clicking on the &quot;Play&quot; button.&lt;&#x2F;p&gt;
&lt;p&gt;Using a similar mechanism, the audio player can send messages to the application to update the UI based on the current playback position.&lt;&#x2F;p&gt;
&lt;p&gt;The application holds the receiving end of a &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;tokio&#x2F;latest&#x2F;tokio&#x2F;sync&#x2F;watch&#x2F;index.html&quot;&gt;tokio::sync::watch&lt;&#x2F;a&gt; channel containing the current timestamp which is published by the audio thread.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; audio_player_beat_subscription&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Stream&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Message&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; beat_receiver&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;beat_receiver&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    stream&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;channel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; move&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; receiver&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; beat_receiver&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;await&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; get tick from audio player&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; tick&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;receiver&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;borrow_and_update&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; publish to UI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            output&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Message&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FocusTick&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;tick&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;send failed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; wait for next beat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;            receiver&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;changed&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;receiver failed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; setup subscription&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Subscription&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;run_with_id&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;audio-player-beat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; audio_player_beat_subscription&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The tablature processes the &lt;code&gt;FocusTick&lt;&#x2F;code&gt; message to update the current measure position and highlight the notes.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2024-07-14&amp;#x2F;measure-cursor.gif&quot;
         alt=&quot;measure cursor&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;A &lt;strong&gt;lot&lt;&#x2F;strong&gt; of details were required to maintain the illusion that everything is properly synchronized with the user&#x27;s actions.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;future-work&quot;&gt;Future work&lt;a class=&quot;zola-anchor&quot; href=&quot;#future-work&quot; aria-label=&quot;Anchor link for: future-work&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;The current version of &lt;code&gt;Ruxguitar&lt;&#x2F;code&gt; is pretty much an MVP to get the project started.&lt;&#x2F;p&gt;
&lt;p&gt;It is nowhere near &lt;code&gt;TuxGuitar&lt;&#x2F;code&gt; in terms of features and usability.&lt;&#x2F;p&gt;
&lt;p&gt;Here are a few ideas for the future:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;support more file formats (currently only &lt;code&gt;.gp5&lt;&#x2F;code&gt; is supported)&lt;&#x2F;li&gt;
&lt;li&gt;display more information about the tablature (e.g. rhythm, time signature, key signature etc.)&lt;&#x2F;li&gt;
&lt;li&gt;support repeating measures&lt;&#x2F;li&gt;
&lt;li&gt;support slowing down and speeding up the playback&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h1&gt;
&lt;p&gt;I have been working on &lt;code&gt;Ruxguitar&lt;&#x2F;code&gt; over the past year and I am very happy with the result.&lt;&#x2F;p&gt;
&lt;p&gt;Not only did I learn a lot on the way but I also actually built a complex piece of software that appears to work.&lt;&#x2F;p&gt;
&lt;p&gt;Working on such a large project alone required a lot of discipline because there were many times when I felt like giving up, running into cryptic bugs or being stuck on a feature for weeks.&lt;&#x2F;p&gt;
&lt;p&gt;It would have been impossible to build &lt;code&gt;Ruxguitar&lt;&#x2F;code&gt; without &lt;code&gt;TuxGuitar&lt;&#x2F;code&gt; as a reference implementation and I am very grateful for the work done by the &lt;code&gt;TuxGuitar&lt;&#x2F;code&gt; team over the years.&lt;&#x2F;p&gt;
&lt;p&gt;After so much work on this project, it&#x27;s about time I get back to playing guitar instead of writing software for it!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust Meetup Linz: Qdrant - a vector search engine in Rust</title>
        <published>2023-05-12T00:00:00+00:00</published>
        <updated>2023-05-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/linz-rust-meetup-qdrant/"/>
        <id>https://agourlay.github.io/linz-rust-meetup-qdrant/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/linz-rust-meetup-qdrant/">&lt;p&gt;I had the privilege and pleasure to give a talk at the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;rust-linz.at&#x2F;&quot;&gt;Rust Meetup Linz&lt;&#x2F;a&gt; about my work as a full time contributor on the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;qdrant&#x2F;qdrant&quot;&gt;Qdrant&lt;&#x2F;a&gt; vector search engine.&lt;&#x2F;p&gt;
&lt;p&gt;I wanted the talk to be rather accessible given that vector search engines have recently been gaining popularity.&lt;&#x2F;p&gt;
&lt;p&gt;The presentation is structured roughly in two parts:&lt;&#x2F;p&gt;
&lt;p&gt;First the focus is on the use cases for the technology to really understand where it shines.&lt;&#x2F;p&gt;
&lt;p&gt;The second part is about peeking under the hood to take a closer look at the internals, and to see why Rust is such a good fit for the job.&lt;&#x2F;p&gt;
&lt;p&gt;The slides are available &lt;a href=&quot;&#x2F;2023-05-12&#x2F;rust-linz-meetup-qdrant.pdf&quot;&gt;here&lt;&#x2F;a&gt; and the recording &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=2cGM1fEbWJQ&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;iframe
    width=&quot;640&quot;
    height=&quot;480&quot;
    src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;2cGM1fEbWJQ&quot;
    frameborder=&quot;0&quot;
    allow=&quot;autoplay; encrypted-media&quot;
    allowfullscreen
&gt;
&lt;&#x2F;iframe&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Follow up on cracking ZIP archives in Rust</title>
        <published>2023-04-03T00:00:00+00:00</published>
        <updated>2023-04-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/follow-up-cracking-zip-rust/"/>
        <id>https://agourlay.github.io/follow-up-cracking-zip-rust/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/follow-up-cracking-zip-rust/">&lt;p&gt;In a &lt;a href=&quot;&#x2F;brute-forcing-protected-zip-rust&#x2F;&quot;&gt;previous article&lt;&#x2F;a&gt;, we explored how to build - step by step - a CLI in Rust to brute-force protected ZIP archives.&lt;&#x2F;p&gt;
&lt;p&gt;The outcome of this research was the creation of the project &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;zip-password-finder&quot;&gt;zip-password-finder&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Since the last publication, the project has been slowly evolving to mitigate the shortcomings that were highlighted.&lt;&#x2F;p&gt;
&lt;p&gt;In this follow-up entry we will go over the improvements made and the latest performance numbers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-short-recap&quot;&gt;A short recap&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-short-recap&quot; aria-label=&quot;Anchor link for: a-short-recap&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The project &lt;code&gt;zip-password-finder&lt;&#x2F;code&gt; supports two different modes to find the password: either from a dictionary file or by generating candidates from a charset.&lt;&#x2F;p&gt;
&lt;p&gt;It uses a channel-based architecture to distribute candidate passwords to a set of workers who are responsible for testing them in parallel.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2023-04-03&amp;#x2F;old-architecture.png&quot;
         alt=&quot;Old architecture&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;It is important to mention that ZIP archives can be encrypted using either ZipCrypto or &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Advanced_Encryption_Standard&quot;&gt;AES&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, ZipCrypto can be &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;blog.devolutions.net&#x2F;2020&#x2F;08&#x2F;why-you-should-never-use-zipcrypto&#x2F;&quot;&gt;attacked&lt;&#x2F;a&gt; and is much cheaper to brute force.&lt;&#x2F;p&gt;
&lt;p&gt;As it can still be found in the wild, most notably produced by Windows machines, &lt;code&gt;zip-password-finder&lt;&#x2F;code&gt; handles this format transparently for the user.&lt;&#x2F;p&gt;
&lt;p&gt;However, we won&#x27;t give it much thought in this article given its issues and our desire to focus on the more difficult AES case.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;test-drive&quot;&gt;Test drive&lt;a class=&quot;zola-anchor&quot; href=&quot;#test-drive&quot; aria-label=&quot;Anchor link for: test-drive&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Here is the CLI we are going to work with.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;zip-password-finder&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Find&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; protected&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ZIP&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Usage:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; zip-password-finder&lt;&#x2F;span&gt;&lt;span&gt; [OPTIONS&lt;&#x2F;span&gt;&lt;span&gt;] --inputFile &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;inputFile&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Options:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  -i,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-inputFile&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;inputFil&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;          path&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; zip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; input&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  -w,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-workers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;worker&lt;&#x2F;span&gt;&lt;span&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;          number&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; workers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  -p,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-passwordDictionary&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;passwordDictionar&lt;&#x2F;span&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;          path&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dictionary&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  -c,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-charset&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;charse&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;          charset&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; use&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; generate&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span&gt; [default:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; medium]&lt;&#x2F;span&gt;&lt;span&gt; [possible&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; values:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; basic,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; easy,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; medium,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hard]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;      --minPasswordLen&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;minPasswordLe&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;          minimum&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span&gt; [default:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;      --maxPasswordLen&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;maxPasswordLe&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;          maximum&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span&gt; [default:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 10]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  -h,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-help&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;          Print&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; help&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; information&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  -V,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;          Print&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; version&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; information&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can give it a try by creating an encrypted zip archive; let&#x27;s call it &lt;code&gt;secret.zip&lt;&#x2F;code&gt; with the four-character password &lt;code&gt;&quot;ab12&quot;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;zipinfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; secret.zip&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Archive:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  secret.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Zip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; file&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 209&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; number&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; entries:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-rw-rw-r--&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  6.3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; unx&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;       13&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Bx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u099&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 23-Mar-27&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 20:17&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; secret.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; file,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 13&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; uncompressed,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 21&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compressed:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;61.5%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Given that the password is pretty short, we can ask &lt;code&gt;zip-password-finder&lt;&#x2F;code&gt; to generate all possible passwords from the charset formed by the lowercase letters, uppercase letters, and digits (called medium).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt; .&#x2F;zip-password-finder -i test-encrypted.zip --charset medium&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It returns with the right answer shortly before the one-minute mark.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt; .&#x2F;zip-password-finder-0.2 -i &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Workspace&#x2F;blog-data&#x2F;find-password-zip&#x2F;secret.zip -c medium&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Using&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; workers&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; test&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; passwords&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Generating&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; passwords&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; from&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; charset&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 62&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;g&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;j&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;k&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;l&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;q&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;w&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;z&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;A&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;B&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;C&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;D&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;E&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;F&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;G&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;H&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;I&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;J&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;K&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;L&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;M&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;N&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;O&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;P&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Q&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;R&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;S&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;U&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;V&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;W&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;X&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Z&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;6&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;7&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;9&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Starting&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; search&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; space&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; (62&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; possibilities&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Starting&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; search&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; space&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt; (3844&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; possibilities&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;61&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; passwords&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; generated&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; so&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; far&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Starting&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; search&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; space&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt; (238328&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; possibilities&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;3905&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; passwords&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; generated&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; so&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; far&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Starting&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; search&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; space&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span&gt; (14776336&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; possibilities&lt;&#x2F;span&gt;&lt;span&gt;) (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;242233&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; passwords&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; generated&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; so&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; far&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; found&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ab12&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;real&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0m54,262s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 3m40,620s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sys&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  0m2,431s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finding a 4-letter password on such a small charset was a rather easy task for a modern CPU.&lt;&#x2F;p&gt;
&lt;p&gt;There are only &lt;code&gt;(26 lower + 26 upper + 10 digit)^4 = 14.776.336&lt;&#x2F;code&gt; candidates to test.&lt;&#x2F;p&gt;
&lt;p&gt;However, a learning from the previous article is that scalability suffers as the number of workers increases.&lt;&#x2F;p&gt;
&lt;p&gt;Improving on this limitation is critical for being able to work against real-world passwords.&lt;&#x2F;p&gt;
&lt;p&gt;We will reuse this test file for the benchmarks in the rest of the article.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;independent-workers&quot;&gt;Independent workers&lt;a class=&quot;zola-anchor&quot; href=&quot;#independent-workers&quot; aria-label=&quot;Anchor link for: independent-workers&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Previous measurements clearly showed that performance did not improve linearly with the number of workers.&lt;&#x2F;p&gt;
&lt;p&gt;We previously attributed the flat line between 4 and 8 workers to the Hyper-threading on my CPU, which does not bode well for this type of workload.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2023-04-03&amp;#x2F;scalability.png&quot;
         alt=&quot;Scalability&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The most logical hypothesis is that there is a source of contention in the current architecture as the number of workers increases.&lt;&#x2F;p&gt;
&lt;p&gt;It seems straightforward to believe that workers are somehow competing and synchronizing with each other to poll candidates from the channel.&lt;&#x2F;p&gt;
&lt;p&gt;Picking an easy architecture helped us get started at the beginning, but it could very well be a limiting factor to get faster.&lt;&#x2F;p&gt;
&lt;p&gt;An interesting insight is that workers do not need to share the same source of passwords.&lt;&#x2F;p&gt;
&lt;p&gt;Each worker could agree upfront to work on a subset of the generated passwords.&lt;&#x2F;p&gt;
&lt;p&gt;Given n workers, each worker generates and tests &lt;code&gt;1&#x2F;n&lt;&#x2F;code&gt; of the passwords with an offset.&lt;&#x2F;p&gt;
&lt;p&gt;For instance, with 3 workers on a lowercase charset:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;first worker : &quot;a&quot;, &quot;d&quot;, &quot;g&quot;, &quot;j&quot;, ...&lt;&#x2F;li&gt;
&lt;li&gt;second worker: &quot;b&quot;, &quot;e&quot;, &quot;h&quot;, &quot;k&quot;, ...&lt;&#x2F;li&gt;
&lt;li&gt;third worker : &quot;c&quot;, &quot;f&quot;, &quot;i&quot;, &quot;l&quot;, ...&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This way, we remove all coordination at runtime, so the workers can make progress in isolation.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2023-04-03&amp;#x2F;new-architecture.png&quot;
         alt=&quot;New architecture&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;This pattern can be elegantly integrated by refactoring the dictionary reader and password generator to be proper &lt;code&gt;Iterator&lt;&#x2F;code&gt;s.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; passwords_iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Iterator&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; strategy&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Strategy&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GenPasswords&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        charset&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        min_password_len&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        max_password_len&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; iterator&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; password_generator_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;charset&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; min_password_len&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; max_password_len&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;iterator&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Strategy&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PasswordFile&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;dictionary_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; iterator&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; password_dictionary_reader_iter&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;dictionary_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;iterator&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; filtering iterator for worker `worker_index`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;passwords_iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; worker_count&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; filtered&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; passwords_iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;filter_map&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; candidate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; worker_count&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; worker_index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;candidate&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;filtered&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    passwords_iter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; processing loop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; passwords_iter&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Benchmarking both architectures on the &lt;code&gt;secret.zip&lt;&#x2F;code&gt; archive with various numbers of workers yields the following result.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2023-04-03&amp;#x2F;independent-workers-effect.png&quot;
         alt=&quot;New architecture effect&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The performance improved slightly, but the shape of the curve did not change, meaning the scalability profile did not get any better.&lt;&#x2F;p&gt;
&lt;p&gt;Switching to independent workers is beneficial, but it did not have the desired effect.&lt;&#x2F;p&gt;
&lt;p&gt;There is more research to be done to improve scalability.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;cheaper-iteration&quot;&gt;Cheaper iteration&lt;a class=&quot;zola-anchor&quot; href=&quot;#cheaper-iteration&quot; aria-label=&quot;Anchor link for: cheaper-iteration&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;One obvious strategy to go faster is to make testing a candidate as cheap as possible.&lt;&#x2F;p&gt;
&lt;p&gt;The first version of the project was rather naive in that regard.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; archive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; zip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ZipArchive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Archive validated before-hand&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; receive_password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;recv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; channel disconnected, stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; archive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;by_index_decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; decrypt first file in archive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; res&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Unexpected error &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; e&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; invalid password - continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                    println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Password found:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                    break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For each candidate, the function &lt;code&gt;archive.by_index_decrypt(0, password)&lt;&#x2F;code&gt; is called; hopefully it does not do too much.&lt;&#x2F;p&gt;
&lt;p&gt;This function belongs to the &lt;code&gt;zip-rs&lt;&#x2F;code&gt; project and performs the following actions:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Find file data in the archive based on file index used (here 0).&lt;&#x2F;li&gt;
&lt;li&gt;Verify that the file is encrypted.&lt;&#x2F;li&gt;
&lt;li&gt;Load raw content of the file.&lt;&#x2F;li&gt;
&lt;li&gt;Prepare AES decoder (get salt &amp;amp; verification key).&lt;&#x2F;li&gt;
&lt;li&gt;Compute key for candidate and salt.&lt;&#x2F;li&gt;
&lt;li&gt;Compare derived key to verification key.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Well, that is a &lt;strong&gt;lot&lt;&#x2F;strong&gt; of repetition!&lt;&#x2F;p&gt;
&lt;p&gt;Ideally, we just want to perform the 5th and 6th steps for each candidate, the rest can be pre-computed.&lt;&#x2F;p&gt;
&lt;p&gt;To do this, I had to fork the &lt;code&gt;zip-rs&lt;&#x2F;code&gt; crate to expose some internals.&lt;&#x2F;p&gt;
&lt;p&gt;On the &lt;code&gt;AesReader&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Read the AES header bytes and returns the key and salt.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; # Returns&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; the key and the salt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; get_key_and_salt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; salt_length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aes_mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;salt_length&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; salt_length&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;reader&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;read_exact&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; next are 2 bytes used for password verification&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; pwd_verification_value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; PWD_VERIFY_LENGTH&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;    self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;reader&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;read_exact&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; pwd_verification_value&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;pwd_verification_value&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And on the &lt;code&gt;ZipArchiveReader&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Returns key and salt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; get_aes_key_and_salt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    file_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ZipResult&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;AesMode&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span&gt;shared&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span&gt;files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;file_number&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ok_or&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ZipError&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FileNotFound&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; !&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;encrypted &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ZipError&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;UnsupportedArchive&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ZipError&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;PASSWORD_REQUIRED&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; limit_reader&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; find_content&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;data&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;reader&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;aes_mode &lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        None&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;aes_mode&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; _&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; AesReader&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;limit_reader&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; aes_mode&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;compressed_size&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get_key_and_salt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; NEW&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;AES reader failed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;aes_mode&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Luckily, Cargo makes it very low-friction to work with a forked crate!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;zip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;zip.git&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; branch&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;zip-password-finder&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Thanks to this insight, it is possible to pre-compute most of the AES information, removing a lot of work from the processing loop.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; AES info bindings initialized once&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; derived_key_len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; derived_key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; salt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; processing loop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; passwords_iter&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; potential_match&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; process AES KEY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; use PBKDF2 with HMAC-Sha1 to derive the key&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    pbkdf2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pbkdf2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hmac&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Sha1&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;password_bytes&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;salt&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; derived_key&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;PBKDF2 should not fail&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; pwd_verify&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;derived_key&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;derived_key_len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; the last 2 bytes should equal the password verification value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    potential_match&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; key&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; pwd_verify&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; potential_match&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; try to decode archive to eliminate collision&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; archive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;by_index_decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; decrypt first file in archive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Benchmarking the difference:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; hyperfine&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-runs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-warmup&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; before&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder-before -i secret.zip -c medium&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; after&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder-after  -i secret.zip -c medium&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;before&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;58.977 ± 0.512&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;58.615&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;59.339&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.08 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;after&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;54.476 ± 0.037&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;54.450&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;54.503&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;A solid 8% improvement is something I gladly take.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performance-over-time&quot;&gt;Performance over time&lt;a class=&quot;zola-anchor&quot; href=&quot;#performance-over-time&quot; aria-label=&quot;Anchor link for: performance-over-time&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Outside of the two previously mentioned improvements, the runtime improved slowly over time.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;62.317 ± 0.224&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;62.159&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;62.475&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.21 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;58.823 ± 0.013&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;58.814&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;58.833&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.14 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;59.423 ± 0.047&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;59.390&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;59.456&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.15 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;55.562 ± 0.034&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;55.538&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;55.586&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.08 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.5&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;56.877 ± 0.362&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;56.621&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;57.132&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.10 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.5.1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;54.230 ± 0.424&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;53.930&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;54.530&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.05 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.6&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;51.619 ± 0.412&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;51.327&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;51.911&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.6.1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;52.421 ± 0.166&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;52.303&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;52.538&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.02 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.6.2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;52.149 ± 0.155&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;52.039&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;52.259&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.01 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.6.3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;52.073 ± 0.193&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;51.937&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;52.209&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.01 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;However, the performance optimizations are hitting a wall; a single bottleneck is now largely dominating the CPU usage.&lt;&#x2F;p&gt;
&lt;p&gt;Each worker is busy doing the following: (full &lt;a href=&quot;&#x2F;2023-04-03&#x2F;final-flamegraph.svg&quot;&gt;flamegraph&lt;&#x2F;a&gt; available).&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2023-04-03&amp;#x2F;flamegraph-worker.png&quot;
         alt=&quot;Flamegraph worker&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Computing the SHA1 for each candidate takes up to 90% of the total CPU time; improving this implementation would have a &lt;strong&gt;massive&lt;&#x2F;strong&gt; impact on the runtime!&lt;&#x2F;p&gt;
&lt;p&gt;It is interesting to note that the function is called &lt;code&gt;sha1::compress::soft::compress&lt;&#x2F;code&gt; - now that&#x27;s a weird name.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s take a look under the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;RustCrypto&#x2F;hashes&#x2F;blob&#x2F;master&#x2F;sha1&#x2F;src&#x2F;compress&#x2F;x86.rs#L102&quot;&gt;hood&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cpufeatures&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;shani_cpuid&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sha&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sse2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;ssse3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sse4.1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; compress&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;state&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; blocks&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; shani_cpuid&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        unsafe&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;            digest_blocks&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;state&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; blocks&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;        super&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;soft&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;compress&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;state&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; blocks&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;#&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;target_feature&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;enable &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sha,sse2,ssse3,sse4.1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;unsafe&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; digest_blocks&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;state&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u32&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; blocks&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;   ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code is picking an implementation at runtime based on the capabilities of the CPU.&lt;&#x2F;p&gt;
&lt;p&gt;The branching depends on the &lt;code&gt;sha&lt;&#x2F;code&gt;, &lt;code&gt;sse2&lt;&#x2F;code&gt;, &lt;code&gt;ssse3&lt;&#x2F;code&gt; and &lt;code&gt;sse4.1&lt;&#x2F;code&gt; instruction sets.&lt;&#x2F;p&gt;
&lt;p&gt;Here, &lt;code&gt;soft&lt;&#x2F;code&gt; stands for &lt;code&gt;software&lt;&#x2F;code&gt;, meaning not using hardware acceleration.&lt;&#x2F;p&gt;
&lt;p&gt;But why is my CPU not eligible for the optimized SIMD implementation?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lscpu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Architecture:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;            x86_64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  CPU&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; op-mode&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;        32-bit,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 64-bit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  Address&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sizes:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;         39&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bits&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; physical,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 48&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bits&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; virtual&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  Byte&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Order:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;            Little&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Endian&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;CPU(s&lt;&#x2F;span&gt;&lt;span&gt;):                  8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  On-line&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; CPU&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; list:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   0-7&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Vendor&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ID:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;               GenuineIntel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  Model&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; name:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;            Intel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;R&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Core&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;TM&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; i7-10610U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; CPU&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1.80GHz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Flags:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;               ...sse&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sse2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ssse3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sse4_1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sse4_2...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Sadly, I have all the necessary &lt;code&gt;sse&lt;&#x2F;code&gt; instructions but missing the &lt;code&gt;sha&lt;&#x2F;code&gt; one.&lt;&#x2F;p&gt;
&lt;p&gt;This means we need to make sure to use a CPU with &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Intel_SHA_extensions&quot;&gt;SHA instructions&lt;&#x2F;a&gt; to get the best performance.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;optimizing-build&quot;&gt;Optimizing build&lt;a class=&quot;zola-anchor&quot; href=&quot;#optimizing-build&quot; aria-label=&quot;Anchor link for: optimizing-build&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Given that I do not have access to adequate hardware, all I can do for the time being is tweak my build in order to squeeze out one last performance gain.&lt;&#x2F;p&gt;
&lt;p&gt;The first idea is to enable Link-time Optimization (LTO), which is an optimization taking place at compile time.&lt;&#x2F;p&gt;
&lt;p&gt;Be aware that it can make the compilation much slower!&lt;&#x2F;p&gt;
&lt;p&gt;There are two possible values for it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[profile.release]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lto = &amp;quot;thin&amp;quot; or &amp;quot;fat&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A second idea is to build a binary with the best instructions for the current CPU.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;RUSTFLAGS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-C target-cpu=native&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Benchmarking those configurations yields the following results:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;native&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;52.456 ± 2.987&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;50.344&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;54.568&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;master&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;57.439 ± 1.135&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;56.637&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;58.241&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.09 ± 0.07&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;native-lto&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;59.161 ± 0.437&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;58.852&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;59.470&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.13 ± 0.06&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;lto-thin&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;61.677 ± 0.153&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;61.569&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;61.786&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.18 ± 0.07&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;lto-fat&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;67.777 ± 0.277&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;67.582&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;67.973&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.29 ± 0.07&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Well, we better not enable LTO but there is a case to be made for a native build.&lt;&#x2F;p&gt;
&lt;p&gt;This performance related section was a bit messy, but we learned a few important things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Do not blindly enable LTO without validating that it is beneficial.&lt;&#x2F;li&gt;
&lt;li&gt;If you are super serious about performance, you would probably benefit from producing native binaries for your hardware.&lt;&#x2F;li&gt;
&lt;li&gt;Some libraries have alternate implementations depending on the hardware capabilities.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;state-of-the-art&quot;&gt;State of the art&lt;a class=&quot;zola-anchor&quot; href=&quot;#state-of-the-art&quot; aria-label=&quot;Anchor link for: state-of-the-art&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;To appreciate the performance of &lt;code&gt;zip-password-finder&lt;&#x2F;code&gt;, I thought it would be a good idea to compare it to the state of the art of ZIP cracking.&lt;&#x2F;p&gt;
&lt;p&gt;It seems &lt;strong&gt;serious&lt;&#x2F;strong&gt; people are using the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;hashcat.net&#x2F;hashcat&#x2F;&quot;&gt;Hashcat&lt;&#x2F;a&gt; project, which is apparently the &quot;World&#x27;s fastest password cracker&quot;!&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2023-04-03&amp;#x2F;hashcat-logo.png&quot;
         alt=&quot;Hashcat logo&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sudo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; apt-get&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hashcat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This tool runs on GPUs; in my case, I had to install the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;intel&#x2F;compute-runtime&#x2F;&quot;&gt;OpenCL Runtime for Intel Core&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It supports a very large list of algorithms, including the one we need here, &lt;code&gt;WinZip&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In order to use &lt;code&gt;Hashcat&lt;&#x2F;code&gt;, we first need to extract the underlying hash of our zip file into a format that is understood by &lt;code&gt;Hashcat&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To that end, we will use &lt;code&gt;zip2john&lt;&#x2F;code&gt; from the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;openwall&#x2F;john&quot;&gt;John the Ripper&lt;&#x2F;a&gt; project.&lt;&#x2F;p&gt;
&lt;p&gt;Installing it &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;superuser.com&#x2F;questions&#x2F;1457837&#x2F;command-zip2john-is-not-working&quot;&gt;manually&lt;&#x2F;a&gt; with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;github.com&#x2F;openwall&#x2F;john&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bleeding-jumbo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; john&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; john&#x2F;src&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;configure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;make&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; clean&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; make&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;sj4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and then running it&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;Workspace&#x2F;john&#x2F;run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;zip2john&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ~&#x2F;zip-files&#x2F;secret.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;yields the text&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;secret.zip&#x2F;secret.txt:$zip2$*0*1*0*abf015b7750c67f9*f8fe*d*c97f48465ca6a99031db50f79a*d9e156b830df03899575*$&#x2F;zip2$:secret.txt:secret.zip:&#x2F;home&#x2F;agourlay&#x2F;zip-files&#x2F;secret.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output needs to be cleaned up and saved into a file, &lt;code&gt;hash.txt&lt;&#x2F;code&gt; here.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$zip2$*0*1*0*abf015b7750c67f9*f8fe*d*c97f48465ca6a99031db50f79a*d9e156b830df03899575*$&#x2F;zip2$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After a rather tedious setup, it is finally time to crack our hash!&lt;&#x2F;p&gt;
&lt;p&gt;We need to instruct &lt;code&gt;hashcat&lt;&#x2F;code&gt; to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;perform a brute force attack&lt;&#x2F;li&gt;
&lt;li&gt;target the &lt;code&gt;hash.txt&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;use an algorithm for ZIP archive hashes&lt;&#x2F;li&gt;
&lt;li&gt;generate passwords for a charset with lower case, upper case and digits (up to 4 chars)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Luckily for us, the help prompt is truly excellent!&lt;&#x2F;p&gt;
&lt;p&gt;Here are the interesting excerpts:&lt;&#x2F;p&gt;
&lt;p&gt;For the attack mode:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Attack&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Modes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; | Mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Straight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Combination&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  3&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Brute-force&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  6&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Hybrid&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Wordlist&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Mask&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  7&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Hybrid&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Mask&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Wordlist&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  9&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Association&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the hash type:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Hash&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; modes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; | Name                                                | Category&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  13600&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; WinZip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;                                              |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Archive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the charset:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  ?&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Charset&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  l&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; abcdefghijklmnopqrstuvwxyz&lt;&#x2F;span&gt;&lt;span&gt; [a-z&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  u&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ABCDEFGHIJKLMNOPQRSTUVWXYZ&lt;&#x2F;span&gt;&lt;span&gt; [A-Z&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; 0123456789&lt;&#x2F;span&gt;&lt;span&gt;                 [0-9&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  h&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; 0123456789abcdef&lt;&#x2F;span&gt;&lt;span&gt;           [0-9a-f&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  H&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; 0123456789ABCDEF&lt;&#x2F;span&gt;&lt;span&gt;           [0-9A-F&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;  !&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;#$%&amp;amp;&amp;#39;()*+,-.&#x2F;:;&amp;lt;=&amp;gt;?@[\]^_&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{|}~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ?l?u?d?s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; 0x00&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0xff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;According to the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;hashcat.net&#x2F;wiki&#x2F;doku.php?id=mask_attack&quot;&gt;documentation&lt;&#x2F;a&gt;, it seems we need to set up a four-character mask that will be explored incrementally.&lt;&#x2F;p&gt;
&lt;p&gt;After a bit of trial and error, it gives the following magic incantation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hashcat&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hash.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 13600&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?l?u?d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?1?1?1?1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-increment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s go!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt; hashcat -a 3 hash.txt -m 13600 -1 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;l&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;d &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;?&lt;&#x2F;span&gt;&lt;span&gt;1 --increment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hashcat&lt;&#x2F;span&gt;&lt;span&gt; (v6.2.5&lt;&#x2F;span&gt;&lt;span&gt;) starting&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;OpenCL&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; API&lt;&#x2F;span&gt;&lt;span&gt; (OpenCL&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3.0&lt;&#x2F;span&gt;&lt;span&gt; ) - Platform&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;1 [Intel(R) Corporation]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;=&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; Device&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;1: Intel(R) UHD Graphics [0x9b41], 12640&#x2F;25384 MB (2047 MB allocatable), 24MCU&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Minimum&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; supported&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; by&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kernel:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Maximum&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; length&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; supported&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; by&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kernel:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 256&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hashes:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; digests&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; unique&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; digests,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; unique&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; salts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Bitmaps:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bits,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 65536&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; entries,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0x0000ffff&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mask,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 262144&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 5&#x2F;13&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; rotates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Optimizers&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; applied:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; Zero-Byte&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; Single-Hash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; Single-Salt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; Brute-Force&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt; Slow-Hash-SIMD-LOOP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Watchdog:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Hardware&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; monitoring&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; interface&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; not&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; found&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; on&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; your&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; system.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Watchdog:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Temperature&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; abort&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; trigger&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; disabled.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Host&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; memory&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; required&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; this&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; attack:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1475&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; MB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;The&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; wordlist&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; or&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mask&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; that&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; you&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; are&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; using&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; too&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; small.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;This&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; means&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; that&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hashcat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cannot&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; use&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; full&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; parallel&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; power&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; your&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; device&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unless&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; you&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; supply&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; work,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; your&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cracking&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; speed&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; will&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; drop.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;For&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; tips&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; on&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; supplying&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; work,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; see:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;hashcat.net&#x2F;faq&#x2F;morework&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Approaching&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; final&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; keyspace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; workload&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; adjusted.&lt;&#x2F;span&gt;&lt;span&gt;           &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Session..........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hashcat&lt;&#x2F;span&gt;&lt;span&gt;                                &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Status...........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Exhausted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hash.Mode........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 13600&lt;&#x2F;span&gt;&lt;span&gt; (WinZip&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hash.Target......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;zip2&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;abf015b7750c67f9&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;f8fe&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c97f48465ca6a9...&#x2F;zip2&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Time.Started.....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:53:49&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;span&gt; (0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; secs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Time.Estimated...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:53:49&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;span&gt; (0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; secs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Kernel.Feature...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Pure&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Kernel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Mask.......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?1&lt;&#x2F;span&gt;&lt;span&gt; [1&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Charset....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?l?u?d,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Queue......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1&#x2F;4&lt;&#x2F;span&gt;&lt;span&gt; (25.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Speed.#1.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;      117&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; H&#x2F;s&lt;&#x2F;span&gt;&lt;span&gt; (6.27ms&lt;&#x2F;span&gt;&lt;span&gt;) @ Accel:32 Loops:999 Thr:8 Vec:1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Recovered........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0&#x2F;1&lt;&#x2F;span&gt;&lt;span&gt; (0.00%&lt;&#x2F;span&gt;&lt;span&gt;) Digests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Progress.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 62&#x2F;62&lt;&#x2F;span&gt;&lt;span&gt; (100.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Rejected.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0&#x2F;62&lt;&#x2F;span&gt;&lt;span&gt; (0.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Restore.Point....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1&#x2F;1&lt;&#x2F;span&gt;&lt;span&gt; (100.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Restore.Sub.#1...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Salt:0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Amplifier:61-62&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Iteration:0-999&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Candidate.Engine.:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Device&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Generator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Candidates.#1....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; X&lt;&#x2F;span&gt;&lt;span&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; X&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;The&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; wordlist&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; or&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mask&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; that&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; you&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; are&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; using&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; too&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; small.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;This&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; means&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; that&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hashcat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cannot&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; use&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; full&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; parallel&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; power&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; your&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; device&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unless&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; you&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; supply&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; work,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; your&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cracking&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; speed&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; will&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; drop.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;For&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; tips&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; on&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; supplying&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; work,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; see:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;hashcat.net&#x2F;faq&#x2F;morework&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Approaching&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; final&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; keyspace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; workload&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; adjusted.&lt;&#x2F;span&gt;&lt;span&gt;           &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Session..........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hashcat&lt;&#x2F;span&gt;&lt;span&gt;                                &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Status...........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Exhausted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hash.Mode........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 13600&lt;&#x2F;span&gt;&lt;span&gt; (WinZip&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hash.Target......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;zip2&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;abf015b7750c67f9&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;f8fe&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c97f48465ca6a9...&#x2F;zip2&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Time.Started.....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:53:52&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;span&gt; (0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; secs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Time.Estimated...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:53:52&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;span&gt; (0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; secs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Kernel.Feature...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Pure&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Kernel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Mask.......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?1?1&lt;&#x2F;span&gt;&lt;span&gt; [2&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Charset....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?l?u?d,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Queue......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 2&#x2F;4&lt;&#x2F;span&gt;&lt;span&gt; (50.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Speed.#1.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;     7321&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; H&#x2F;s&lt;&#x2F;span&gt;&lt;span&gt; (6.27ms&lt;&#x2F;span&gt;&lt;span&gt;) @ Accel:16 Loops:999 Thr:16 Vec:1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Recovered........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0&#x2F;1&lt;&#x2F;span&gt;&lt;span&gt; (0.00%&lt;&#x2F;span&gt;&lt;span&gt;) Digests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Progress.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 3844&#x2F;3844&lt;&#x2F;span&gt;&lt;span&gt; (100.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Rejected.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0&#x2F;3844&lt;&#x2F;span&gt;&lt;span&gt; (0.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Restore.Point....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 62&#x2F;62&lt;&#x2F;span&gt;&lt;span&gt; (100.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Restore.Sub.#1...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Salt:0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Amplifier:61-62&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Iteration:0-999&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Candidate.Engine.:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Device&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Generator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Candidates.#1....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Xa&lt;&#x2F;span&gt;&lt;span&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; XQ&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;The&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; wordlist&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; or&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; mask&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; that&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; you&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; are&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; using&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; too&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; small.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;This&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; means&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; that&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hashcat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cannot&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; use&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; full&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; parallel&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; power&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; your&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; device&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;s&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Unless&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; you&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; supply&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; work,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; your&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cracking&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; speed&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; will&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; drop.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;For&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; tips&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; on&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; supplying&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; work,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; see:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;hashcat.net&#x2F;faq&#x2F;morework&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Approaching&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; final&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; keyspace&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; workload&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; adjusted.&lt;&#x2F;span&gt;&lt;span&gt;           &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Session..........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hashcat&lt;&#x2F;span&gt;&lt;span&gt;                                &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Status...........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Exhausted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hash.Mode........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 13600&lt;&#x2F;span&gt;&lt;span&gt; (WinZip&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hash.Target......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;zip2&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;abf015b7750c67f9&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;f8fe&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c97f48465ca6a9...&#x2F;zip2&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Time.Started.....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:53:55&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;span&gt; (6&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; secs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Time.Estimated...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:54:01&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;span&gt; (0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; secs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Kernel.Feature...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Pure&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Kernel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Mask.......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?1?1?1&lt;&#x2F;span&gt;&lt;span&gt; [3&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Charset....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?l?u?d,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Queue......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 3&#x2F;4&lt;&#x2F;span&gt;&lt;span&gt; (75.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Speed.#1.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;    40570&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; H&#x2F;s&lt;&#x2F;span&gt;&lt;span&gt; (8.17ms&lt;&#x2F;span&gt;&lt;span&gt;) @ Accel:16 Loops:999 Thr:16 Vec:1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Recovered........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0&#x2F;1&lt;&#x2F;span&gt;&lt;span&gt; (0.00%&lt;&#x2F;span&gt;&lt;span&gt;) Digests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Progress.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 238328&#x2F;238328&lt;&#x2F;span&gt;&lt;span&gt; (100.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Rejected.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0&#x2F;238328&lt;&#x2F;span&gt;&lt;span&gt; (0.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Restore.Point....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 3844&#x2F;3844&lt;&#x2F;span&gt;&lt;span&gt; (100.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Restore.Sub.#1...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Salt:0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Amplifier:61-62&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Iteration:0-999&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Candidate.Engine.:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Device&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Generator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Candidates.#1....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; XFz&lt;&#x2F;span&gt;&lt;span&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; XQz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;zip2&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;abf015b7750c67f9&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;f8fe&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;c97f48465ca6a99031db50f79a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;d9e156b830df03899575&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;$&#x2F;zip2$:ab12&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                                          &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Session..........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hashcat&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Status...........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Cracked&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hash.Mode........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 13600&lt;&#x2F;span&gt;&lt;span&gt; (WinZip&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Hash.Target......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;zip2&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;abf015b7750c67f9&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;f8fe&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;c97f48465ca6a9...&#x2F;zip2&lt;&#x2F;span&gt;&lt;span&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Time.Started.....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:54:04&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;span&gt; (1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; sec&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Time.Estimated...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:54:05&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;span&gt; (0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; secs&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Kernel.Feature...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Pure&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Kernel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Mask.......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?1?1?1?1&lt;&#x2F;span&gt;&lt;span&gt; [4&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Charset....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ?l?u?d,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Undefined&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Guess.Queue......:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 4&#x2F;4&lt;&#x2F;span&gt;&lt;span&gt; (100.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Speed.#1.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;    49139&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; H&#x2F;s&lt;&#x2F;span&gt;&lt;span&gt; (101.71ms&lt;&#x2F;span&gt;&lt;span&gt;) @ Accel:16 Loops:999 Thr:16 Vec:1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Recovered........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1&#x2F;1&lt;&#x2F;span&gt;&lt;span&gt; (100.00%&lt;&#x2F;span&gt;&lt;span&gt;) Digests&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Progress.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 36864&#x2F;14776336&lt;&#x2F;span&gt;&lt;span&gt; (0.25%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Rejected.........:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0&#x2F;36864&lt;&#x2F;span&gt;&lt;span&gt; (0.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Restore.Point....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0&#x2F;238328&lt;&#x2F;span&gt;&lt;span&gt; (0.00%&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Restore.Sub.#1...:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Salt:0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Amplifier:5-6&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Iteration:0-999&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Candidate.Engine.:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Device&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Generator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Candidates.#1....:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; aari&lt;&#x2F;span&gt;&lt;span&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; arIS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Started:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:53:42&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Stopped:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Sat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Apr&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:54:05&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2023&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;real&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0m23,617s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 0m6,331s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sys&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  0m10,747s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That&#x27;s a lot of logs; each block represents the outcome of the exploration of length-value space.&lt;&#x2F;p&gt;
&lt;p&gt;In any case, it found the password in 23 seconds, two times faster than &lt;code&gt;zip-password-finder&lt;&#x2F;code&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;At peak speed, it processed &lt;code&gt;49139 H&#x2F;s&lt;&#x2F;code&gt; which is roughly 10 times faster than &lt;code&gt;zip-password-finder&lt;&#x2F;code&gt; on my configuration.&lt;&#x2F;p&gt;
&lt;p&gt;It does so while still complaining about not being able to fully use the system.&lt;&#x2F;p&gt;
&lt;p&gt;For this reason, I expect the difference between the two tools to be much larger with a larger password.&lt;&#x2F;p&gt;
&lt;p&gt;Especially if you have a real graphics card, the throughput will likely be expressed in &lt;code&gt;MH&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Hashcat is a fantastic tool with great performance; it was however not easy to set up, so it may be reserved for advanced users.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-work&quot;&gt;Future work&lt;a class=&quot;zola-anchor&quot; href=&quot;#future-work&quot; aria-label=&quot;Anchor link for: future-work&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The re-architecting has not solved the scaling issues; it would be interesting to dig deeper and benchmark the code on a machine with a much larger number of cores.&lt;&#x2F;p&gt;
&lt;p&gt;Talking about testing different hardware, it would be great to have results using a CPU with the &lt;code&gt;sha&lt;&#x2F;code&gt; instruction to benefit from proper hardware acceleration.&lt;&#x2F;p&gt;
&lt;p&gt;Being able to speed up the default implementation of the &lt;code&gt;sha1&lt;&#x2F;code&gt; crate would also yield significant gains.&lt;&#x2F;p&gt;
&lt;p&gt;A current issue is the accumulation of technical debt; by contributing the AES info extraction helpers upstream to &lt;code&gt;zip-rs&lt;&#x2F;code&gt;, we would avoid having to maintain a fork forever.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, Hashcat has made a great impression, and I would like to explore it for further inspiration.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This article has explained a few performance optimizations that helped make &lt;code&gt;zip-password-finder&lt;&#x2F;code&gt; a bit faster over time.&lt;&#x2F;p&gt;
&lt;p&gt;However, it has also highlighted that the recent efforts have entered a zone of diminishing returns due to a clear bottleneck.&lt;&#x2F;p&gt;
&lt;p&gt;It seems cracking hashes requires dedicated hardware: be it CPUs with particular instructions or even better GPUs.&lt;&#x2F;p&gt;
&lt;p&gt;This has been made somewhat clear by comparing our Rust program to the great Hashcat.&lt;&#x2F;p&gt;
&lt;p&gt;In general, expert tooling tends to perform very well but suffers from an accessibility issue.&lt;&#x2F;p&gt;
&lt;p&gt;The project &lt;code&gt;zip-password-finder&lt;&#x2F;code&gt; is very easy to use but has a long way to go to be competitive.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Support for thread dump in hprof-slurp 0.5.0</title>
        <published>2022-10-17T00:00:00+00:00</published>
        <updated>2022-10-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/threads-in-hprof-slurp-0-5-0/"/>
        <id>https://agourlay.github.io/threads-in-hprof-slurp-0-5-0/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/threads-in-hprof-slurp-0-5-0/">&lt;p&gt;This short article is an announcement for the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;hprof-slurp&#x2F;releases&#x2F;tag&#x2F;v0.5.0&quot;&gt;0.5.0&lt;&#x2F;a&gt; release of the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;hprof-slurp&quot;&gt;hprof-slurp&lt;&#x2F;a&gt; project.&lt;&#x2F;p&gt;
&lt;p&gt;The goal of this project is to build a JVM heap dump analyzer written in Rust specialized for very large heap dumps.&lt;&#x2F;p&gt;
&lt;p&gt;This release introduces the support for reporting the traces of the threads found in the heap dump.&lt;&#x2F;p&gt;
&lt;p&gt;Meaning, users can now see which part of their application was running at the time of the dump!&lt;&#x2F;p&gt;
&lt;p&gt;It is achieved by stitching together the stacktrace and stackframe data into a coherent output at the end of the parsing phase.&lt;&#x2F;p&gt;
&lt;p&gt;It may slightly increase the memory consumption at runtime due to the additional data captured.&lt;&#x2F;p&gt;
&lt;p&gt;There is still room for improvement as important pieces of information are missing, such as the name of the thread and its &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;en&#x2F;java&#x2F;javase&#x2F;18&#x2F;docs&#x2F;api&#x2F;java.base&#x2F;java&#x2F;lang&#x2F;Thread.State.html&quot;&gt;Java Thread.State&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;However, the addition of this feature is a net improvement over what was previously possible and will hopefully help users during their investigations.&lt;&#x2F;p&gt;
&lt;p&gt;All non-empty threads&#x27; stacktraces are reported and their format should be compatible with existing tools, such as the &lt;code&gt;Analyze stacktrace&lt;&#x2F;code&gt; feature in IntelliJ IDEA for convenience.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example&quot;&gt;Example&lt;a class=&quot;zola-anchor&quot; href=&quot;#example&quot; aria-label=&quot;Anchor link for: example&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;I will use the &lt;code&gt;pets.bin&lt;&#x2F;code&gt; dump file introduced in a previous benchmarking &lt;a href=&quot;&#x2F;rust-performance-retrospective-part1&#x2F;&quot;&gt;article&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This is a 34Gb heap dump taken while hammering a running instance of &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;spring-petclinic&#x2F;spring-petclinic-rest&quot;&gt;Spring&#x27;s REST petclinic&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The thread dump feature is on by default, the analysis of &lt;code&gt;pets.bin&lt;&#x2F;code&gt; outputs a total of 224 stacktraces.&lt;&#x2F;p&gt;
&lt;p&gt;Below is the longest I could find for fun.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Thread 222&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at jdk.internal.misc.Unsafe.park (Unsafe.java:native method)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at java.util.concurrent.locks.LockSupport.parkNanos (LockSupport.java:252)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at java.util.concurrent.SynchronousQueue$TransferQueue.transfer (SynchronousQueue.java:704)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at java.util.concurrent.SynchronousQueue.poll (SynchronousQueue.java:903)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at com.zaxxer.hikari.util.ConcurrentBag.borrow (ConcurrentBag.java:151)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at com.zaxxer.hikari.pool.HikariPool.getConnection (HikariPool.java:180)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at com.zaxxer.hikari.pool.HikariPool.getConnection (HikariPool.java:162)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at com.zaxxer.hikari.HikariDataSource.getConnection (HikariDataSource.java:128)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection (DatasourceConnectionProviderImpl.java:122)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.hibernate.internal.NonContextualJdbcConnectionAccess.obtainConnection (NonContextualJdbcConnectionAccess.java:38)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.acquireConnectionIfNeeded (LogicalConnectionManagedImpl.java:108)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.getPhysicalConnection (LogicalConnectionManagedImpl.java:138)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.hibernate.internal.SessionImpl.connection (SessionImpl.java:520)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction (HibernateJpaDialect.java:152)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.orm.jpa.JpaTransactionManager.doBegin (JpaTransactionManager.java:421)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction (AbstractPlatformTransactionManager.java:400)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction (AbstractPlatformTransactionManager.java:373)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary (TransactionAspectSupport.java:595)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction (TransactionAspectSupport.java:382)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.transaction.interceptor.TransactionInterceptor.invoke (TransactionInterceptor.java:119)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:186)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed (CglibAopProxy.java:753)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept (CglibAopProxy.java:698)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.samples.petclinic.service.ClinicServiceImpl$$EnhancerBySpringCGLIB$$a06977e9.findAllVisits (&amp;lt;generated&amp;gt;:unknown line number)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.samples.petclinic.rest.controller.VisitRestController.listVisits (VisitRestController.java:60)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.samples.petclinic.rest.controller.VisitRestController$$FastClassBySpringCGLIB$$8641bcb0.invoke (&amp;lt;generated&amp;gt;:unknown line number)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.cglib.proxy.MethodProxy.invoke (MethodProxy.java:218)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint (CglibAopProxy.java:783)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:163)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed (CglibAopProxy.java:753)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.validation.beanvalidation.MethodValidationInterceptor.invoke (MethodValidationInterceptor.java:123)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:186)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed (CglibAopProxy.java:753)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept (CglibAopProxy.java:698)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.samples.petclinic.rest.controller.VisitRestController$$EnhancerBySpringCGLIB$$2bf2b676.listVisits (&amp;lt;generated&amp;gt;:unknown line number)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (NativeMethodAccessorImpl.java:native method)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:77)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at java.lang.reflect.Method.invoke (Method.java:568)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke (InvocableHandlerMethod.java:205)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest (InvocableHandlerMethod.java:150)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle (ServletInvocableHandlerMethod.java:117)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod (RequestMappingHandlerAdapter.java:895)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal (RequestMappingHandlerAdapter.java:808)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle (AbstractHandlerMethodAdapter.java:87)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.servlet.DispatcherServlet.doDispatch (DispatcherServlet.java:1067)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.servlet.DispatcherServlet.doService (DispatcherServlet.java:963)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.servlet.FrameworkServlet.processRequest (FrameworkServlet.java:1006)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.servlet.FrameworkServlet.doGet (FrameworkServlet.java:898)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at javax.servlet.http.HttpServlet.service (HttpServlet.java:655)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.servlet.FrameworkServlet.service (FrameworkServlet.java:883)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at javax.servlet.http.HttpServlet.service (HttpServlet.java:764)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:227)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:162)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.tomcat.websocket.server.WsFilter.doFilter (WsFilter.java:53)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:189)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:162)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:327)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke (FilterSecurityInterceptor.java:115)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter (FilterSecurityInterceptor.java:81)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter (ExceptionTranslationFilter.java:122)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter (ExceptionTranslationFilter.java:116)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.session.SessionManagementFilter.doFilter (SessionManagementFilter.java:126)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.session.SessionManagementFilter.doFilter (SessionManagementFilter.java:81)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter (AnonymousAuthenticationFilter.java:109)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter (SecurityContextHolderAwareRequestFilter.java:149)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter (RequestCacheAwareFilter.java:63)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter (LogoutFilter.java:103)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter (LogoutFilter.java:89)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter (HeaderWriterFilter.java:90)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal (HeaderWriterFilter.java:75)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:117)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter (SecurityContextPersistenceFilter.java:110)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter (SecurityContextPersistenceFilter.java:80)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal (WebAsyncManagerIntegrationFilter.java:55)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:117)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter (FilterChainProxy.java:336)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy.doFilterInternal (FilterChainProxy.java:211)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.security.web.FilterChainProxy.doFilter (FilterChainProxy.java:183)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate (DelegatingFilterProxy.java:354)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.DelegatingFilterProxy.doFilter (DelegatingFilterProxy.java:267)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:189)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:162)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.RequestContextFilter.doFilterInternal (RequestContextFilter.java:100)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:117)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:189)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:162)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.FormContentFilter.doFilterInternal (FormContentFilter.java:93)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:117)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:189)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:162)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal (WebMvcMetricsFilter.java:96)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:117)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:189)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:162)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal (CharacterEncodingFilter.java:201)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.springframework.web.filter.OncePerRequestFilter.doFilter (OncePerRequestFilter.java:117)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter (ApplicationFilterChain.java:189)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:162)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.StandardWrapperValve.invoke (StandardWrapperValve.java:197)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.StandardContextValve.invoke (StandardContextValve.java:97)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.authenticator.AuthenticatorBase.invoke (AuthenticatorBase.java:540)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.StandardHostValve.invoke (StandardHostValve.java:135)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:92)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.core.StandardEngineValve.invoke (StandardEngineValve.java:78)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.catalina.connector.CoyoteAdapter.service (CoyoteAdapter.java:357)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.coyote.http11.Http11Processor.service (Http11Processor.java:382)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.coyote.AbstractProcessorLight.process (AbstractProcessorLight.java:65)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.coyote.AbstractProtocol$ConnectionHandler.process (AbstractProtocol.java:895)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun (NioEndpoint.java:1732)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.tomcat.util.net.SocketProcessorBase.run (SocketProcessorBase.java:49)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1191)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:659)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run (TaskThread.java:61)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  at java.lang.Thread.run (Thread.java:833)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Brute forcing protected ZIP archives in Rust</title>
        <published>2022-10-03T00:00:00+00:00</published>
        <updated>2022-10-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/brute-forcing-protected-zip-rust/"/>
        <id>https://agourlay.github.io/brute-forcing-protected-zip-rust/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/brute-forcing-protected-zip-rust/">&lt;p&gt;This article explains how to brute force the password of protected ZIP archives using Rust. It is primarily targeted at beginner Rust developers, but it will surely be interesting to a wider audience.&lt;&#x2F;p&gt;
&lt;p&gt;The full code with better error handling and proper command line arguments (CLI) is available at &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;zip-password-finder&quot;&gt;zip-password-finder&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;context&quot;&gt;Context&lt;a class=&quot;zola-anchor&quot; href=&quot;#context&quot; aria-label=&quot;Anchor link for: context&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;A while back, I found myself in possession of a ZIP archive containing family data that I could not access.
The archive was protected by a password which no one knew.&lt;&#x2F;p&gt;
&lt;p&gt;After a short investigation, I found several tools advertised as being capable of recovering passwords for various types of compressed archives.
However, most of them looked rather fishy or required a license, which made me rather skeptical.&lt;&#x2F;p&gt;
&lt;p&gt;It is at that point that I reached the conclusion that building such a tool myself would be a good learning opportunity.&lt;&#x2F;p&gt;
&lt;p&gt;I might be able to recover the data and it could be the subject of a blog article!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;a class=&quot;zola-anchor&quot; href=&quot;#architecture&quot; aria-label=&quot;Anchor link for: architecture&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;We can picture our future program as having two main parts.&lt;&#x2F;p&gt;
&lt;p&gt;The first part is about generating candidate passwords. This could be done by either loading passwords from a dictionary or by simply generating all possible words ourselves.&lt;&#x2F;p&gt;
&lt;p&gt;The second part is then responsible for testing those candidates against the archive, one by one until the password is found or no more candidates are available.&lt;&#x2F;p&gt;
&lt;p&gt;Testing millions of passwords using a brute force strategy sounds like something that is CPU bound. Therefore, we should structure our program so that the second part can scale nicely with the number of cores on the host machine.&lt;&#x2F;p&gt;
&lt;p&gt;A common approach for this type of problem is to use a set of workers to process tasks from a shared queue.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-10-03&amp;#x2F;architecture.png&quot;
         alt=&quot;Architecture&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;In practice, we will orchestrate the password generator and workers as threads communicating via a channel.&lt;&#x2F;p&gt;
&lt;p&gt;Channels are a type of unidirectional asynchronous communication between threads that allows information to flow between the &lt;code&gt;Sender&lt;&#x2F;code&gt; and the &lt;code&gt;Receiver&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There are several flavors of channels. In our case, we need to support a single producer and multiple consumers, a.k.a. SPMC (but MPMC will do as well).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dictionary&quot;&gt;Dictionary&lt;a class=&quot;zola-anchor&quot; href=&quot;#dictionary&quot; aria-label=&quot;Anchor link for: dictionary&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In order to keep the scope small for the beginning, we will start by retrieving passwords from an existing dictionary file.&lt;&#x2F;p&gt;
&lt;p&gt;The following file &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;danielmiessler&#x2F;SecLists&#x2F;blob&#x2F;master&#x2F;Passwords&#x2F;xato-net-10-million-passwords.txt&quot;&gt;Passwords&#x2F;xato-net-10-million-passwords.txt&lt;&#x2F;a&gt; found on GitHub looks like a perfect candidate.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s fetch it and have a peek at its content:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;wget&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;danielmiessler&#x2F;SecLists&#x2F;master&#x2F;Passwords&#x2F;xato-net-10-million-passwords.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ls&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;lah&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; xato-net-10-million-passwords.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; awk&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;F&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;print $5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;47M&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;wc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; xato-net-10-million-passwords.txt&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;5189454&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; xato-net-10-million-passwords.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;10&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; xato-net-10-million-passwords.txt&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;123456&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;password&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;12345678&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;qwerty&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;123456789&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;12345&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;1234&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;111111&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;1234567&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;dragon&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It actually contains only 5.189.454 passwords but that should be more than enough for our testing use case. We can start getting our hands dirty.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; zip-password-finder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Our program will have a thread reading the content of the password dictionary and pushing each line into a shared channel with the workers.&lt;&#x2F;p&gt;
&lt;p&gt;There will be millions of password candidates. We need something very fast.&lt;&#x2F;p&gt;
&lt;p&gt;We will use the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;crossbeam-rs&#x2F;crossbeam&quot;&gt;crossbeam-channel&lt;&#x2F;a&gt; crate for our channels because they are far superior to the channels available in &lt;code&gt;std::sync::mpsc&lt;&#x2F;code&gt; in every way.&lt;&#x2F;p&gt;
&lt;p&gt;Those better channels might even make it to the standard library in the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;pull&#x2F;93563&quot;&gt;future&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; zip-password-finder&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; crossbeam-channel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here is our reader:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; crossbeam_channel&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Sender&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;File&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;BufRead&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; BufReader&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;thread&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;JoinHandle&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; start_password_reader&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;file_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; PathBuf&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; send_password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Sender&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; JoinHandle&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Builder&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;password-reader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; File&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; reader&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; BufReader&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; line&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; reader&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lines&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; send_password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;line&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                    Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; channel disconnected, stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are a few interesting things to note here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It is a good practice to give names to threads for better error reporting and performance observability.&lt;&#x2F;li&gt;
&lt;li&gt;The function returns a &lt;code&gt;JoinHandle&lt;&#x2F;code&gt; for the caller, our main thread, to wait on.&lt;&#x2F;li&gt;
&lt;li&gt;The entire file is read and pushed into the channel. This might be a problem for larger files.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;password-checker-worker&quot;&gt;Password checker worker&lt;a class=&quot;zola-anchor&quot; href=&quot;#password-checker-worker&quot; aria-label=&quot;Anchor link for: password-checker-worker&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;We will be using the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zip-rs&#x2F;zip&quot;&gt;zip-rs&lt;&#x2F;a&gt; crate for testing the password candidates pulled from the channel.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It supports both &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zip-rs&#x2F;zip&#x2F;pull&#x2F;115&quot;&gt;ZipCrypto&lt;&#x2F;a&gt; and &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zip-rs&#x2F;zip&#x2F;pull&#x2F;203&quot;&gt;AES&lt;&#x2F;a&gt; encrypted zip archives.&lt;&#x2F;p&gt;
&lt;p&gt;This is the first version of the worker thread:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; crossbeam_channel&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Sender&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;File&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;BufRead&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; BufReader&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;thread&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;JoinHandle&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; password_checker&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    index&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    file_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    receive_password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Receiver&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; JoinHandle&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;File&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;file_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;File should exist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Builder&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;format!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;worker-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; index&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; archive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; zip&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ZipArchive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;file&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Archive validated before-hand&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;            loop&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; receive_password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;recv&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                    Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; break&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; channel disconnected, stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                    Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;password&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;                        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; archive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;by_index_decrypt&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; decrypt first file in archive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                        match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; res&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                            Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Unexpected error &lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; e&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                            Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; invalid password - continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                            Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                                println!&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Password found:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;                                break&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This straightforward approach is unfortunately not enough as it yields false positive passwords from time to time.&lt;&#x2F;p&gt;
&lt;p&gt;The Rustdoc for &lt;code&gt;by_index_decrypt&lt;&#x2F;code&gt; actually warns about it.&lt;&#x2F;p&gt;

&lt;blockquote class=&quot;callout warning has-title&quot;&gt;
  
  
  &lt;p class=&quot;title&quot;&gt;
    &lt;span class=&quot;icon&quot;&gt;
      &lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot; height=&quot;18&quot;&gt;&lt;path d=&quot;M12.865 3.00017L22.3912 19.5002C22.6674 19.9785 22.5035 20.5901 22.0252 20.8662C21.8732 20.954 21.7008 21.0002 21.5252 21.0002H2.47266C1.92037 21.0002 1.47266 20.5525 1.47266 20.0002C1.47266 19.8246 1.51886 19.6522 1.60663 19.5002L11.1329 3.00017C11.4091 2.52187 12.0206 2.358 12.4989 2.63414C12.651 2.72191 12.7772 2.84815 12.865 3.00017ZM4.20471 19.0002H19.7932L11.9989 5.50017L4.20471 19.0002ZM10.9989 16.0002H12.9989V18.0002H10.9989V16.0002ZM10.9989 9.00017H12.9989V14.0002H10.9989V9.00017Z&quot; fill=&quot;currentColor&quot;&gt;&lt;&#x2F;path&gt;&lt;&#x2F;svg&gt;

    &lt;&#x2F;span&gt;
    &lt;strong&gt;Warning&lt;&#x2F;strong&gt;
  &lt;&#x2F;p&gt;
  &lt;div class=&quot;content&quot;&gt;
    &lt;p&gt;This function sometimes accepts wrong passwords.
This is because the ZIP spec only allows us to check for a 1&#x2F;256 chance that the password is correct.
There are many passwords out there that will also pass the validity checks we are able to perform.
This is a weakness of the ZipCrypto algorithm, due to its fairly primitive approach to cryptography.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
  
&lt;&#x2F;blockquote&gt;

&lt;p&gt;We can work around those collisions by performing a full read of the archive with the password to make sure it is actually correct.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use crossbeam_channel::{Receiver, Sender};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::fs::File;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;use std::io::{BufRead, BufReader};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;use std::io::{BufRead, BufReader, Read};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::path::{Path, PathBuf};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::thread::JoinHandle;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::{fs, thread};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -38,10 +38,14&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_checker(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        let res = archive.by_index_decrypt(0, password.as_bytes()); &#x2F;&#x2F; decrypt first file in archive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        match res {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Err(e) =&amp;gt; panic!(&amp;quot;Unexpected error {:?}&amp;quot;, e),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            Ok(Err(_)) =&amp;gt; (), &#x2F;&#x2F; invalid password - continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;           Ok(Ok(_)) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;               println!(&amp;quot;Password found:{}&amp;quot;, password);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;               break; &#x2F;&#x2F; stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;           Ok(Err(_)) =&amp;gt; (), &#x2F;&#x2F; invalid password&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;           Ok(Ok(mut zip)) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;               &#x2F;&#x2F; Validate password by reading the zip file to make sure it is not merely a hash collision.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;               let mut buffer = Vec::with_capacity(zip.size() as usize);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;               match zip.read_to_end(&amp;amp;mut buffer) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                   Err(_) =&amp;gt; (), &#x2F;&#x2F; password collision - continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                   Ok(_) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                       println!(&amp;quot;Password found:{}&amp;quot;, password);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                       break; &#x2F;&#x2F; stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                   }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;               }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Again, a few interesting things to note here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Each worker thread gets a unique name.&lt;&#x2F;li&gt;
&lt;li&gt;The worker is &lt;code&gt;looping&lt;&#x2F;code&gt; until the password is found or the channel is closed.&lt;&#x2F;li&gt;
&lt;li&gt;Each worker opens the Zip file in memory to avoid extra coordination.&lt;&#x2F;li&gt;
&lt;li&gt;The password found is printed to the console.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;putting-it-together&quot;&gt;Putting it together&lt;a class=&quot;zola-anchor&quot; href=&quot;#putting-it-together&quot; aria-label=&quot;Anchor link for: putting-it-together&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;We can now wire things up together nicely and get one step closer to our goal.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; password_finder&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;zip_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password_list_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; workers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; zip_file_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;zip_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password_list_file_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;password_list_path&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;to_path_buf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; channel with backpressure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;send_password&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; receive_password&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Sender&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Receiver&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;String&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;        crossbeam_channel&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;bounded&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;workers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10_000&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; thread handle for password reader&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; password_gen_handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; start_password_reader&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;password_list_file_path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; send_password&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; save all workers handles&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; worker_handles&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;with_capacity&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;workers&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;workers&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; join_handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; password_checker&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; zip_file_path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; receive_password&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        worker_handles&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;push&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;join_handle&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; wait for workers to finish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; h&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; worker_handles&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        h&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; wait for the end of the file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    password_gen_handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first important point here is the use of a bounded channel between the password generator and the workers.&lt;&#x2F;p&gt;
&lt;p&gt;A bounded channel will block the sender once its capacity is reached. This is handy to implement back-pressure.&lt;&#x2F;p&gt;
&lt;p&gt;In our case, the producer is much faster than the consumers, so we are at risk of loading the entire dictionary inside the channel, which is not great for memory usage.&lt;&#x2F;p&gt;
&lt;p&gt;To avoid slowing down the consumers, the capacity is sized according to the number of workers.&lt;&#x2F;p&gt;
&lt;p&gt;Secondly, we are saving all &lt;code&gt;JoinHandle&lt;&#x2F;code&gt; to await the termination of all threads.&lt;&#x2F;p&gt;
&lt;p&gt;And finally, the main function!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; zip_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; env&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;nth&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; dictionary_path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;opt&#x2F;xato-net-10-million-passwords.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; workers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    password_finder&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;zip_path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; dictionary_path&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; workers&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As a command line argument our program accepts the path to an encrypted Zip file, which will be brute forced using a dictionary with 3 workers.&lt;&#x2F;p&gt;
&lt;p&gt;The dictionary path is hard-coded for the time being.&lt;&#x2F;p&gt;
&lt;p&gt;For testing purposes, we need an archive encrypted using a password from the dictionary.&lt;&#x2F;p&gt;
&lt;p&gt;I am picking the entry number 1.000.000, &lt;code&gt;vaanes&lt;&#x2F;code&gt;, to create our encrypted test zip.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sed&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;ne&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1000000p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; xato-net-10-million-passwords.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;vaanes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here are the details of the test archive created using this password.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;zipinfo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; encrypted-test-dict.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Archive:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  encrypted-test-dict.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Zip&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; file&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 202&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; number&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; entries:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;-rw-rw-r--&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  6.3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; unx&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;        9&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Bx&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u099&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 22-Sep-24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 12:19&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; test-xato&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; file,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; uncompressed,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; compressed:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;  -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;77.8%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is pretty small and uses compression as a storage method.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s run our program!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;target&#x2F;release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt; .&#x2F;zip-password-finder encrypted-test-dict.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Checking on the CPU usage with &lt;code&gt;htop&lt;&#x2F;code&gt; yields an expected result.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-10-03&amp;#x2F;htop-3-workers.png&quot;
         alt=&quot;CPU usage with 3 workers&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Three worker threads are going at full speed, and one thread is reading the passwords at a leisurely pace.&lt;&#x2F;p&gt;
&lt;p&gt;After 4 minutes, the program prints on the terminal.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Password found:vaanes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But the program does not terminate right away; it takes more than 20 minutes to finish!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;real&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    23m36,203s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;    72m29,567s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sys&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     0m41,570s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;First the good news: the program found the password!&lt;&#x2F;p&gt;
&lt;p&gt;It processed 1 million passwords in around four minutes using 3 workers which gives us:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1.000.000 passwords tested &#x2F; (4 * 60 seconds) &#x2F; 3 workers =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1389 passwords tested per second per worker assuming linear scaling&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This result provides us with an idea of what can be achieved with this approach.&lt;&#x2F;p&gt;
&lt;p&gt;Secondly, the bad news: our program does not terminate properly, which is a big issue.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;graceful-shutdown&quot;&gt;Graceful shutdown&lt;a class=&quot;zola-anchor&quot; href=&quot;#graceful-shutdown&quot; aria-label=&quot;Anchor link for: graceful-shutdown&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Looking at the code more closely, we can see that we terminate our threads only under specific conditions.&lt;&#x2F;p&gt;
&lt;p&gt;For the password dictionary thread:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If the channel has no consumers attached.&lt;&#x2F;li&gt;
&lt;li&gt;If we reach the end of the dictionary.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And for the worker threads:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If the channel is empty and has no producer attached.&lt;&#x2F;li&gt;
&lt;li&gt;If we find the password.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This explains why our program kept on running previously; we only stopped the thread that found the password!&lt;&#x2F;p&gt;
&lt;p&gt;The program went through the rest of the dictionary using only two workers.&lt;&#x2F;p&gt;
&lt;p&gt;There are different ways to solve this problem. We will try to come up with an &lt;strong&gt;explicit&lt;&#x2F;strong&gt; shutdown sequence that does not rely on timeout nor on the channel being disconnected.&lt;&#x2F;p&gt;
&lt;p&gt;We need a way for the worker thread that finds the password to be able to inform other threads that they can shut down.&lt;&#x2F;p&gt;
&lt;p&gt;First, let&#x27;s have worker threads communicate the password to the main thread instead of simply printing it out in the terminal.&lt;&#x2F;p&gt;
&lt;p&gt;This design is much better and will enable unit testing later on!&lt;&#x2F;p&gt;
&lt;p&gt;As a follow-up, once the main thread receives the password, it will notify all threads to stop using a thread-safe signal.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::path::{Path, PathBuf};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;use std::sync::atomic::{AtomicBool, Ordering};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;use std::sync::Arc;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::thread::JoinHandle;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::{env, fs, thread};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;pub fn start_password_reader(file_path: PathBuf, send_password: Sender&amp;lt;String&amp;gt;) -&amp;gt; JoinHandle&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;pub fn start_password_reader(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    file_path: PathBuf,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    send_password: Sender&amp;lt;String&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    stop_signal: Arc&amp;lt;AtomicBool&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;) -&amp;gt; JoinHandle&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     thread::Builder::new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         .name(&amp;quot;password-reader&amp;quot;.to_string())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         .spawn(move || {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             let file = File::open(file_path).unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             let reader = BufReader::new(file);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             for line in reader.lines() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                match send_password.send(line.unwrap()) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    Ok(_) =&amp;gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    Err(_) =&amp;gt; break, &#x2F;&#x2F; channel disconnected, stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                if stop_signal.load(Ordering::Relaxed) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    break;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                } else {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    match send_password.send(line.unwrap()) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        Ok(_) =&amp;gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        Err(_) =&amp;gt; break, &#x2F;&#x2F; channel disconnected, stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -25,13 +35,15&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_checker(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     index: usize,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     file_path: &amp;amp;Path,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     receive_password: Receiver&amp;lt;String&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    stop_signal: Arc&amp;lt;AtomicBool&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    send_password_found: Sender&amp;lt;String&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; ) -&amp;gt; JoinHandle&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let file = fs::File::open(file_path).expect(&amp;quot;File should exist&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     thread::Builder::new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         .name(format!(&amp;quot;worker-{}&amp;quot;, index))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         .spawn(move || {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             let mut archive = zip::ZipArchive::new(file).expect(&amp;quot;Archive validated before-hand&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;            loop {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            while !stop_signal.load(Ordering::Relaxed) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 match receive_password.recv() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     Err(_) =&amp;gt; break, &#x2F;&#x2F; channel disconnected, stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     Ok(password) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -44,7 +56,12&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_checker(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                 let mut buffer = Vec::with_capacity(zip.size() as usize);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                 match zip.read_to_end(&amp;amp;mut buffer) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                     Err(_) =&amp;gt; (), &#x2F;&#x2F; password collision - continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                    Ok(_) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                        println!(&amp;quot;Password found:{}&amp;quot;, password);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                        break; &#x2F;&#x2F; stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                    Ok(_) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                        &#x2F;&#x2F; Send password and continue processing while waiting for signal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                        send_password_found&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                            .send(password)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                            .expect(&amp;quot;Send found password should not fail&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                 }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                             }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -55,7 +72,7&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_checker(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         .unwrap()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The threads can exit their looping state by probing a stop signal materialized by an &lt;code&gt;Arc&amp;lt;AtomicBool&amp;gt;&lt;&#x2F;code&gt; which is safe and cheap to operate.&lt;&#x2F;p&gt;
&lt;p&gt;Even the worker thread which finds the password will simply wait for the signal, this way we avoid having to handle the special case where there is only a single worker.&lt;&#x2F;p&gt;
&lt;p&gt;And for the wiring and actual graceful shutdown.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;pub fn password_finder(zip_path: &amp;amp;str, password_list_path: &amp;amp;str, workers: usize) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;pub fn password_finder(zip_path: &amp;amp;str, password_list_path: &amp;amp;str, workers: usize) -&amp;gt; Option&amp;lt;String&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let zip_file_path = Path::new(zip_path);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let password_list_file_path = Path::new(password_list_path).to_path_buf();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -63,28 +80,59&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_finder(zip_path: &amp;amp;str, password_list_path: &amp;amp;str, workers: usize)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let (send_password, receive_password): (Sender&amp;lt;String&amp;gt;, Receiver&amp;lt;String&amp;gt;) =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         crossbeam_channel::bounded(workers * 10_000);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let (send_found_password, receive_found_password): (Sender&amp;lt;String&amp;gt;, Receiver&amp;lt;String&amp;gt;) =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        crossbeam_channel::bounded(1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    &#x2F;&#x2F; stop signals to shut down threads&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let stop_workers_signal = Arc::new(AtomicBool::new(false));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let stop_gen_signal = Arc::new(AtomicBool::new(false));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &#x2F;&#x2F; thread handle for password reader&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    let password_gen_handle = start_password_reader(password_list_file_path, send_password);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let password_gen_handle = start_password_reader(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        password_list_file_path,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        send_password,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        stop_gen_signal.clone(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &#x2F;&#x2F; save all workers handles&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let mut worker_handles = Vec::with_capacity(workers);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     for i in 1..=workers {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;        let join_handle = password_checker(i, zip_file_path, receive_password.clone());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        let join_handle = password_checker(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            i,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            zip_file_path,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            receive_password.clone(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            stop_workers_signal.clone(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            send_found_password.clone(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         worker_handles.push(join_handle);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    &#x2F;&#x2F; wait for workers to finish&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    for h in worker_handles {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;        h.join().unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    &#x2F;&#x2F; drop reference in `main` so that it disappears completely with workers for a clean shutdown&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    drop(send_found_password);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    &#x2F;&#x2F; wait for the end of the file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    password_gen_handle.join().unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    match receive_found_password.recv() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        Ok(password_found) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            &#x2F;&#x2F; stop generating values first to avoid deadlock on channel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            stop_gen_signal.store(true, Ordering::Relaxed);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            password_gen_handle.join().unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            &#x2F;&#x2F; stop workers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            stop_workers_signal.store(true, Ordering::Relaxed);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            for h in worker_handles {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                h.join().unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            Some(password_found)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        Err(_) =&amp;gt; None,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; fn main() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let zip_path = env::args().nth(1).unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let dictionary_path = &amp;quot;&#x2F;home&#x2F;agourlay&#x2F;Workspace&#x2F;blog-data&#x2F;find-password-zip&#x2F;xato-net-10-million-passwords.txt&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let workers = 3;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    password_finder(&amp;amp;zip_path, dictionary_path, workers);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    match password_finder(&amp;amp;zip_path, dictionary_path, workers) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        Some(password_found) =&amp;gt; println!(&amp;quot;Password found:{}&amp;quot;, password_found),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        None =&amp;gt; println!(&amp;quot;No password found :(&amp;quot;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The shutdown procedure must be carefully handled to avoid a deadlock of our threads.&lt;&#x2F;p&gt;
&lt;p&gt;Using channels can make our threads block forever if the channel is not disconnected:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;A consuming thread blocks on an empty channel.&lt;&#x2F;li&gt;
&lt;li&gt;A producing thread blocks on a full bounded channel.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This makes the task more difficult given that signals are efficient only if the threads are able to run their inner loop.&lt;&#x2F;p&gt;
&lt;p&gt;Given that we are using a bounded channel, it makes sense to shut down the producer first.&lt;&#x2F;p&gt;
&lt;p&gt;In addition, it is important to manually drop &lt;code&gt;send_found_password&lt;&#x2F;code&gt; to shut down properly when no password is found:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The password generator thread exits at the end of the dictionary.&lt;&#x2F;li&gt;
&lt;li&gt;All workers exit when the channel is disconnected.&lt;&#x2F;li&gt;
&lt;li&gt;All workers drop their clone of &lt;code&gt;Arc&amp;lt;send_found_password&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Deadlock occurs: &lt;code&gt;receive_found_password.recv()&lt;&#x2F;code&gt; won&#x27;t be triggered unless all producers are gone &lt;strong&gt;but&lt;&#x2F;strong&gt; the main thread still holds the initial &lt;code&gt;Arc&amp;lt;send_found_password&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This gives us a valid shutdown sequence:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Drop the initial &lt;code&gt;Arc&amp;lt;send_found_password&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Wait for the found password from a worker.&lt;&#x2F;li&gt;
&lt;li&gt;Toggle shutdown signal password generator.&lt;&#x2F;li&gt;
&lt;li&gt;Join the password generator handle.&lt;&#x2F;li&gt;
&lt;li&gt;Toggle shutdown signal for workers.&lt;&#x2F;li&gt;
&lt;li&gt;Join all the worker handles.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Finding a correct sequence can be a bit subtle, so it is better to test it.&lt;&#x2F;p&gt;
&lt;p&gt;An alternative solution would be to use the timeout-flavored API &lt;code&gt;recv_timeout&lt;&#x2F;code&gt; and &lt;code&gt;send_timeout&lt;&#x2F;code&gt; which enable you to block only for a specific duration.&lt;&#x2F;p&gt;
&lt;p&gt;I have decided to not use those as they are not strictly required, and it forces us to better understand our shutdown sequence :)&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s give it a try!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;target&#x2F;release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt; .&#x2F;zip-password-finder encrypted-test-dict.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; found:vaanes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;real&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  4m23,968s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  13m30,767s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sys&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   0m7,130s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is much better; the application shuts down as soon as the password is found!&lt;&#x2F;p&gt;
&lt;p&gt;But something important is still missing. As a user, we have no feedback while the program is waiting.&lt;&#x2F;p&gt;
&lt;p&gt;It would be great to see how much progress the program is making and have an idea of the estimated run time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;progress-bar&quot;&gt;Progress bar&lt;a class=&quot;zola-anchor&quot; href=&quot;#progress-bar&quot; aria-label=&quot;Anchor link for: progress-bar&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The easiest way to visualize the progress of our program is to set up a progress bar.&lt;&#x2F;p&gt;
&lt;p&gt;One of the best crates for this is &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;console-rs&#x2F;indicatif&quot;&gt;Indicatif&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; indicatif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The progress bar needs to be configured according to our use case.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let zip_file_path = Path::new(zip_path);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let password_list_file_path = Path::new(password_list_path).to_path_buf();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    &#x2F;&#x2F; Setup progress bar&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let progress_bar = ProgressBar::new(0);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let progress_style = ProgressStyle::default_bar()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        .template(&amp;quot;[{elapsed_precise}] {wide_bar} {pos}&#x2F;{len} throughput:{per_sec} (eta:{eta})&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        .expect(&amp;quot;Failed to create progress style&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    progress_bar.set_style(progress_style);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    &#x2F;&#x2F; Refresh terminal 2 times per second to avoid flickering effect&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let draw_target = ProgressDrawTarget::stdout_with_hz(2);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    progress_bar.set_draw_target(draw_target);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    &#x2F;&#x2F; Size progress bar according to dictionary size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let file =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        BufReader::new(File::open(password_list_file_path.clone()).expect(&amp;quot;Unable to open file&amp;quot;));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let total_password_count = file.lines().count();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    progress_bar.set_length(total_password_count as u64);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &#x2F;&#x2F; MPMC channel with backpressure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let (send_password, receive_password): (Sender&amp;lt;String&amp;gt;, Receiver&amp;lt;String&amp;gt;) =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         crossbeam_channel::bounded(workers * 10_000);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -103,6 +122,7&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_finder(zip_path: &amp;amp;str, password_list_path: &amp;amp;str, workers: usize)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             receive_password.clone(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             stop_workers_signal.clone(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             send_found_password.clone(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            progress_bar.clone(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         worker_handles.push(join_handle);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -120,6 +140,7&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_finder(zip_path: &amp;amp;str, password_list_path: &amp;amp;str, workers: usize)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             for h in worker_handles {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 h.join().unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            progress_bar.finish_and_clear();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             Some(password_found)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         Err(_) =&amp;gt; None,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The most important points are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We set up a template to display some useful information regarding processing speed and ETA.&lt;&#x2F;li&gt;
&lt;li&gt;The progress bar refresh rate is fixed to avoid flickering due to the high frequency of updates.&lt;&#x2F;li&gt;
&lt;li&gt;The progress bar length is sized according to the length of the dictionary.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The integration is rather straightforward on the workers&#x27; side; simply increment the progress bar after each candidate.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -37,6 +38,7&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_checker(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     receive_password: Receiver&amp;lt;String&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     stop_signal: Arc&amp;lt;AtomicBool&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     send_password_found: Sender&amp;lt;String&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    progress_bar: ProgressBar,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; ) -&amp;gt; JoinHandle&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let file = fs::File::open(file_path).expect(&amp;quot;File should exist&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     thread::Builder::new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -65,6 +67,7&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_checker(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                 }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                             }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        progress_bar.inc(1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running this new version displays our new fancy progress bar in action!&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-10-03&amp;#x2F;progressbar.png&quot;
         alt=&quot;Progress bar&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The processing speed and ETA confirm our previous observations.&lt;&#x2F;p&gt;
&lt;p&gt;But can we go any faster?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scaling-up&quot;&gt;Scaling up&lt;a class=&quot;zola-anchor&quot; href=&quot;#scaling-up&quot; aria-label=&quot;Anchor link for: scaling-up&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;We previously found that the program can test around 1389 passwords per second per worker when used with 3 workers.&lt;&#x2F;p&gt;
&lt;p&gt;What about automatically sizing the number of workers according to the host?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::sync::atomic::{AtomicBool, Ordering};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::sync::Arc;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;use std::thread::JoinHandle;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;use std::thread::{available_parallelism, JoinHandle};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; use std::{env, fs, thread};&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;use std::cmp::max;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; pub fn start_password_reader(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     file_path: PathBuf,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -151,7 +152,8&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; fn main() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let zip_path = env::args().nth(1).unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let dictionary_path = &amp;quot;&#x2F;opt&#x2F;xato-net-10-million-passwords.txt&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    let workers = 3;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let num_cores = available_parallelism().unwrap().get();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let workers = max(1,  num_cores - 1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this change, we are using &lt;code&gt;num_cores - 1&lt;&#x2F;code&gt; worker threads and one dictionary reader thread.&lt;&#x2F;p&gt;
&lt;p&gt;On my 8-core machine, it yields the following usage.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-10-03&amp;#x2F;htop-7-workers.png&quot;
         alt=&quot;CPU usage 7 workers&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;This is a nice CPU utilization to keep you warm during the winter.&lt;&#x2F;p&gt;
&lt;p&gt;Unfortunately, it does not seem to be much faster.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; &#x2F;target&#x2F;release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;time&lt;&#x2F;span&gt;&lt;span&gt; .&#x2F;zip-password-finder encrypted-test-dict.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Password&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; found:vaanes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;real&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  3m57,826s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  27m52,591s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;sys&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;   0m9,621s&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is barely 30 seconds faster than the 3 workers version!&lt;&#x2F;p&gt;
&lt;p&gt;It seems our program is suffering from scalability issues.&lt;&#x2F;p&gt;
&lt;p&gt;To investigate this, let&#x27;s start by making the number of workers configurable through the CLI.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; fn main() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    let zip_path = env::args().nth(1).unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let mut args_iter = env::args().skip(1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let zip_path = args_iter.next().unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let dictionary_path = &amp;quot;&#x2F;opt&#x2F;xato-net-10-million-passwords.txt&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    let num_cores = available_parallelism().unwrap().get();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    let workers = max(1,  num_cores - 1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let workers: usize = match args_iter.next() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        None =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            let num_cores = available_parallelism().unwrap().get();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            max(1, num_cores - 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        Some(count) =&amp;gt; count.parse().unwrap(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then let&#x27;s reach for our favorite CLI benchmarking tool, the fantastic &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sharkdp&#x2F;hyperfine&quot;&gt;hyperfine&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Using the following magic incantation, we will get reliable measurements for runs with different worker count.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hyperfine&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-runs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-warmup&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-markdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; workers.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-json&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; workers.json&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 6&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 7&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 7&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After the runs, the &lt;code&gt;workers.md&lt;&#x2F;code&gt; file contains the following table:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;559.522 ± 7.091&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;554.509&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;564.536&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2.51 ± 0.03&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;338.590 ± 0.102&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;338.518&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;338.662&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.52 ± 0.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;264.297 ± 0.650&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;263.838&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;264.757&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.18 ± 0.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;223.284 ± 0.047&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;223.251&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;223.317&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;5&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;224.617 ± 0.082&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;224.559&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;224.675&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.01 ± 0.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;6&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;226.690 ± 0.421&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;226.392&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;226.987&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.02 ± 0.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;7&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;232.129 ± 0.009&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;232.122&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;232.135&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.04 ± 0.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;8&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;234.367 ± 0.118&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;234.284&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;234.450&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.05 ± 0.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;It looks quite bad. Let&#x27;s plot it so that visual people can be disappointed as well.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-10-03&amp;#x2F;whiskers.png&quot;
         alt=&quot;Whiskers plot&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;One would expect performance to grow linearly, but that is absolutely not the case here.&lt;&#x2F;p&gt;
&lt;p&gt;Not only is the speedup not linear, but the program only gets faster up to 4 workers at approximately 4500 passwords&#x2F;sec.&lt;&#x2F;p&gt;
&lt;p&gt;Sounds like a good time to mention &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Amdahl%27s_law&quot;&gt;Amdahl&#x27;s law&lt;&#x2F;a&gt;, which predicts the theoretical speedup when using multiple processors depending on the portion of the work being parallel.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-10-03&amp;#x2F;AmdahlsLaw-wiki.png&quot;
         alt=&quot;AmdahlsLaw graph&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Our workload is &lt;strong&gt;supposed&lt;&#x2F;strong&gt; to be very parallelisable, each worker processing candidate passwords in isolation at full speed. We should be getting more impressive speedups.&lt;&#x2F;p&gt;
&lt;p&gt;The simplest explanation is that our program is not as parallel as we thought. There must be some form of hidden coordination preventing our program from scaling properly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hyper-threading&quot;&gt;Hyper-threading&lt;a class=&quot;zola-anchor&quot; href=&quot;#hyper-threading&quot; aria-label=&quot;Anchor link for: hyper-threading&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;However, I find it very suspicious that the best performance occurs at 4 workers. This is a nice power of 2.&lt;&#x2F;p&gt;
&lt;p&gt;I am running the benchmarks on a laptop running Linux on an Intel &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.intel.com&#x2F;content&#x2F;www&#x2F;us&#x2F;en&#x2F;products&#x2F;sku&#x2F;201896&#x2F;intel-core-i710610u-processor-8m-cache-up-to-4-90-ghz&#x2F;specifications.html&quot;&gt;i7-10610U&lt;&#x2F;a&gt; CPU.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the specification, we can see the following.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;lscpu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Vendor&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ID:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;               GenuineIntel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  Model&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; name:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;            Intel&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;R&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Core&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;TM&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; i7-10610U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; CPU&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; @&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1.80GHz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    CPU&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; family:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;          6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Model:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;               142&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Thread(s&lt;&#x2F;span&gt;&lt;span&gt;) per core:  2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    Core(s&lt;&#x2F;span&gt;&lt;span&gt;) per socket:  4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Instead of 8 cores, there are 4 physical cores and 2 logical threads per core!&lt;&#x2F;p&gt;
&lt;p&gt;In my case this is &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hyper-threading&quot;&gt;Intel&#x27;s Hyper-threading Technology&lt;&#x2F;a&gt;, which enables cores to have two lanes of execution. The core can switch between those while waiting for data to be fetched from main memory or caches.&lt;&#x2F;p&gt;
&lt;p&gt;Outside the various marketing performance claims from Intel, it seems that &lt;code&gt;Hyper-threading&lt;&#x2F;code&gt; is not adapted to all types of workload.&lt;&#x2F;p&gt;
&lt;p&gt;Given our very CPU-heavy workload, in which we need the full attention of each core on a single worker. It makes sense to not rely on it and only use the number of physical cores to size the number of workers.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; num_cpus&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The previous benchmark has also shown that the best performance occurs where the number of workers is equal to the number of cores, meaning that the reader thread is very cheap in comparison.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let workers: usize = match args_iter.next() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;        None =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;            let num_cores = available_parallelism().unwrap().get();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;            max(1, num_cores - 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        None =&amp;gt; num_cpus::get_physical(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         Some(count) =&amp;gt; count.parse().unwrap(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Hopefully, those workers will be allocated to different cores even if the host supports &lt;code&gt;Hyper-threading&lt;&#x2F;code&gt; for maximum efficiency.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;going-faster&quot;&gt;Going faster&lt;a class=&quot;zola-anchor&quot; href=&quot;#going-faster&quot; aria-label=&quot;Anchor link for: going-faster&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Even limiting ourselves to physical cores, the scaling from one to four cores was not entirely linear.&lt;&#x2F;p&gt;
&lt;p&gt;For a quick sanity check, we can generate a flamegraph to see where the CPU time is spent.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-10-03&amp;#x2F;flamegraph.png&quot;
         alt=&quot;Flamegraph&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The various threads are nicely visible (full &lt;a href=&quot;&#x2F;2022-10-03&#x2F;flamegraph.svg&quot;&gt;flamegraph&lt;&#x2F;a&gt; available).&lt;&#x2F;p&gt;
&lt;p&gt;It seems the reader thread spends most of its time snoozing, blocked when the channel is full, meaning that it is not a bottleneck.&lt;&#x2F;p&gt;
&lt;p&gt;We can zoom in on one of the workers.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-10-03&amp;#x2F;flamegraph-worker.png&quot;
         alt=&quot;Flamegraph&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;It is basically spending most of its time in &lt;code&gt;sha1::compress::soft::compress&lt;&#x2F;code&gt; in a deep call stack from &lt;code&gt;zip-rs&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There is nothing obvious to optimize from our worker code given the decryption API we have to work with.&lt;&#x2F;p&gt;
&lt;p&gt;We can focus on decreasing potential synchronization issues between our worker threads. When can they possibly interfere with each other?&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the code closely, we can see that for every password candidate the workers are accessing:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the receive channel handle&lt;&#x2F;li&gt;
&lt;li&gt;the shutdown signal&lt;&#x2F;li&gt;
&lt;li&gt;the progress bar&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A first hypothesis is that those actions increase the cost of processing a single candidate and introduce some form of coordination between threads as they are accessing shared memory.&lt;&#x2F;p&gt;
&lt;p&gt;A naive approach to reducing coordination is to give more to the workers to process in isolation by, for instance, batching up a bunch of candidates together in the channel.&lt;&#x2F;p&gt;
&lt;p&gt;What would the optimal batch size be? Let&#x27;s implement batching and make the batch size configurable in place of the &quot;workers&quot; argument for a quick experiment.&lt;&#x2F;p&gt;
&lt;p&gt;First batching the reader thread:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; pub fn start_password_reader(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     file_path: PathBuf,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    send_password: Sender&amp;lt;String&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    send_password: Sender&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    batch_size: usize,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     stop_signal: Arc&amp;lt;AtomicBool&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; ) -&amp;gt; JoinHandle&amp;lt;()&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     thread::Builder::new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -19,13 +20,18&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn start_password_reader(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         .spawn(move || {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             let file = File::open(file_path).unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             let reader = BufReader::new(file);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;            let mut batch = Vec::with_capacity(batch_size);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             for line in reader.lines() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                if stop_signal.load(Ordering::Relaxed) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    break;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                } else {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    match send_password.send(line.unwrap()) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                        Ok(_) =&amp;gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                        Err(_) =&amp;gt; break, &#x2F;&#x2F; channel disconnected, stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                batch.push(line.unwrap());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                &#x2F;&#x2F; push once the batch is full&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                if batch.len() == batch_size {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    if stop_signal.load(Ordering::Relaxed) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        break;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    } else {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        match send_password.send(batch.clone()) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                            Ok(_) =&amp;gt; batch.clear(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                            Err(_) =&amp;gt; break, &#x2F;&#x2F; channel disconnected, stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then the worker thread:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; pub fn password_checker(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     index: usize,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     file_path: &amp;amp;Path,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    receive_password: Receiver&amp;lt;String&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    receive_password: Receiver&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     stop_signal: Arc&amp;lt;AtomicBool&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     send_password_found: Sender&amp;lt;String&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     progress_bar: ProgressBar,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -49,26 +55,30&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_checker(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             while !stop_signal.load(Ordering::Relaxed) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 match receive_password.recv() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     Err(_) =&amp;gt; break, &#x2F;&#x2F; channel disconnected, stop thread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    Ok(password) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                        let res = archive.by_index_decrypt(0, password.as_bytes());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                        match res {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                            Err(e) =&amp;gt; panic!(&amp;quot;Unexpected error {:?}&amp;quot;, e),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                            Ok(Err(_)) =&amp;gt; (), &#x2F;&#x2F; invalid password - continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                            Ok(Ok(mut zip)) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                &#x2F;&#x2F; Validate password by reading the zip file to make sure it is not merely a hash collision.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                let mut buffer = Vec::with_capacity(zip.size() as usize);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                match zip.read_to_end(&amp;amp;mut buffer) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                    Err(_) =&amp;gt; (), &#x2F;&#x2F; password collision - continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                    Ok(_) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                        &#x2F;&#x2F; Send password and continue processing while waiting for signal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                        send_password_found&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                            .send(password)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                                            .expect(&amp;quot;Send found password should not fail&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    Ok(passwords) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        let passwords_len = passwords.len() as u64;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        &#x2F;&#x2F; process batch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        for password in passwords {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                            let res = archive.by_index_decrypt(0, password.as_bytes());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                            match res {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                Err(e) =&amp;gt; panic!(&amp;quot;Unexpected error {:?}&amp;quot;, e),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                Ok(Err(_)) =&amp;gt; (), &#x2F;&#x2F; invalid password - continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                Ok(Ok(mut zip)) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                    &#x2F;&#x2F; Validate password by reading the zip file to make sure it is not merely a hash collision.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                    let mut buffer = Vec::with_capacity(zip.size() as usize);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                    match zip.read_to_end(&amp;amp;mut buffer) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                        Err(_) =&amp;gt; (), &#x2F;&#x2F; password collision - continue&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                        Ok(_) =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                            &#x2F;&#x2F; Send password and continue processing while waiting for signal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                            send_password_found&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                                .send(password)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                                .expect(&amp;quot;Send found password should not fail&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                     }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                 }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                             }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                         }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                        progress_bar.inc(1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        progress_bar.inc(passwords_len);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And a bit of wiring up:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;pub fn password_finder(zip_path: &amp;amp;str, password_list_path: &amp;amp;str, workers: usize) -&amp;gt; Option&amp;lt;String&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;pub fn password_finder(zip_path: &amp;amp;str, password_list_path: &amp;amp;str, workers: usize, batch_size: usize) -&amp;gt; Option&amp;lt;String&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let zip_file_path = Path::new(zip_path);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let password_list_file_path = Path::new(password_list_path).to_path_buf();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -97,7 +107,7&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_finder(zip_path: &amp;amp;str, password_list_path: &amp;amp;str, workers: usize)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     progress_bar.set_length(total_password_count as u64);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     &#x2F;&#x2F; MPMC channel with backpressure&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    let (send_password, receive_password): (Sender&amp;lt;String&amp;gt;, Receiver&amp;lt;String&amp;gt;) =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let (send_password, receive_password): (Sender&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;, Receiver&amp;lt;Vec&amp;lt;String&amp;gt;&amp;gt;) =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         crossbeam_channel::bounded(workers * 10_000);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let (send_found_password, receive_found_password): (Sender&amp;lt;String&amp;gt;, Receiver&amp;lt;String&amp;gt;) =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -111,6 +121,7&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; pub fn password_finder(zip_path: &amp;amp;str, password_list_path: &amp;amp;str, workers: usize)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let password_gen_handle = start_password_reader(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         password_list_file_path,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         send_password,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;        batch_size,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         stop_gen_signal.clone(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     );&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -153,12 +164,11&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; fn main() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let zip_path = args_iter.next().unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     let dictionary_path =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         &amp;quot;&#x2F;home&#x2F;agourlay&#x2F;Workspace&#x2F;blog-data&#x2F;find-password-zip&#x2F;xato-net-10-million-passwords.txt&amp;quot;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    let workers: usize = match args_iter.next() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;        None =&amp;gt; num_cpus::get_physical(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;        Some(count) =&amp;gt; count.parse().unwrap(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let batch_size: usize = args_iter.next().unwrap().parse().unwrap();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    let workers: usize = num_cpus::get_physical();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    match password_finder(&amp;amp;zip_path, dictionary_path, workers) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    match password_finder(&amp;amp;zip_path, dictionary_path, workers, batch_size) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         Some(password_found) =&amp;gt; println!(&amp;quot;Password found:{}&amp;quot;, password_found),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         None =&amp;gt; println!(&amp;quot;No password found :(&amp;quot;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using Hyperfine again, we will compare different batch sizes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hyperfine&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-runs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-warmup&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-markdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; batch.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-json&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; batch.json&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 10&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 50&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 50&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 500&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 500&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 1000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 5000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 5000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;zip-password-finder encrypted-test-dict.zip 10000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It seems &lt;code&gt;1000&lt;&#x2F;code&gt; yields the best results.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;10&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;234.756 ± 0.292&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;234.550&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;234.963&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.09 ± 0.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;50&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;226.616 ± 9.372&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;219.989&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;233.243&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.05 ± 0.04&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;100&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;216.498 ± 1.364&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;215.534&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;217.462&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;500&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;217.122 ± 1.992&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;215.714&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;218.531&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;1000&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;216.080 ± 0.066&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;216.033&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;216.127&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;5000&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;218.929 ± 0.114&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;218.848&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;219.009&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.01 ± 0.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;10000&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;222.792 ± 0.213&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;222.642&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;222.943&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.03 ± 0.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;However, the version without batching for 4 cores used to run in 224 seconds. That&#x27;s only an 8-second improvement. I am not sure if it is worth the added complexity.&lt;&#x2F;p&gt;
&lt;p&gt;We started from a wild guess regarding the source of the synchronization, so we should not be surprised by the disappointing results.&lt;&#x2F;p&gt;
&lt;p&gt;We are stopping the performance investigation here in order to save some content for the future :)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;password-generator&quot;&gt;Password generator&lt;a class=&quot;zola-anchor&quot; href=&quot;#password-generator&quot; aria-label=&quot;Anchor link for: password-generator&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Our dictionary approach was great to get us started, but in real life, it is rather improbable to find the password you are targeting within a dictionary.&lt;&#x2F;p&gt;
&lt;p&gt;Well, at least it did not work for me.&lt;&#x2F;p&gt;
&lt;p&gt;A password generator is present in the final code available at &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;zip-password-finder&quot;&gt;zip-password-finder&lt;&#x2F;a&gt;, but I won&#x27;t go into the implementation details because the code is rather ugly and does not add much at this point.&lt;&#x2F;p&gt;
&lt;p&gt;What we need is to generate all the possible passwords based on a set of constraints.&lt;&#x2F;p&gt;
&lt;p&gt;First, the minimum and maximum length to generate. For instance, between 3 and 7 characters.&lt;&#x2F;p&gt;
&lt;p&gt;Second, the charset to use. It could be only letters, with uppercase, maybe with digits and punctuation.&lt;&#x2F;p&gt;
&lt;p&gt;We can compute the number of passwords possible based on those constraints.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; total_password_count&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; min_password_len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;max_password_len&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    total_password_count&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; charset_len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;pow&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here is an example to convince yourself that this grows very fast.&lt;&#x2F;p&gt;
&lt;p&gt;Given a charset with lowercase letters, upper case letters and digits. Forming a set of &lt;code&gt;26 + 26 + 10 = 62&lt;&#x2F;code&gt; elements.&lt;&#x2F;p&gt;
&lt;p&gt;A simple 7-character password using elements from this charset yields &lt;code&gt;62^7 = 3.521.614.606.208&lt;&#x2F;code&gt; combinations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;62^7 passwords &#x2F; 4500 passwords per sec &#x2F; 60 &#x2F; 60 &#x2F; 24 &#x2F; 365 =~ 25 years&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A naive brute force strategy requires much better performance to be tractable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-work&quot;&gt;Future work&lt;a class=&quot;zola-anchor&quot; href=&quot;#future-work&quot; aria-label=&quot;Anchor link for: future-work&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;I still have not found the password for the archive that spawned this experiment and article.&lt;&#x2F;p&gt;
&lt;p&gt;However, given the current throughput, I&#x27;d have to let the program run for much longer than I am comfortable with.&lt;&#x2F;p&gt;
&lt;p&gt;Fixing the scalability issue is the most important task to make this application run efficiently on machines with a higher core count.&lt;&#x2F;p&gt;
&lt;p&gt;Then, improving the nominal performance per worker by investigating possible gains in the &lt;code&gt;zip-rs&lt;&#x2F;code&gt; crate or a different approach to get a multiplying effect.&lt;&#x2F;p&gt;
&lt;p&gt;I will make sure to document my progress in a follow-up article.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In this article we have built a simple tool in Rust to brute force the password of protected ZIP archives.&lt;&#x2F;p&gt;
&lt;p&gt;It can process around 4500 passwords&#x2F;sec on 4-core machines and has issues scaling up which makes it impractical for non-trivial passwords.&lt;&#x2F;p&gt;
&lt;p&gt;To get there we have learned how to apply the &lt;code&gt;pool of workers&lt;&#x2F;code&gt; pattern and how to shut it down gracefully.&lt;&#x2F;p&gt;
&lt;p&gt;We also learned how to measure performance in a systematic way and discussed scalability expectations.&lt;&#x2F;p&gt;
&lt;p&gt;At a more general level, we confirmed that long passwords are very efficient against brute force attacks.&lt;&#x2F;p&gt;
&lt;p&gt;This fact has been very well described in this &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;xkcd.com&#x2F;936&#x2F;&quot;&gt;xkcd&lt;&#x2F;a&gt; comic.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-10-03&amp;#x2F;xkcd_password_strength.png&quot;
         alt=&quot;XKCD 936&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;And that&#x27;s all for today, I hope you learned a thing or two on the way - thank you for making it to the end!&lt;&#x2F;p&gt;
&lt;p&gt;If you want to play with the application, the full code with better error handling &amp;amp; proper CLI is available at &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;zip-password-finder&quot;&gt;zip-password-finder&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;blockquote class=&quot;callout note has-title&quot;&gt;
  
  
  &lt;p class=&quot;title&quot;&gt;
    &lt;span class=&quot;icon&quot;&gt;
      &lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot; height=&quot;18&quot;&gt;&lt;path d=&quot;M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM11 7H13V9H11V7ZM11 11H13V17H11V11Z&quot; fill=&quot;currentColor&quot;&gt;&lt;&#x2F;path&gt;&lt;&#x2F;svg&gt;

    &lt;&#x2F;span&gt;
    &lt;strong&gt;Update&lt;&#x2F;strong&gt;
  &lt;&#x2F;p&gt;
  &lt;div class=&quot;content&quot;&gt;
    &lt;p&gt;The article submission on &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;xv94o6&#x2F;brute_forcing_protected_zip_archives_in_rust&#x2F;&quot;&gt;reddit&#x2F;r&#x2F;rust&lt;&#x2F;a&gt; contains excellent comments.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
  
&lt;&#x2F;blockquote&gt;

</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A performance retrospective using Rust (part 3)</title>
        <published>2022-08-08T00:00:00+00:00</published>
        <updated>2022-08-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/rust-performance-retrospective-part3/"/>
        <id>https://agourlay.github.io/rust-performance-retrospective-part3/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/rust-performance-retrospective-part3/">&lt;p&gt;This article is the third part of a performance retrospective regarding the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;hprof-slurp&quot;&gt;hprof-slurp&lt;&#x2F;a&gt; project.&lt;&#x2F;p&gt;
&lt;p&gt;It is highly recommended to start with the &lt;a href=&quot;&#x2F;rust-performance-retrospective-part1&#x2F;&quot;&gt;first part&lt;&#x2F;a&gt; to get a good grasp of the context.&lt;&#x2F;p&gt;
&lt;p&gt;In this edition, we will focus on an arguably minor performance issue that will teach us a bit more about Rust along the way.&lt;&#x2F;p&gt;
&lt;p&gt;A short disclaimer: this article has been written using Rust 1.62.1 and its conclusions might not be valid in the future.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;try-trait&quot;&gt;Try trait&lt;a class=&quot;zola-anchor&quot; href=&quot;#try-trait&quot; aria-label=&quot;Anchor link for: try-trait&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;As usual, our investigation is prompted by a strange artefact in a flamegraph.&lt;&#x2F;p&gt;
&lt;p&gt;Below - in purple - you can see &lt;code&gt;core::ops::try_trait::Try&amp;gt;::branch&lt;&#x2F;code&gt; represents 8.5% of the work in the parser thread (full &lt;a href=&quot;&#x2F;2022-08-08&#x2F;flamegraph-try-branch.svg&quot;&gt;flamegraph&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-08-08&amp;#x2F;flamegraph-try-branch.png&quot;
         alt=&quot;Flamegraph with try&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;You should know by now that the parser thread is the bottleneck for the whole application. It needs to be as fast as possible.&lt;&#x2F;p&gt;
&lt;p&gt;Therefore, every bit of computation happening on it must be accounted for.&lt;&#x2F;p&gt;
&lt;p&gt;In this case, the slowness seemed to be caused by the &lt;code&gt;Try&lt;&#x2F;code&gt; trait, which does not appear in the code base explicitly.&lt;&#x2F;p&gt;
&lt;p&gt;Our best chance is to simply look at the Rust doc for the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;core&#x2F;ops&#x2F;trait.Try.html#tymethod.branch&quot;&gt;branch&lt;&#x2F;a&gt; method.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-08-08&amp;#x2F;branch-doc.png&quot;
         alt=&quot;Try::branch docs&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Alright, so this function is a &#x27;nightly-only experimental&#x27; API and is called every time the operator &lt;code&gt;?&lt;&#x2F;code&gt; is used on something that implements the &lt;code&gt;Try&lt;&#x2F;code&gt; trait.&lt;&#x2F;p&gt;
&lt;p&gt;The only possible implementations when using stable Rust are found in the standard library.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-08-08&amp;#x2F;try-implementors.png&quot;
         alt=&quot;Try implementor docs&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;In our case the culprit must be the &lt;code&gt;Result&lt;&#x2F;code&gt; type which is used to track the errors occurring during the parsing phase.&lt;&#x2F;p&gt;
&lt;p&gt;After some digging, I found an existing &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;issues&#x2F;37939&quot;&gt;issue&lt;&#x2F;a&gt; on GitHub appropriately named &lt;code&gt;Reduced performance when using question mark operator instead of try!&lt;&#x2F;code&gt; where several users are reporting similar experiences.&lt;&#x2F;p&gt;
&lt;p&gt;The issue seems to be a bit stale, so we are going to use a workaround this time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;workaround&quot;&gt;Workaround&lt;a class=&quot;zola-anchor&quot; href=&quot;#workaround&quot; aria-label=&quot;Anchor link for: workaround&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;If the question mark operator is having an impact on the performance, the most logical step is to not use it.&lt;&#x2F;p&gt;
&lt;p&gt;The previous flamegraph points us to the &lt;code&gt;parse_hprof_record&lt;&#x2F;code&gt; function where we will start by replacing &lt;code&gt;?&lt;&#x2F;code&gt; with combinators on &lt;code&gt;Result&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The first change uses &lt;code&gt;Result::and_then&lt;&#x2F;code&gt; to chain two results:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     pub fn parse_hprof_record(&amp;amp;mut self) -&amp;gt; impl FnMut(&amp;amp;[u8]) -&amp;gt; IResult&amp;lt;&amp;amp;[u8], Record&amp;gt; + &amp;#39;_ {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         |i| {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             if self.heap_dump_remaining_len == 0 {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                let (r1, tag) = parse_u8(i)?;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                if self.debug_mode {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    println!(&amp;quot;Found record tag:{} remaining bytes:{}&amp;quot;, tag, i.len());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                match tag {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_STRING =&amp;gt; parse_utf8_string(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_LOAD_CLASS =&amp;gt; parse_load_class(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_UNLOAD_CLASS =&amp;gt; parse_unload_class(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_STACK_FRAME =&amp;gt; parse_stack_frame(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_STACK_TRACE =&amp;gt; parse_stack_trace(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_ALLOC_SITES =&amp;gt; parse_allocation_sites(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_HEAP_SUMMARY =&amp;gt; parse_heap_summary(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_START_THREAD =&amp;gt; parse_start_thread(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_END_THREAD =&amp;gt; parse_end_thread(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_CONTROL_SETTING =&amp;gt; parse_control_settings(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_CPU_SAMPLES =&amp;gt; parse_cpu_samples(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_HEAP_DUMP_END =&amp;gt; parse_heap_dump_end(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    TAG_HEAP_DUMP | TAG_HEAP_DUMP_SEGMENT =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                        map(parse_header_record, |hr| {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                            &#x2F;&#x2F; record expected GC segments length&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                            self.heap_dump_remaining_len = hr.length;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                            HeapDumpStart { length: hr.length }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                        })(r1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                parse_u8(i).and_then(|(r1, tag)| {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    if self.debug_mode {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        println!(&amp;quot;Found record tag:{} remaining bytes:{}&amp;quot;, tag, i.len());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    match tag {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_STRING =&amp;gt; parse_utf8_string(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_LOAD_CLASS =&amp;gt; parse_load_class(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_UNLOAD_CLASS =&amp;gt; parse_unload_class(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_STACK_FRAME =&amp;gt; parse_stack_frame(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_STACK_TRACE =&amp;gt; parse_stack_trace(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_ALLOC_SITES =&amp;gt; parse_allocation_sites(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_HEAP_SUMMARY =&amp;gt; parse_heap_summary(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_START_THREAD =&amp;gt; parse_start_thread(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_END_THREAD =&amp;gt; parse_end_thread(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_CONTROL_SETTING =&amp;gt; parse_control_settings(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_CPU_SAMPLES =&amp;gt; parse_cpu_samples(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_HEAP_DUMP_END =&amp;gt; parse_heap_dump_end(r1),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        TAG_HEAP_DUMP | TAG_HEAP_DUMP_SEGMENT =&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                            map(parse_header_record, |hr| {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                &#x2F;&#x2F; record expected GC segments length&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                self.heap_dump_remaining_len = hr.length;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                                HeapDumpStart { length: hr.length }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                            })(r1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        x =&amp;gt; panic!(&amp;quot;{}&amp;quot;, format!(&amp;quot;unhandled record tag {}&amp;quot;, x)),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                    x =&amp;gt; panic!(&amp;quot;{}&amp;quot;, format!(&amp;quot;unhandled record tag {}&amp;quot;, x)),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                }                     &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And a second change using &lt;code&gt;Result::map&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             } else {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 &#x2F;&#x2F; GC record mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                let (r1, gc_sub) = parse_gc_record(i)?;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                let gc_sub_len = i.len() - r1.len();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                self.heap_dump_remaining_len -= gc_sub_len as u32;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;                Ok((r1, GcSegment(gc_sub)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                parse_gc_record(i).map(|(r1, gc_sub)| {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    let gc_sub_len = i.len() - r1.len();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    self.heap_dump_remaining_len -= gc_sub_len as u32;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    (r1, GcSegment(gc_sub))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After applying those two changes, we can indeed see that &lt;code&gt;core::ops::try_trait::Try&amp;gt;::branch&lt;&#x2F;code&gt; now represents only 0.5% of time in a different call stack.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-08-08&amp;#x2F;flamegraph-after-fix.png&quot;
         alt=&quot;Flamegraph after fix&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Most of it now comes from &lt;code&gt;nom::combinator::flat_map&lt;&#x2F;code&gt; and when zooming in we can also find a tiny contribution from &lt;code&gt;nom::combinator::map&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-08-08&amp;#x2F;flamegraph-after-fix-extra.png&quot;
         alt=&quot;Flamegraph after fix zoom&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The previous occurrence of &lt;code&gt;core::ops::try_trait::Try&amp;gt;::branch&lt;&#x2F;code&gt; has been replaced by &lt;code&gt;Result::map&lt;&#x2F;code&gt; which informs us that our second change is executed more often.&lt;&#x2F;p&gt;
&lt;p&gt;Observing flamegraphs is nice but does it translate into runtime performance gains?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hyperfine&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-runs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-warmup&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-markdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hprof.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with-?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-with-? -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with-combinators&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-combinators -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;with-?&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;36.614 ± 0.138&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;36.373&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;36.835&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.04 ± 0.02&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;with-combinators&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;35.062 ± 0.766&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;34.202&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;35.969&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Using the question mark operator is 4% slower than the combinators version on this run.&lt;&#x2F;p&gt;
&lt;p&gt;That is not a massive improvement, but I think it is a reasonable trade-off given the change applied and the application&#x27;s context.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;going-deeper&quot;&gt;Going deeper&lt;a class=&quot;zola-anchor&quot; href=&quot;#going-deeper&quot; aria-label=&quot;Anchor link for: going-deeper&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;We can go deeper by applying the same tricks to &lt;code&gt;nom&lt;&#x2F;code&gt; to see if we can scrape some additional gains.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s clone the repository and apply the following changes.&lt;&#x2F;p&gt;
&lt;p&gt;First on the &lt;code&gt;flat_map&lt;&#x2F;code&gt; combinator.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pub fn flat_map&amp;lt;I, O1, O2, E: ParseError&amp;lt;I&amp;gt;, F, G, H&amp;gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  mut parser: F,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  mut applied_parser: G,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;) -&amp;gt; impl FnMut(I) -&amp;gt; IResult&amp;lt;I, O2, E&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  F: Parser&amp;lt;I, O1, E&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  G: FnMut(O1) -&amp;gt; H,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  H: Parser&amp;lt;I, O2, E&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   move |input: I| {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    let (input, o1) = parser.parse(input)?;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    applied_parser(o1).parse(input)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;    parser&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;      .parse(input)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;      .and_then(|(input, o1)| applied_parser(o1).parse(input))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then for the &lt;code&gt;map&lt;&#x2F;code&gt; combinator.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;pub fn map&amp;lt;I, O1, O2, E, F, G&amp;gt;(mut parser: F, mut f: G) -&amp;gt; impl FnMut(I) -&amp;gt; IResult&amp;lt;I, O2, E&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;where&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  F: Parser&amp;lt;I, O1, E&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  G: FnMut(O1) -&amp;gt; O2,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;  move |input: I| {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    let (input, o1) = parser.parse(input)?;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;    Ok((input, f(o1)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;  move |input: I| parser.parse(input).map(|(input, o1)| (input, f(o1)))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In order to use our local patched version of &lt;code&gt;nom&lt;&#x2F;code&gt;, we simply need to tell Cargo about it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; [dependencies]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-deleted&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-deleted&quot;&gt;nom = &amp;quot;7.1.1&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;nom = { path = &amp;quot;..&#x2F;nom&amp;quot; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a pretty neat feature from Cargo which enables quick experiments!&lt;&#x2F;p&gt;
&lt;p&gt;After validating that the flamegraph is now free from any traces of &lt;code&gt;branch&lt;&#x2F;code&gt; (trust me on this one, there are enough screenshots in this article), we can run a final benchmark.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hyperfine&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-runs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-warmup&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-markdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hprof.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with-?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-with-? -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with-combinators&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-combinators -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with-nom-combinators&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-combinators -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I re-ran the benchmark several times and the result is that the gain of the &lt;code&gt;nom&lt;&#x2F;code&gt; patch is more often 0% than 1%.&lt;&#x2F;p&gt;
&lt;p&gt;It is more or less what we could expect from optimizing a chunk of code accounting for 0.5% of the CPU time.&lt;&#x2F;p&gt;
&lt;p&gt;This means it is not worth it to make a PR to upstream the performance patch as we do not have enough data to back it up with.&lt;&#x2F;p&gt;
&lt;p&gt;An important aspect of performance work is that diminishing returns can occur quickly. Therefore, knowing when to stop digging in the same spot is essential.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In this article, we have learned that the question mark operator can have an impact on the runtime performance of a program.&lt;&#x2F;p&gt;
&lt;p&gt;How much of an impact, however, depends on the exact workload of the program and where the operator is used.&lt;&#x2F;p&gt;
&lt;p&gt;It seems reasonable to believe that this behaviour should not be an issue for the majority of Rust programs out there where the question mark operator is not used to shortcut very hot code.&lt;&#x2F;p&gt;
&lt;p&gt;As always, it is good to benchmark instead of making assumptions, which could lead to making the code less readable without concrete gains.&lt;&#x2F;p&gt;
&lt;p&gt;The next article in this &lt;a href=&quot;&#x2F;tags&#x2F;series&#x2F;&quot;&gt;series&lt;&#x2F;a&gt; will go through another interesting optimization encountered while making &lt;code&gt;hprof-slurp&lt;&#x2F;code&gt; faster.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A performance retrospective using Rust (part 2)</title>
        <published>2022-07-23T00:00:00+00:00</published>
        <updated>2022-07-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/rust-performance-retrospective-part2/"/>
        <id>https://agourlay.github.io/rust-performance-retrospective-part2/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/rust-performance-retrospective-part2/">&lt;p&gt;This article is the second part of a performance retrospective regarding the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;hprof-slurp&quot;&gt;hprof-slurp&lt;&#x2F;a&gt; project. It is highly recommended to start with the &lt;a href=&quot;&#x2F;rust-performance-retrospective-part1&#x2F;&quot;&gt;first part&lt;&#x2F;a&gt; to get a good grasp of the context.&lt;&#x2F;p&gt;
&lt;p&gt;We left off after a presentation of the project and a detailed description of the benchmarking methodology used to measure performance gains.&lt;&#x2F;p&gt;
&lt;p&gt;In this article we will focus on a specific issue that has been plaguing the 0.3.x series.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;avoiding-memcopy&quot;&gt;Avoiding memcopy&lt;a class=&quot;zola-anchor&quot; href=&quot;#avoiding-memcopy&quot; aria-label=&quot;Anchor link for: avoiding-memcopy&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;As the program got faster, I witnessed the &lt;code&gt;memcpy&lt;&#x2F;code&gt; instructions slowly creeping up in the flamegraphs to the point where they accounted for most of the computation.&lt;&#x2F;p&gt;
&lt;p&gt;Below - in purple - you can see the &lt;code&gt;_memcpy_avx_unaligned_erms&lt;&#x2F;code&gt; representing most of the work in the parser thread (full &lt;a href=&quot;&#x2F;2022-07-23&#x2F;flamegraph-0.3.3.svg&quot;&gt;flamegraph&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-07-23&amp;#x2F;flamegraph-memcopy.png&quot;
         alt=&quot;Flamegraph with memcopy&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;At first, I thought it was an inherent cost of parsing large files, but as it grew to become the largest bottleneck in &lt;code&gt;hprof-slurp&lt;&#x2F;code&gt;, I decided to investigate the issue to - at the very least - understand it.&lt;&#x2F;p&gt;
&lt;p&gt;I found the answer to this mystery in the fantastic &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;nnethercote.github.io&#x2F;perf-book&#x2F;type-sizes.html&quot;&gt;Rust performance book&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote class=&quot;quote&quot;&gt;
  
  &lt;div class=&quot;icon&quot; style=&quot;display: none;&quot;&gt;&lt;svg fill=&quot;currentColor&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;  width=&quot;10&quot; height=&quot;10&quot; viewBox=&quot;796 698 200 200&quot;&gt;
&lt;g&gt;
	&lt;path d=&quot;M885.208,749.739v-40.948C836.019,708.791,796,748.81,796,798v89.209h89.208V798h-48.26
		C836.948,771.39,858.598,749.739,885.208,749.739z&quot;&#x2F;&gt;
	&lt;path d=&quot;M996,749.739v-40.948c-49.19,0-89.209,40.019-89.209,89.209v89.209H996V798h-48.26
		C947.74,771.39,969.39,749.739,996,749.739z&quot;&#x2F;&gt;
&lt;&#x2F;g&gt;
&lt;&#x2F;svg&gt;
&lt;&#x2F;div&gt;
  &lt;div class=&quot;content&quot;&gt;&lt;p&gt;Rust types that are larger than 128 bytes are copied with memcpy rather than inline code.
Shrinking these types to 128 bytes or less can make the code faster by avoiding memcpy calls and reducing memory traffic.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
  
  &lt;div class=&quot;from&quot;&gt;
    &lt;p&gt;— Rust performance book&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
  
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Therefore, within my code I needed to find the large types that are used very often on the parser&#x27;s path.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s generate the type sizes with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;RUSTFLAGS&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Z&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;z&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; +nightly&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; build&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my opinion, it can be a bit cumbersome to navigate the output of &lt;code&gt;-Zprint-type-sizes&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;One alternative recommended by the Rust performance book is to use DHAT’s “copy profiling” mode, which works great as well.&lt;&#x2F;p&gt;
&lt;p&gt;I will stick to &lt;code&gt;-Zprint-type-sizes&lt;&#x2F;code&gt; for the remainder of the article as it helps understand the memory layout on the way.&lt;&#x2F;p&gt;
&lt;p&gt;Looking at the types I own in the output section, we can find the following&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;parser::record::Record&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 136&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     discriminant:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GcSegment&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 134&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 128&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;AllocationSites&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 62&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.flags&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.cutoff_ratio&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.total_live_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.total_live_instances&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.number_of_sites&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.total_bytes_allocated&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.total_instances_allocated&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.allocation_sites&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; variants&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; decreasing&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;parser::record::Record&lt;&#x2F;code&gt; is an enum which represents all possible top-level records found in an &lt;code&gt;hprof&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;
&lt;p&gt;The largest variant is &lt;code&gt;GcSegment&lt;&#x2F;code&gt;, with 134 bytes, which is larger than the 128 bytes mentioned above.&lt;&#x2F;p&gt;
&lt;p&gt;The corresponding Rust code looks like the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Record&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  GcSegment&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GcRecord&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  AllocationSites&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    flags&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    cutoff_ratio&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    total_live_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    total_live_instances&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    total_bytes_allocated&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    total_instances_allocated&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    number_of_sites&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    allocation_sites&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;AllocationSite&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  ...&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; variants&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;parser::gc_record::GcRecord&lt;&#x2F;code&gt; is itself an enum as well. It models all possible elements found on the JVM&#x27;s heap.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s find in the output the size of a &lt;code&gt;GcRecord&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;parser::gc_record::GcRecord&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 128&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     discriminant:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ClassDump&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 127&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.constant_pool_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.stack_trace_serial_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.instance_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.super_class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.class_loader_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.signers_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.protection_domain_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.const_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.static_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.instance_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ObjectArrayDump&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 55&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.stack_trace_serial_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.number_of_elements&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.array_class_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.elements&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; decreasing&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the following definition:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GcRecord&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    ClassDump&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        stack_trace_serial_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        super_class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        class_loader_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        signers_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        protection_domain_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        instance_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        constant_pool_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        const_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ConstFieldInfo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FieldValue&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        static_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FieldInfo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FieldValue&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        instance_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FieldInfo&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    ObjectArrayDump&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        stack_trace_serial_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        number_of_elements&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        array_class_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        elements&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-other&quot;&gt; variants&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At this point, we can see that there is logically a direct mapping between the fields of the structs and their actual sizes.&lt;&#x2F;p&gt;
&lt;p&gt;Moreover, there is a critical observation to make regarding enums.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Enums are sized according to the largest variant&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;An enum is sized with its largest variant plus some memory for an internal discriminant field.&lt;&#x2F;p&gt;
&lt;p&gt;This means the 134 bytes for a &lt;code&gt;GcSegment&lt;&#x2F;code&gt; are being allocated for every &lt;code&gt;parser::record::Record&lt;&#x2F;code&gt; variant.&lt;&#x2F;p&gt;
&lt;p&gt;This quickly adds up when a program is crunching millions of records.&lt;&#x2F;p&gt;
&lt;p&gt;The common wisdom for decreasing the stack memory footprint is to use heap allocation, often referred to as boxing.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s try boxing the content of &lt;code&gt;GcSegment&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GcSegment&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GcRecord&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This change gives the following type sizes (after applying the necessary modifications to handle the new Box type at the call sites).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;parser::record::Record&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     discriminant:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;AllocationSites&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 62&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.flags&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.cutoff_ratio&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.total_live_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.total_live_instances&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.number_of_sites&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.total_bytes_allocated&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.total_instances_allocated&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.allocation_sites&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; more&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; with&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; decreasing&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;GcSegment&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 14&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looking good!&lt;&#x2F;p&gt;
&lt;p&gt;The type &lt;code&gt;parser::record::Record&lt;&#x2F;code&gt; went from 136 bytes to 64 bytes because all variants are now sized according to the next largest variant, &lt;code&gt;AllocationSites&lt;&#x2F;code&gt; at 62 bytes.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;code&gt;memcpy&lt;&#x2F;code&gt; should not be a problem anymore.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hyperfine&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-runs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-markdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hprof.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.3.3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.3.3 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; box&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.3.3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;77.442 ± 2.537&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;74.513&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;78.968&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;box&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;270.785 ± 0.907&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;270.031&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;271.792&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3.50 ± 0.12&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Ouch! It is over three times slower!&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s have a look at the flamegraph to understand where the CPU spends its time.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-07-23&amp;#x2F;flamegraph-box.png&quot;
         alt=&quot;Flamegraph with boxing&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;In purple, you can see the cost of &lt;code&gt;Box::new&lt;&#x2F;code&gt; in the parser thread (full &lt;a href=&quot;&#x2F;2022-07-23&#x2F;flamegraph-box.svg&quot;&gt;flamegraph&lt;&#x2F;a&gt; available).&lt;&#x2F;p&gt;
&lt;p&gt;Welp, we did fix the &lt;code&gt;memcpy&lt;&#x2F;code&gt; issue, but the application is terribly slow.&lt;&#x2F;p&gt;
&lt;p&gt;Boxing is, unfortunately, not some kind of magic sauce that will fix all our problems.&lt;&#x2F;p&gt;
&lt;p&gt;Performing heap allocation has a higher cost than stack allocation, and we are now performing it for each instance found in the JVM heap dump.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reasonable-boxing&quot;&gt;Reasonable boxing&lt;a class=&quot;zola-anchor&quot; href=&quot;#reasonable-boxing&quot; aria-label=&quot;Anchor link for: reasonable-boxing&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In the previous section, we have seen that &lt;code&gt;GcSegment&lt;&#x2F;code&gt; cannot be boxed efficiently because it appears too frequently during the execution of the application.&lt;&#x2F;p&gt;
&lt;p&gt;We also have seen that the largest variant of &lt;code&gt;GcSegment&lt;&#x2F;code&gt; is &lt;code&gt;ClassDump&lt;&#x2F;code&gt;, clocking in at 127 bytes.&lt;&#x2F;p&gt;
&lt;p&gt;Based on the enumeration sizing discovery, we know that the 127 bytes for a &lt;code&gt;ClassDump&lt;&#x2F;code&gt; are being allocated for every &lt;code&gt;GcSegment&lt;&#x2F;code&gt; record.&lt;&#x2F;p&gt;
&lt;p&gt;However, the &lt;code&gt;ClassDump&lt;&#x2F;code&gt; is a relatively rare element compared to the actual instance dumps. An application has a few hundred classes but millions of instances.&lt;&#x2F;p&gt;
&lt;p&gt;It is unfortunate to systematically pay the full price for something that is infrequent.&lt;&#x2F;p&gt;
&lt;p&gt;The intuition is that we should be moving the boxing cost to the &lt;code&gt;ClassDump&lt;&#x2F;code&gt; only.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s try to box the individual fields in &lt;code&gt;ClassDump&lt;&#x2F;code&gt; instead.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GcRecord&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    ClassDump&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        stack_trace_serial_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        super_class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        class_loader_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        signers_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        protection_domain_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        instance_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        constant_pool_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        const_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ConstFieldInfo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FieldValue&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        static_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FieldInfo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FieldValue&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        instance_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FieldInfo&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;Vec&lt;&#x2F;code&gt; type contains three words: a length, a capacity, and a pointer. That is 3 * 8 = 24 bytes on a 64-bit architecture.&lt;&#x2F;p&gt;
&lt;p&gt;Boxing each vector would save 16 bytes per field.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GcRecord&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    ClassDump&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        stack_trace_serial_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        super_class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        class_loader_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        signers_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        protection_domain_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        instance_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        constant_pool_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        const_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ConstFieldInfo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FieldValue&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        static_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FieldInfo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FieldValue&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        instance_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FieldInfo&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Fetching the new type&#x27;s size yields the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;parser::gc_record::GcRecord&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 80&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     discriminant:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ClassDump&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 79&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.constant_pool_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.stack_trace_serial_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.instance_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.super_class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.class_loader_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.signers_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.protection_domain_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.const_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.static_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.instance_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is exactly what we were expecting; one word per boxed field.&lt;&#x2F;p&gt;
&lt;p&gt;But we have learned the hard way not to celebrate prematurely before checking how it pans out in a benchmark.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hyperfine&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-runs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-markdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hprof.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.3.3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.3.3 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; boxes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.3.3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;76.691 ± 3.326&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;73.080&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;79.629&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.12 ± 0.05&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;boxes&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;68.625 ± 1.262&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;67.202&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;69.605&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;It runs 11% faster. It&#x27;s not bad for such a small change!&lt;&#x2F;p&gt;
&lt;p&gt;But let&#x27;s try to go faster by reducing the size of the &lt;code&gt;ClassDump&lt;&#x2F;code&gt; variant even more.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; ClassDumpFields&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    const_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ConstFieldInfo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FieldValue&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    static_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FieldInfo&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; FieldValue&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;    instance_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;FieldInfo&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt; enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; GcRecord&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;    ClassDump&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        stack_trace_serial_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        super_class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        class_loader_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        signers_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        protection_domain_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        instance_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        constant_pool_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-other&quot;&gt;        fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ClassDumpFields&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which has the following type size:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;parser::gc_record::ClassDumpFields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 72&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.const_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.static_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.instance_fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 24&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;parser::gc_record::GcRecord&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     discriminant:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;ClassDump&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 63&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.constant_pool_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.stack_trace_serial_number&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.instance_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         padding:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes,&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; alignment:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.super_class_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.class_loader_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.signers_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.protection_domain_object_id&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;print-type-size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         field&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We shaved off 16 more bytes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hyperfine&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-runs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-markdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hprof.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.3.3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.3.3 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; boxes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-boxes -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; box-struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.3.3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;75.638 ± 4.154&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;70.900&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;78.660&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.15 ± 0.06&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;boxes&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;68.621 ± 0.399&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;68.194&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;68.986&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.04 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;box-struct&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;65.978 ± 0.185&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;65.764&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;66.086&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;This last change gave us an extra 4%, which is quite nice.&lt;&#x2F;p&gt;
&lt;p&gt;To go further, one would need to remove unnecessary fields from the &lt;code&gt;ClassDump&lt;&#x2F;code&gt; variant.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clippy&quot;&gt;Clippy&lt;a class=&quot;zola-anchor&quot; href=&quot;#clippy&quot; aria-label=&quot;Anchor link for: clippy&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Before wrapping up this article, it is mandatory to note that Clippy has a lint for this class of problems, which I, &lt;strong&gt;of course&lt;&#x2F;strong&gt; discovered only much later.&lt;&#x2F;p&gt;
&lt;p&gt;It is called &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rust-clippy&#x2F;master&#x2F;index.html#large_enum_variant&quot;&gt;large_enum_variant&lt;&#x2F;a&gt; and kicks in when the difference between the largest variant and the smallest variant is larger than 200 bytes.&lt;&#x2F;p&gt;
&lt;p&gt;The documentation warns us about something very important that we discovered as well.&lt;&#x2F;p&gt;

&lt;blockquote class=&quot;callout warning has-title&quot;&gt;
  
  
  &lt;p class=&quot;title&quot;&gt;
    &lt;span class=&quot;icon&quot;&gt;
      &lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot; height=&quot;18&quot;&gt;&lt;path d=&quot;M12.865 3.00017L22.3912 19.5002C22.6674 19.9785 22.5035 20.5901 22.0252 20.8662C21.8732 20.954 21.7008 21.0002 21.5252 21.0002H2.47266C1.92037 21.0002 1.47266 20.5525 1.47266 20.0002C1.47266 19.8246 1.51886 19.6522 1.60663 19.5002L11.1329 3.00017C11.4091 2.52187 12.0206 2.358 12.4989 2.63414C12.651 2.72191 12.7772 2.84815 12.865 3.00017ZM4.20471 19.0002H19.7932L11.9989 5.50017L4.20471 19.0002ZM10.9989 16.0002H12.9989V18.0002H10.9989V16.0002ZM10.9989 9.00017H12.9989V14.0002H10.9989V9.00017Z&quot; fill=&quot;currentColor&quot;&gt;&lt;&#x2F;path&gt;&lt;&#x2F;svg&gt;

    &lt;&#x2F;span&gt;
    &lt;strong&gt;Warning&lt;&#x2F;strong&gt;
  &lt;&#x2F;p&gt;
  &lt;div class=&quot;content&quot;&gt;
    &lt;p&gt;This lint obviously cannot take the distribution of variants in your running program into account. It is possible that the smaller variants make up less than 1% of all instances, in which case the overhead is negligible and the boxing is counter-productive. Always measure the change this lint suggests.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
  
&lt;&#x2F;blockquote&gt;

&lt;p&gt;Let&#x27;s give this lint a try by creating a &lt;code&gt;clippy.toml&lt;&#x2F;code&gt; file in the project and configuring this lint to be more aggressive with:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;enum-variant-size-threshold&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; instead of the default value 200&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running &lt;code&gt;cargo clippy&lt;&#x2F;code&gt; yields two entries:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;warning:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; large&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; difference&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; between&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; variants&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  --&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; src&#x2F;parser&#x2F;record.rs:97:5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;97&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;     GcSegment(GcRecord&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;     ^^^^^^^^^^^^^^^^^^^&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; this&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 128&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;note:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; and&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; second-largest&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 58&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;  --&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; src&#x2F;parser&#x2F;record.rs:55:5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;55&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     AllocationSites&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;56&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         flags:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u16,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;57&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         cutoff_ratio:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;58&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         total_live_bytes:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;  |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;63&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         allocation_sites:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;AllocationSit&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;     },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;_____^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;   =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; help:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; further&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; information&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; visit&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rust-clippy&#x2F;master&#x2F;index.html#large_enum_variant&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;help:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; consider&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; boxing&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; large&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reduce&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; total&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; enum&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;97&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;     GcSegment(Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;GcRecord&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We tried this already and it did not work. Clippy tries its best, but remember, it cannot know about the distribution of variants through a static analysis.&lt;&#x2F;p&gt;
&lt;p&gt;And the second entry:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;warning:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; large&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; difference&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; between&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; variants&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;   --&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; src&#x2F;parser&#x2F;gc_record.rs:127:5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;127&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     ClassDump&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;128&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         class_object_id:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u64,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;129&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         stack_trace_serial_number:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;130&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         super_class_object_id:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u64,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;138&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         instance_fields:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;FieldInf&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;139&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;     },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;_____^&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; this&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 122&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; note:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;[warn(clippy::large_enum_variant)]&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; on&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; by&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;note:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; and&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; second-largest&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; variant&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 49&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; bytes:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;   --&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; src&#x2F;parser&#x2F;gc_record.rs:120:5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;120&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;     PrimitiveArrayDump&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;121&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         object_id:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u64,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;122&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         stack_trace_serial_number:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;123&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         number_of_elements:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; u32,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;124&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         element_type:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; FieldType,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;125&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         array_value:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ArrayValue,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;126&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;     },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;_____^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; help:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; further&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; information&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; visit&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rust-clippy&#x2F;master&#x2F;index.html#large_enum_variant&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;help:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; consider&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; boxing&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; large&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; fields&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; reduce&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; total&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; size&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; of&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; enum&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;138&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;         instance_fields:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;FieldInf&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;                          ~~~~~~~~~~~~~~~~~~~&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which is the lead we ended up exploring as well.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes the best way to learn is to rediscover what everyone already knows for yourself.&lt;&#x2F;p&gt;
&lt;p&gt;Clippy is truly a fantastic tool and one of my personal favorites in the whole Rust ecosystem. Depending on your context, it may make sense to configure custom values for certain lints to get the most out of them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This article has presented a bottleneck due to excessive &lt;code&gt;memcopy&lt;&#x2F;code&gt; which was slowing down &lt;code&gt;hprof-slurp&lt;&#x2F;code&gt; prior to the 0.4.0 release.&lt;&#x2F;p&gt;
&lt;p&gt;The final fix took only a few lines of code but had a &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;hprof-slurp&#x2F;commit&#x2F;73392f1210c09a86e5dbd59629b6ed0302a05dfc&quot;&gt;strong&lt;&#x2F;a&gt; positive effect on performance.&lt;&#x2F;p&gt;
&lt;p&gt;In order to get there, we had to understand a few details regarding the way Rust sizes types internally, more specifically, enumerations.&lt;&#x2F;p&gt;
&lt;p&gt;As a rule of thumb, it is recommended to avoid single outsized variants when creating enumerations as it impacts the memory usage of all variants.&lt;&#x2F;p&gt;
&lt;p&gt;One also must be careful when trying to reduce the stack memory pressure via boxing. Allocating on the heap is not magic, and its cost must be understood in the context of the application.&lt;&#x2F;p&gt;
&lt;p&gt;The next article in this &lt;a href=&quot;&#x2F;tags&#x2F;series&#x2F;&quot;&gt;series&lt;&#x2F;a&gt; will go through another interesting optimization encountered while making &lt;code&gt;hprof-slurp&lt;&#x2F;code&gt; faster.&lt;&#x2F;p&gt;

&lt;blockquote class=&quot;callout note has-title&quot;&gt;
  
  
  &lt;p class=&quot;title&quot;&gt;
    &lt;span class=&quot;icon&quot;&gt;
      &lt;svg xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot; viewBox=&quot;0 0 24 24&quot; width=&quot;18&quot; height=&quot;18&quot;&gt;&lt;path d=&quot;M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM11 7H13V9H11V7ZM11 11H13V17H11V11Z&quot; fill=&quot;currentColor&quot;&gt;&lt;&#x2F;path&gt;&lt;&#x2F;svg&gt;

    &lt;&#x2F;span&gt;
    &lt;strong&gt;Update&lt;&#x2F;strong&gt;
  &lt;&#x2F;p&gt;
  &lt;div class=&quot;content&quot;&gt;
    &lt;p&gt;The article submission on &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;w7pelk&#x2F;a_performance_retrospective_using_rust_part_2&#x2F;&quot;&gt;reddit&#x2F;r&#x2F;rust&lt;&#x2F;a&gt; contains excellent comments.&lt;&#x2F;p&gt;

  &lt;&#x2F;div&gt;
  
&lt;&#x2F;blockquote&gt;

</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A performance retrospective using Rust (part 1)</title>
        <published>2022-07-11T00:00:00+00:00</published>
        <updated>2022-07-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://agourlay.github.io/rust-performance-retrospective-part1/"/>
        <id>https://agourlay.github.io/rust-performance-retrospective-part1/</id>
        
        <content type="html" xml:base="https://agourlay.github.io/rust-performance-retrospective-part1/">&lt;p&gt;This is the first article in a series regarding making a simple JVM heap dump analyzer in Rust faster over time.&lt;&#x2F;p&gt;
&lt;p&gt;Although it is primarily targeted at intermediate Rust developers, it will surely be relevant for engineers interested in performance in general.&lt;&#x2F;p&gt;
&lt;p&gt;Performance optimization is highly context-dependent so it makes sense to spend some time explaining what problem we are trying to solve.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;context&quot;&gt;Context&lt;a class=&quot;zola-anchor&quot; href=&quot;#context&quot; aria-label=&quot;Anchor link for: context&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;In a previous life, I found myself needing to analyze large JVM heap dumps. For a sense of scale, &quot;large&quot; stands for more than 50Gb in that context.&lt;&#x2F;p&gt;
&lt;p&gt;The JVM ecosystem is pretty rich in terms of tooling regarding heap dump analysis. Most JVM developers are familiar with &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;visualvm.github.io&#x2F;&quot;&gt;VisualVM&lt;&#x2F;a&gt; and &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.eclipse.org&#x2F;mat&#x2F;&quot;&gt;EclipseMat&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Those tools are truly excellent; they offer a large panel of &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;eclipsesource.com&#x2F;blogs&#x2F;2013&#x2F;01&#x2F;21&#x2F;10-tips-for-using-the-eclipse-memory-analyzer&#x2F;&quot;&gt;features&lt;&#x2F;a&gt; to drill down on the content of heap dumps to help you pinpoint your issue very precisely.&lt;&#x2F;p&gt;
&lt;p&gt;However, they tend to be extremely memory hungry and slow when analyzing large files, which is forcing users to spin up expensive beefy instances from a cloud provider to get the job done.&lt;&#x2F;p&gt;
&lt;p&gt;The tool I needed was fairly specific, my main concern was to get a quick overview of large heap dumps using a regular developer machine to decide if it actually makes sense to investigate further using the aforementioned workflow.&lt;&#x2F;p&gt;
&lt;p&gt;The goal is not to replace the existing tooling but to optimize the investigation workflow and this led me to create the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;hprof-slurp&quot;&gt;hprof-slurp&lt;&#x2F;a&gt; project.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hprof-slurp&quot;&gt;Hprof-slurp&lt;a class=&quot;zola-anchor&quot; href=&quot;#hprof-slurp&quot; aria-label=&quot;Anchor link for: hprof-slurp&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The project is a CLI written in Rust which processes dump files in a streaming fashion.&lt;&#x2F;p&gt;
&lt;p&gt;It trades off features for speed by performing only a single pass without storing intermediary results on the host, which reduces the depth of the analysis possible.&lt;&#x2F;p&gt;
&lt;p&gt;The project is named after the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;javase&#x2F;8&#x2F;docs&#x2F;technotes&#x2F;samples&#x2F;hprof.html&quot;&gt;hprof&lt;&#x2F;a&gt; format which is used by the JDK to encode heap dumps.&lt;&#x2F;p&gt;
&lt;p&gt;The 3 main features available are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;report top &lt;code&gt;k&lt;&#x2F;code&gt; allocated classes.&lt;&#x2F;li&gt;
&lt;li&gt;report the count of instances per class.&lt;&#x2F;li&gt;
&lt;li&gt;report the largest instance size per class.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let&#x27;s have a look at an example of output processing: a &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;hprof-slurp&#x2F;tree&#x2F;master&#x2F;test-heap-dumps&quot;&gt;tiny heap dump&lt;&#x2F;a&gt; which is used as part of the integration test pipeline.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;du&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;BM&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hprof-64.bin&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;2M&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hprof-64.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s process that 2Mb heap dump!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;hprof-slurp&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hprof-64.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which instantaneously yields those two tables&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Top 20 allocated classes:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Total size | Instances |     Largest | Class name                                  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;------------------------------------------------------------------------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   1.99MiB |       436 |   634.78KiB | int[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 197.11KiB |      1991 |    16.02KiB | char[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  85.25KiB |       443 |     8.02KiB | byte[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  47.38KiB |      1516 |  32.00bytes | java&#x2F;lang&#x2F;String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  45.42KiB |       560 |     8.02KiB | java&#x2F;lang&#x2F;Object[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  15.26KiB |       126 | 124.00bytes | java&#x2F;lang&#x2F;reflect&#x2F;Field&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  14.77KiB |       378 |  40.00bytes | java&#x2F;util&#x2F;LinkedList$Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   9.94KiB |       212 |  48.00bytes | java&#x2F;util&#x2F;HashMap$Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   8.91KiB |       190 |  48.00bytes | java&#x2F;util&#x2F;LinkedList&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   8.42KiB |        98 |  88.00bytes | java&#x2F;lang&#x2F;ref&#x2F;SoftReference&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   6.05KiB |       258 |  24.00bytes | java&#x2F;lang&#x2F;Integer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   5.91KiB |        18 |     2.02KiB | java&#x2F;util&#x2F;HashMap$Node[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   5.86KiB |       150 |  40.00bytes | java&#x2F;lang&#x2F;StringBuilder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   5.44KiB |       116 |  48.00bytes | java&#x2F;util&#x2F;Hashtable$Entry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   5.05KiB |        38 | 136.00bytes | sun&#x2F;util&#x2F;locale&#x2F;LocaleObjectCache$CacheEntry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   5.00KiB |        40 | 128.00bytes | java&#x2F;lang&#x2F;ref&#x2F;Finalizer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   3.50KiB |        32 | 112.00bytes | java&#x2F;net&#x2F;URL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   3.42KiB |        73 |  48.00bytes | java&#x2F;io&#x2F;File&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   3.17KiB |        12 | 776.00bytes | java&#x2F;util&#x2F;Hashtable$Entry[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   3.13KiB |        56 | 144.00bytes | java&#x2F;lang&#x2F;String[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Top 20 largest instances:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; Total size | Instances |     Largest | Class name                                   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--------------------------------------------------------------------------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    1.99MiB |       436 |   634.78KiB | int[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  197.11KiB |      1991 |    16.02KiB | char[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   85.25KiB |       443 |     8.02KiB | byte[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   45.42KiB |       560 |     8.02KiB | java&#x2F;lang&#x2F;Object[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    5.91KiB |        18 |     2.02KiB | java&#x2F;util&#x2F;HashMap$Node[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    2.05KiB |         2 |     2.02KiB | java&#x2F;lang&#x2F;invoke&#x2F;MethodHandle[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    2.02KiB |         1 |     2.02KiB | java&#x2F;lang&#x2F;Integer[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    3.17KiB |        12 | 776.00bytes | java&#x2F;util&#x2F;Hashtable$Entry[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;462.00bytes |         1 | 462.00bytes | sun&#x2F;misc&#x2F;Launcher$AppClassLoader&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;454.00bytes |         1 | 454.00bytes | sun&#x2F;misc&#x2F;Launcher$ExtClassLoader&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;680.00bytes |         2 | 340.00bytes | simple&#x2F;Producer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;680.00bytes |         2 | 340.00bytes | simple&#x2F;Consumer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    2.30KiB |         7 | 336.00bytes | java&#x2F;util&#x2F;jar&#x2F;JarFile$JarFileEntry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;334.00bytes |         1 | 334.00bytes | java&#x2F;lang&#x2F;ref&#x2F;Finalizer$FinalizerThread&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;332.00bytes |         1 | 332.00bytes | java&#x2F;lang&#x2F;ref&#x2F;Reference$ReferenceHandler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    1.01KiB |         9 | 312.00bytes | java&#x2F;lang&#x2F;reflect&#x2F;Field[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    1.48KiB |         7 | 272.00bytes | java&#x2F;util&#x2F;concurrent&#x2F;ConcurrentHashMap$Node[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;236.00bytes |         1 | 236.00bytes | sun&#x2F;net&#x2F;www&#x2F;protocol&#x2F;file&#x2F;FileURLConnection&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;440.00bytes |         2 | 220.00bytes | java&#x2F;io&#x2F;ExpiringCache$1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;432.00bytes |         2 | 216.00bytes | java&#x2F;lang&#x2F;NoSuchMethodError&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And that&#x27;s all there is to it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;a class=&quot;zola-anchor&quot; href=&quot;#architecture&quot; aria-label=&quot;Anchor link for: architecture&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;As mentioned previously, the CLI is written in Rust and works in a synchronous multithreaded fashion.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a simplified architecture diagram for the current version (0.4.7).&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-07-11&amp;#x2F;architecture.png&quot;
         alt=&quot;Architecture&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The various threads are wired up together via channels to form a processing pipeline where all stages run in parallel (if the host has enough cores).&lt;&#x2F;p&gt;
&lt;p&gt;The file reader thread proactively loads chunks of 64Mb from the input file to not starve the rest of the pipeline while waiting for IO. Loading too many chunks in advance has a direct impact on the memory usage, so I settled on 3 chunks based on experiments.&lt;&#x2F;p&gt;
&lt;p&gt;Those chunks are then sent over to the streaming parser which was the most challenging work of the project because it must handle incomplete inputs.
A single chunk can contain millions of records, and a chunk is of course not aligned on the actual boundary of the &lt;code&gt;hprof&lt;&#x2F;code&gt; records.&lt;&#x2F;p&gt;
&lt;p&gt;Therefore, the parser tries to make sense of the incoming binary data while carefully managing its inner buffer.&lt;&#x2F;p&gt;
&lt;p&gt;More concretely, it has been written by following the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;hg.openjdk.java.net&#x2F;jdk&#x2F;jdk&#x2F;file&#x2F;ee1d592a9f53&#x2F;src&#x2F;hotspot&#x2F;share&#x2F;services&#x2F;heapDumper.cpp#l62&quot;&gt;full specification of the hprof format&lt;&#x2F;a&gt; found in the heap dumper code of the JDK.&lt;&#x2F;p&gt;
&lt;p&gt;The parser itself is written with the &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Geal&#x2F;nom&quot;&gt;nom&lt;&#x2F;a&gt; library, which I found a real pleasure to work with due to its support for parsing incomplete data.&lt;&#x2F;p&gt;
&lt;p&gt;As the content of the file is streamed through the parser, the class information is extracted and forwarded to the statistics recorder thread which keeps track of the instance counts in order to later compute the heavy hitters.&lt;&#x2F;p&gt;
&lt;p&gt;Spoiler alert: as of version 0.4.7, the performance bottleneck is the parsing thread.&lt;&#x2F;p&gt;
&lt;p&gt;Speeding up other stages of the pipeline would not yield any performance improvements.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;test-data&quot;&gt;Test data&lt;a class=&quot;zola-anchor&quot; href=&quot;#test-data&quot; aria-label=&quot;Anchor link for: test-data&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;We are about to do some performance testing, which means we need some meaningful test data.&lt;&#x2F;p&gt;
&lt;p&gt;For the sake of transparency or reproducibility, I will show you exactly how to generate a similar heap dump.&lt;&#x2F;p&gt;
&lt;p&gt;To avoid completely synthetic data, we will be using &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;spring-petclinic&#x2F;spring-petclinic-rest&quot;&gt;Spring&#x27;s REST petclinic&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It is a reasonable choice because it is relatively well known, and it uses an in-memory database by default which naturally amplifies the memory usage.&lt;&#x2F;p&gt;
&lt;p&gt;In order to not waste too much time growing the heap, we will simply use the Java &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;blogs.oracle.com&#x2F;javamagazine&#x2F;post&#x2F;epsilon-the-jdks-do-nothing-garbage-collector&quot;&gt;Epsilon GC&lt;&#x2F;a&gt; which does not clean up anything.&lt;&#x2F;p&gt;
&lt;p&gt;This is the change to apply if you want to try this at home.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git diff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-header&quot;&gt;diff --git a&#x2F;pom.xml b&#x2F;pom.xml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;index b936a37..7621eb9 100644&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-header z-from-file&quot;&gt;---&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-header z-from-file&quot;&gt; a&#x2F;pom.xml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-header z-to-file&quot;&gt;+++&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-header z-to-file&quot;&gt; b&#x2F;pom.xml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; -165,6 +165,15&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-diff z-range&quot;&gt; @@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             &amp;lt;plugin&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;&#x2F;groupId&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 &amp;lt;artifactId&amp;gt;spring-boot-maven-plugin&amp;lt;&#x2F;artifactId&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                &amp;lt;configuration&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    &amp;lt;executable&amp;gt;true&amp;lt;&#x2F;executable&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    &amp;lt;jvmArguments&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        -Xmx32g&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        -XX:+UnlockExperimentalVMOptions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                        -XX:+UseEpsilonGC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                    &amp;lt;&#x2F;jvmArguments&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-inserted&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-markup z-inserted&quot;&gt;                &amp;lt;&#x2F;configuration&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                 &amp;lt;executions&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                     &amp;lt;execution&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You could also add &lt;code&gt;-XX:+HeapDumpOnOutOfMemoryError&lt;&#x2F;code&gt; if you prefer to produce a heap dump whenever an &lt;code&gt;OutOfMemoryError&lt;&#x2F;code&gt; is thrown instead of performing the dump manually.&lt;&#x2F;p&gt;
&lt;p&gt;In any case we can start the application using Maven.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;mvnw&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; spring-boot:run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In order to increase the memory pressure, we will gently hammer one of the REST endpoints using &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rakyll&#x2F;hey&quot;&gt;Hey&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hey&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; POST&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;D&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;payload-owner.json&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; application&#x2F;json&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;A&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; application&#x2F;json&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;z&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 3m&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 50&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt; http:&#x2F;&#x2F;127.0.0.1:9966&#x2F;petclinic&#x2F;api&#x2F;owners&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the following &lt;code&gt;payload-owner.json&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;address&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;110 W. Liberty St.&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;city&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Madison&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;firstName&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;George&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;lastName&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Franklin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;telephone&lt;&#x2F;span&gt;&lt;span class=&quot;z-support&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;6085551023&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once the desired heap size is reached, we can generate a heap dump with &lt;code&gt;jmap&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;jmap&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;dump:format=b,file=pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pi&lt;&#x2F;span&gt;&lt;span&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which gives us a decent 34Gb heap dump file to play with.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;du&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;BM&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pets.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;34486M&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pets.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s see what &lt;code&gt;hprof-slurp&lt;&#x2F;code&gt; has to say about it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;.&#x2F;hprof-slurp&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Top 20 allocated classes:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Total size | Instances |     Largest | Class name                                                                                 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-----------------------------------------------------------------------------------------------------------------------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   4.02GiB |  90184199 |   544.20KiB | byte[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   2.13GiB |  55748013 |   109.80KiB | java&#x2F;lang&#x2F;Object[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   1.72GiB |  51264762 |  36.00bytes | java&#x2F;lang&#x2F;String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   1.57GiB |  14807226 | 114.00bytes | org&#x2F;hibernate&#x2F;validator&#x2F;internal&#x2F;engine&#x2F;path&#x2F;NodeImpl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   1.18GiB |   8536353 | 148.00bytes | java&#x2F;nio&#x2F;HeapByteBuffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   1.03GiB |  18074217 |     3.75MiB | int[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1022.73MiB |   5765654 | 186.00bytes | java&#x2F;lang&#x2F;reflect&#x2F;Method&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1021.18MiB |  26769597 |  40.00bytes | java&#x2F;util&#x2F;ArrayList&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 896.73MiB |  21370207 |  44.00bytes | java&#x2F;lang&#x2F;StringBuilder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 838.65MiB |   7594346 |    16.02KiB | java&#x2F;util&#x2F;HashMap$Node[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 744.79MiB |   5276798 | 148.00bytes | java&#x2F;nio&#x2F;StringCharBuffer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 743.57MiB |   5340350 | 146.00bytes | java&#x2F;util&#x2F;LinkedHashMap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 631.70MiB |   6899814 |  96.00bytes | java&#x2F;util&#x2F;regex&#x2F;Matcher&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 606.64MiB |   6490868 |  98.00bytes | org&#x2F;hibernate&#x2F;validator&#x2F;internal&#x2F;engine&#x2F;constraintvalidation&#x2F;ConstraintValidatorContextImpl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 605.70MiB |    610435 |   128.02KiB | java&#x2F;util&#x2F;concurrent&#x2F;ConcurrentHashMap$Node[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 584.97MiB |  14604425 |  42.00bytes | org&#x2F;hibernate&#x2F;validator&#x2F;internal&#x2F;engine&#x2F;path&#x2F;PathImpl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 556.55MiB |  14589693 |  40.00bytes | java&#x2F;util&#x2F;ArrayList$Itr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 520.24MiB |   6818920 |  80.00bytes | java&#x2F;util&#x2F;HashMap&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 425.14MiB |   8330358 |    32.02KiB | char[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 424.89MiB |   9281863 |  48.00bytes | java&#x2F;util&#x2F;HashMap$Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Top 20 largest instances:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Total size | Instances |   Largest | Class name                                                        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;--------------------------------------------------------------------------------------------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   1.03GiB |  18074217 |   3.75MiB | int[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   4.02GiB |  90184199 | 544.20KiB | byte[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 605.70MiB |    610435 | 128.02KiB | java&#x2F;util&#x2F;concurrent&#x2F;ConcurrentHashMap$Node[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   2.13GiB |  55748013 | 109.80KiB | java&#x2F;lang&#x2F;Object[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 425.14MiB |   8330358 |  32.02KiB | char[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  13.70MiB |    211087 |  24.02KiB | long[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   5.81MiB |      3456 |  16.07KiB | jdk&#x2F;internal&#x2F;org&#x2F;objectweb&#x2F;asm&#x2F;SymbolTable$Entry[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 314.02KiB |       159 |  16.07KiB | org&#x2F;springframework&#x2F;asm&#x2F;SymbolTable$Entry[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 838.65MiB |   7594346 |  16.02KiB | java&#x2F;util&#x2F;HashMap$Node[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  81.18MiB |   2093066 |   9.05KiB | java&#x2F;lang&#x2F;String[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; 432.84KiB |        54 |   8.02KiB | java&#x2F;nio&#x2F;ByteBuffer[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  15.83KiB |         2 |   7.91KiB | java&#x2F;util&#x2F;Locale[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  13.94MiB |    405627 |   4.67KiB | java&#x2F;lang&#x2F;Object[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  30.21KiB |        12 |   4.02KiB | net&#x2F;bytebuddy&#x2F;jar&#x2F;asm&#x2F;SymbolTable$Entry[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  47.46MiB |    214730 |   3.01KiB | java&#x2F;lang&#x2F;reflect&#x2F;Method[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   4.23KiB |         6 |   2.97KiB | [[B[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   2.84KiB |         1 |   2.84KiB | java&#x2F;lang&#x2F;Character$UnicodeBlock[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   2.67KiB |         1 |   2.67KiB | jdk&#x2F;internal&#x2F;math&#x2F;FDBigInteger[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   4.28KiB |         2 |   2.14KiB | sun&#x2F;security&#x2F;util&#x2F;KnownOIDs[]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   2.11KiB |         1 |   2.11KiB | org&#x2F;springframework&#x2F;boot&#x2F;web&#x2F;embedded&#x2F;tomcat&#x2F;TomcatEmbeddedContext&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This output looks about right for an application using an in-memory database. We find the usual suspects regarding various arrays, HashMap nodes and Strings.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performance-over-time&quot;&gt;Performance over time&lt;a class=&quot;zola-anchor&quot; href=&quot;#performance-over-time&quot; aria-label=&quot;Anchor link for: performance-over-time&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;It is often interesting to track the performance of a piece of software over time to be able to attribute gains to precise changes.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes a single line change can have a tremendous effect, and sometimes a complete change of architecture is required to remove a bottleneck.&lt;&#x2F;p&gt;
&lt;p&gt;Using the benchmarking tool &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sharkdp&#x2F;hyperfine&quot;&gt;hyperfine&lt;&#x2F;a&gt; we are able to measure accurately the execution time of our CLI in a blackbox fashion.&lt;&#x2F;p&gt;
&lt;p&gt;For reference, I will be running the benchmarks on a laptop running Linux on an Intel &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;www.intel.com&#x2F;content&#x2F;www&#x2F;us&#x2F;en&#x2F;products&#x2F;sku&#x2F;201896&#x2F;intel-core-i710610u-processor-8m-cache-up-to-4-90-ghz&#x2F;specifications.html&quot;&gt;i7-10610U&lt;&#x2F;a&gt; CPU.&lt;&#x2F;p&gt;
&lt;p&gt;In this comparison analysis, we are interested in the relative speedup between releases and not the absolute durations, which are mostly a function of the dump size given a stable throughput.&lt;&#x2F;p&gt;
&lt;p&gt;After downloading all the versions of &lt;code&gt;hprof-slurp&lt;&#x2F;code&gt; into the same directory, we can compare how they handle the &lt;code&gt;pets.bin&lt;&#x2F;code&gt; heap dump using the following &lt;code&gt;hyperfine&lt;&#x2F;code&gt; magic incantation.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;hyperfine&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-runs&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-markdown&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hprof.md&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;-export-json&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hprof.json&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.1.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.1.0 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.2.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.2.0 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.2.1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.2.1 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.2.2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.2.2 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.3.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.3.0 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.3.1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.3.1 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.3.2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.3.2 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.3.3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.3.3 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.4.0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.4.0 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.4.1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.4.1 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.4.2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.4.2 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.4.3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.4.3 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.4.4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.4.4 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.4.5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.4.5 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.4.6&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.4.6 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; 0.4.7&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;hprof-slurp-0.4.7 -i pets.bin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which - after a long time - yields the following Markdown table in &lt;code&gt;hprof.md&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Command&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Mean [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Min [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Max [s]&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Relative&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.1.0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;131.227 ± 4.072&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;126.660&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;134.475&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3.83 ± 0.12&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.2.0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;119.450 ± 0.244&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;119.206&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;119.694&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3.49 ± 0.03&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.2.1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;119.038 ± 0.513&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;118.452&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;119.405&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3.47 ± 0.03&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.2.2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;92.710 ± 0.893&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;91.685&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;93.324&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2.71 ± 0.03&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.3.0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;84.097 ± 0.159&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;83.953&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;84.268&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2.45 ± 0.02&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.3.1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;81.579 ± 0.073&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;81.497&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;81.639&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2.38 ± 0.02&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.3.2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;81.255 ± 0.211&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;81.028&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;81.445&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2.37 ± 0.02&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.3.3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;77.121 ± 0.228&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;76.937&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;77.376&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2.25 ± 0.02&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.4.0&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;67.911 ± 0.979&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;66.826&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;68.728&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.98 ± 0.03&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.4.1&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;65.925 ± 0.344&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;65.645&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;66.309&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.92 ± 0.02&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.4.2&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;65.779 ± 0.240&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;65.602&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;66.053&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.92 ± 0.02&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.4.3&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;63.398 ± 0.104&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;63.291&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;63.499&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.85 ± 0.02&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.4.4&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;35.473 ± 0.047&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;35.444&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;35.527&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.04 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.4.5&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;34.695 ± 0.302&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;34.440&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;35.028&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.01 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.4.6&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;34.285 ± 0.048&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;34.254&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;34.340&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00 ± 0.01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;code&gt;0.4.7&lt;&#x2F;code&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;34.264 ± 0.289&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;34.000&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;34.574&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1.00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;And using the &lt;code&gt;hprof.json&lt;&#x2F;code&gt; file and some python &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sharkdp&#x2F;hyperfine&#x2F;tree&#x2F;master&#x2F;scripts&quot;&gt;scripts&lt;&#x2F;a&gt; we generate the following whisker graph.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-07-11&amp;#x2F;hprof-graph.png&quot;
         alt=&quot;Whisker graph&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Some observations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;the throughput increased by more than 70%&lt;&#x2F;li&gt;
&lt;li&gt;0.1.0 has a large variance (might be a warmup issue)&lt;&#x2F;li&gt;
&lt;li&gt;starting from 0.4.5 the iterative improvement is minimal&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In any case, we reached a solid 1Gb&#x2F;s throughput in the latest version given the size of our test file.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s have a look at the peak memory consumption for 0.4.7 using &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;KDE&#x2F;heaptrack&quot;&gt;Heaptrack&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name&quot;&gt;heaptrack&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&#x2F;hprof-slurp-0.4.7&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; pets.bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This opens up the UI directly after the run if it is installed.&lt;&#x2F;p&gt;

    

&lt;figure&gt;
    &lt;img
        src=&quot;&amp;#x2F;2022-07-11&amp;#x2F;latest-heaptrack-consumed.png&quot;
         alt=&quot;Heaptrack memory consumed&quot;
        
        
    &gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The memory usage is pretty stable; it seems we have been able to stream the whole 34 Gb file within 500Mb.&lt;&#x2F;p&gt;
&lt;p&gt;Most of it is actually due to the various internal buffers which are used to communicate between the threads.
Those are pre-allocated and can grow to a certain size before being shrunk to release the memory.&lt;&#x2F;p&gt;
&lt;p&gt;One could expect a stable similar memory usage for much larger dumps unless those contain large arrays of primitives or objects which need to be parsed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-work&quot;&gt;Future work&lt;a class=&quot;zola-anchor&quot; href=&quot;#future-work&quot; aria-label=&quot;Anchor link for: future-work&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Obviously, I am still interested in making &lt;code&gt;hprof-slurp&lt;&#x2F;code&gt; faster — hopefully not at the expense of code readability.&lt;&#x2F;p&gt;
&lt;p&gt;Outside the performance concern, I believe the output could still be improved to be more useful.&lt;&#x2F;p&gt;
&lt;p&gt;First, I would like to validate the precision of the statistics reported by comparing the output of &lt;code&gt;hprof-slurp&lt;&#x2F;code&gt; against the existing tools. My gut feeling is that the numbers are not too far off and serve as a pretty good proxy.&lt;&#x2F;p&gt;
&lt;p&gt;Moreover, additional extractions could be performed as long as it happens in a single pass, such as rendering the complete thread stack traces at the moment of the heap dump.&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to &lt;a href=&quot;&#x2F;about&#x2F;&quot;&gt;reach out&lt;&#x2F;a&gt; if you have suggestions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a class=&quot;zola-anchor&quot; href=&quot;#conclusion&quot; aria-label=&quot;Anchor link for: conclusion&quot; style=&quot;visibility: hidden;&quot;&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;This article has shown that &lt;a rel=&quot;nofollow noreferrer external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;agourlay&#x2F;hprof-slurp&quot;&gt;hprof-slurp&lt;&#x2F;a&gt; has gotten faster over time and that it is now processing heap dumps at around 1Gb&#x2F;s.&lt;&#x2F;p&gt;
&lt;p&gt;It fulfills the initial goal, which was to offer a quick overview of large heap dumps using a regular developer machine.&lt;&#x2F;p&gt;
&lt;p&gt;The next articles in this &lt;a href=&quot;&#x2F;tags&#x2F;series&#x2F;&quot;&gt;series&lt;&#x2F;a&gt; will go through a selection of the most interesting optimizations that had the largest impact on performance.&lt;&#x2F;p&gt;
&lt;p&gt;In the meantime, you can try to reproduce those results or, even better, analyze larger real-world heap dumps!&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
