<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="4.1.1">Jekyll</generator><link href="https://oliverhughes.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://oliverhughes.dev/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2023-01-03T15:46:32+00:00</updated><id>https://oliverhughes.dev/feed.xml</id><title type="html">Oliver Hughes</title><subtitle>---</subtitle><author><name>Oliver Hughes</name></author><entry><title type="html">Honey, I Shrunk the Image! (Hunting a Tiny Docker Image)</title><link href="https://oliverhughes.dev/honey-i-shrunk-the-image/" rel="alternate" type="text/html" title="Honey, I Shrunk the Image! (Hunting a Tiny Docker Image)" /><published>2021-11-16T00:00:00+00:00</published><updated>2021-11-16T00:00:00+00:00</updated><id>https://oliverhughes.dev/honey-i-shrunk-the-image</id><content type="html" xml:base="https://oliverhughes.dev/honey-i-shrunk-the-image/"><![CDATA[<h1 id="hunting-for-the-smallest-possible-docker-image">Hunting For The Smallest Possible Docker Image</h1>

<p>I came across the challenge of creating the smallest possible “Hello world”
docker image from this <a href="https://idbs-engineering.com/">engineering blog</a>.</p>

<p><em>(Almost did a placement year there, thanks Covid)</em></p>

<!-- I came across this challenge reading through an [engineering blog](https://idbs-engineering.com/)  -->
<!-- from a company I had originally applied to do a placement at during my degree.  -->

<h2 id="container-competition"><a href="https://idbs-engineering.com/docker/containers/2021/01/28/container-competition.html">Container Competition</a></h2>

<p>An internal competition they had, where the challenge was:</p>
<blockquote>
  <p>To build and publish a Docker image that prints the phrase “hello IDBS engineering” 
(or similar) when run. At a minimum, you will need to build a Docker image, 
run that image locally to test and publish to a Docker registry.</p>
</blockquote>

<blockquote>
  <p>We’ll keep it simple and the following dimensions will be taken into account:
The image runs and prints to console. Image size - the smaller, the better.</p>
</blockquote>

<p>I got about half way through this article before I decided that it sounded like
a fun challenge to spend an afternoon on, so cracked on with trying it myself
before I spoiled too much of their solution.</p>

<p>So here’s some of my thought process and journey towards creating the smallest
possible “Hello World” docker image.</p>

<h2 id="docker-run-hello-world">docker run hello-world</h2>

<p>I figured the best way to start would be to find a baseline image to try and
beat or improve from. Luckily Docker themselves have a ‘hello-world’ image.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>❯ docker run hello-world
...
Hello from Docker!
...
</code></pre></div></div>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>❯ docker images
REPOSITORY     SIZE
hello-world    13.3kB
</code></pre></div></div>

<p>So our score to beat is 13.3kB, smaller than I was expecting (or hoping), this
may take some work to beat. The alternative baseline is an ubuntu base image:</p>

<h3 id="ubuntu">ubuntu</h3>

<p>Use the ubuntu base image, and simply echo “Hello world!”:</p>
<pre><code class="language-Docker">FROM ubuntu
CMD ["echo", "Hello World!"]
</code></pre>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>❯ docker build <span class="nb">.</span> <span class="nt">-t</span> ubuntu-hello

❯ docker run ubuntu-hello:latest
Hello There!

❯ docker images
REPOSITORY     SIZE
ubuntu-hello   72.8MB
hello-world    13.3kB
</code></pre></div></div>

<h2 id="smaller-base-image-options">Smaller base image options</h2>

<p>The base ubuntu image is pretty gigantic, the actual Hello World is negligible
in size compared to the overhead of the ubuntu base. So what other options are
there for base images to use?</p>

<h3 id="alpine"><a href="https://hub.docker.com/_/alpine">alpine</a></h3>

<p>Alpine is a “great image base for utilities and even production applications”
and based around <a href="https://musl.libc.org/">musl-libc</a> and BusyBox.</p>

<pre><code class="language-Docker">FROM alpine

CMD ["echo","Hello There!"]
</code></pre>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>❯ docker build . -t alpine-hello

❯ docker run alpine-hello:latest
Hello There!

❯ docker images
REPOSITORY     SIZE
alpine-hello   5.61MB
ubuntu-hello   72.8MB
hello-world    13.3kB
</code></pre></div></div>

<p>Down to 5.61MB is definitely an improvement on the ubuntu base, but alpine is
based on an image of busybox, and contains some ‘optional’ extras we don’t need.
So how small is a plain busybox version?</p>

<h3 id="busybox"><a href="https://hub.docker.com/_/busybox">BusyBox</a></h3>

<p>BusyBox “provides a fairly complete environment for any small or embedded system”. 
It only comes with the very bare necessities, this is fine however as in our case 
we only need one of them: “echo”</p>

<pre><code class="language-Docker">FROM busybox

CMD ["echo","Hello There!"]
</code></pre>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>❯ docker build <span class="nb">.</span> <span class="nt">-t</span> busybox-hello

❯ docker run busybox-hello:latest
Hello There!

❯ docker images 
REPOSITORY      SIZE
busybox-hello   1.24MB
alpine-hello    5.61MB
ubuntu-hello    72.8MB
hello-world     13.3kB
</code></pre></div></div>

<p>An improvement! But still an order of magnitude larger than the hello-world example
image. Just over 1MB is not bad, although the image still contains a
bunch of utilities that we don’t need..</p>

<h3 id="scratch">scratch</h3>

<blockquote>
  <p>0 BYTES</p>
</blockquote>

<p>The ‘SCRATCH’ docker base image contains nothing. It contains 0 dependencies, 0
utilities, and is exactly what we’re looking for. By removing all of the
overhead, the minimum size is now just the smallest self contained executable we
can build.</p>

<h1 id="c">c</h1>
<p>My first thought here was to start with a simple c program.</p>

<h3 id="gcc">gcc</h3>

<p>As a baseline, I started with the classic printf hello world.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// hellogcc.c</span>
<span class="cp">#include</span> <span class="cpf">&lt;stdio.h&gt;</span><span class="cp">
</span><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">printf</span><span class="p">(</span><span class="s">"Hello World</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>And then compile with gcc:</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcc hellogcc.c <span class="nt">-static</span> <span class="nt">-o</span> hello1
</code></pre></div></div>

<p>Compiling with gcc, (and the -static flag to include dependencies), results in a
massive 892KB executable. Luckily we can quickly shrink this with some compiler
flags.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcc hellogcc.c <span class="nt">-Os</span> <span class="nt">-s</span> <span class="nt">-static</span> <span class="nt">-o</span> hello2
</code></pre></div></div>

<p>Telling the compiler to optimise for size using “-Os”, and “-s” to remove linker
table info from the executable. This results in a 793KB executable, better - but
still not good enough.</p>

<p>A bit more searching around brought me to <a href="https://stackoverflow.com/a/33630488">this stackoverflow answer</a>
Which outlines how even though nothing from the c libraries is used in the
actual program, the C runtime (CRT) startfiles that call the main function do
call on some libraries.</p>

<p>The solution to this is to specify startfiles, then choose to not include them
in compilation.</p>

<p>The new code:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;unistd.h&gt;</span><span class="cp">
</span><span class="kt">void</span> <span class="nf">_start</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
  <span class="n">write</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"Hello world!"</span><span class="p">,</span> <span class="mi">12</span><span class="p">);</span>
  <span class="n">_exit</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>gcc hello_write.c <span class="nt">-s</span> <span class="nt">-static</span> <span class="nt">--nostartfiles</span> <span class="nt">-o</span> hello3
