<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lucian (LKB)</title>
    <description>The latest articles on DEV Community by Lucian (LKB) (@lucian_lkb_1f009d).</description>
    <link>https://dev.to/lucian_lkb_1f009d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4026097%2Feb9247a0-cd26-41b9-9613-ddcb120a9d66.jpg</url>
      <title>DEV Community: Lucian (LKB)</title>
      <link>https://dev.to/lucian_lkb_1f009d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucian_lkb_1f009d"/>
    <language>en</language>
    <item>
      <title>The North Star isn't the brightest star. It's not even in the top 40.</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Fri, 11 Sep 2026 06:28:54 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/the-north-star-isnt-the-brightest-star-its-not-even-in-the-top-40-430j</link>
      <guid>https://dev.to/lucian_lkb_1f009d/the-north-star-isnt-the-brightest-star-its-not-even-in-the-top-40-430j</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Syndicated from the original on &lt;strong&gt;&lt;a href="https://lkforge.com/blog/is-the-north-star-the-brightest/" rel="noopener noreferrer"&gt;lkforge.com&lt;/a&gt;&lt;/strong&gt;. The ranking below is printed by one short, dependency-free script.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The North Star is the most famous star in the sky, and almost everyone assumes fame means brightness. It doesn't. Rank the stars by how bright they actually appear and Polaris isn't close to the top - it isn't even in the top forty.&lt;/p&gt;

&lt;h2&gt;
  
  
  The correction
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Polaris ranks about 48th&lt;/strong&gt; in apparent brightness.&lt;/li&gt;
&lt;li&gt;The real brightest star, &lt;strong&gt;Sirius (magnitude -1.46), outshines Polaris (+1.98) by roughly 24 to 1.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Polaris shines at only &lt;strong&gt;4.2% of Sirius&lt;/strong&gt;, beaten by two dozen household-name stars before you even reach the fainter ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The actual brightest stars (as a share of Sirius)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Star&lt;/th&gt;
&lt;th&gt;Brightness vs Sirius&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Sirius&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Canopus&lt;/td&gt;
&lt;td&gt;52%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Alpha Centauri&lt;/td&gt;
&lt;td&gt;33%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Arcturus&lt;/td&gt;
&lt;td&gt;27%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Vega&lt;/td&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Capella&lt;/td&gt;
&lt;td&gt;24%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Rigel&lt;/td&gt;
&lt;td&gt;23%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Procyon&lt;/td&gt;
&lt;td&gt;19%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Betelgeuse&lt;/td&gt;
&lt;td&gt;18%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...(35+ more)&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;~48&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Polaris&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.2%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why the numbers run backwards
&lt;/h2&gt;

&lt;p&gt;The scale is the confusing part. &lt;strong&gt;Apparent magnitude&lt;/strong&gt; measures brightness with &lt;em&gt;smaller = brighter&lt;/em&gt; - a leftover from the ancient Greeks, who called the brightest stars "first magnitude" and the faintest "sixth." It's also logarithmic: every 5 steps of magnitude is a factor of exactly 100 in brightness.&lt;/p&gt;

&lt;p&gt;So Sirius at -1.46 is genuinely brilliant, Polaris at +1.98 is middling, and a magnitude-6 star is at the edge of naked-eye visibility. To turn magnitudes into a linear "how many times brighter," you use:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;brightness ratio = 10 ^ (-0.4 * delta-magnitude)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For Sirius vs Polaris that's a gap of ~3.44 magnitudes, or about 24x.&lt;/p&gt;

&lt;h2&gt;
  
  
  So why is Polaris famous?
&lt;/h2&gt;

&lt;p&gt;Position, not brightness. &lt;strong&gt;Polaris sits within about 0.7 degrees of the north celestial pole&lt;/strong&gt; - the point Earth's axis points at - so as the planet turns, every other star wheels in a circle while Polaris barely moves. It marks true north and holds still, which for two thousand years made it the single most useful star for navigation in the Northern Hemisphere.&lt;/p&gt;

&lt;p&gt;It won't hold the job forever: Earth's axis slowly wobbles (precession), so the pole star changes over millennia - the bright star Vega sat near the pole around 12,000 BC and will again near 13,700 AD. Polaris is simply the star on duty now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce it
&lt;/h2&gt;

&lt;p&gt;Every figure comes from &lt;a href="https://gist.github.com/lucian-devops/713652004ebe524af16cfbcb1d5c0831" rel="noopener noreferrer"&gt;one short script&lt;/a&gt;: standard published apparent magnitudes (Hipparcos / Yale Bright Star Catalogue), ranked, then converted to linear brightness. Several bright stars are slightly variable, so ranks near a tie can shift a place; Polaris's ~48th is the widely cited figure.&lt;/p&gt;

&lt;p&gt;Full write-up with the ranked chart is on the original: &lt;strong&gt;&lt;a href="https://lkforge.com/blog/is-the-north-star-the-brightest/" rel="noopener noreferrer"&gt;Is the North Star the Brightest?&lt;/a&gt;&lt;/strong&gt; You can find Polaris and everything wheeling around it with the &lt;a href="https://lkforge.com/tools/space/sky/" rel="noopener noreferrer"&gt;Sky Explorer&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>data</category>
      <category>science</category>
      <category>astronomy</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The UN voted to drop the Mercator map. Here's exactly how wrong it was, measured.</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Thu, 10 Sep 2026 21:24:50 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/the-un-voted-to-drop-the-mercator-map-heres-exactly-how-wrong-it-was-measured-4d81</link>
      <guid>https://dev.to/lucian_lkb_1f009d/the-un-voted-to-drop-the-mercator-map-heres-exactly-how-wrong-it-was-measured-4d81</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Syndicated from the original on &lt;strong&gt;&lt;a href="https://lkforge.com/blog/true-size-of-countries/" rel="noopener noreferrer"&gt;lkforge.com&lt;/a&gt;&lt;/strong&gt;. The country data is the same set behind my &lt;a href="https://lkforge.com/tools/atlas/" rel="noopener noreferrer"&gt;World Atlas&lt;/a&gt;, and the script that prints every number below is public and dependency-free.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On September 4, 2026 the UN General Assembly backed a push to retire the &lt;strong&gt;Mercator&lt;/strong&gt; projection - the world map most of us grew up with - in favor of equal-area maps. The complaint is old but correct: Mercator badly misrepresents size. I wanted the actual numbers, so I took the real land areas behind my World Atlas and measured it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The headline: Greenland is not the size of Africa
&lt;/h2&gt;

&lt;p&gt;On a Mercator map they look about equal. They are not close.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Africa is 14.0x larger than Greenland&lt;/strong&gt; (30.3M km2 across 50 countries vs 2.17M km2).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Africa is 1.8x larger than Russia&lt;/strong&gt; (17.1M km2), the biggest country on Earth.&lt;/li&gt;
&lt;li&gt;Greenland is only the &lt;strong&gt;12th-largest landmass&lt;/strong&gt; on the list. &lt;strong&gt;Algeria alone (2.38M km2) is bigger than Greenland.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The real top of the ranking (millions of km2)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Country&lt;/th&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Russia&lt;/td&gt;
&lt;td&gt;17.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Canada&lt;/td&gt;
&lt;td&gt;10.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;China&lt;/td&gt;
&lt;td&gt;9.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;United States&lt;/td&gt;
&lt;td&gt;9.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Brazil&lt;/td&gt;
&lt;td&gt;8.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Algeria&lt;/td&gt;
&lt;td&gt;2.4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;DR Congo&lt;/td&gt;
&lt;td&gt;2.3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;Greenland&lt;/td&gt;
&lt;td&gt;2.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why the map lies, in one formula
&lt;/h2&gt;

