Just a few days in the past I blogged a couple of web page I added to my web site to render all six thousand plus weblog posts I’ve revealed. It is one in every of many “one-off” pages I’ve constructed right here for numerous causes, in order I used to be the supposed goal, I wasn’t terribly involved in regards to the pace or UX of the web page itself. I knew the code producing the web page was kinda crap, however because it was a build-time solely concern, I did not suppose an excessive amount of about it.
The extra I considered it although, the extra I used to be inquisitive about simply how “unhealthy” my web page was. To be clear, it is undoubtedly unhealthy logic. In case you did not learn the earlier publish, I am doing this to generate the “all” web page:
- Get all posts
- Determine my 12 months vary (first publish to final)
- For yearly, loop over each publish and print a hyperlink if the 12 months of the publish matches the 12 months of the index
That is roughly 20 (years) * 6000 (variety of posts) iterations, or 120K. Fortunately, nevertheless, that is the one inefficient code I’ve written in my life so I do not really feel too unhealthy. However I made a decision to do some digging to see if I might work out some particulars on simply how unhealthy it’s.
Earlier than I begin sharing examples, observe that I am testing this domestically the place I’ve obtained an .eleventyignore
file that ignores a overwhelming majority of my web site. To see how unhealthy issues are, I went forward and renamed that so I might see what would occur in manufacturing. Additionally, I am utilizing Eleventy 2.0.0-canary.16
besides in a single case that I am going to particularly name out.
First Try – Easy Timings
The very first thing I attempted was so simple as you can get, printing out the time earlier than and after the ‘unhealthy’ code. To try this, I used this code:
{ log }
This prints out the present time to the millisecond. Once I did a construct, I obtained the next:
08:36:58:208
08:37:02:014
As you’ll be able to see, roughly 4 seconds. As you’ll be able to see, not unhealthy. I considered getting fancier and printing the distinction in milliseconds. I believed I might assign the worth to a variable after which use Liquid’s minus
filter, however whereas you will get “time since epoch” as a date format filter, it is in seconds, not milliseconds. You could possibly multiply that out, however I used to be nervous in regards to the loss in precision when doing so.
Okay, in order that appeared cool, and I actually needed to maintain my code to the template in query, however for the heck of it, I created this shortcode:
let _timer;
eleventyConfig.addLiquidShortcode("timer", () => {
if(!_timer) {
_timer = new Date();
console.log('TIMER INITIALIZED');
} else {
let now = new Date();
console.log('TIMER DIFF: ', now.getTime() - _timer.getTime());
_timer = new Date();
}
});
This makes use of a world variable, _timer
, to document the present time, after which print the diff on the second and later calls. I can then simply add timer
calls to my code. Right here it’s within the all.liquid
template:
---
structure: web page
title: All Posts
description: Each.... single publish. Ever
body_class: page-template
---
reverse %
date: "%Y" %
first %
date: "%Y" %
{% timer %}
{% for 12 months in (firstYear..thisYear) reversed %}
<particulars>
<abstract>{{12 months}}</abstract>
<h3>Posts for {{ 12 months }}</h3>
{% for publish in posts %}
plus: 0 %
{% if postYear == 12 months %}
<a href="{{ publish.url }}">{{ publish.information.title }}</a> ({ date: "%m/%d/%Y" })<br/>
{% endif %}
{% endfor %}
</particulars>
{% endfor %}
{% timer %}
poop
{% timer %}
The poop
on the finish was only a fast method for me to substantiate {that a} third name would correctly present the distinction after the second name. This returned the next pretty output:
TIMER INITIALIZED
TIMER DIFF: 3747
TIMER DIFF: 0
As a result of I am unable to get tinkering, I remembered that Node itself had some timing code inbuilt. I did a fast search, and located the console.time
perform. Along with console.timeEnd
and console.timeLog
, it allows you to create timers. Whereas it would not require a label, I constructed a brief code that might enable for it. It would not ever “finish” the timer, which I believe is okay however I am not sure:
let _timer2 = {};
eleventyConfig.addLiquidShortcode("timer2", (label) => {
if(!_timer2[label]) {
console.time(label);
_timer2[label] = true;
} else {
console.timeLog(label);
}
});
Clearly, I would not use timer2
, simply timer
, however I used to be testing this together with my earlier shortcode. I added it to my template like so:
{% timer2 "all loop" %}
This is the way it outputs:
all loop: 3.430s
all loop: 3.431s
This does not present a diff however has extremely correct timings. The primary output is after the sluggish code, and the second is after the poop. (Sorry, I am mainly 12 years outdated.)
Second Try – Debugging
For my second try, I remembered that Eleventy would report timing data in combination when doing a construct, for instance:
[11ty] Copied 38 information / Wrote 6399 information in 35.28 seconds (5.5ms every, v2.0.0-canary.16)
And I additionally remembered it could “flag” information information that took too lengthy. However I used to be curious if there have been extra choices obtainable by way of the CLI. Seems, there is a DEBUG
worth you should utilize on the CLI as documented right here: Efficiency
Earlier than I proceed, let me say that it’s FREAKING REFRESHING for a technical web site just like the Eleventy docs to offer directions for each Mac/Linux and Home windows. I am actually uninterested in websites that assume Mac/Linux and do not present assist for Home windows customers, particularly on this case the place the syntax is completely different.
In my case, I am on WSL, so I used this command:
DEBUG=Eleventy:Benchmark* npx @11ty/eleventy
This returns a lot of data, however this is a snippet:
Eleventy:Benchmark Benchmark 2ms 0% 2× (Combination) > Compile > ./_posts/2021/05/16/2021-05-16-building-a-choose-your-own-adventure-site-with-eleventy.md +0ms
Eleventy:Benchmark Benchmark 2ms 0% 2× (Combination) > Compile > ./_posts/2021/11/13/2021-11-13-congratulating-yourself-with-pipedream-and-microsoft-to-do.md +0ms
Eleventy:Benchmark Benchmark 2ms 0% 2× (Combination) > Compile > ./_posts/2022/06/18/2022-06-18-building-a-quiz-with-eleventy-and-eleventy-serverless.md +0ms
Eleventy:Benchmark Benchmark 2ms 0% 2× (Combination) > Compile > ./_posts/2022/09/13/2022-09-13-discover-new-music-with-the-spotify-api-and-pipedream.md +0ms
Eleventy:Benchmark Benchmark 0ms 0% 21× (Combination) (depend) > Render Permalink > ./classes.liquid (21 pages) +0ms
Eleventy:Benchmark Benchmark 2ms 0% 42× (Combination) > Render > ./classes.liquid (21 pages) +0ms
Eleventy:Benchmark Benchmark 0ms 0% 12908× (Combination) (depend) Template Compile Cache Hit +0ms
Eleventy:Benchmark Benchmark 0ms 0% 45× (Combination) (depend) > Render Permalink > ./tags.liquid (45 pages) +0ms
Eleventy:Benchmark Benchmark 1ms 0% 90× (Combination) > Render > ./tags.liquid (45 pages) +0ms
Eleventy:Benchmark Benchmark 7ms 0% 1× (Combination) > Render > ./recentPosts.md +0ms
Eleventy:Benchmark Benchmark 4ms 0% 1× (Combination) > Render > ./readme.md +0ms
Eleventy:Benchmark Benchmark 6ms 0% 1× (Combination) > Render > ./index.liquid +0ms
Eleventy:Benchmark Benchmark 3652ms 10% 1× (Combination) > Render > ./all.liquid +1ms
Eleventy:Benchmark Benchmark 63ms 0% 1× (Combination) > Compile > ./theme/publish.liquid +0ms
Eleventy:Benchmark Benchmark 4ms 0% 1× (Combination) > Compile > ./theme/default.liquid +0ms
Eleventy:Benchmark Benchmark 3ms 0% 1× (Combination) > Compile > ./theme/web page.liquid +0ms
Eleventy:Benchmark Benchmark 3ms 0% 1× (Combination) > Compile > ./theme/tag.liquid +0ms
Eleventy:Benchmark Benchmark 3ms 0% 1× (Combination) > Compile > ./theme/class.liquid +0ms
Eleventy:Benchmark Benchmark 8874ms 24% 6399× (Combination) Template Write +0ms
Eleventy:Benchmark Benchmark 18ms 0% 1× (Information) `./_data/medium.js` +6ms
[11ty] Copied 38 information / Wrote 6399 information in 36.24 seconds (5.7ms every, v2.0.0-canary.16)
ray@Hoth:~/tasks/raymondcamden2020$
You will discover all.liquid
sort of within the center there and you’ll see it is an enormous a part of the full time. Though not the more severe, additional up within the output I discovered:
Eleventy:Benchmark Benchmark 11702ms 32% 38× (Combination) Passthrough Copy File +0ms
Which frankly was stunning, as I did not suppose I used to be copying that many information. I do have a number of calls to addPassthroughCopy
in my config, however all in all I did not suppose that many information had been being copied. I’ve obtained one thing new to analysis now.
Talking of Mac/Linux versus Home windows issues, I found that the debug data above was not “common” output. I found this after I added a pipe > output.txt
and it nonetheless printed to the display screen. After a fast search, I found this syntax:
command >file.txt 2>&1
The half on the finish is what handles grabbing the non-standard output and piping it as nicely. Apparently, the debug information was stderr
, which … appears bizarre, however no matter. That labored. 🙂
Cool, so on to the third thought!
Third Try – Listing Output Plugin
Once I first began trying into this, I reached out to Zach on Mastodon (observe, Eleventy has an official presence now: https://fosstodon.org/@eleventy), and he shared a plugin I bear in mind listening to about, however by no means really used: Listing Output. You put in it by merely including it to your config after which utilizing addPlugin
, as soon as accomplished, the result’s a really properly rendered desk:
The above screenshot is just a part of it, however you’ll be able to see the way it renders each dimension and timings, which is cool. You may as well configure a warning for information which might be too massive, and actually, I used to be shocked my all
web page did not set off that, however it’s only a bunch of quick hyperlinks, so maybe it isn’t too unhealthy.
I do wish to level out that there’s a reported bug with this plugin and the most recent Eleventy Canary. I generated the end result above utilizing model 1.0.2.
Closing Ideas
So, I did all of this and I nonetheless did not trouble bettering my all
web page. Truthfully, I simply needed to study what my choices are, and one factor Eleventy has been actually constant about is offering a number of methods to resolve issues. That is really why I really like the undertaking!
Photograph by Kolleen Gladden on Unsplash