</code></pre></div></div>

<p>File sizes so far:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>❯ <span class="nb">ls</span> <span class="nt">-lh</span> | <span class="nb">awk</span> <span class="s1">'{print $9 " : " $5}'</span>
 : 
hello1 : 869K
hello2 : 793K
hello3 : 8.9K
</code></pre></div></div>

<p>This reduces the executable size down to just 8.9KB, which is finally smaller
than the example hello-world docker image. But I think we can still go smaller..</p>

<h3 id="tcc">tcc</h3>

<p><a href="https://bellard.org/tcc/">Tiny C Compiler</a> (TCC) is a tiny but hyper fast C
compiler. Luckily for us, it also generally creates much smaller executables.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="n">write</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">"Hello World</span><span class="se">\n</span><span class="s">"</span><span class="p">,</span> <span class="mi">12</span><span class="p">);</span>
  <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>Compile with tcc:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tcc hello.c <span class="nt">-o</span> hellotcc
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ls -lh | awk '{print $9 " : " $5}'
hello.c : 136
hellotcc : 3.0K
</code></pre></div></div>

<p>Down to just 3KB just by swapping compiler, not bad!</p>

<p><em>Results so far:</em></p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>❯ docker images <span class="nt">--format</span> <span class="s2">"table </span><span class="se">\t</span><span class="s2">"</span>
REPOSITORY      SIZE
tcc-hello       2.99kB
gcc-hello       9.06kB
busybox-hello   1.24MB
alpine-hello    5.61MB
ubuntu-hello    72.8MB