&lt;p&gt;Mercator keeps compass directions straight, and the price is size. It stretches the map by a factor that grows toward the poles, on &lt;strong&gt;both&lt;/strong&gt; axes - so &lt;strong&gt;area&lt;/strong&gt; is scaled by that factor squared:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Mercator area inflation = sec^2(latitude)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Evaluate it at each country's centroid latitude and the whole illusion falls out:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Country&lt;/th&gt;
&lt;th&gt;Centroid lat&lt;/th&gt;
&lt;th&gt;Area shown on Mercator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Greenland&lt;/td&gt;
&lt;td&gt;72 N&lt;/td&gt;
&lt;td&gt;x10.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Russia&lt;/td&gt;
&lt;td&gt;60 N&lt;/td&gt;
&lt;td&gt;x4.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Canada&lt;/td&gt;
&lt;td&gt;60 N&lt;/td&gt;
&lt;td&gt;x4.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;United States&lt;/td&gt;
&lt;td&gt;38 N&lt;/td&gt;
&lt;td&gt;x1.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DR Congo&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;x1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brazil&lt;/td&gt;
&lt;td&gt;10 S&lt;/td&gt;
&lt;td&gt;x1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Greenland sits near 72 N, where Mercator inflates area more than tenfold - which is exactly how a 2-million-km2 island ends up looking like a 30-million-km2 continent. Countries on the equator are drawn true to size.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce it
&lt;/h2&gt;

&lt;p&gt;Every figure here is printed by &lt;a href="https://gist.github.com/lucian-devops/1b0fe6703fa3e43cc502a8124f56a954" rel="noopener noreferrer"&gt;one short script&lt;/a&gt; that fetches the same country dataset (area + centroid latitude) my World Atlas ships and does the arithmetic - no dependencies. The centroid-latitude distortion is a per-country approximation, since a country spans latitudes, but it captures the effect.&lt;/p&gt;

&lt;p&gt;The full write-up, with the ranked chart and the distortion table, is on the original: &lt;strong&gt;&lt;a href="https://lkforge.com/blog/true-size-of-countries/" rel="noopener noreferrer"&gt;The True Size of Countries&lt;/a&gt;&lt;/strong&gt;. You can watch the distortion appear and vanish by switching between the flat map and the globe in the &lt;a href="https://lkforge.com/tools/atlas/" rel="noopener noreferrer"&gt;atlas&lt;/a&gt; itself.&lt;/p&gt;

</description>
      <category>data</category>
      <category>geography</category>
      <category>maps</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How Much Quality Do You Lose Compressing an Image? We Measured It on 24 Photos</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Thu, 10 Sep 2026 07:01:24 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/how-much-quality-do-you-lose-compressing-an-image-we-measured-it-on-24-photos-18mo</link>
      <guid>https://dev.to/lucian_lkb_1f009d/how-much-quality-do-you-lose-compressing-an-image-we-measured-it-on-24-photos-18mo</guid>
      <description>&lt;p&gt;"Compress without losing quality" is a promise lossy formats can't fully keep — every step of compression trades some fidelity for bytes. The useful question isn't &lt;em&gt;whether&lt;/em&gt; you lose quality but &lt;em&gt;how much, for how many bytes saved&lt;/em&gt;. So we measured the trade directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The method
&lt;/h2&gt;

&lt;p&gt;Across the &lt;strong&gt;24-image Kodak reference suite&lt;/strong&gt; — the standard set for this kind of test — we saved every photo as &lt;strong&gt;JPEG&lt;/strong&gt; and &lt;strong&gt;WebP&lt;/strong&gt; at qualities 20 through 95, and scored each output on &lt;strong&gt;SSIM&lt;/strong&gt; (structural similarity to the original, 0 to 1) rather than eyeballing it. Every figure below is the mean over all 24 images, so it's not one lucky photo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diminishing returns are brutal
&lt;/h2&gt;

&lt;p&gt;The size-vs-quality curve bends hard: the first kilobytes buy almost all of the quality, and after that it flattens into a long tail where you pay a lot for very little.&lt;/p&gt;

&lt;p&gt;The clearest example: pushing JPEG from &lt;strong&gt;quality 85 to 95 nearly doubles the file&lt;/strong&gt; — from about 14% to 26% of the original — for an SSIM gain of just &lt;strong&gt;0.025&lt;/strong&gt; (0.95 → 0.98). That is double the bytes for a difference most people can't see on most images. The habit of exporting at 95 or 100 "to be safe" is, for photographs, mostly wasted space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Format beats quality-cranking
&lt;/h2&gt;

&lt;p&gt;Changing the codec does more than turning the quality dial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;WebP is about 30% smaller than JPEG at the same SSIM&lt;/strong&gt; — 29.6% smaller at SSIM 0.95, 31.9% at 0.97. Same perceived fidelity, a third less weight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Staying fully lossless costs roughly 7× a quality-85 JPEG.&lt;/strong&gt; "Keep it lossless to be safe" usually means paying seven times over for bytes no one will perceive.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The practical takeaway
&lt;/h2&gt;

&lt;p&gt;For photographs, the &lt;strong&gt;sweet spot is quality 80–85&lt;/strong&gt;, ideally in WebP. But the honest answer is that the right setting is image-dependent — a flat sky compresses beautifully, fine texture does not — so &lt;strong&gt;a live preview beats any single recommended number&lt;/strong&gt;. Pick the point on the curve where the preview stops changing, not a fixed "95".&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce it
&lt;/h2&gt;

&lt;p&gt;The study is a straightforward encode-and-score sweep over the Kodak set, driven by a short script — point it at your own images and you'll get the same shape of curve. And if you just need to compress something, the &lt;a href="https://lkforge.com/tools/image/compressor/" rel="noopener noreferrer"&gt;image compressor&lt;/a&gt; and the rest of the &lt;a href="https://lkforge.com/tools/image/" rel="noopener noreferrer"&gt;image tools&lt;/a&gt; run entirely in your browser with a live preview — nothing uploaded.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://lkforge.com/blog/image-compression-quality-vs-file-size/" rel="noopener noreferrer"&gt;LK Forge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>performance</category>
      <category>images</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Dollar-Cost Averaging vs Lump Sum: What 75 Years of S&amp;P 500 Data Shows</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Wed, 09 Sep 2026 06:02:28 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/dollar-cost-averaging-vs-lump-sum-what-75-years-of-sp-500-data-shows-2ohh</link>
      <guid>https://dev.to/lucian_lkb_1f009d/dollar-cost-averaging-vs-lump-sum-what-75-years-of-sp-500-data-shows-2ohh</guid>
      <description>&lt;p&gt;You have a sum of money and you want it in the market. Do you invest it all at once, or feed it in gradually -- dollar-cost averaging -- so you don't buy right before a crash?&lt;/p&gt;

