
JS1024 Results – 1k JavaScript Demos - KilledByAPixel
https://js1024.fun/results/2020
======
lifthrasiir
Post-mortem writeups by submitters:

Frank Force: [https://frankforce.com/?p=7617](https://frankforce.com/?p=7617)
(1st place)

Raimon Ràfols: [http://blog.rafols.org/index.php/2020/07/21/javascript-
ballo...](http://blog.rafols.org/index.php/2020/07/21/javascript-
balloon-1k-postmortem/) (10th place)

Mattia Fortunati: [https://www.mattiafortunati.com/detective-moji-
postmortem-a-...](https://www.mattiafortunati.com/detective-moji-postmortem-a-
javascript-game-in-just-1024-bytes/) (16th place)

~~~
dietrichepp
I haven’t written a post-mortem but I’ll take a quick stab here, and post a
more polished post-mortem on my website later.

My demo is Star Traveler, which placed #1 in the 2D Canvas category. The
GitHub repository is here: [https://github.com/depp/demo-
traveler](https://github.com/depp/demo-traveler)

Source code: [https://github.com/depp/demo-
traveler/blob/trunk/src.js](https://github.com/depp/demo-
traveler/blob/trunk/src.js)

What I like about 1K demos is that you can make them in a relatively short
amount of time—something like a week or so, without taking time off. After a
week of work I was happy with what I had written, out of space, and had
diminishing returns when I attempted to reduce the size. By comparison, JS13K
can be a lot more work.

The first thing I did was set up a development environment which would reload
in the browser every time I saved changes. The development page showed the
number of bytes left at the top of the screen and put the exact, submission-
ready code in an iframe. Saving changes would trigger everything to be
minified and packed again. Packing is done with Terser -> RegPack. No
potentially incompatible techniques like method hashing were used, but that’s
probably because I didn’t see a size improvement when I tried them. There are
some custom transformations on the code during compilation, mostly so I could
have ESLint watch my back.

The demo itself has three parts to it. Most of the objects are rendered by
callback functions, and there’s a big array of callback functions in back-to-
front order. The function closures contain any generated data necessary for
drawing the data. The parts are:

1\. Mountains and clouds, which are just simple midpoint displacement
fractals. The mountains were flipped upside down and stretched to make clouds.
Various techniques for generating a fractal were tried, a recursive functional
approach ended up being the smallest.

2\. Stars, which are just randomly placed in 3D space and randomly resized
each frame to make them twinkle.

3\. The planet, which is drawn separately. The submitted version draws it over
the clouds. This was fixed in the repo, but not re-submitted.

Notes on technique:

\- Path2D turns out to be a very efficient way to specify a path for a Canvas.
It uses an SVG path string to specify the path, which is more compact than
using .moveTo() and .lineTo(). There is room for improvement.

\- The 'color' function is a beast, it lets you represent an RGB color as a
3-digit number from 111 to 999, and calculate things like gradients. There was
a lot of tweaking to get colors that I liked.

\- Did a lot of inlining and un-inlining of functions at the end. For example,
if a function f(x) is defined like f(x) = 4 * ..., then you can move the
constant out of the function, or into the function from the call sites.

\- Checked the minified code to see how functions were being emitted. If they
were emitted as (x) => { a; b; }, I would try to change the code so they could
be emitted as (x) => (a,b).

\- RegPack gives you limited space savings for repetitive code, so use it.

\- If you need local variables, just add arguments to your function and use
those.

~~~
leeoniya
> Path2D turns out to be a very efficient way to specify a path for a Canvas.
> It uses an SVG path string to specify the path, which is more compact than
> using .moveTo() and .lineTo().

Path2D w/ SVG strings is byte-efficient, but is less computationally efficient
vs the same Path2D w/ lineTo(), etc.

~~~
dietrichepp
Some context—in JS1024, the code has to fit in 1024 bytes, so you can safely
assume that “efficiency” refers to size and not runtime performance.

This particular demo only creates the Path2D objects once, at startup, and
then hammers the canvas with a ridiculous amount of overdraw.

------
nlh
There’s something ironic about a site hosting intentionally tiny snippets of
code that’s crashed / sluggish under the social media hug of death...

BUT - the few that I’ve managed to see are super cool, so when it comes back
to life it’s worth checking out!

~~~
jakear
Question for people that run websites that have been “hug of death”ed: would
your website be able to be statically hosted on something like github pages,
if no why not — if yes why do you choose not to, given it is free and would
make all scaling troubles go away (or so I’ve heard).

~~~
chrismorgan
There are two reasons why sites fall over in cases like this: CPU saturation,
where the solution is better caching (which includes going fully static), and
network saturation, where the solution is either to get fatter pipes or to
reduce the data transferred. Hugs of death are normally due to CPU saturation.

But in this case, I suspect that the server is just saturating its network
connection because of poor treatment of images.

I have JavaScript disabled so maybe it’s loading more if you have JavaScript
enabled, but when you exclude images, it’s only transferring about 152KB.
Images are where it goes wrong: it’s serving up a large number of images, and
some of them are unreasonably large and high quality (like 34ᵗʰ place, a
1000×1000 PNG of a fractal being shown at 400×400), and most significantly
it’s using quite a few multi-megabyte GIFs, which is flatly stupid and wrong
and they _deserve_ to have their site fall over for pulling that.

So the end result is at least 20MB. 20MB = 160Mb, and if your server has only
a one gigabit link (very common), you can suddenly only cope with about six
visitors per second (though in practice things will start falling over before
that, maybe round down to five), which is not quite enough for the peaks
you’ll get when high on HN, and it becomes a bit of a cascading problem, kinda
like a capacitor but bad.

The solution is to treat the images properly: actually _compress_ them, use
videos instead of GIFs, that sort of thing. I reckon 3MB total is readily
attainable here, which would allow you to serve 40 visitors per second, which
is probably enough.

So yeah, putting your pages on a platform with really fat pipes will solve
problems like this after a fashion, but I’d argue that it’s not really
_solving_ them, it’s just letting you get away with doing a bad job and
shifting the burden onto users.

~~~
lifthrasiir
There was 5MB preview image limit for each submission. I was a bit surprised
when my preview image went straight into the listing after review. The
organizer was a bit struggling with the website (for example, there was no
HTTPS for the first days of the contest and multiple people helped to get it
working), hopefully next time it will improve.

------
vesinisa
I only get a secure connection error with Firefox 79 (on ArchLinux) when
trying to connect to that domain. The certificate configuration seems to be
missing some intermediate certs:

[https://www.sslshopper.com/ssl-
checker.html#hostname=js1024....](https://www.sslshopper.com/ssl-
checker.html#hostname=js1024.fun)

[https://www.ssllabs.com/ssltest/analyze.html?d=js1024.fun](https://www.ssllabs.com/ssltest/analyze.html?d=js1024.fun)

~~~
malinens
Alway there is that one arch guy in the comments

~~~
Tajnymag
Having the same error on Firefox Preview

------
jjcm
I really appreciate how well documented a lot of the source files are. There
are a lot of cool golf hacks/tricks in these!

i.e.:
[https://js1024.fun/demos/2020/16/source](https://js1024.fun/demos/2020/16/source)

~~~
lifthrasiir
Besides from being one of the winners (AquaPop1K), I also had a pleasure to
read every single source code to rate submissions (as every submitter could
rate other entries). I recommend to do the same if you have time.

------
chrismorgan
“Shedding snake” reminds me of a game I made on my Casio CFX-9850GB+ Color in
high school. It started out as snake, but keeping track of the positions of
the snake’s pixels in an array or matrix, even if treating it as a ring buffer
so you weren’t constantly shuffling all the values in it, was really slow, so
that by the time the snake was even six pixels long there was not the
slightest bit of challenge to it because it was moving less than two pixels
per second (and by ten, below one). So I turned it into what I called Snail
Trail, with it just laying down pixels behind it and never keeping track of
them, because you could query “is this pixel filled?” much more rapidly (and
it was O(1) rather than O(n²) or worse). That was much faster, and I rapidly
worked out the optimal strategy. A year or two later I transferred it to
someone’s newer model of calculator which was generally about six times as
fast, and… yeah, I had to insert busy loops to make it playable!

I had good times with that calculator. 32KB taught me frugality not unlike
that needed for competitions like JS1024, and how to find that there was a
character/instruction akin to a semicolon in Python that took one byte, where
the new line character/instruction took two bytes. (I only obtained a manual
for the calculator after having it for two years. Figured out one or two new
tricks after that, but I’d worked almost everything possible out by trial and
error.) So power efficient, too: I changed the four AAA batteries only twice
in more than three years of _very_ heavy usage (looking back on it, I probably
got more than 200h of life from each set), while all the rest of the class
that had the newer, faster version (except one other who had the same model as
me) would need to change them around once a term, and they didn’t use their
calculators even a _quarter_ as much as me. I’m going to guess figures of a
CPU 6× as fast and power consumption 30× as high. And those newer ones were
even only monochrome rather than three-colour LCD.

Then after I left they shifted to CAS calculators and battery life was a
zillion times worse again. And laptops, phones and such will be even worse
still. Ah well.

~~~
skitter
Same for me, except with the FX-9860GII and for the 'trails' feature
originally being a bug in my ring buffer that triggered when it grew.

It definitely was fun to experiment within such constraints. I can't remember
being very concerned with program size, although after a certain size there
was a boundary the jump statements weren't able to cross any more. Only having
global one-letter variables and no function calls (and a 21*7 character
screen) also made the code hard to read/write, but it was a fun puzzle and I
ended up writing a ray caster (god it was slow), something akin to the game
Concrete Jungle and a complete 2-player implementation of Settlers of Catan,
amongst other things. Not sure if my math teacher was a fan of me not paying
attention in class though.

~~~
chrismorgan
I say 32KB, but the actual usable space was more like 20KB, due to things like
4KB for a screen buffer if you went graphics mode rather than text mode, which
I did for some things and needed to do if ever actually graphing, however much
if you used lists or matrices, _& c._ Anyway, I kept writing programs
(sometimes games, sometimes useful things like automating the techniques we
learned, such as a surd simplifier or a quadratic solver or a prime checker),
so every so often I’d run out of space and rename a multi-letter program down
to one letter to save a few bytes, or comb through a program to find ways of
saving a few more bytes. I certainly spent _many_ hours coming up with clever
ways of saving single bytes. It was good fun. Even sold a few programs to
other students for a few dollars if they had the necessary transfer cable.
Occasionally I’d regretfully delete a program if it was no longer pulling its
weight.

I definitely never tried a ray caster or anything that complex. I can imagine
that taking literally hours to render a single frame, if I even coded it
right.

I kept my calculator in my pencil case, so I always had it with me in classes.
I think all the teachers (definitely not just maths) were pretty much resigned
to me using it when I finished my work in their classes (or if I didn’t want
to do it and reckoned I could get away with it). Having three elder siblings
that would read books or used calculators under the desk certainly helped. One
teacher complained volubly about the first couple of us for this very reason
(and I was very probably worse than them), but by halfway through my schooling
he said to my mother once that he always loved having Morgans in his class.
This amused mum greatly. Stockholm syndrome, we decided.

------
ggregoire
I'm not into graphics/games development so that might be why, but I had never
heard of Shaders (the third category), which doesn't look at all like
JavaScript.

Demo: [https://js1024.fun/demos/2020/12](https://js1024.fun/demos/2020/12)

Source code:
[https://js1024.fun/demos/2020/12/source](https://js1024.fun/demos/2020/12/source)

Shaders: [https://developer.mozilla.org/en-
US/docs/Games/Techniques/3D...](https://developer.mozilla.org/en-
US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders)

~~~
iainmerrick
It’s WebGL.

Check out [https://www.shadertoy.com/](https://www.shadertoy.com/) for lots
more of these demos. You can do some really amazing stuff.

------
throwaway_pdp09
It's slow AF because the smallish images are in fact much larger but shrunk
and many animated on top of that. So far that page has pulled 15MB down and is
still going.

Edit: up to 24.5MB now.

Edit: 34.5MB now and still going

Edit: 44.4MB and still going. It's clearly slowing down badly. I'm killing it.

------
tyingq
The site is unusable in portrait orientation on a phone. You can't see the [X]
to dismiss the pop up divs unless you rotate the phone to horizontal.

------
smusamashah
I though this is same as [https://js1k.com/](https://js1k.com/) it's not

~~~
value0null
Js1k closed 1 year ago.

------
jacquesm
Bad time to have your cert go bad on you.

------
LeonM
That 'Wetlands' demo (winner in shader class) is completely borked in my
browser (FF 79, Linux).

~~~
jlokier
Same here, Firefox 80.0b2, MacOS 10.15.

But it's not Firefox: I see exactly the same artifacts with Safari 13.1.2.
(Safari is also much slower with this demo than Firefox.)

Surprisingly, it depends which GPU it starts with, not the one it's running
on. Some Macbooks have two GPUs, only one active at a time.

If Wetlands is started with the Intel GPU active, it looks fine, and continues
to look fine if the GPU is switched to nVidia. But if started with the nVidia
GPU active, it looks a mess, lots of colour noise, and continues to look that
way if the GPU is switched to Intel.

I've checked all combinations and found the same on both Firefox and Safari.
So I guess it's probably the underlying OpenGL driver. I'm relieved, this
means it's not a faulty GPU :-)

------
flywheel
If you enjoy this kind of thing, check out the wizardry/madness over at
[https://www.dwitter.net/](https://www.dwitter.net/) \- javascript animations
in 140 bytes (the size of a tweet, hence the name, "dwitter").

~~~
Traubenfuchs
Thanks. In 10 minutes I have seen more art than one can see in the average
museum of modern art.