hello-world     13.3kB

</code></pre></div></div>

<h1 id="assembly">Assembly</h1>

<p>The next logical step to try and go smaller than compiled c is to just write
straight assembly. Now, whilst I have some experience with ASM - the majority
of that is for GameBoy or N64. Whilst I could sit down and learn my way around,
this challenge was meant to be about Docker - so why reinvent the wheel when I
can just Google it..</p>

<p>My first thought was to check the <a href="codegolf.stackexchange.com/">code golf</a>
stackexchange for a solution. I found one <a href="https://codegolf.stackexchange.com/a/55479">here</a>,
however right after that I found what is arguably the holy grail:</p>

<h3 id="elf-executable-magic"><a href="http://www.muppetlabs.com/~breadbox/software/tiny">ELF Executable Magic</a></h3>

<p>In an example of pure wizardry by Brian Raiter, an ELF executable “Hello, World”
program in just 62 Bytes.</p>

<p>Every ELF executable has a 52 Byte header, containing data on: if it’s 32/64
bit, little or big-endian, the target architecture etc. By placing the
instructions to write “hello, world” in the header, (and some other tricks
absolutely violating every inch of the ELF file standard), he produces a 62 Byte
executable.</p>

<p>So a simple Dockerfile that just copies this executable to the image:</p>

<pre><code class="language-Docker">FROM scratch
COPY hello hello
CMD ["/hello"]
</code></pre>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>REPOSITORY      SIZE
asm-hello       62B
tcc-hello       2.99kB
gcc-hello       9.06kB
busybox-hello   1.24MB
alpine-hello    5.61MB
ubuntu-hello    72.8MB
hello-world     13.3kB
</code></pre></div></div>

<h1 id="cheating">Cheating</h1>

<p>Unless I can break some laws of physics, it seems like 62 Bytes is the smallest
possible size for a Docker image with an executable in it.</p>

<p>But can we cheat by not having to include an executable at all?</p>

<p>Yes.. <em>kind of</em></p>

<pre><code class="language-Docker">FROM scratch
CMD ["dir/hello"]
</code></pre>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>❯ docker build <span class="nb">.</span> <span class="nt">-t</span> cheat-hello
</code></pre></div></div>

<p>This docker image simply runs an executable called ‘hello’ in the folder ‘dir’.
This folder and executable don’t exist when the image is created, so it gives an
error if ran normally, but this does mean that the actual Docker image is
exactly 0 Bytes.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>REPOSITORY         SIZE
cheat-hello        0B
asm-hello          62B
tcc-hello          2.99kB
gcc-hello          9.06kB
busybox-hello      1.24MB
alpine-hello       5.61MB
ubuntu-hello       72.8MB
hello-world        13.3kB

</code></pre></div></div>

<p>The image is ran using a directory on the host machine linked as a volume in the
container. If the directory linked contains an executable called ‘hello’, then
the container will run the executable and output “hello world”.</p>

<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>❯ docker run <span class="nt">-v</span> ~/path/to/folder/containg/executable/:/dir cheat-hello
hello, world
</code></pre></div></div>

<p>Is this cheating? Yes. The original competition did specify that it should be
able to be published to a Docker registry. I did try for a while to link to the
host machine’s <code class="language-plaintext highlighter-rouge">/bin/</code> to grab <code class="language-plaintext highlighter-rouge">echo</code> from there, which would make it somewhat 
portable. However grabbing dependencies from the host machine is quite literally
the antithesis of the role of Docker, so even if figured it out, writing it down
seemed a little blasphemous.</p>

<h1 id="conclusion">Conclusion</h1>

<p>Whilst the challenge quite quickly strayed away from Docker, learning to
dismantle and violate it’s principles has been a great learning experience. As
has diving into the ELF file format and some c compiler options.</p>

<p>Having now read the rest of the original challenge post - we both ended up at
the same final answer. (Theirs is slightly longer only due to a longer message).
Once you get to zero Docker overhead, there’s only so far you can go.</p>