&lt;p&gt;It's one of investing's oldest arguments, and it's answerable with data. So I ran it against every starting month of the S&amp;amp;P 500 from 1950 to 2025: deploy the whole amount now, or spread it evenly over the next few months, then compare which ended up ahead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The headline result
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Investing a lump sum beat spreading it over a year 76% of the time&lt;/strong&gt; (S&amp;amp;P 500 total return, 1950-2025). And the longer you dragged the money in, the more often the lump won:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;How long the money was spread in&lt;/th&gt;
&lt;th&gt;Lump sum won&lt;/th&gt;
&lt;th&gt;DCA won&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;6 months&lt;/td&gt;
&lt;td&gt;72.4%&lt;/td&gt;
&lt;td&gt;27.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1 year&lt;/td&gt;
&lt;td&gt;76.2%&lt;/td&gt;
&lt;td&gt;23.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 years&lt;/td&gt;
&lt;td&gt;82.7%&lt;/td&gt;
&lt;td&gt;17.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3 years&lt;/td&gt;
&lt;td&gt;86.3%&lt;/td&gt;
&lt;td&gt;13.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The reason is mundane: the market goes up more often than it goes down, so money sitting on the sidelines waiting to be invested is money missing the average day's gain. On a concrete $10,000 deployed over a year, the lump sum finished about &lt;strong&gt;$607 ahead on average&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  But averages hide the interesting part
&lt;/h2&gt;

&lt;p&gt;Dollar-cost averaging lost the &lt;em&gt;typical&lt;/em&gt; year. But when it won, it won for one reason: the market fell right after you started. Sort every one-year period by how much DCA beat the lump sum, and the top of the list isn't scattered across history -- it bunches up in one place.&lt;/p&gt;

&lt;p&gt;The single best month to have been averaging in slowly rather than all at once was &lt;strong&gt;August 2008&lt;/strong&gt;, on the eve of the financial crisis. DCA finished about 30 points ahead there, because each later purchase bought in cheaper as the market collapsed. The runners-up are the other months of 2007 and 2008.&lt;/p&gt;

&lt;p&gt;So the honest reading: &lt;strong&gt;dollar-cost averaging is not a way to earn more, it's a way to be wrong by less when your timing is unlucky.&lt;/strong&gt; You're trading a bit of expected return -- that ~$607 on $10,000 -- for protection against the one scenario everyone fears, putting it all in at the top. Whether that trade is worth it is about temperament, not math.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it was measured
&lt;/h2&gt;

&lt;p&gt;Like-for-like: both strategies invest the same total. The lump goes in at month zero; the DCA version splits it into equal monthly buys and both are compared at the end of the window, when both are fully invested. I used S&amp;amp;P 500 &lt;em&gt;total return&lt;/em&gt; (dividends reinvested), and assumed the not-yet-invested DCA cash earns nothing (the conservative, common assumption). Every ending value is a real historical outcome, run for every start month 1950-2025, then tallied.&lt;/p&gt;

&lt;p&gt;One scope note: this is the classic "deploy a windfall now vs later" question, not regular saving from a paycheck. If you invest each month as you earn it, you're already dollar-cost averaging by necessity -- there's no lump sum to compare against.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check it yourself
&lt;/h2&gt;

&lt;p&gt;The whole study is built on a monthly S&amp;amp;P 500 total-return index, and you can spot-check any single period in the two free, browser-based calculators it links to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full write-up with the interactive chart: &lt;a href="https://lkforge.com/blog/dca-vs-lump-sum/" rel="noopener noreferrer"&gt;Dollar-Cost Averaging vs Lump Sum&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://lkforge.com/tools/calculators/dollar-cost-averaging/" rel="noopener noreferrer"&gt;Dollar-Cost Averaging Calculator&lt;/a&gt; -- backtest investing a fixed amount every month&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://lkforge.com/tools/calculators/sp500-return/" rel="noopener noreferrer"&gt;S&amp;amp;P 500 Return Calculator&lt;/a&gt; -- what a lump sum would have grown to&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Past performance doesn't predict the future; this is history, not advice.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>finance</category>
      <category>investing</category>
      <category>statistics</category>
    </item>
    <item>
      <title>Why a Tuner and Your Ear Disagree: The 13.7-Cent Compromise</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Tue, 08 Sep 2026 07:27:46 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/why-a-tuner-and-your-ear-disagree-the-137-cent-compromise-3hpk</link>
      <guid>https://dev.to/lucian_lkb_1f009d/why-a-tuner-and-your-ear-disagree-the-137-cent-compromise-3hpk</guid>
      <description>&lt;p&gt;Tune a guitar perfectly to a digital tuner, play a full open major chord, and something is still faintly &lt;em&gt;off&lt;/em&gt; — a slow shimmer in the sound. The tuner isn't wrong, and neither is your ear. They're using two different definitions of "in tune," and the distance between them is a fixed, computable number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two definitions of "in tune"
&lt;/h2&gt;

&lt;p&gt;A digital tuner uses &lt;strong&gt;equal temperament&lt;/strong&gt;: the octave is divided into twelve &lt;em&gt;exactly&lt;/em&gt; equal steps of 100 cents each (a cent is 1/100 of a semitone). That perfect evenness is what lets one instrument play in all keys without retuning. Your ear, on the other hand, hears an interval as &lt;strong&gt;pure&lt;/strong&gt; when its two frequencies form a &lt;strong&gt;simple whole-number ratio&lt;/strong&gt; — a perfect fifth is 3:2, a major third is 5:4 — because then the waveforms lock and stop beating. The problem: those pure ratios don't land on the equal 100-cent grid.&lt;/p&gt;

&lt;h2&gt;
  
  
  How far apart they are
&lt;/h2&gt;

&lt;p&gt;Computing the deviation for every interval (equal-tempered cents minus the pure ratio in cents):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Interval&lt;/th&gt;
&lt;th&gt;Pure ratio&lt;/th&gt;
&lt;th&gt;Equal temp.&lt;/th&gt;
&lt;th&gt;Pure (cents)&lt;/th&gt;
&lt;th&gt;Off by&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minor 2nd&lt;/td&gt;
&lt;td&gt;16/15&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;111.73&lt;/td&gt;
&lt;td&gt;−11.73&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Major 2nd&lt;/td&gt;
&lt;td&gt;9/8&lt;/td&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;203.91&lt;/td&gt;
&lt;td&gt;−3.91&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minor 3rd&lt;/td&gt;
&lt;td&gt;6/5&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;315.64&lt;/td&gt;
&lt;td&gt;−15.64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Major 3rd&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5/4&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;400&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;386.31&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+13.69&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perfect 4th&lt;/td&gt;
&lt;td&gt;4/3&lt;/td&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;498.04&lt;/td&gt;
&lt;td&gt;+1.96&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tritone&lt;/td&gt;
&lt;td&gt;45/32&lt;/td&gt;
&lt;td&gt;600&lt;/td&gt;
&lt;td&gt;590.22&lt;/td&gt;
&lt;td&gt;+9.78&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Perfect 5th&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3/2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;700&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;701.96&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;−1.96&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minor 6th&lt;/td&gt;
&lt;td&gt;8/5&lt;/td&gt;
&lt;td&gt;800&lt;/td&gt;
&lt;td&gt;813.69&lt;/td&gt;
&lt;td&gt;−13.69&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Major 6th&lt;/td&gt;
&lt;td&gt;5/3&lt;/td&gt;
&lt;td&gt;900&lt;/td&gt;
&lt;td&gt;884.36&lt;/td&gt;
&lt;td&gt;+15.64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minor 7th&lt;/td&gt;
&lt;td&gt;9/5&lt;/td&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;1017.60&lt;/td&gt;
&lt;td&gt;−17.60&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Major 7th&lt;/td&gt;
&lt;td&gt;15/8&lt;/td&gt;
&lt;td&gt;1100&lt;/td&gt;
&lt;td&gt;1088.27&lt;/td&gt;
&lt;td&gt;+11.73&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;strong&gt;major third is 13.7 cents sharp&lt;/strong&gt;, the major sixth 15.6 sharp, and the minor seventh nearly 18 out. But the &lt;strong&gt;perfect fifth is only 2 cents flat&lt;/strong&gt;, and the fourth 2 cents sharp. Since a trained ear notices about &lt;strong&gt;5 cents&lt;/strong&gt;, the fifths and fourths pass as clean while the thirds and sixths carry the audible "tempered" beating. That's exactly the shimmer in the held major chord — the third is doing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it has to be this way
&lt;/h2&gt;

&lt;p&gt;A piano can't be perfectly in tune &lt;em&gt;and&lt;/em&gt; perfectly playable in every key at once — the two goals are mathematically incompatible. Equal temperament is the elegant surrender: spread the error evenly so no key is worse than any other. Instruments with no frets or keys — a string quartet, a barbershop quartet — can slide each note onto the pure ratio and get beat-free thirds. That pure sound is what your ear is quietly asking a fretted, tempered instrument for, and not quite getting.&lt;/p&gt;

&lt;h2&gt;
  
  
  What your tuner targets
&lt;/h2&gt;

&lt;p&gt;A tuner takes each string's equal-tempered frequency and shows how many cents you're above or below it. All from &lt;code&gt;f = 440 × 2^((m − 69) / 12)&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Guitar:&lt;/strong&gt; E2 82.41, A2 110.00, D3 146.83, G3 196.00, B3 246.94, E4 329.63 Hz&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bass:&lt;/strong&gt; E1 41.20, A1 55.00, D2 73.42, G2 98.00 Hz&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Violin:&lt;/strong&gt; G3 196.00, D4 293.66, A4 440.00, E5 659.26 Hz&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ukulele:&lt;/strong&gt; G4 392.00, C4 261.63, E4 329.63, A4 440.00 Hz&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reproduce it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ratio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ratio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;midiToFreq&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;440&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// major third: 100*4 - cents(5/4) = 400 - 386.31 = +13.69 cents&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full write-up, chart and the free browser &lt;a href="https://lkforge.com/tools/music/" rel="noopener noreferrer"&gt;tuners, tone generator and circle of fifths&lt;/a&gt; to hear it: &lt;a href="https://lkforge.com/blog/why-a-tuner-and-your-ear-disagree/" rel="noopener noreferrer"&gt;Why a Tuner and Your Ear Disagree&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://lkforge.com/blog/why-a-tuner-and-your-ear-disagree/" rel="noopener noreferrer"&gt;LK Forge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>music</category>
      <category>math</category>
      <category>javascript</category>
      <category>audio</category>
    </item>
    <item>
      <title>What the Average Big Five Result Actually Looks Like (n = 19,718)</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Mon, 07 Sep 2026 04:21:38 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/what-the-average-big-five-result-actually-looks-like-n-19718-5am8</link>
      <guid>https://dev.to/lucian_lkb_1f009d/what-the-average-big-five-result-actually-looks-like-n-19718-5am8</guid>
      <description>&lt;p&gt;Personality tests love to hand you a tidy "type". So we took 19,718 real Big Five responses — the IPIP-50 instrument, from the Open-Source Psychometrics Project — scored them into the five OCEAN traits, and looked at what the distribution actually says.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nobody is average on everything
&lt;/h2&gt;

&lt;p&gt;The first result is the bluntest one: &lt;strong&gt;0 of 19,718 people&lt;/strong&gt; scored in the top band on all five traits at once. Not a single person. "Average across the board" is a statistical fiction — real people are high on some traits, low on others, and middling on the rest. In fact &lt;strong&gt;46%&lt;/strong&gt; land in the middle band on three or more traits, which is why the confident one-word "type" a quiz gives you throws away most of the picture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The traits barely relate to each other
&lt;/h2&gt;

&lt;p&gt;The Big Five is designed so the five traits are close to independent, and the data agrees. The &lt;strong&gt;strongest correlation between any two traits is r = 0.33&lt;/strong&gt; (Extraversion and Agreeableness); across all ten pairs the &lt;strong&gt;average is |r| = 0.17&lt;/strong&gt;. That's weak. Knowing someone is extraverted tells you almost nothing about whether they're conscientious or open. The common intuition — "she's outgoing, so she's probably organized too" — simply isn't in the numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which traits skew, and which spread
&lt;/h2&gt;

&lt;p&gt;Not every trait is shaped the same. &lt;strong&gt;Openness&lt;/strong&gt; and &lt;strong&gt;Agreeableness&lt;/strong&gt; skew high (most people rate themselves above the midpoint), while &lt;strong&gt;Extraversion&lt;/strong&gt; and &lt;strong&gt;Neuroticism&lt;/strong&gt; have the &lt;strong&gt;widest spread&lt;/strong&gt; — people are all over the range. So an "average" score on Openness is genuinely common, but an "average" score on Extraversion is almost a coin flip between reserved and outgoing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest caveat
&lt;/h2&gt;

&lt;p&gt;This is a self-selected online sample — people who chose to take a personality test. That biases the absolute means (the &lt;em&gt;where&lt;/em&gt; of each peak), so don't read the exact averages as the human baseline. What it doesn't undermine are the &lt;strong&gt;shapes&lt;/strong&gt; and the &lt;strong&gt;correlations&lt;/strong&gt;: the near-independence of the traits and the near-total absence of "top on everything" people are robust to who showed up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it / reproduce it
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://lkforge.com/tools/quizzes/" rel="noopener noreferrer"&gt;free Big Five test&lt;/a&gt; uses the same IPIP-50 instrument, runs entirely in your browser, and asks for no signup. The full distribution study — every number above, plus the correlation matrix and per-trait histograms — is &lt;a href="https://lkforge.com/blog/big-five-personality-distribution/" rel="noopener noreferrer"&gt;reproducible from a public script&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://lkforge.com/blog/big-five-personality-distribution/" rel="noopener noreferrer"&gt;LK Forge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>psychology</category>
      <category>statistics</category>
      <category>javascript</category>
    </item>
    <item>
      <title>We Ran Our Own Blog Through Our Word Counter: 22.1 Words a Sentence</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Sun, 06 Sep 2026 05:52:18 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/we-ran-our-own-blog-through-our-word-counter-221-words-a-sentence-4ehh</link>
      <guid>https://dev.to/lucian_lkb_1f009d/we-ran-our-own-blog-through-our-word-counter-221-words-a-sentence-4ehh</guid>
      <description>&lt;p&gt;A word counter's &lt;em&gt;least&lt;/em&gt; useful output is the word count. The number that shows up biggest is the one that matters least — the value is in the analysis underneath it: how long your sentences run, which words you lean on, how readable the whole thing actually is. So instead of describing what the tool measures, we pointed it at ourselves and reported what it found — including where it found a problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The corpus