<p>It was an absolute blast for an afternoon - and I’d love to come back and try a
slightly modified challenge: perhaps a Docker quine (an image that recreates
itself) or the smallest possible Docker web server etc.</p>

<h1 id="resources">Resources</h1>
<p><a href="https://idbs-engineering.com/docker/containers/2021/01/28/container-competition.html">https://idbs-engineering.com/docker/containers/2021/01/28/container-competition.html</a></p>

<p><a href="http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html">http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html</a></p>

<p><a href="http://timelessname.com/elfbin/">http://timelessname.com/elfbin/</a></p>

<p><a href="https://registry.hub.docker.com/_/busybox/">https://registry.hub.docker.com/_/busybox/</a></p>

<p><a href="https://devopsdirective.com/posts/2021/04/tiny-container-image/">https://devopsdirective.com/posts/2021/04/tiny-container-image/</a></p>

<p><a href="https://codegolf.stackexchange.com/a/55479">https://codegolf.stackexchange.com/a/55479</a></p>

<p><a href="https://docs.docker.com/engine/reference/commandline/run/">https://docs.docker.com/engine/reference/commandline/run/</a></p>]]></content><author><name>Oliver Hughes</name></author><category term="docker" /><category term="docker" /><summary type="html"><![CDATA[Hunting For The Smallest Possible Docker Image]]></summary></entry><entry><title type="html">World Wide Web Winners</title><link href="https://oliverhughes.dev/World-Wide-Web-Winners/" rel="alternate" type="text/html" title="World Wide Web Winners" /><published>2021-11-12T00:00:00+00:00</published><updated>2021-11-12T00:00:00+00:00</updated><id>https://oliverhughes.dev/World-Wide-Web-Winners</id><content type="html" xml:base="https://oliverhughes.dev/World-Wide-Web-Winners/"><![CDATA[<h1 id="resources--inspiration">Resources &amp; Inspiration</h1>

<p>This list is a culmination of my absolute favourite resources and inspiring
posts and stories across the internet. 
These are all things that I find myself coming back to every few months, some
are inspiring, some motivating, some frankly have just taken three or four tries
to actually understand what’s happening..</p>

<p>All the links here are to resources that remind me of why I love programming and
all the quirks and challenges that come along with it. Hopefully some of them
can do that for you too.</p>

<h2 id="fast-inverse-square-root">Fast Inverse Square Root</h2>

<p>From the source of ‘Quake 3’, a black magic approximation of an inverse square
root function.</p>

<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">float</span> <span class="nf">Q_rsqrt</span><span class="p">(</span> <span class="kt">float</span> <span class="n">number</span> <span class="p">)</span>
<span class="p">{</span>
    <span class="kt">long</span> <span class="n">i</span><span class="p">;</span>
    <span class="kt">float</span> <span class="n">x2</span><span class="p">,</span> <span class="n">y</span><span class="p">;</span>
    <span class="k">const</span> <span class="kt">float</span> <span class="n">threehalfs</span> <span class="o">=</span> <span class="mi">1</span><span class="p">.</span><span class="mi">5</span><span class="n">F</span><span class="p">;</span>

    <span class="n">x2</span> <span class="o">=</span> <span class="n">number</span> <span class="o">*</span> <span class="mi">0</span><span class="p">.</span><span class="mi">5</span><span class="n">F</span><span class="p">;</span>
    <span class="n">y</span>  <span class="o">=</span> <span class="n">number</span><span class="p">;</span>
    <span class="n">i</span>  <span class="o">=</span> <span class="o">*</span> <span class="p">(</span> <span class="kt">long</span> <span class="o">*</span> <span class="p">)</span> <span class="o">&amp;</span><span class="n">y</span><span class="p">;</span>    <span class="c1">// evil floating point bit level hacking</span>
    <span class="n">i</span>  <span class="o">=</span> <span class="mh">0x5f3759df</span> <span class="o">-</span> <span class="p">(</span> <span class="n">i</span> <span class="o">&gt;&gt;</span> <span class="mi">1</span> <span class="p">);</span>               <span class="c1">// what the fuck? </span>
    <span class="n">y</span>  <span class="o">=</span> <span class="o">*</span> <span class="p">(</span> <span class="kt">float</span> <span class="o">*</span> <span class="p">)</span> <span class="o">&amp;</span><span class="n">i</span><span class="p">;</span>
    <span class="n">y</span>  <span class="o">=</span> <span class="n">y</span> <span class="o">*</span> <span class="p">(</span> <span class="n">threehalfs</span> <span class="o">-</span> <span class="p">(</span> <span class="n">x2</span> <span class="o">*</span> <span class="n">y</span> <span class="o">*</span> <span class="n">y</span> <span class="p">)</span> <span class="p">);</span>   <span class="c1">// 1st iteration</span>
<span class="c1">//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration,</span>
                                              <span class="c1">// this can be removed</span>

    <span class="k">return</span> <span class="n">y</span><span class="p">;</span>
<span class="p">}</span>