&lt;/h2&gt;

&lt;p&gt;We ran &lt;strong&gt;all 22 posts on this blog — 24,003 words across 1,084 sentences&lt;/strong&gt; — through our own &lt;a href="https://lkforge.com/tools/wordcounter/" rel="noopener noreferrer"&gt;word counter&lt;/a&gt;. One writer, one blog, no cherry-picking: whatever the tool flagged, we kept.&lt;/p&gt;

&lt;h2&gt;
  
  
  We write long sentences
&lt;/h2&gt;

&lt;p&gt;Average sentence length across the whole blog: &lt;strong&gt;22.1 words.&lt;/strong&gt; The common readability guideline is &lt;strong&gt;15–20&lt;/strong&gt;, so we run consistently over. And the average hides the tail — our worst post averaged &lt;strong&gt;39.7 words a sentence&lt;/strong&gt;, which reads as a wall of text no matter how carefully it's punctuated.&lt;/p&gt;

&lt;p&gt;Long sentences aren't a sin; some ideas need the room. But drift is invisible without the number. You don't feel yourself creeping from 18 to 22 to 26 words a sentence over a year of writing — you just notice, eventually, that everything reads a little heavy. The counter makes the drift visible while you can still fix it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our crutch word wasn't on any list
&lt;/h2&gt;

&lt;p&gt;The single most-overused word in the whole blog was &lt;strong&gt;"every" — 93 uses.&lt;/strong&gt; It's not on a single "words to cut" list, because those lists are generic and crutch words are personal. Meanwhile the words those articles always name — &lt;em&gt;very&lt;/em&gt;, &lt;em&gt;really&lt;/em&gt;, &lt;em&gt;just&lt;/em&gt; — &lt;strong&gt;barely appeared&lt;/strong&gt; in our writing at all.&lt;/p&gt;

&lt;p&gt;That's the whole argument for measuring your &lt;em&gt;own&lt;/em&gt; text rather than running a canned checklist over it. A generic filler-word list can't know that you, specifically, reach for "every" when you mean "many." Counting your actual words can, and does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;Point the tool at your own writing first. The word count is trivia; the sentence-length distribution and your personal crutch words are the product. Fix the top one or two habits and every later post inherits the improvement — which is a far better return than obsessing over a target word count.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://lkforge.com/tools/wordcounter/" rel="noopener noreferrer"&gt;word counter&lt;/a&gt; runs entirely in your browser — sentence and paragraph stats, reading time, keyword frequency, readability — with nothing uploaded. Run your last post through it and see what it says about you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://lkforge.com/blog/word-counter-audit-of-our-own-blog/" rel="noopener noreferrer"&gt;LK Forge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>writing</category>
      <category>productivity</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>How Much Grass Seed Do You Actually Need? It Swings 5 by Grass Type</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Sat, 05 Sep 2026 05:40:39 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/how-much-grass-seed-do-you-actually-need-it-swings-5-by-grass-type-1lel</link>
      <guid>https://dev.to/lucian_lkb_1f009d/how-much-grass-seed-do-you-actually-need-it-swings-5-by-grass-type-1lel</guid>
      <description>&lt;p&gt;"How much grass seed for my lawn?" sounds like it should have one answer. It doesn't — and the surprise is that it depends more on the &lt;em&gt;grass&lt;/em&gt; than the lawn. Using the seeding rates a grass-seed calculator ships (typical U.S. cooperative-extension figures), the amount you need swings &lt;strong&gt;5.3×&lt;/strong&gt; from one species to the next.&lt;/p&gt;

&lt;h2&gt;
  
  
  The seeding rate runs from 1.5 to 8
&lt;/h2&gt;

&lt;p&gt;Seeding rate is measured in pounds per 1,000 square feet, and it's a property of the grass, not the yard:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Grass (new lawn)&lt;/th&gt;
&lt;th&gt;lb per 1,000 sq ft&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Perennial ryegrass&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tall fescue&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generic / mixed&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kentucky bluegrass&lt;/td&gt;
&lt;td&gt;2.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bermuda&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's a &lt;strong&gt;5.3× gap&lt;/strong&gt; between perennial ryegrass and Bermuda, with the others across the middle.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means for a real lawn
&lt;/h2&gt;

&lt;p&gt;Multiply the rate by your area in thousands of square feet and the gap becomes concrete. On the same &lt;strong&gt;5,000 sq ft&lt;/strong&gt; lawn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perennial ryegrass → &lt;strong&gt;40 lb&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Tall fescue → 35 lb&lt;/li&gt;
&lt;li&gt;Kentucky bluegrass → 12.5 lb&lt;/li&gt;
&lt;li&gt;Bermuda → &lt;strong&gt;7.5 lb&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same yard, same job, five times the seed. Buy for the wrong grass and you either waste half a bag or sow too thin to fill in.&lt;/p&gt;

&lt;h2&gt;
  
  
  One bag, wildly different coverage
&lt;/h2&gt;

&lt;p&gt;Flip it around and it's sharper still. A single &lt;strong&gt;20 lb bag&lt;/strong&gt; covers about &lt;strong&gt;13,333 sq ft of Bermuda&lt;/strong&gt; — but only &lt;strong&gt;2,500 sq ft of perennial ryegrass&lt;/strong&gt;, a 5.3× difference from the identical bag weight. Which is why "one bag does an average lawn" is useless advice: the bag doesn't know what grass is in it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why: seed size, not area
&lt;/h2&gt;

&lt;p&gt;The reason is seed size. A good lawn is set by &lt;strong&gt;seeds per square foot&lt;/strong&gt;, not pounds — and Bermuda seed is so small that a pound holds a vast number of them, while ryegrass seed is many times heavier, so a pound holds far fewer. Same target density, very different weight. That single fact is the whole 5.3× spread. (And overseeding an existing lawn uses about half the new-lawn rate, since you're thickening turf rather than covering bare soil.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce it
&lt;/h2&gt;

&lt;p&gt;Every figure is the rate table times one line of arithmetic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RATE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;perennial-rye&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tall-fescue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;generic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
               &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;kentucky-bluegrass&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bermuda&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// lb / 1,000 sq ft&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pounds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;areaSqFt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;areaSqFt&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;// pounds(8, 5000) = 40 lb rye  ·  pounds(1.5, 5000) = 7.5 lb Bermuda&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rates are mid-range extension figures — a starting point; always follow your seed bag's label. The &lt;a href="https://lkforge.com/tools/nature/grass-seed-calculator/" rel="noopener noreferrer"&gt;grass-seed calculator&lt;/a&gt; does this for your area and grass (with a rate override), in the browser.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://lkforge.com/blog/how-much-grass-seed-by-type/" rel="noopener noreferrer"&gt;LK Forge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>data</category>
      <category>diy</category>
      <category>gardening</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Does That "Free Online PDF" Tool Upload Your File? How to Tell.</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Fri, 04 Sep 2026 09:24:56 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/does-that-free-online-pdf-tool-upload-your-file-how-to-tell-1cig</link>
      <guid>https://dev.to/lucian_lkb_1f009d/does-that-free-online-pdf-tool-upload-your-file-how-to-tell-1cig</guid>
      <description>&lt;p&gt;Most free online PDF tools work by uploading your document to a server, processing it there, and sending it back. For a lot of files that's fine. For a signed contract, a payslip, a medical form, or a scanned ID, it's the entire privacy problem: your document now lives on someone else's machine, subject to their logging, retention, and breach exposure.&lt;/p&gt;

&lt;p&gt;It doesn't have to work that way. A modern browser can split, merge, compress, sign, and even OCR a PDF &lt;strong&gt;without the file ever leaving your device&lt;/strong&gt; — using libraries like &lt;code&gt;pdf-lib&lt;/code&gt;, &lt;code&gt;pdf.js&lt;/code&gt;, &lt;code&gt;jsPDF&lt;/code&gt; and &lt;code&gt;SheetJS&lt;/code&gt; that run entirely in JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to tell an uploader from a client-side tool
&lt;/h2&gt;

&lt;p&gt;You don't have to trust a marketing claim. Two checks settle it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Watch the network.&lt;/strong&gt; Open your browser's DevTools → Network tab, then run the tool on a file. If you see your file leave in a POST/PUT request, it uploaded. A client-side tool shows no upload of the document itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull the plug.&lt;/strong&gt; Load the page, then turn off Wi-Fi and try the tool again. A client-side tool keeps working offline. An uploader breaks the moment the network is gone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The honest tools pass both tests. If a site can't work offline, your file is going somewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trade-offs, stated honestly
&lt;/h2&gt;

&lt;p&gt;Client-side processing isn't a free lunch, and any tool that pretends it is should make you suspicious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory.&lt;/strong&gt; Very large PDFs are held in browser memory, so there's a ceiling a server wouldn't have.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed.&lt;/strong&gt; OCR in WebAssembly is slower than a server GPU. It's private, not fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fidelity.&lt;/strong&gt; Converting PDF → Word transfers the &lt;em&gt;text&lt;/em&gt;, not the layout — the same is true of every converter, but a client-side one can't hide it behind a server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compression limits.&lt;/strong&gt; A PDF shrinks by downsampling embedded images or rasterizing pages; a small or text-only PDF may not shrink at all, and rasterizing removes selectable text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We built &lt;a href="https://lkforge.com/tools/pdf/" rel="noopener noreferrer"&gt;24 client-side PDF tools&lt;/a&gt; on exactly this principle and wrote down where each limit is, rather than papering over them. If you're evaluating any online PDF tool — ours or anyone's — the network check and the offline check are the two minutes of due diligence worth doing before you upload something you'd rather not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read more
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lkforge.com/blog/are-online-pdf-tools-safe/" rel="noopener noreferrer"&gt;Are Online PDF Tools Safe?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lkforge.com/blog/building-a-no-upload-pdf-suite/" rel="noopener noreferrer"&gt;Building a No-Upload PDF Suite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lkforge.com/blog/how-pdf-compression-works/" rel="noopener noreferrer"&gt;How PDF Compression Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lkforge.com/blog/pdf-to-word-what-transfers/" rel="noopener noreferrer"&gt;PDF to Word: What Transfers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://lkforge.com/blog/are-online-pdf-tools-safe/" rel="noopener noreferrer"&gt;LK Forge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The Online JSON Formatter Guide: Formatter vs Validator, Privacy, and Four Time-Wasters</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Fri, 04 Sep 2026 06:46:39 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/the-online-json-formatter-guide-formatter-vs-validator-privacy-and-four-time-wasters-2kpg</link>
      <guid>https://dev.to/lucian_lkb_1f009d/the-online-json-formatter-guide-formatter-vs-validator-privacy-and-four-time-wasters-2kpg</guid>
      <description>&lt;p&gt;A single missing comma in minified JSON can cost you an hour. JSON is trivial to read and miserable to hand-edit — one misplaced bracket and the whole thing is invalid, with no compiler to point at the line. A formatter fixes that in a second, but "paste JSON into the first result in search" quietly causes more problems than it solves. Here's how to use one well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formatter vs validator: don't confuse the two
&lt;/h2&gt;

&lt;p&gt;They sound interchangeable and aren't. A &lt;strong&gt;formatter&lt;/strong&gt; pretty-prints — it takes valid (or nearly valid) JSON and lays it out with consistent indentation so you can read it. A &lt;strong&gt;validator&lt;/strong&gt; tells you &lt;em&gt;whether&lt;/em&gt; it's valid and, crucially, &lt;em&gt;where&lt;/em&gt; it breaks — line and character of the offending token. When JSON won't parse, you want the validator's error location first; formatting broken JSON just rearranges the problem. Reach for the validator to find the fault, the formatter to make the fixed result readable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy is the one criterion you can't skip
&lt;/h2&gt;

&lt;p&gt;JSON payloads carry the sensitive stuff: auth tokens, personal data, internal API shapes. Many online tools upload whatever you paste to a server to process it — which is exactly what you don't want for a payload with credentials in it. You don't have to guess:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Watch the Network panel.&lt;/strong&gt; Open DevTools → Network and run the tool. If your input leaves in a request, it uploaded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull the plug.&lt;/strong&gt; A genuinely client-side tool keeps working with the network off. If it breaks offline, your data is going somewhere.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Confirm a tool processes data locally &lt;em&gt;before&lt;/em&gt; you paste anything real into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four mistakes that quietly waste hours
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pasting broken JSON into code without validating first.&lt;/strong&gt; It resurfaces as a runtime error you then trace backwards. Validate before it ever reaches your codebase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pasting sensitive payloads into an unverified tool.&lt;/strong&gt; Under time pressure it's tempting to grab the first search result. Confirm it's client-side before anything with credentials or personal data goes in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leaving pretty-printed JSON in production.&lt;/strong&gt; Human-readable indentation is dead weight over the wire. Minify for deployment; keep the formatted version for your repo and reviews.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mismatched indentation across a team.&lt;/strong&gt; One person on tabs, another on four spaces, and a three-line change becomes a 400-line diff. Agree on one style — two spaces is the most common — and let the formatter enforce it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When JSON isn't the final form
&lt;/h2&gt;

&lt;p&gt;Once it's clean, the converters pick up where the formatter stops: turn a response into a spreadsheet with JSON → CSV, into markup with JSON → XML, or go the other way with CSV → JSON. And the neighbours run the same way, entirely in the browser: a &lt;a href="https://lkforge.com/tools/developers/jwt-decoder/" rel="noopener noreferrer"&gt;JWT decoder&lt;/a&gt;, a &lt;a href="https://lkforge.com/tools/developers/sql-formatter/" rel="noopener noreferrer"&gt;SQL formatter&lt;/a&gt; across 11 dialects, &lt;a href="https://lkforge.com/tools/developers/base64/" rel="noopener noreferrer"&gt;Base64&lt;/a&gt;, a &lt;a href="https://lkforge.com/tools/developers/regex/" rel="noopener noreferrer"&gt;regex tester&lt;/a&gt; and a &lt;a href="https://lkforge.com/tools/developers/diff/" rel="noopener noreferrer"&gt;diff&lt;/a&gt; — none of which upload what you give them.&lt;/p&gt;

&lt;p&gt;Use the &lt;a href="https://lkforge.com/tools/developers/jsonformatter/" rel="noopener noreferrer"&gt;JSON formatter&lt;/a&gt; and the rest of the &lt;a href="https://lkforge.com/tools/developers/" rel="noopener noreferrer"&gt;developer tools&lt;/a&gt; — no sign-up, nothing uploaded, working offline once loaded.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://lkforge.com/blog/json-formatter-online-guide/" rel="noopener noreferrer"&gt;LK Forge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>json</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>security</category>
    </item>
    <item>
      <title>Free Puzzle Games Online — and the Honest Answer to "Do They Help Your Brain?"</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Thu, 03 Sep 2026 05:49:26 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/free-puzzle-games-online-and-the-honest-answer-to-do-they-help-your-brain-56i3</link>
      <guid>https://dev.to/lucian_lkb_1f009d/free-puzzle-games-online-and-the-honest-answer-to-do-they-help-your-brain-56i3</guid>
      <description>&lt;p&gt;A quick mental break, a proper brain workout, or somewhere to put fifteen restless minutes — a good puzzle does all three, and the best ones cost nothing and need no download. Before the tour, though, the question everyone asks and few answer honestly: do puzzles actually keep your brain sharp?&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest version of the research
&lt;/h2&gt;

&lt;p&gt;The study that gets cited — usually with more confidence than it earns — is the &lt;strong&gt;2019 PROTECT study&lt;/strong&gt; (University of Exeter and King's College London), which looked at &lt;strong&gt;19,078 adults aged 50 and over&lt;/strong&gt;. The people who did puzzles most often scored on some cognitive tests like someone years younger.&lt;/p&gt;

&lt;p&gt;That sounds decisive. It isn't. It's a &lt;strong&gt;correlation from self-reported data&lt;/strong&gt;: sharper people may simply do more puzzles, rather than puzzles making them sharper — and the researchers said exactly that. So the honest pitch for a daily puzzle isn't "get smarter." It's a genuinely enjoyable, focused way to spend fifteen minutes, with a possible cognitive upside the science is still working out. That's plenty. A puzzle doesn't have to be medicine to be worth doing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The games, by the thinking they train
&lt;/h2&gt;

&lt;p&gt;With that settled, here's what's worth bookmarking — all free, all in the browser, no sign-up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pure logic&lt;/strong&gt; — &lt;strong&gt;Sudoku&lt;/strong&gt; is the anchor: classic 9×9, a gentler 6×6 for kids or a quick round, and a 16×16 hexadoku for a long sit-down, across Easy to Expert (with printable packs). &lt;strong&gt;Minesweeper&lt;/strong&gt; and &lt;strong&gt;Connect 4&lt;/strong&gt; live here too.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spatial &amp;amp; planning&lt;/strong&gt; — a &lt;strong&gt;15-puzzle&lt;/strong&gt; and a block-unblock puzzle: pure move-planning, no clock.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt; — &lt;strong&gt;Memory Match&lt;/strong&gt;: flip cards, remember positions, clear the board in as few moves as you can.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast &amp;amp; satisfying&lt;/strong&gt; — &lt;strong&gt;2048&lt;/strong&gt; (one rule you learn in seconds) and &lt;strong&gt;Color Lines&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Word&lt;/strong&gt; — a &lt;strong&gt;word-search&lt;/strong&gt; maker and solver.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unbeatable AI&lt;/strong&gt; — &lt;strong&gt;Tic-Tac-Toe&lt;/strong&gt; you cannot beat, only draw.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where to start if you bounce off puzzles
&lt;/h2&gt;

&lt;p&gt;Start with &lt;strong&gt;Sudoku on Easy, 2048, or Memory Match&lt;/strong&gt;. Easy Sudoku leaves enough numbers filled in that every move is a simple check; 2048 has one rule; Memory Match has no real failure state. All three build confidence fast, and you can step up to Minesweeper, Connect 4 or harder Sudoku once the basics feel comfortable.&lt;/p&gt;

&lt;p&gt;Play any of them at &lt;a href="https://lkforge.com/games/puzzles/" rel="noopener noreferrer"&gt;lkforge.com/games/puzzles&lt;/a&gt; — and if you'd rather have a machine finish a stubborn grid, the &lt;a href="https://lkforge.com/tools/puzzles/" rel="noopener noreferrer"&gt;solver tools&lt;/a&gt; cover Sudoku, word search, crosswords, mazes, Minesweeper and more, all in the browser.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://lkforge.com/blog/free-puzzle-games-online/" rel="noopener noreferrer"&gt;LK Forge&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>puzzles</category>
      <category>braintraining</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Tiled vs naive matrix multiplication: loop order was the bigger win</title>
      <dc:creator>Lucian (LKB)</dc:creator>
      <pubDate>Wed, 02 Sep 2026 08:48:45 +0000</pubDate>
      <link>https://dev.to/lucian_lkb_1f009d/tiled-vs-naive-matrix-multiplication-loop-order-was-the-bigger-win-4ipn</link>
      <guid>https://dev.to/lucian_lkb_1f009d/tiled-vs-naive-matrix-multiplication-loop-order-was-the-bigger-win-4ipn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Syndicated from the original on &lt;strong&gt;&lt;a href="https://lkforge.com/blog/tiled-vs-naive-matrix-multiplication/" rel="noopener noreferrer"&gt;lkforge.com&lt;/a&gt;&lt;/strong&gt;, where the same numbers drive two inline charts. The matrix tools it links to are at &lt;a href="https://lkforge.com/tools/math/" rel="noopener noreferrer"&gt;lkforge.com/tools/math&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tiling — splitting the matrices into cache-sized blocks — is the famous trick for making matrix multiplication fast, and it's the first optimization most guides reach for. So I wrote all three versions in C, compiled them the same way (&lt;code&gt;cc -O2&lt;/code&gt;), and timed them against the thing you'd actually use in practice: a BLAS library. The numbers said something the tutorials usually skip: &lt;strong&gt;the biggest free win isn't tiling at all.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everything below was measured on Apple Silicon (macOS), Accelerate BLAS backend. Absolute rates vary by machine — the &lt;em&gt;pattern&lt;/em&gt; is what reproduces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four ways to multiply the same two matrices
&lt;/h2&gt;

&lt;p&gt;Same matrices, same machine, four implementations, GFLOP/s (higher is faster):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;n&lt;/th&gt;
&lt;th&gt;naive &lt;code&gt;ijk&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;reordered &lt;code&gt;ikj&lt;/code&gt;
&lt;/th&gt;
&lt;th&gt;best tiled&lt;/th&gt;
&lt;th&gt;BLAS (numpy &lt;code&gt;@&lt;/code&gt;)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;td&gt;2.19&lt;/td&gt;
&lt;td&gt;17.26&lt;/td&gt;
&lt;td&gt;13.52&lt;/td&gt;
&lt;td&gt;317.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1024&lt;/td&gt;
&lt;td&gt;2.64&lt;/td&gt;
&lt;td&gt;16.73&lt;/td&gt;
&lt;td&gt;14.83&lt;/td&gt;
&lt;td&gt;410.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2048&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;16.28&lt;/td&gt;
&lt;td&gt;14.01&lt;/td&gt;
&lt;td&gt;458.8&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All four produced the identical result (checksums matched); only the speed differs. Three findings jump out at n=1024:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Loop order alone was 6.3× faster&lt;/strong&gt; than naive (2.64 → 16.73), with no blocking at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tiling was situational&lt;/strong&gt; — my best tiled version (14.83) never beat the plain reordered loop on this hardware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BLAS was another 24.5×&lt;/strong&gt; ahead of my best loop (410 vs 16.73), and 155× the naive loop — and that gap is &lt;em&gt;not&lt;/em&gt; cache tiling.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The free lunch: loop order
&lt;/h2&gt;

&lt;p&gt;The naive order is &lt;code&gt;for i, for j, for k: C[i][j] += A[i][k]·B[k][j]&lt;/code&gt;. The problem is the inner loop over &lt;code&gt;k&lt;/code&gt;: &lt;code&gt;A[i][k]&lt;/code&gt; walks along a row (contiguous, good), but &lt;code&gt;B[k][j]&lt;/code&gt; walks &lt;strong&gt;down a column&lt;/strong&gt; — every step jumps a full row ahead in memory. At n=1024 that's an 8 KB stride per multiply, so almost every access misses cache. The CPU spends its time waiting on memory, which is why naive sits at just 2.6 GFLOP/s. The multiplies are cheap; the memory stalls are the cost.&lt;/p&gt;

&lt;p&gt;Swap the last two loops to &lt;code&gt;for i, for k, for j&lt;/code&gt; and the inner loop becomes &lt;code&gt;C[i][j] += a·B[k][j]&lt;/code&gt; with &lt;code&gt;a = A[i][k]&lt;/code&gt; hoisted out. Now &lt;code&gt;C[i][j]&lt;/code&gt; and &lt;code&gt;B[k][j]&lt;/code&gt; both march along contiguous rows — &lt;strong&gt;unit stride&lt;/strong&gt;. The hardware prefetcher and the compiler's auto-vectorizer both love that pattern, and the same arithmetic runs 6.3× faster. Not one line of blocking code; just touching memory in the order it's laid out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where tiling helps — and where it doesn't
&lt;/h2&gt;

&lt;p&gt;Tiling computes the answer one small block at a time so a T×T patch of each matrix stays hot in cache while it's reused. That's a real effect, and you can watch it work — sweeping the tile size at n=1024:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;tile size T&lt;/th&gt;
&lt;th&gt;16&lt;/th&gt;
&lt;th&gt;32&lt;/th&gt;
&lt;th&gt;64&lt;/th&gt;
&lt;th&gt;128&lt;/th&gt;
&lt;th&gt;256&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GFLOP/s&lt;/td&gt;
&lt;td&gt;8.83&lt;/td&gt;
&lt;td&gt;10.12&lt;/td&gt;
&lt;td&gt;11.86&lt;/td&gt;
&lt;td&gt;14.12&lt;/td&gt;
&lt;td&gt;14.83&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Throughput climbs steadily as the block grows — bigger tiles reuse more before eviction, right up until three tiles (&lt;code&gt;3·T²·8&lt;/code&gt; bytes) stop fitting in L2. But here's the honest part: &lt;strong&gt;every one of those bars is below 16.73&lt;/strong&gt; — the same loops reordered with no tiling at all.&lt;/p&gt;

&lt;p&gt;Why the famous trick underperformed: this CPU has a large L2, and the compiler already auto-vectorizes the clean reordered inner loop into wide SIMD stores. A hand-written blocked loop adds index arithmetic and loop overhead the reordered version doesn't pay, and the cache pressure it relieves wasn't the bottleneck yet. Tiling earns its keep on smaller-cache CPUs, at much larger matrices, or — crucially — as one layer of a &lt;strong&gt;multi-level&lt;/strong&gt; blocking scheme (registers → L1 → L2), which is exactly what real libraries do. As a bolt-on to a loop that already streams cache-friendly, it's a wash.&lt;/p&gt;

&lt;p&gt;The lesson isn't "tiling is useless." It's &lt;strong&gt;measure on your hardware; the famous optimization isn't automatically the winning one.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The 24.5× that's left over
&lt;/h2&gt;

&lt;p&gt;My best hand loop reached 16.73 GFLOP/s. numpy reached about 410 — still 24.5× more, from the same silicon. None of that remaining gap is cache tiling. It's &lt;strong&gt;SIMD&lt;/strong&gt; (one instruction multiplying a whole vector at once), &lt;strong&gt;register blocking&lt;/strong&gt; (keeping a tiny sub-block of the result in registers so it never touches memory mid-accumulation), &lt;strong&gt;multithreading&lt;/strong&gt; across cores, and microkernels hand-tuned per CPU. Cache tiling is one rung on that ladder, not the ladder.&lt;/p&gt;

&lt;p&gt;The practical takeaway is the oldest one in performance work: for real matmul, call the library — and spend your own effort only where no library exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce it
&lt;/h2&gt;

&lt;p&gt;The three loops are below. Compile with &lt;code&gt;cc -O2&lt;/code&gt;, time each, and divide &lt;code&gt;2·n³&lt;/code&gt; by the seconds for GFLOP/s. Your absolute numbers will differ by machine, but the shape — naive slow, reorder ~6×, tiling situational, BLAS far ahead — reproduces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="c1"&gt;// naive — inner loop reads B down a column (stride n): cache-hostile&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ijk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// reordered — inner loop over j is unit-stride: the 6.3x win&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ikj&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// tiled — same math, blocked into T-sized patches for cache reuse&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;tiled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ii&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;kk&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
      &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;jj&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The BLAS baseline is one line of Python — &lt;code&gt;C = A @ B&lt;/code&gt; with numpy — timed the same way.&lt;/p&gt;




&lt;p&gt;Original writeup with the charts: &lt;strong&gt;&lt;a href="https://lkforge.com/blog/tiled-vs-naive-matrix-multiplication/" rel="noopener noreferrer"&gt;lkforge.com/blog/tiled-vs-naive-matrix-multiplication&lt;/a&gt;&lt;/strong&gt; · try the browser matrix tools: &lt;strong&gt;&lt;a href="https://lkforge.com/tools/math/matrix-multiply/" rel="noopener noreferrer"&gt;matrix multiply&lt;/a&gt;&lt;/strong&gt; · &lt;a href="https://lkforge.com/tools/math/" rel="noopener noreferrer"&gt;all math tools&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>performance</category>
      <category>cpp</category>
      <category>python</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