</code></pre></div></div>

<p>A mesmerizing piece of code so inspiring I can’t help but return to bask in it’s
glow every few months. No other lines of code have ever made me want to sit down
and write code more than this has.</p>

<ul>
  <li>Great YouTube video explaining the algorithm:
    <ul>
      <li><a href="https://youtu.be/p8u_k2LIZyo" title="Nemean on
Youtube">Fast Inverse Square Root by Nemean</a></li>
    </ul>
  </li>
  <li>Medium post with some more of the history behind it:
    <ul>
      <li><a href="https://medium.com/hard-mode/the-legendary-fast-inverse-square-root-e51fee3b49d9">The Legendary Fast Inverse Square Root</a></li>
    </ul>
  </li>
</ul>

<h2 id="ioccc---yusuke-endohs-ascii-fluid-simulation">IOCCC - Yusuke Endoh’s ASCII Fluid Simulation</h2>
<p>IOCCC, or the International Obfuscated C Code Contest is an annual “celebration
of C’s syntactical opaqueness” that first started in 1984.</p>

<p>This particular 2012 submission by Yusuke Endoh (Also a developer of Ruby) is an
ASCII fluid simulation, that can use it’s own source code as a starting
configuration:</p>

<p><strong>endoh1.c</strong></p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#  include&lt;stdio.h&gt;//  .IOCCC                                         Fluid-  #
#  include &lt;unistd.h&gt;  //2012                                         _Sim!_  #
#  include&lt;complex.h&gt;  //||||                     ,____.              IOCCC-  #
#  define              h for(                     x=011;              2012</span><span class="cm">/*  #
#  */</span><span class="cp">-1&gt;x              ++;)b[                     x]//-'              winner  #
#  define              f(p,e)                                         for(</span><span class="cm">/*  #
#  */</span><span class="cp">p=a;              e,p&lt;r;                                        p+=5)//  #
#  define              z(e,i)                                        f(p,p</span><span class="cm">/*  #
## */</span><span class="cp">[i]=e)f(q,w=cabs  (d=*p-  *q)/2-     1)if(0  &lt;(x=1-      w))p[i]+=w*/// ##
</span>   <span class="kt">double</span> <span class="n">complex</span> <span class="n">a</span> <span class="p">[</span>  <span class="mi">97687</span><span class="p">]</span>  <span class="p">,</span><span class="o">*</span><span class="n">p</span><span class="p">,</span><span class="o">*</span><span class="n">q</span>     <span class="p">,</span><span class="o">*</span><span class="n">r</span><span class="o">=</span><span class="n">a</span><span class="p">,</span>  <span class="n">w</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span><span class="n">d</span><span class="p">;</span>    <span class="kt">int</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">;</span><span class="kt">char</span> <span class="n">b</span><span class="cm">/* ##
## */</span><span class="p">[</span><span class="mi">6856</span><span class="p">]</span><span class="o">=</span><span class="s">"</span><span class="se">\x1b</span><span class="s">[2J"</span>  <span class="s">"</span><span class="se">\x1b</span><span class="s">"</span>  <span class="s">"[1;1H     "</span><span class="p">,</span> <span class="o">*</span><span class="n">o</span><span class="o">=</span>  <span class="n">b</span><span class="p">,</span> <span class="o">*</span><span class="n">t</span><span class="p">;</span>   <span class="kt">int</span> <span class="nf">main</span>   <span class="p">(){</span><span class="cm">/** ##
## */</span><span class="k">for</span><span class="p">(</span>              <span class="p">;</span><span class="mi">0</span><span class="o">&lt;</span><span class="p">(</span><span class="n">x</span><span class="o">=</span>  <span class="n">getc</span> <span class="p">(</span>     <span class="n">stdin</span><span class="p">)</span>  <span class="p">);)</span><span class="n">w</span><span class="o">=</span><span class="n">x</span>  <span class="o">&gt;</span><span class="mi">10</span><span class="o">?</span><span class="mi">32</span><span class="o">&lt;</span>     <span class="n">x</span><span class="o">?</span><span class="mi">4</span><span class="p">[</span><span class="cm">/* ##
## */</span><span class="o">*</span><span class="n">r</span><span class="o">++</span>              <span class="o">=</span><span class="n">w</span><span class="p">,</span><span class="n">r</span><span class="p">]</span><span class="o">=</span>  <span class="n">w</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="o">*</span><span class="n">r</span>     <span class="o">=</span><span class="n">r</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span><span class="o">=</span>  <span class="n">x</span><span class="o">==</span><span class="mi">35</span><span class="p">,</span>  <span class="n">r</span><span class="o">+=</span><span class="mi">9</span><span class="o">:</span><span class="mi">0</span>      <span class="p">,</span><span class="n">w</span><span class="o">-</span><span class="n">I</span><span class="cm">/* ##
## */</span><span class="o">:</span><span class="p">(</span><span class="n">x</span><span class="o">=</span>              <span class="n">w</span><span class="o">+</span><span class="mi">2</span><span class="p">);;</span>  <span class="k">for</span><span class="p">(;;</span>     <span class="n">puts</span><span class="p">(</span><span class="n">o</span>  <span class="p">),</span><span class="n">o</span><span class="o">=</span><span class="n">b</span><span class="o">+</span>  <span class="mi">4</span><span class="p">){</span><span class="n">z</span><span class="p">(</span><span class="n">p</span>      <span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="err">*/</span><span class="o">*</span> <span class="err">##</span>
<span class="cp">## */9,2)              w;z(G,  3)(d*(     3-p[2]  -q[2])  *P+p[4      ]*V-</span><span class="cm">/* ##
## */</span><span class="cp">q[4]              *V)/p[  2];h=0     ;f(p,(  t=b+10  +(x=*p      *I)+</span><span class="cm">/* ##
## */</span><span class="cp">80*(              y=*p/2  ),*p+=p    [4]+=p  [3]/10  *!p[1])     )x=0</span><span class="cm">/* ##
## */</span><span class="cp"> &lt;=x              &amp;&amp;x&lt;79   &amp;&amp;0&lt;=y&amp;&amp;y&lt;23?1[1  [*t|=8   ,t]|=4,t+=80]=1</span><span class="cm">/* ##
## */</span><span class="cp">, *t              |=2:0;    h=" '`-.|//,\\"  "|\\_"    "\\/\x23\n"[x</span><span class="cm">/** ##
## */</span><span class="cp">%80-              9?x[b]      :16];;usleep(  12321)      ;}return 0;}</span><span class="cm">/* ##
####                                                                       ####
###############################################################################
**###########################################################################*/</span><span class="cp">
</span></code></pre></div></div>

<p>Self-documenting code in the worst way..</p>

<ul>
  <li>Here is the IOCCC hint page for this submission:
    <ul>
      <li><a href="https://www.ioccc.org/2012/endoh1/hint.html">Most Complex ASCII Fluid</a></li>
    </ul>
  </li>
  <li>And a YouTube video of the simulation in action:
    <ul>
      <li><a href="https://youtu.be/QMYfkOtYYlg">ASCII fluid dynamics by Yusuke Endoh</a></li>
    </ul>
  </li>
</ul>

<h2 id="how-i-cut-gta-online-loading-times-by-70">“How I cut GTA Online loading times by 70%”</h2>
<p>Fixing an JSON parsing bug in an 8 year old game that’s made over $6.4 billion
since launch.
An incredible story of profiling, decompilation and reverse-engineering to fix a
6 minute load time that dropped down to under 2 minutes.</p>

<ul>
  <li>His blog post detailing his journey &amp; the fix:
    <ul>
      <li><a href="https://nee.lv/2021/02/28/How-I-cut-GTA-Online-loading-times-by-70/">How I cut GTA Online loading times by 70%</a></li>
    </ul>
  </li>
</ul>

<h2 id="effective-java-by-joshua-bloch">Effective Java by Joshua Bloch</h2>
<p>Not exactly an internet gem, but a book that I really enjoyed reading, with some
serious great advice and guidelines on writing better Java code. A must read in
my opinion for someone at an <em>intermediate</em> or so level of Java.</p>

<p>Personally it really helped me overcome some imposter syndrome type feelings,
and something I like to come back to every now and then to refresh my memory.</p>

<ul>
  <li><a href="https://www.oreilly.com/library/view/effective-java/9780134686097/">Effective Java (Third Edition)</a></li>
</ul>

<h2 id="the-case-of-the-500-mile-email">The case of the 500-mile email</h2>

<p>A classic funny tech support story from the mid 90s, a university professor that
“can’t send an email more than 500 miles”. A great story if you’ve never read it
before, and certainly one of my favourites out there.</p>

<ul>
  <li><a href="https://www.ibiblio.org/harris/500milemail.html">The case of the 500-mile email, Trey Harris</a></li>
</ul>

<h2 id="the-hutter-prize">The Hutter Prize</h2>
<p>A compression challenge to compress 1GB of text from Wikipedia. Marcus Hutter
launched the challenge in 2006 with a €50,000 prize, and has recently (2020)
been upped to a €500,000 prize.</p>

<p>The motivation behind the contest is the idea that general compression is
closely related to intelligence, and whilst intelligence is a difficult concept
to quantify, file sizes give a hard quantitative score. The contest has been
largely dominated by Alexander Rhatushnyak, although the most recent winner is
Artemiy Margaritov in May 2021 who compressed the 1GB file down to just 115MB.</p>

<p>The compression techniques used are pretty magical, and the contest as a whole
is a great rabbit hole to get lost in for an afternoon.</p>

<ul>
  <li><a href="http://prize.hutter1.net/">Compressing Human Knowledge</a></li>
</ul>

<h2 id="ben-eater">Ben Eater</h2>

<p>Hours and hours of detailed video content building breadboard computers.
Fantastic for learning how computers work, both the 8-bit and 6502 computers
from scratch series are a great intro into that space. Covering from the very
bottom with logic gates, all the way to functional breadboard computers and ASM.</p>

<ul>
  <li>8-bit computer from scratch:
    <ul>
      <li><a href="https://eater.net/8bit">Website Page</a></li>
      <li><a href="https://youtube.com/playlist?list=PLowKtXNTBypGqImE405J2565dvjafglHU">Youtube Playlist</a></li>
    </ul>
  </li>
  <li>6502 breadboard computer:
    <ul>
      <li><a href="https://eater.net/6502">Website Page</a></li>
      <li><a href="https://youtube.com/playlist?list=PLowKtXNTBypFbtuVMUVXNR0z1mu7dp7eH">Youtube Playlist</a></li>
    </ul>
  </li>
</ul>

<h2 id="code-golf-stackexchange">Code Golf StackExchange</h2>
<p>Programming challenges with the winner decided by the fewest number of bytes in
the source code. A celebration of language quirks, specialised languages, arguably useless
optimisation.</p>

<ul>
  <li><a href="https://codegolf.stackexchange.com/">Code Golf</a></li>
</ul>

<h3 id="fizz-buzz"><a href="https://codegolf.stackexchange.com/questions/58615/1-2-fizz-4-buzz">Fizz Buzz</a></h3>
<p>Code Golf thread for the classic Fizz Buzz programming exercise, great examples
of some of the fun and crazy solutions across various languages.</p>

<p>It’s full of impressive ingenuity, solving useless problems. 
Here are some of my favourite answers across the site:</p>

<ul>
  <li><a href="https://codegolf.stackexchange.com/a/74906">Fizz Buzz in Hexagony</a>:
    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    3 } 1 " $ .
   ! $ &gt; ) } g 4
  _ . { $ ' ) ) \
 &lt; $ \ . \ . @ \ }
F \ $ / ; z ; u ; &lt;
 % &lt; _ &gt; _ . . $ &gt; B /
&lt; &gt; } ) ) ' % &lt; &gt; {
 &gt; ; e " - &lt; / _ %
  ; \ / { } / &gt; .
   \ ; . z ; i ;
    . . &gt; ( ( '
</code></pre></div>    </div>
  </li>
  <li><a href="https://codegolf.stackexchange.com/a/58623">Fizz Buzz in Python 2</a>:
An weirdly genius solution in a more common language:
    <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Python 2, 56 bytes
</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="k">exec</span><span class="s">"print i%3/2*'Fizz'+i%5/4*'Buzz'or-~i;i+=1;"</span><span class="o">*</span><span class="mi">100</span>
</code></pre></div>    </div>
    <h3 id="high-throughput-fizz-buzz">High Throughput Fizz Buzz</h3>
  </li>
  <li><a href="https://codegolf.stackexchange.com/a/236630">High Throughput Fizz Buzz</a>:
Whilst arguably not so much in the spirit of code-golf, outputting fizz buzz at
over 54 GiB/s is a masterpiece.</li>
</ul>

<h2 id="object-detection-from-9fps-to-650-fps-in-6-steps">Object Detection from 9FPS to 650 FPS in 6 Steps</h2>

<p>A great read on pushing Python-based object detection pipeline to the limit. 
Even more impressive is the two follow on articles, pushing all the way to
2530 FPS.</p>
<ul>
  <li><a href="https://paulbridger.com/posts/video-analytics-pipeline-tuning/">Object detection from 9FPS to 650 FPS in 6 Steps</a></li>
  <li><a href="https://paulbridger.com/posts/video-analytics-deepstream-pipeline/">Object detection at 1840 FPS</a></li>
  <li><a href="https://paulbridger.com/posts/tensorrt-object-detection-quantized/">Object detection at 2530
FPS</a></li>
</ul>]]></content><author><name>Oliver Hughes</name></author><category term="resources" /><category term="resources" /><summary type="html"><![CDATA[Resources &amp; Inspiration]]></summary></entry><entry><title type="html">Personal &amp;amp; Blog Info</title><link href="https://oliverhughes.dev/blog-info/" rel="alternate" type="text/html" title="Personal &amp;amp; Blog Info" /><published>2021-11-03T00:00:00+00:00</published><updated>2021-11-03T00:00:00+00:00</updated><id>https://oliverhughes.dev/blog-info</id><content type="html" xml:base="https://oliverhughes.dev/blog-info/"><![CDATA[<h1 id="blog-info">Blog Info:</h1>

<h2 id="tech">Tech</h2>
<ul>
  <li>Site is built with <a href="https://www.jekyllrb.com">Jekyll</a> a static site generator.</li>
  <li>Posts are markdown based</li>
  <li>Temporarily hosted via <a href="https://www.netlify.com">Netlify</a> - with the aim to shift to a DigitalOcean instance soon for finer CI/CD control.</li>
</ul>

<h1 id="personal-info">Personal Info:</h1>
<ul>
  <li>Grew up in Singapore</li>
  <li>First class Computer Science degree from University of Surrey</li>
  <li>Started “programming” with Scratch 10+ years ago</li>
  <li>Python soon after, Java from 2016 &amp; C++ from 2018</li>
  <li>(Ruby, Haskell, Prolog, Assembly, C#) along the way</li>
</ul>

<h2 id="first-ever-project">First ever project:</h2>
<p>First ever real programming project with a purpose was a chrome browser extension. My school at the time used an online Virtual Learning Environment (VLE) to set homework tasks and share files/etc. for classes.</p>

<p>The homework/task list was extremely inefficient - just a list of homework titles and when it was due:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[  Assignment  ]         | [Due Date]
Maths - Complete the ... | [Tomorrow]
English - Read from 3... | [Tomorrow]
Physics - Past paper ... | [ Friday ]
</code></pre></div></div>
<ul>
  <li>In order to mark the task as done, you had to open the task webpage.</li>
  <li>In order to read the full description of the task, you had to open the task webpage, then open another link that opened a pop-up window with the full description.</li>
</ul>

<p>This resulted in having to open a bunch of pages to see the full homework tasks and to be able to plan what work to do and when.</p>

<p>Even marking off tasks that you had already completed required opening another webpage!!</p>

<p>In order to fix this, I learnt the basics of JavaScript, JQuery and building chrome extensions. Using JQuery I called each of the links to tasks, and added extra columns to show the full description on the main page, as well as to add the mark as done button to each task.</p>

<p>This resulted in a page that looked more like this:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[  Assignment  ]                                 | [Due Date] | [Mark As Done]
Maths - Complete the handout                     | [Tomorrow] |      [X]
English - Read from 314 - 512, make notes        | [Tomorrow] |      [ ]
Physics - Finish past paper questions from class | [ Friday ] |      [X]
</code></pre></div></div>

<p>The implementation was messy, and since it loaded two pages for every task set - extremely slow.
And whilst it wasn’t the biggest change, it streamlined the user experience, and so achieved its purpose.</p>]]></content><author><name>Oliver Hughes</name></author><category term="info" /><category term="info" /><summary type="html"><![CDATA[Blog Info:]]></summary></entry></feed>