mirror of
https://github.com/foomo/foomo-docs.git
synced 2025-10-16 12:35:40 +00:00
48 lines
161 KiB
HTML
48 lines
161 KiB
HTML
<!doctype html>
|
||
<html lang="en" dir="ltr" class="blog-wrapper blog-list-page plugin-blog plugin-id-default">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="generator" content="Docusaurus v2.4.0">
|
||
<title data-rh="true">Blog | foomo project docs</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://www.foomo.org/blog"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" property="og:title" content="Blog | foomo project docs"><meta data-rh="true" name="description" content="Blog"><meta data-rh="true" property="og:description" content="Blog"><meta data-rh="true" name="docusaurus_tag" content="blog_posts_list"><meta data-rh="true" name="docsearch:docusaurus_tag" content="blog_posts_list"><link data-rh="true" rel="icon" href="/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://www.foomo.org/blog"><link data-rh="true" rel="alternate" href="https://www.foomo.org/blog" hreflang="en"><link data-rh="true" rel="alternate" href="https://www.foomo.org/blog" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://SUATUVZDDM-dsn.algolia.net" crossorigin="anonymous"><link rel="alternate" type="application/rss+xml" href="/blog/rss.xml" title="foomo project docs RSS Feed">
|
||
<link rel="alternate" type="application/atom+xml" href="/blog/atom.xml" title="foomo project docs Atom Feed">
|
||
|
||
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml" title="foomo project docs" href="/opensearch.xml"><link rel="stylesheet" href="/assets/css/styles.45fe17b6.css">
|
||
<link rel="preload" href="/assets/js/runtime~main.339c949d.js" as="script">
|
||
<link rel="preload" href="/assets/js/main.4cf1833b.js" as="script">
|
||
</head>
|
||
<body class="navigation-with-keyboard">
|
||
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}return t}()||function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
|
||
<div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><b class="navbar__title text--truncate">foomo</b></a><a class="navbar__item navbar__link" href="/docs/general">General</a><a class="navbar__item navbar__link" href="/docs/frontend">Frontend</a><a class="navbar__item navbar__link" href="/docs/backend">Backend</a><a class="navbar__item navbar__link" href="/docs/devops">DevOps</a><a class="navbar__item navbar__link" href="/docs/projects">Projects</a></div><div class="navbar__items navbar__items--right"><a aria-current="page" class="navbar__item navbar__link navbar__link--active" href="/blog">Blog</a><div class="searchBox_ZlJk"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="docusaurus_skipToContent_fallback" class="main-wrapper mainWrapper_z2l0"><div class="container margin-vert--lg"><div class="row"><aside class="col col--3"><nav class="sidebar_re4s thin-scrollbar" aria-label="Blog recent posts navigation"><div class="sidebarItemTitle_pO2u margin-bottom--md">Recent posts</div><ul class="sidebarItemList_Yudw clean-list"><li class="sidebarItem__DBe"><a class="sidebarItemLink_mo7H" href="/blog/go-race-conditions-testing-and-coverage">Go race conditions testing and coverage</a></li><li class="sidebarItem__DBe"><a class="sidebarItemLink_mo7H" href="/blog/accuracy-of-decimal-computations">Accuracy of decimal computations</a></li><li class="sidebarItem__DBe"><a class="sidebarItemLink_mo7H" href="/blog/why-bundle-size-is-important">Why bundle size is important?</a></li><li class="sidebarItem__DBe"><a class="sidebarItemLink_mo7H" href="/blog/prometheus-cardinality-issues">Prometheus Is Out Of Memory. Again.</a></li><li class="sidebarItem__DBe"><a class="sidebarItemLink_mo7H" href="/blog/searching-for-search-engines">The never ending search a search engine 2022-01 edition</a></li></ul></nav></aside><main class="col col--7" itemscope="" itemtype="http://schema.org/Blog"><article class="margin-bottom--xl" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting"><header><h2 class="title_f1Hy" itemprop="headline"><a itemprop="url" href="/blog/go-race-conditions-testing-and-coverage">Go race conditions testing and coverage</a></h2><div class="container_mt6G margin-vert--md"><time datetime="2023-03-17T00:00:00.000Z" itemprop="datePublished">March 17, 2023</time></div><div class="margin-top--md margin-bottom--sm row"><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/cvidmar" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/cvidmar.png" alt="Cristian Vidmar"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/cvidmar" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Cristian Vidmar</span></a></div><small class="avatar__subtitle" itemprop="description">Content Chef</small></div></div></div><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/dreadl0ck" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/dreadl0ck.png" alt="Philipp Mieden"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/dreadl0ck" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Philipp Mieden</span></a></div><small class="avatar__subtitle" itemprop="description">MSc</small></div></div></div></div></header><div class="markdown" itemprop="articleBody"><p>Go has extensive support for concurrency through goroutines and channels. This feature allows programs to progress on several tasks at the same time but it requires some extra care to prevent situations where multiple goroutines might collide and lead to a panic. These are known as race conditions and they happen when a shared variable is read and written at the same time by two different routines. A typical example is a concurrent read/write of a map in memory.</p><p>To illustrate an example let's consider <a href="https://github.com/foomo/gocontentful" target="_blank" rel="noopener noreferrer">gocontentful</a>, the code generator that creates an API to access a Contentful CMS from go. The generated API uses an in-memory cache to store a copy of a Contentful space and some extra data structures to allow go programs to access Contentful data, inspect and resolve references and so on. In a typical scenario, the client is used in a service that responds to HTTP calls and makes heavy use of concurrency because it needs to be able, at the same time, to:</p><ul><li>Read entries, assets and references from the cache</li><li>Update/Delete single entities and their connections with others (for example the map of parent entries)</li><li>Incrementally sync the content of the cache with data changes coming from Contentful</li><li>Rebuild the cache entirely and swap the existing one with a new copy</li></ul><p>In addition, for performance reasons, when the cache is created or rebuilt the gocontentful client spawns up to four goroutines to download chunks of data in parallel across the Internet, dynamically selecting the size the sorting of the chunks to leverage the maximum parallelism.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="detecting-race-conditions-through-unit-tests">Detecting race conditions through unit tests<a href="#detecting-race-conditions-through-unit-tests" class="hash-link" aria-label="Direct link to Detecting race conditions through unit tests" title="Direct link to Detecting race conditions through unit tests"></a></h2><p>We experienced race conditions with the client in the past, and we fixed them to maintain it production-ready with every new version. To help with this, we included a testing framework in gocontentful that generates a sample API from a local export of a Contentful space and then runs several unit tests that, among others, test the client for concurrency safety:</p><p><img loading="lazy" alt="make test" src="/assets/images/make-test-e708de4fbdbded8bf679660769b6d1af.webp" width="1570" height="756" class="img_ev3q"></p><p>One of these unit tests spawns tens of thousands of goroutines to concurrently read, write and inspect the references of specific entries while at the same time keeps rebuilding the cache. From the screenshot above we see that no race condition is shown. Even at this concurrency level, though there's no guarantee that running</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">go </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">test</span><span class="token plain"> ./</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token plain">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>will be enough to generate a collision. What we really want to do is to add a new parameter to enable the go race detector with</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">go </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">test</span><span class="token plain"> -race ./</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token plain">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>(In gocontentful you can run <em>make race</em> to fire up both the API generation and the race test)</p><p>From the documentation at <a href="https://go.dev/blog/race-detector" target="_blank" rel="noopener noreferrer">https://go.dev/blog/race-detector</a>:</p><blockquote><p><em>When the -race command-line flag is set, the compiler instruments all memory accesses with code that records when and how the memory was accessed, while the runtime library watches for unsynchronized accesses to shared variables. When such “racy” behavior is detected, a warning is printed.</em></p></blockquote><p>Running this in gocontentful shows that we indeed have a potential collision condition:</p><p><img loading="lazy" alt="Race condition" src="/assets/images/race-condition-5d0a166992c4af58e43708a7eaf41eb9.webp" width="1681" height="1918" class="img_ev3q"></p><p><em>Note: After you run this test you'll want to search for "race" inside the terminal output. Make sure you enable a very long (if not infinite) scrollback or you might miss some hits.</em></p><p>The race detector reports the filenames and lines of code that generated the race condition. Looking at those lines in our example shows that a field of the cache (the "offline" boolean) is written protecting it with a proper mutex lock but the lock handling is missing around the read operation:</p><p><img loading="lazy" alt="Read access" src="/assets/images/read-access-e74fbfc1d026ab850775c44f7511bcf0.webp" width="1489" height="402" class="img_ev3q"></p><p><img loading="lazy" alt="Write access" src="/assets/images/write-access-e8b23abfbe4c9a9379f8facf8e1a3c0e.webp" width="1618" height="1004" class="img_ev3q"></p><p>The fix is very simple but in this particular case the offline flag is read and then a 2 seconds delay is started. Deferring the unlock would keep the variable locked for far too long, so we will read-lock it only for the time needed to copy its value to a local variable:</p><p><img loading="lazy" alt="Fix race condition" src="/assets/images/fix-race-condition-e41a80c7dda8ce75c9414b2f2b37e1b8.webp" width="1695" height="538" class="img_ev3q"></p><p>After fixing the issue in the generator templates and regenerating the code, the tests with the race detector run fine. In gocontentful this can be done all in one step with make race:</p><p><img loading="lazy" alt="No race condition" src="/assets/images/no-race-condition-3d4eb2e0a194a1677f60d351fa3798ac.webp" width="1370" height="686" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="test-coverage">Test coverage<a href="#test-coverage" class="hash-link" aria-label="Direct link to Test coverage" title="Direct link to Test coverage"></a></h2><p>That was nice! But how do we know if we're covering all test cases? Go has been supporting test code coverage since 1.12 through the -cover option. We can also limit the coverage to a specific package. In our case, we're only interested in the <em>testapi</em> sub-package because we want to test the generated API, not the generator itself.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">go </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">test</span><span class="token plain"> -cover -coverpkg</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">./test/testapi ./</span><span class="token punctuation" style="color:rgb(199, 146, 234)">..</span><span class="token plain">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Let's try and run the tests with coverage:</p><p><img loading="lazy" alt="Basic coverage" src="/assets/images/basic-coverage-1b4ff1807c3030afadd3d964d0dad9e3.webp" width="1930" height="290" class="img_ev3q"></p><p>The summary shows we are only covering 22% of the code. The goal is not to cover 100%, some parts only work online calling the actual API of a real Contentful space, but we definitely have room for improvement.</p><p>The question is: how do we know exactly which lines of code we're covering through the test suite? Again, go test comes to the rescue through another option: <em>-coverprofile</em> lets us specify an output file that will contain references to each single line of code involved in the analysis. It is a text file, but not very readable:</p><div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:21.86,22.15 1 1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:25.2,25.18 1 1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:28.2,29.16 2 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:32.2,33.16 2 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:36.2,37.37 2 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:40.2,40.24 1 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:22.15,24.3 1 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:25.18,27.3 1 1</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:29.16,31.3 1 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:33.16,35.3 1 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:37.37,39.3 1 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:43.114,44.35 1 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:47.2,48.18 2 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:51.2,53.16 3 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">github.com/foom...tapi/gocontentfulvolibproduct.go:56.2,57.16 2 0</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>We can use <em>go tool</em> to convert it to a much better representation in HTML:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">go tool cover -html</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain">cover.out -o cover.html</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Opening this file in a browser reveals a lot of useful information:</p><p><img loading="lazy" alt="Coverage HTML" src="/assets/images/coverage-html-31939a8031afbabb8f2d0af5c7476644.webp" width="1750" height="1778" class="img_ev3q"></p><p>At the top left of the page there's a menu where we can select from all the files analyzed, listed along with the percentage of coverage for each one. Inside every file the lines covered by the tests are green while the red ones are not covered. In the example above we can see that the getAllAssets function is covered but it includes an <em>else</em> condition that is never met.</p><p>In gocontentful (starting from 1.0.18) we can generate the test API, run the tests with coverage, convert the output file and open it in the browser with a single command:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token function" style="color:rgb(130, 170, 255)">make</span><span class="token plain"> cover</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>As stated above, not necessarily 100% of the code needs to be covered by the tests, but this view in combination with the race detector gives us incredibly useful information to make the code more solid.</p></div><footer class="row docusaurus-mt-lg"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/golang">golang</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/concurrency">concurrency</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/testing">testing</a></li></ul></div></footer></article><article class="margin-bottom--xl" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting"><header><h2 class="title_f1Hy" itemprop="headline"><a itemprop="url" href="/blog/accuracy-of-decimal-computations">Accuracy of decimal computations</a></h2><div class="container_mt6G margin-vert--md"><time datetime="2023-03-06T00:00:00.000Z" itemprop="datePublished">March 6, 2023</time></div><div class="margin-top--md margin-bottom--sm row"><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/uebriges" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/uebriges.png" alt="Patrick Buchner"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/uebriges" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Patrick Buchner</span></a></div><small class="avatar__subtitle" itemprop="description">MSc</small></div></div></div><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/marusicbostjan" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/marusicbostjan.png" alt="Boštjan Marušič"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/marusicbostjan" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Boštjan Marušič</span></a></div><small class="avatar__subtitle" itemprop="description">PhD</small></div></div></div></div></header><div class="markdown" itemprop="articleBody"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="intro">Intro<a href="#intro" class="hash-link" aria-label="Direct link to Intro" title="Direct link to Intro"></a></h2><p>Calculating with money can be tricky if not taken proper precautions. Some might be tempted to use float representation for calculating with currency values. That is problematic because of possible rounding errors.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="finite-accuracy-of-representation">Finite accuracy of representation<a href="#finite-accuracy-of-representation" class="hash-link" aria-label="Direct link to Finite accuracy of representation" title="Direct link to Finite accuracy of representation"></a></h2><p>Floating points are represented like this</p><p><img loading="lazy" alt="Floating point representation" src="/assets/images/floating_point_representation-efc73a8c1b722a82b772c2cd7ee7ba99.webp" width="810" height="226" class="img_ev3q"></p><p>Not every number can be represented with a finite number of decimal places</p><p>0.01 —> 0.0000011001100110011…</p><p>Taking 17 places of the above results in 0.010000000000000001</p><p>Consider the following code snipet that shows the missing accuracy</p><div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token keyword" style="font-style:italic">func</span><span class="token plain"> </span><span class="token function" style="color:rgb(130, 170, 255)">main</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token keyword" style="font-style:italic">var</span><span class="token plain"> n </span><span class="token builtin" style="color:rgb(130, 170, 255)">float64</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token keyword" style="font-style:italic">for</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(137, 221, 255)">:=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">0</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> i </span><span class="token operator" style="color:rgb(137, 221, 255)"><</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">1000</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><span class="token plain"> i</span><span class="token operator" style="color:rgb(137, 221, 255)">++</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> n </span><span class="token operator" style="color:rgb(137, 221, 255)">+=</span><span class="token plain"> </span><span class="token number" style="color:rgb(247, 140, 108)">.01</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> fmt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Println</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">n</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Result: 9.999999999999831</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="money-computations">Money computations<a href="#money-computations" class="hash-link" aria-label="Direct link to Money computations" title="Direct link to Money computations"></a></h2><p>They can't be done with floating-point as it would inevitably lead to rounding errors.</p><p>Even the following packages are problematic:</p><p><a href="https://github.com/shopspring/decimal" target="_blank" rel="noopener noreferrer">github.com/shopspring/decimal</a></p><p><a href="https://github.com/Rhymond/go-money" target="_blank" rel="noopener noreferrer">github.com/Rhymond/go-money</a></p><div class="language-go codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-go codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">a </span><span class="token operator" style="color:rgb(137, 221, 255)">:=</span><span class="token plain"> decimal</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">NewFromInt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">2</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">b </span><span class="token operator" style="color:rgb(137, 221, 255)">:=</span><span class="token plain"> decimal</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">NewFromFloat</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">300.99</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">c </span><span class="token operator" style="color:rgb(137, 221, 255)">:=</span><span class="token plain"> a</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Mul</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">b</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">d </span><span class="token operator" style="color:rgb(137, 221, 255)">:=</span><span class="token plain"> c</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">Div</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">decimal</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token function" style="color:rgb(130, 170, 255)">NewFromInt</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token number" style="color:rgb(247, 140, 108)">3</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="solution">Solution<a href="#solution" class="hash-link" aria-label="Direct link to Solution" title="Direct link to Solution"></a></h2><p>Use Int by representing money in cents:</p><ul><li>10.99 -> 1099 (cents)</li><li>10.9900 -> 109900 (4 digit tax)</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h2><p><strong>Division is a problem!</strong></p><p>1/3 - > 0.33333333…
|
||
Correct way: 0.33, 0.33, 0.34</p><p>When doing money calculations one should avoid division as it inevitably leads to loss of accuracy.
|
||
When dividing make sure to round to cent and deal with diffs.</p><p>Division by 10^k is ok as long as we are inside of the range of the data type.</p></div><footer class="row docusaurus-mt-lg"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/golang">golang</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/currency">currency</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/decimal-accuracy">decimal accuracy</a></li></ul></div></footer></article><article class="margin-bottom--xl" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting"><header><h2 class="title_f1Hy" itemprop="headline"><a itemprop="url" href="/blog/why-bundle-size-is-important">Why bundle size is important?</a></h2><div class="container_mt6G margin-vert--md"><time datetime="2022-03-17T00:00:00.000Z" itemprop="datePublished">March 17, 2022</time></div><div class="margin-top--md margin-bottom--sm row"><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/nicolaturcato" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/nicolaturcato.png" alt="Nicola Turcato"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/nicolaturcato" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Nicola Turcato</span></a></div><small class="avatar__subtitle" itemprop="description">Memelord brother</small></div></div></div></div></header><div class="markdown" itemprop="articleBody"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="intro">Intro<a href="#intro" class="hash-link" aria-label="Direct link to Intro" title="Direct link to Intro"></a></h2><p>JavaScript is parsed, compiled and executed in the main thread of the browser. Which means that users have to wait for all of this before they can interact with the website.</p><p>Frontend performance optimization is critical because it accounts for around 80-90% of user response time (10-20% backend).
|
||
So when a user is waiting for a page to load, around 80-90% of the time is due to frontend related code and assets.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="nobody-likes-waiting">Nobody likes waiting…<a href="#nobody-likes-waiting" class="hash-link" aria-label="Direct link to Nobody likes waiting…" title="Direct link to Nobody likes waiting…"></a></h2><p>A study found that if a site takes longer than 4 seconds to load, up to 25% of users would abandon the site.</p><p>Sending large JavaScript payloads impacts the speed of your site significantly.</p><p><img loading="lazy" alt="Mazzarri" src="data:image/webp;base64,UklGRsYjAABXRUJQVlA4WAoAAAAsAAAAmQEAEwEASUNDUBQCAAAAAAIUYXBwbAQAAABtbnRyUkdCIFhZWiAH5gADABEACAAyADdhY3NwQVBQTAAAAABBUFBMAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGycI4tw2obgutNn6fT9ab4VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApkZXNjAAAA/AAAAGVjcHJ0AAABZAAAACN3dHB0AAABiAAAABRyWFlaAAABnAAAABRnWFlaAAABsAAAABRiWFlaAAABxAAAABRyVFJDAAAB2AAAABBjaGFkAAAB6AAAACxiVFJDAAAB2AAAABBnVFJDAAAB2AAAABBkZXNjAAAAAAAAAAtST0cgUEcyNDhRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIEluYy4sIDIwMjIAAFhZWiAAAAAAAADzUgABAAAAARa+WFlaIAAAAAAAAG+kAAA49gAAA5FYWVogAAAAAAAAYpQAALeGAAAY2lhZWiAAAAAAAAAkngAAD4QAALbCcGFyYQAAAAAAAAAAAAH2BHNmMzIAAAAAAAEMPwAABd3///MoAAAHkQAA/ZH///uj///9owAAA9sAAMB5VlA4IGYfAABQzQCdASqaARQBPpFCm0slo6kspJH7gZASCWVuiIDE9kjGK9qiXpFygqoPt263oX4NFBX/tftCQbd9BasuZYroAeT//weXvUT6WpZWU9CN300hOJRwSkc+RrDjYRt4NuaAJQ+9Xub6becmqoD8yLTS8BamMxq2+Lwr5o73Q8d4K381UwZAHStTJ4I0wZwlRbK0gfQ9li03TDiNQ35qaZYoSfy09eUG0vH/73R2Bkx9jFrtFa5qf7ipFnR6dt6y2BnSNDdys91qqmQV6hAzvVKi9SsMIM80D+fSD2qYhPSUx6K/yjQvBmamLNcldy6wHyPgv+09PiD5TcU3qQa5c62bhdU0DFYsUxkJDXfKzmzSnGRpHsunxoKCo2No7iqA4bNze6snA4YpYfuZVbNegeOARKyIX9UeA0/RsVXva/UDqJOBKREfhbqh0K3BfKl2O+Dk4qFHJo4MuzOPx7Eufw6AIHyaIij3NNToSLly1q/gJ5la8LSIbmoL9N8aZ/aUbZbYzKVogMz1jfj7g3I2wQfqKqCZ0/Z6KKmxeIyVCMkkBNY1tPOwyYAvtCCmH5fdlegrLW72m4mtmILzzbTUakK2BLDih3GP38gJzD023nP6djxwx5iCaOzpHcfEMU0LhgyNHCc9eoDxkDj10AuRlYWxRvNYmoS7Fs5FPszJuZpTPdPNZcOsk6ZVHTTfrDYkUUShc7B8FbLhstRj4fKd17dHhN8A+ZlKEX7T9mS9PrYgGttReZImb0An1zKpnn28bS5hTVUk4B5G5SoRpl5ojr4wlKjVKxWrg735fb1O0L3+rNZakZ1o0MbJ+ms16N85TBxqlMvivMsShmZswdmbTeQRvBOXcEHyjDFyOOI+v1fYtJltwkgN1+qFCy178uzpkXcGN5R/7YKyPsIwo0NlyUUbqzvrbclhgmutWIrcuAQ7tIii53JRynOmKscO73bPQFvr1CFWgWZodfCAnb7O2MoZuX56Unky5RB/qkClUagYtLWcLTs7jFfRhcPl2s6dDeYBGdSg8PCRKMufTqsacEWSmHWqdurGv+1+WcbUFE0zNeGx6AxbtKbxXF+uawnGpj3OG5IFLLr1F9rq6oHu/YQEl4p9HpL1TrkhI/L0F9FHwTbuIGQj1xcBXh4Uq0ckMGOTCEya4gSLskm57ZCLKgI1Rme27WhfqGl6LteIVr3vffrN3BRBsr2Db9RxetopHXDNgk5OPzbvf5c3bAATCVa4qOW/ywY+oourvb0RRlxI4/8bnzPu09ocl1D8iZcLzZCy7GLV6m3tHumTRWHVTiU29EqOFNrTZYY3hZOMmuj3nl+53SrSCs4+5iZXVl/RDwZ3wl/53HZyeEX9bd9AIeu/FnAW4pqFmR202lRUroFsk/ky8F3Z+iZhUo3SQ9hGYlSbBbo9P6XUpTwTfowyy0gLC7QleV3exrWumOwdMPzVeQ4V1JuvGn4RrWxEoM6G778lxFvlSZezcWOMFnUTjm2VDns4kcs60R7lYMaQLwDGkRSRLI9axObQpw38nk4OldDpxDZ9QkxwNFJ1Z3ASnPeSPlnvzByyxjsJAInkPIbCJYYR9ok2ny7ImKWHgpKs/ktHHslzahpNF+ewwo0wiN7aI2CuEsUmYZC2WBnz/70WN0ejmkWa0oEFms4QuT503/RW4qjKgWPTsihpr30kPsSEXANi4tyxo667RYDsQ0S6ax00xPPES6uQtqCoipB5KQrsfyVm6s7ew2DoTUiLMcoXMs/t4EsGrcG7IPC4gubiiimt9AU/FXQd+F0TfQWn7XGx9x26ObZMbj/lJk8HuoZdBf5emd/UgFxlQovFTGIoVLsOzHMa9usLyIliVJhVCBK9wvmhB/i/YtO/PtMS4SlsPxn/KWH48rfD/vd2FCAQnzQohgS+qzh887MRnd10e0ioSWj+7SiVw/yVF6bmyp4nlFK5o8GkSX8oAoun2DOEmGqYFDf9/Pa4XPIijIL2F0QeRMHpB+kxoKpmzyzZwA58rxmkO8bDOf0G1/ejzfQ6DMA1iweo55v+BX9Ln6rp0CTZhW2L7iO6ZArnCcOJqCIf8GGwA3f1NEFmLktYKPMXszr5SaO4kSuJbB3njEB/972Tdmh1oTQzAwe63g/Sd2IaZgb51qlWywq0ETv0i1wx9inRdES6Q1MbcgUnHbkof0mG3AjSS8zRM5Opld+Np1oZtSgAAP3bJt3g+ykBDm+tvaQt88Ov2eKnnTc/i8A7clz1g9mFq8OY6Ai6Dv9CjI7a6WilZpHZUI2fzXrT0IMPSIYGT3tX/Mcji/0RG92LG8zeoXIChHyzlrEPBWdFaXTOZkjKZMOTv1nU9reo4kmI7LO5/Zwq2KHcnVqWoFYu3DIsrCxRkNF59UcfKEV6ZrgEoh8PkDn3zDQRt1gVu8Yp7uyLK4/N+iEESq/FIGGeKK1itN3hmXYDmY5yaXrg9tWPhNV0D2y0yHo5ZcmxN8VA7YbhRbTFfTqvB1AFo9Ru6fvFUhBQXHAFW0WvwXrbGZ463zwg2hNreB/ly1MAx1FDPoyWXign3oNWSTMeIrBsMB0uT7kFG1ufLRZA4HtjKQXWjBVw1pZOYRMPBO/tmtbeAL7T4COvn1W9ssCGr54yUcQSWVXNHQnlXc5T9JbPC+FkW1QpEkjzwZvthV8JJX3PO9aGYcddqaRGRZ5t0mf0+4hrQvhw+fpIK8tWc/nDopY1qgj/AxTn/4AzQLBDvZTl3A3otG24IgxWxCsLxtSKB8FmZgkMzKdk0F/Cj3As9+LGytYOH359SHXRTQ4ucLfSU2BQ5Fw07NeoS58IqLjGf9FVhR9ab/6uXMSYqDEivURyMwGUxkJjMx8iysqCJ3fX2QbX7MdPJ8qUmaWPZKLRnU8tzF6wKOqVE8iJXkBcppohhcn9+ue6SYUMchUKYEr7n8GGcm030ZbGmf+UIHq1P3ZiabISPj32nUUfqiQphrhOdwty818hQL02/DoVvlSGqvVqGEWh3ttthj651ul47D/jYEpgFW5KQJJt99hwosXHsvjcKh967bj7gXSsht3+nSLyK/3q2NzydkmhzehtT/lRHjMqQko0KHMp59hSlCfmAjvD8uKqs3i3K1d4FARC91ypSZGIGlpK/wUoqKZBepHkCA6e/ULLAnS0f0TVlLwE2Ci8JIYv3rCgcXnX+V9L7J7R2cJ7JtUzJt5t9KFRNO4SR5ya2eQ3Svphld0wlHhjmiF2iW1guRoOuQSfKEWb/ZuXfMiH3SkWJqET8FRYK4q0y+wIFbPYD5QAbO9lb9eKQfJA1B2uoH7N4MDQnEXGcILzkH7HD18nOXoLYutOprVNI/sKVPU9VjKL0dfE7TCK8e39hj6SYXFO9ojFWAmz6pxJvoEKAKkZPygdjXpmjCl4MnYb564CAlolaoRVpoyPmRPXDo6YJZflBNPiUegkafy1Fjhu3gyHGjFj9ue99VdWpnaAIOEzsc8twcrwe3yreE+iSFfFwpFE1enwz/Ej9UVPP6P9CpC3jtoTeRKsQazicAU5OwX27Hv5/lBL0vs6MAF5XzXx7ug5Fg2JytAFYZBRZzD/Rdgge/i2WELP2NhpLqPej9ZlTZrqlnM/sOnV7POrkdhxi1INt+9+shNeZNlY25Dkoxw/daMVDvNWIRhbEclOTgGAGW6uTMUF4o+RcmWnB/HlUd9JtMtpHmJMR623ScHXMcGBefoHmkS93RMaqnH3iwW5np7mUxWQhnu9Z1tfpJlCOqrrLF4HScorzLjbwzx49mqT36hrkOAdrIYMH7pBwRbFqPMXRqkdl472xU26oNs6o+W2he9IKl1vR8VquB78sWaPA3a7gw71x1ZQAelaWi/1UrNEz3bU3CCON5q2gCAeUe7+asV0QIIbqBEqmsEoOyrccxCJ67uNCM+UFk8dFY9+PMn+O2tCAw6XS5yVka+eAwYTtNqFqb542gMlkvHFHgmyPDQyYb+SpvnUO4FGIUOmXsfyymbpnxQZgH5lBoCgs5yTVQoDsnlxkC9GhGhDAlDWTTyC14hQtvK5XUTMjAbDEK7iAvoowq8fyiw4+NhStTwynR3LsclfdLi1w0wNXigBdNq9Kxcdd/3P26vUNbPVjv7K46fjMvAqahVayzxL4X7rG40s5OpEPCfCVc0X6PpfUjge2AhVl89dc9QFfK7tpTgOhwdEplrFWbeMh2Lg8KASEKw/mItCRJy9Y3ggrORvGUpmJ83rOqApap+x1+uHLakMZ3Wtuwj/232Ae+iFhovMBeo36GB2Mp+1hleVP3Ta3goArH8ts4ZmsOBkuXZPy6bXMKcnsWqIeB2XTOEVe1/yG1/HHqOQlotBMs3OlFuHqIKSq8wddrxD1EIdoa4fOKTB4QhBytgEXVJploTCVoXmhKnXiE/KkKcBWfIM5d2jqwUP9eFZtb7//F6n/XZmZD874OmKopGam/YJfAOL5oeN6mMWfpfr25cBAr8m+pS9TFcLcH/ckv51DURmktHeYVRRRogaZemlmE37BxR4KdNVxyo7s2fIXZ40hjq70zjPE7ptQBu9iWw7e/9P2KxcPFCga2dmnma/g2cHVy4thnW4TUoPEEKI/4jK5HUdbwbcyCKs4aSM2v1Q78kL5zaD5uH5iPfv4wByjdfKLR9sv+ODT4eHOOHKfd4qgFe6Z/H5zwLMJuTcuP9ARjIF9ed7y4qhvq4uU1lIzLGSBmgPoWGQN1MwLTG5SlaU/lHlSEmlD1YxouAlLoei4X4O+DZD2yzzP0i3fiBn738a+Jdwbppn1ztkj6EaTjV6K3utzv/mb+igPkMSUW3Hh19hsHwNnKjN/IJJwRqeSjJ46wO38h17SVsyWYXkWboveecIgeIaW2eZhuZCfzP6apJ0mg8/HA4E/J/G45FOJpA9b148Z1J0zpGjpbh4xxZ75ahIiaIketd18wQfinGdcrOegyHfJAjQKDEIoxp4i18d0nABK2Jjh4S1M61FkpkJo6787xEkEV4vS+gaRs0gRj07iXD4fL8JWs0gyD1QI8CoQCGv6YUog4C2ELcJ3Ec3knjlhF8M8UlPcmxFandeF5k96TEpJE/KL2llbZkYqFu637PN1RmMQigbjQz6k9Gwwc5ycaRkyiN5pcJY2HudeSuPcAdpL5V6YkWEfmFPUh2Ea6RJ8DrQQbBjTFFrpulCNWmQ/bNmu4BQOjPzDPKfiBTQwtVxUKsbEsSrxxqGE9w6cuZcafM/ZXgwxzdbQ5OwqzN5s5FR+Ropf5KIN8nm3d5h78lxroAfvjfmIkvOgasuX8VqrH/VjucKmPJNNSxJ7QNF3NBjHBDuRfGOcgkauvrMiKMmMHPoOg3xe6eyukA/eB8fZoagfA8mvQdQCU3fJf/N32p40Etq7twSqKpFu/J4sxgaIa1frgJXjvv6lLvcexwFreN31QGjFbmICGHSLNmk0U1Kj7/m0ez3iaVLYMb9zGxVqwfX/kNXUN8YYS7210VrY/7hhNcKVHhtNgckFRdIkTuiBc8ern3urOj5Gzq7q/g+HSMPguNgF4PCqAwsitjmysos5147mUrBMg54gBk42sEbVCBj1WTHjR3a/xP5P688R2Og86oSFaRSJlTyCGuKZhNeXPDXf8RreGUFgWs8wXzsyebb/rKPuxZxjxz1ER5oLx/+uMsPUJd78V1Ml4NC7gLLVWUGxwGn4ssYcNHj20Z2UjzmYveyw/OIsUOBN+SGIn/acuRSg3SDGP5lX6a/+9a5P3nzSk5T392GMpRxfYkdSbsXaRjPW0HqXxcFI1mHZcPaErpene7czmIloyzLGFF7+TMwSXevaDGDv3D+xAJzpa+QhWbXh/bsn3+SybB9RgLGotmWQjjcDWheCIfcM4ufSawwI3oKGUE7JP9vIJtW0xpELSPC7GthpZKnWtnFaNTqHDNps+oBO20/88rzHynkwE/FzY8BCwq7Loip1li5QTFCNO9xpbbuRO+lFfyFsU5pJivdSsDtPhI5qftkF1A9PlKtcvB6dQPos22r6qr/J0sLwH0n+AnIsdXmsOZLo/31NdAR/JgYmI2DFzfJnfnubn064wvuqZeR4hdG47/lDBWZdsemjoorwIIeGv1WhTuh+6/XzHqsRz1RC3mRTGHAs9r2goQNOQP5tpE1Gycm6xWzMig1FVw7QReFie99bghznT3+pqdxEsWrROq/8YUMsbeIOM7LCkbv1lvGySb4iYnb3HjrF64FqS4pDaJ2Kom9xyY+CcHYausNKjCFQ0x2oAZoFUnxDfQfbk358Gxj1CslwMEJTW/a8P3Z72nOWeX75reQnNiFpwVS7cfIww1i6GXXhCRLDwcpLs4aAoxxDEgmQUHPDhsckzyIz3kWjqpshdGlDrXAA97Sx1GeBDklZqykz593qcc4QMrOtqQ5mlPCe0QieDKY1gcG37J0Dh2DW7VWe+jkTYjHN0z/b0rzfX94b7NebX6uZ1wS+fhPHkOYhicYP+75oWjALDmxh127RVimkrIFk5rw5NCclLB/b1UgvZLR/XogkOwAymR9YpSfh7Gb4whTJImkWVO+rvp6E+4aH/Rfcm+KXmemw3QZj8PWqWbUP3KMMNjEHpWzMZ5FdPMI9hHAYQFVXpg5KtMkF4LEJ/bvhgtLn9J6W6pQmiX7w2sMGv5r+RQPMIlUPemR3PKrX11Q0MtFEjp22Yud4fZuFIz0x16cU8CHkz/xAnsg01ppeLFKFZ4lIT5m6lKjMNX6e95iPntXduxCe5n1GXaXYSSh+aUWtBnIwzXyTil9xwC6MBvQJjYsYTgu9JOc+X6oqW481LroFyyi36tmqy6fGRDooDBw/+yaAoaW6zWq0KZBD4f5ZqEeICfmRe1UbVJcIPHjymIlO4e7OcuDl+foUe3/nS/yWskE2x8ma2gMksKUzWROFm2fDt+1rRZYNl4v7N7Mh/j0MV5ww5YQAYqy8c5yZXiBLlDapWsZRNvZhL52ongFUYeRI7p7ZNVz0MfvOpQTm321B0QvaINUZ7pVgqTv2RxVm2fIclIMgOlB268uytZWDZeHHAA/Tw3oMRWopI4ox3xYcEAeOINu6XuyhGJ1qyGYBv7KmvhSuVZRFNORX3av26rpiPoX+0Cnq64w6UFUFYb4LD3JbndEuLAKaxBlwmbH4jId797bgoWyLXdv70G9EEY2179SXmPD0d9S/d5XwkRIgB9MBTfUIyzGL2eCeNrn9UyxjiGzUhta/hnyGrlIrD3Iupy5HPEgqHP0XZwhkTCVhxemmE1FhYrQuXk89FKg1k91t4MfJDah2HWKmqiPG0Vmu2PP3g32DhCHc8kLVHj0WnZEPhoYgj9gLFhYm6PBB36fbOcUFGpFl5esVhYBvDx0rrZDqE8kb+OoJPNm1UGzA+VE8wCd8mZkBdPu9Zko95PaF7Mpq7XHqJ6eXtcyttkKME87ORZ+NhxBAGE66PKSfZobHh5dWVp4kdD5DzmAy3OsauFboN6jD5Z/sAXYeCkPz/JBg/zkidRU6UV4+bYXRPsUtZo67CqI+PtDFWGRdYiZHtXSOXGz1pYXwX5/HcdxtIaV27vf+Gb+tLUZjEgtuhmju0Sl8Mxz3czs7iLBCGPr6YxYhn4veMOQbepDDSojADW4uT3M0qPEZcOPehhFGre8ikF9pLw7beXmZxyqNGsowYVrbpmhA9+n8KBw3Ww9alSNzAUeTlI1LBDIPdjYU8DZRZj8ibAtVI911DAIOQDE/qr565p8NQHswoY/4XUTBwARHohhyNTRYOY+9u/sZx9ZrrQWOr7wxpR5MIKsu1uhk98FxA/3TKv2mOAET8jp/s91GgyUy7gGUAIFY1aVS2DpFJxb83Qh+Wsgrt6X1KcXFJ8edI/Jo06Nb9DPmCAlzdhwm6QgzwGr8U4RgZs5sAMjf7rTAhpioB6H2Z5JgWnQ+hv6sOraf4mPJj7hssYxSOGv9HE1CdDyxM4I8gQMukLL4aQHMH+BXkmyCo2LH2W0N4ydyvrPnXXR5qgIMTNqsnhA457E8tPdkB2U+KAkD3Xw6CdNlRclGk0QUXYoLHon6Vq5gjZ0FHS9eFV+06mLJistk4WwtcoQsbSanXkOvTQr07dRrLwHILO4CSvGVHTVM47XpKY7qpGr79osqskxb4p2PNkWYlTuJu7k7Ev1Tyo0E6hZeKdZaiNoELuGnYdY48PMWgfYTeFL0AW+lk27YEoQxC1ut0f+NjYRSU53rf2KCUKVJnRGRoxzORVdPIvBB4RbEDl01ij7dEldp27iXVMbrNdjoXOmc+d7NUdjMAX/cDzKNRKjyTY5QlSJKS2RAPF3clxrYQOR+foEqyo0t4AMl6tUBuqWNRO6flUlo01cWAvxDvqsWP/HPMfb2BLy9ezYAi2uU3ikYNK6R8UfHW0h1MK2HfWU7dd6VIYauw0/jSTOwkE2BY7SLzLIBoLcKf/VjA2hiJVKqy++OahMMM0iLFDO8EQ9N02MrpPp1b4rejdtitvurevyO1ePbKkQx59Wiq3ta/+slCoIbF5XiPJm9PUadVmUCv+ZrLLGtUGAou2LDza1ajxI1fc1BmFXKEUcHWqdRKIq6tytBfITwVA3AJXtIND4RFqAAvg0SrZyHv6SFlhJCNM50HFRvcRVrUpk9xTpN4b2d1FlYUQkbwezbeQsu+/RWpbDFnwFIxh1P+WxHOZoltGy3WrbFHe9WJiirGCe39xpauk/4+y+ZPMbJ8rX2oOgg4rUczAnmX0o5M0VcCk3JDEe6cAy0Ka7L1t4i+Q2SsQj2v8CN0Q23YQ68eUNLHSkTBrs4jIJB3jjpaekl45CuYp5mQ0vfc0Yk8GJieZGP1pFhrjgI+I7QT0JD3zyqqQK9lOsZnmGRfLoKVJipduSYcTjrM/oJnYQ6hgoKg/B6rCBGXTjLf0n1XSZljbTmfFcbLXYsesLTGSzh/kHuwht/6YA56cLLiA/eolmHsG0ztFY+PPTMHm55yMTJjc6TAIJch4v7myheneiwf1Nloh6jhbNtJ/99O08YArksGIJELC4d1mtz99T28M2sfQrUzq/rlfuC+Mi8BiSRM8ANXkHlcBiprepAYrWBMsjf84b+UTSZyn2dIl19OPm7RyzyaITxA444RJ1FlZN1CNywnd8p5YUKZCCDx/AUH6uLKqZ6VG5ndwinV1Y/YH/tCkZLFYG4w97kFU4t/qZKwv/E9mpPtzZb/jury9UZm9Do3MCNgIfdggK4rH7Bpu3ZfiuGqzrjW/L3kvZZrpl935ey8OeoN01b+/08p4R2zoO2LhuiiChkssx1maPX6oQyw1L+gj9Bst1kyzF0KKultr4UELtNB1bW1Xx+H8FEKu0vGginTvCZBn7yrwAgu8tGq1097oLx7qcFoiJK69WZQWHqhc2JW+rbpsR+zAONla4SYxC61rp4k4O6FOQvXi9Ho7UfadrRxFOERFeYuvZrdH6iWgoSu1AHgWA7AiCrzCeSd07us2lWeGzFi9CGCyOa3UJamMT3hWPoSzFfGJKLFQSJoog1Lf/mwRZisXK/bRzZFTdKZbuF5iu1MwHCBZAnzzpM0VnwlYEQKNomuUz6Fyp7JmMAFZ9jXRe7tMXB5ooS8u0MG1w0zlUacP0rwADi1K/ye/EE/kobMW2Bwx8u7I3RgHXPWnSNuSiPxyfAaCzZ/4MVkP5UosZfYJuAzto9OdMBE9bD3v/zqITxrkn0ca85/IEyKGEf//6skZmG75hUGK8LaXUzPMbnQr1QAMml8yUtsxKs9wXV4davadsfsGDocg11vddD5qWsM5kL1Ggeic6LjZ0bjNpvbhgIEtZfjYDZnCDBsZYBB3cO6JiGfloHY9jB47Xsnce6V+y9ObUTqN/bv5LjaSOzZHAO57UGj+gaE8DOiB8NafdP4Qak9XJzOneLiHzr9TbmBS1lu4ZSevHxhJcxFuPTw4FG62Rme49cWZghhg2uheDyxeDlIdURPNbw+8EOlnJEfairN6mU3yDdqUHCi730yCTMUtIEFCQlOsG+UglaYsBlFL54cw/H9wTL3hMc3pOBNTaXGQpfjhh5++niYybFzF4MYb5dPUHhs5cr4W48fbG0YBO8KzHr+LA17KHdZxYMTAAUpcIp1VnAxgo31955bEsLblDFuBy5dlIEDsrWBpK464x+XXAKVkwXRr/6wHYa71OvfyxCA1GDVeOMppgCM+SdSSV+Z4ZOovufzwbrFiK3sBdeld88AOcgwYxb7qpz7mhGS+zB64o5jXBTZSyA0MDXdYQvBoDLJ20qMaLfoJFEqWGz2rC81rxT/bY7gBgPtFqMlpyIMYi4u3Yf1172FNN4/W/xvmZprZO3IbwFq9PQMoJbQXQrwxVYYZwvWGXERPk2Uhlz9gRWmzNaVqkp7mubKLzLAUJ6lcuebTvMqkcxJJymwmZtTUr5Gxvd/HWyOx2AAfyO55mL93wAKh7ARoMajGsPnAMsEfBuYIWIdlP2J4tFsRWmhppa6AQ0cfFbM4a8+RPS2EsWikEK0LhB4GwUWRPGqjgRduFXpKdIIclPO1V8FWUIErCbCAPvTG621JcUfAF9zBHAyEDUplreZZ7sJWMytQpAAkQo1oYHokzkMAkASVnsb09gWQHFj9DRXBQN7QHdbarq61G9+bdIH7RjBlmBo2PkcAwx6UQB2Gs+3fjaO2CxPFOSFo3qLw54OIXVcwaQOoFyZksQpx38MAMv8LX68Pl6brrz7OlB1oNcsJNDiE7+FeHZ/8/I0oZAAAARVhJRlYAAABNTQAqAAAACAABh2kABAAAAAEAAAAaAAAAAAADkoYABwAAABIAAABEoAIABAAAAAEAAAGaoAMABAAAAAEAAAEUAAAAAEFTQ0lJAAAAU2NyZWVuc2hvdFhNUCDAAQAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpleGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyI+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4yNzY8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+NDEwPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6VXNlckNvbW1lbnQ+U2NyZWVuc2hvdDwvZXhpZjpVc2VyQ29tbWVudD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cg==" width="410" height="276" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-a-bundle">What is a "bundle"?<a href="#what-is-a-bundle" class="hash-link" aria-label="Direct link to What is a "bundle"?" title="Direct link to What is a "bundle"?"></a></h2><p>Your frontend application needs a bunch of JS files to run. These files can be in the format of internal dependency like the JS files you have written yourself. But they can also be external dependencies you use to build your application.</p><p>JS bundling is an optimization technique to reduce the number of server requests for JavaScript files. Bundling accomplishes this by merging multiple JA files together into one file to reduce the number of page requests.</p><p><img loading="lazy" alt="Bundle Everywhere" src="/assets/images/bundle_everywhere-12122e37ab5ca6bcdd61061c4dc32fd4.webp" width="448" height="245" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="performance-implications">Performance implications<a href="#performance-implications" class="hash-link" aria-label="Direct link to Performance implications" title="Direct link to Performance implications"></a></h2><ul><li><strong>Time to transmit over the network</strong>: considering slow connections with some mobile devices, it's possible that your page will not be interactive until it loads.-> More bytes = longer download times</li><li><strong>JS parse and compile time</strong>: more code you load, more the browser must parse.-> JS gets parsed and compiled on the main thread, when the main thread is busy, the page can't respond to user input</li><li><strong>JS execution time</strong>: optimally you will only pack the code that you expect to execute. The more code you want to execute the longer it will take. It's possible that your page won't be interactive until some of this completes.-> JS is also executed on the main thread, if your page runs a lot of code before it's really needed, that also delays your Time to Interactive</li><li><strong>Memory consumption</strong>: everything fills up the space -> code itself, runtime variables, DOM elements created, etc.-> Pages appear slow when it consumes a lot of memory. Memory leaks can cause your page to freeze up completely!!</li></ul><h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-the-recommended-bundle-size">What is the recommended bundle size?<a href="#what-is-the-recommended-bundle-size" class="hash-link" aria-label="Direct link to What is the recommended bundle size?" title="Direct link to What is the recommended bundle size?"></a></h2><p>AS SMALL AS POSSIBLE! I experienced that is not really possible to give a precise answer because each application is different. Generally you want the resources on initial load to be as small as possible, so that you decrease the initial load time, and then load more resources as needed on the fly.</p><p><img loading="lazy" alt="Mr Chao" src="data:image/webp;base64,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" width="406" height="250" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-do-we-do-then">What do we do then?<a href="#what-do-we-do-then" class="hash-link" aria-label="Direct link to What do we do then?" title="Direct link to What do we do then?"></a></h2><p><img loading="lazy" alt="Meh" src="/assets/images/meh-3b42aead7d2246467fd0101518403734.webp" width="539" height="399" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-to-start-decreasing-the-bundle-size">How to start decreasing the bundle size?<a href="#how-to-start-decreasing-the-bundle-size" class="hash-link" aria-label="Direct link to How to start decreasing the bundle size?" title="Direct link to How to start decreasing the bundle size?"></a></h2><ul><li><strong>Measure</strong>: first of all you want to measure. The first step is to use Lighthouse and try to understand the results. It will give you a couple of interesting metrics and some tips. Time to interactive (TTI) is a good reflection of your bundle size because your bundle needs to be evaluated entirely before a user can interact with your web app.</li><li><strong>Analyze</strong>: Consists on analyzing the bundle in order to detect critical chunks. A useful tool is Webpack Bundle Analyzer.</li></ul><p><img loading="lazy" alt="Stonks" src="data:image/webp;base64,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" width="309" height="229" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="breaking-up-the-bundle">Breaking up the bundle...<a href="#breaking-up-the-bundle" class="hash-link" aria-label="Direct link to Breaking up the bundle..." title="Direct link to Breaking up the bundle..."></a></h2><ul><li><strong>Monitor network requests</strong>: These happens between our FCP and TTI. As the initial request for data often occurs when our components initially mount.</li><li><strong>Reduce the total dom nodes</strong>: the less the page needs to render, the less time it takes.</li><li><strong>Moving work off the main thread</strong>: By moving heavy computations to a web worker, the computation will be run on a separate thread, and not block the actual rendering of the page</li><li><strong>Caching</strong>: Even if not useful for users on first page landing, caching data, bundles, and assets can make subsequent visits way fast</li></ul><p><img loading="lazy" alt="Breaking Bad" src="data:image/webp;base64,UklGRu4UAABXRUJQVlA4WAoAAAAsAAAAKgEA5QAASUNDUBQCAAAAAAIUYXBwbAQAAABtbnRyUkdCIFhZWiAH5gADABEACAAyADdhY3NwQVBQTAAAAABBUFBMAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGycI4tw2obgutNn6fT9ab4VAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApkZXNjAAAA/AAAAGVjcHJ0AAABZAAAACN3dHB0AAABiAAAABRyWFlaAAABnAAAABRnWFlaAAABsAAAABRiWFlaAAABxAAAABRyVFJDAAAB2AAAABBjaGFkAAAB6AAAACxiVFJDAAAB2AAAABBnVFJDAAAB2AAAABBkZXNjAAAAAAAAAAtST0cgUEcyNDhRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIEluYy4sIDIwMjIAAFhZWiAAAAAAAADzUgABAAAAARa+WFlaIAAAAAAAAG+kAAA49gAAA5FYWVogAAAAAAAAYpQAALeGAAAY2lhZWiAAAAAAAAAkngAAD4QAALbCcGFyYQAAAAAAAAAAAAH2BHNmMzIAAAAAAAEMPwAABd3///MoAAAHkQAA/ZH///uj///9owAAA9sAAMB5VlA4II4QAADQXQCdASorAeYAPpFCnUolpymhppRq0TASCWVuvmuw79keW/jednnzCQ/RvwepvytelDzpunodFr6yV/HdabprfdChx8p/BX73/AelXhL8edQj8n/nX+z/LHjIgB/l/9k8AbVN8I+wFwx1AbxeNKP1x7C5RlQHbXX/SmLxg06O4ESVNMvFPll/jDjWw+ePOaso3Z/rv8wUwX0sS+8NcGQzbTICuUaT8rpjVX2cE6IpxLvORxOqA5Bs60gIcifRZ2w5Up/m/HMWQSgHbVtQkLDuwzQDd+Kq3sXiGZ/FT4MaxEwkPTjCkA37LFr2YEOcQVFx/BYRdF3czzTHjeGvKxLtcelUKQO/itvqoSDR1tdptNfplWnz48M+8xwWyRylqjhlq/aAaf1duB1WO3m9Rnq0EFTRBibOPSVUSP6OGrag1xnRWudnaKKfcdQstHaRdhrYlTZR7nUPBA6emSdHqF4YCG6gYnxuDupJ2BPZl/sa4t95yaCZ2iDiFXtxFDdDFaE8vlxFQInyEV7Sso5xdzNNSvGSsYMZxMe7ILpmCFSf+kBWA1IyYHzOaL1CARNtwflzHOr+JZDu1O7h/LRCzZAQpExUafNAXl5SGgU9zCy6Qi9FDvHK+DBjigbsc8K6f+kda3jFwaV1opsOzjWuOiQJYAWgayDHwWwqWEwxJZWxdMEPwupQju958GVr1qggM4mCWQIhn2QcDHDC3EBNEH87E8qfSBi7br4rbtczIHA7bJyr4ByqI3niOPou0pNW7Ev3JC4+en5UQ/AWYZWELa3LrprKZew7QPhMvwVVD4UhIwiH7eOF/zQxdS6UY5IGgPq2ENVSPHJxWxse8mDBlyglZE9Hw022n/SmLC4vKFjVfvOrKnkoSrSmjcxycepD5j6III9LNGyiAswysIWSXGRffD7kDrtNlAvoh0twuXZVHfBoCGPSGzbXFmziUS/eUm9lcj/usNSJHPcTK7mbZJsnK3843xGtHpDZxv5soY8b4B215MSzloAA/v3UMfWi1FR+yKPIyFHA4u+pqnCrIquNx3IuqtjAD5zBgNXBY63ZrxEZOmthL23ZogncuQ1aDAff2716s/baz3My4Z5tSqemGx93vipcNRmY9EAB5/UBzWonspFvm2rw7Mrz8onU9ggBI7UHI+OQbR4790sDcXCoJV0//3c4p50+aHhfM0lm8rCBIFR04J6d9xKrudb5q4+y53kPA1uds3jqDSkpBBaNQ1Et7N4F1ndBBoj6N3M5tcKqaSs0z0CLLHknEqgTohA9RSYGmvzcuo7JNVjUFzfR3ChUkbxRmtG3wB4cOjDeVJZ/QouLRly41g0COis5voBBZ9ecJ8qBSF8/zsu4urY1/40ggoLoCBLx5zneqOrAsVEz9PxGPrzZtj3b4BR0DQtMD2NX/DyRaezxOnJ4L8P59L3hNfXz87Gyv9jClZSFoSZ3jVqFz6mfVJO1f276jju4hyesrHSYXdwDEVzrvfsh30YkebkEynaB/W+X68OLT3s/76gODEvVDGupn+ACUmrB1qJ90TXJh8vr5RcYPCZjmiSFECy65++GLCyBvlkmnPNGfFmEcRiB4DtOq7Uz83tXFKF+SulchLz4QzY/m6K4xlV/697103TcBzR5j28nW82VN6LuyaKDYBIN+lejFUvD6DNPNTtQO4v+lLvulaCranlodvzoVqN85u+K0yAgBGo1X1rgYQ8Mant2UCMDCs+EzTmiorGO8s/JpR07QGudgcmnpsrzwFdX4C0ZJPQu4Zy1WGUNlIddShumGxdE96njZS25EUPA7I+TDBVO47uV+qYbcqBWQz5AucWvfMI6hOVizCp0nn8v7ft6hCaQwh59J9mNSOcZ3Z6nrLH3kSQ0JdOnsjDIRUTEh1KfcdOuagL3TrjoUTakOCzxAXIMT13q9Q0TZ4qNXYlCaVGFe2X4og7ZJ0ejgZWEOut6XfFTmp4MXsOL01gsFORtxUddDqI/1Uw7ic7kuOG8G2tK0/F/TvKo5P595jZYXFXnswhHht44rVhVBdzrup58GWUWVxN2gRNbX3v4WzfRak+gt5EQHyPJKKHwgECt4xwfUEIzc5Lw5VGAl1mCDJJd6WDNlXpm+wFZ+xmmBuKfMamh3hFEgylOS5dmBtrtP05pL0Kc6N52vAXo+ZYnF3Pm5SPLqc8e+Kd2INxc0b9zrepdlCCOV598yeZOB4UHEAngMXKklioIBpdi8EdOphElnoVG6DUWnU0xzC5wu2/UHVw6bWt+vZPtY/ZDi34uq3T8vPExfmTt0m5Dc5R1Wdq1rbjZWo4g79iQvx64BIafu43nrulz9Gl78khsFdGy0aAP4XR8eJFHNvTIOvI4N/8Xyoe6kVarpLlnDC1pJSOWPk8HWRiK4m7wW5uS+6d1MOzsRTCjrXJrGvGsJ8UDE66ldjEASuaurRVKk4Um7nuOZp63GKERvFq0yTUijW2HC3zeX1nXXVIKF+DNuMPYiuj5gPnzW6iat/c1YZhJ4+7WYE0pKUQdpKpZe/z1tjvNlqonMr2BihCe5vGu9+P/E03au3S7gaik7coH0JQSloY2wv9oszKysaW5AgERKpD4prsrl/5l2dd7AMCyS1m4Mo17waPqtb03Rqjcoen0i0a/nhzyGFa2eaEDEVSHqbOzbZVFRYRFeGAdCvEVRFvuUqUEvQVYfw83LI3rks1pqkaYFgY8lHg2Vcpe693D2vIYt/gXxoZBh1EFDxeyJ/yhLCfWO5J6F0xxLm27VZPQDPpBbiIR/mcWzjGAC4nTQ4ymcilb/siMz6NRazz3tHuCJxktvdLBgfPGJjd3LRFy/gc262zXk0B64KNuE7wq44C2PXdqrceIq3m+u3VCD2EYJ44Wf61FfwNOrfkDkdmmgvRinnvlXvjLI+PAL3GJB5fhJaUaud+ijqq9bRyv8PgYff1UupN5FFjLzB2pqh0z5RyeC8Nz3UUvpY1xJr1GnvD1PYocvzeOljhjo+A0oplWrpGSnf+5zKgYY8hGmt1eJHqdgSXh2vidqdO8ZEEeBvT0FX7jr6JMroyI4aar2X2wWk0oQ4oHE4uAPShC69u4Lq7K+d/h69eEXob7Zv89DEVNISHb0rAI3bO8zMWQgJdhr0DJQVcXYalie0aWIEqGHMgZAq6BGpjUJzk4oSSB3A9Hb4Ckd90u51CVjtb5m920knNodVSpBmJt9d98HRjduTv/gCibNWOdEJptBdmMca4usEf2SbSnefhMSnXscI/85hKdw9uU6z5/YLboLZfPkndObMKrppPIegKB0Fa/fsgXVrdppTB+NsUN0ZYoeT4E22Z0/T5N+p6SAP0Sw9zV5vVHBVyCznaQhMQcYVScbiGa4gyPx+cZ6gBLcbxS2kmt6QNJZC+F05T/NqGd/JapdhVARpTLD8jrvJK3i+18E9VW0ROcXTg2TR/fF1lKVyqzT1xK011piRnyNkZu8Ik8Dwlmi9iCX4e4OkXhu7cYWzAwxyJcj/BJoE0hVq6Vn46Jtjdf0t40HuZVJK0lVBrLMKzyQqkMvrIuf7c0a1aW6jmMs7fTFYeb50hY+YLJxtwP+1Fabh0/siNDqqYy1NI9NYim77DItRhH9v29nTruX4bB/nfnUed4is//efWaWYrTvZ9QvH//e4B5X5n4irLeS8D5fH729bqhuF0w+M/sh04QNfBNohtiE1uWl+Vf/8BaeL+7VCO4D6K0XEbO9K+0x9/Udh49sHR20964G0Wsg2OI5FQ+tpZaUJLF60RpAIbVMk0Xz+WcpU5L+G0q5ONuro3aNc40DnAU1IiS5f8r2I94aql0PQx/VjGP70JgQLocs1O12pIiITbSgA6WkYnCSH/OlEngrgOOGcQxnC71IAZj0BC7iJg+gMxQerK75QWSbDNU0FLzNZKHUVR+Z7+mXlbHDYf5HE3mnk1qfaJueSQEE7DGdgIl+0KQmGSAGd2gv4meXJl4nmTUMKVnmOzdqXNFJKeU8RkQaYRJRvQ5cXBR6inLPaNxOV77qvqTavkU5MjqkvRkAqlwt4iSSdX2xq7fRswgFcB3W8vuey8KISQSWSibx5B6YKyp5RI2qta5pls7xcmfecwHn4psnQmWER49PdW0WxB0rDRJwD8Qs87HLj3IEJnvZNlQ+1PIwKC2VYqBwrYzfgBies31Zs6PKDqLmreEAoVzjDsEwle8jEsXc8m1yEYAy//K7YzelD/5SfC3D/H56iMGRquiVtierxvzEvPUlcC1kOoQS6+qjX3PblNbnXi2zwUKoIu/L9znOdKXJAm0yJ00d3UyXPBImYtSGKwrNII406/umb0KoWDmG5ODoUAr/CkcizwyYf83gzcYUgzuWrhRuBY93Z7t6iDdnAvpC/xgigttxO3BIcTN9W8/s70oWYjWWzgeA6hUVptA7jokfcpFQeHXkJR8CYPjV+Co46nwnzsqODjH8tw2DdDxUGAgSqeX1CEp1yTg0uH4TuCOSW4zhWRdZyB7mTuUTh4F+JfLXj54MF/v4fjZg//80gD8oEu0REk7HsThE/S7mue1cuP54b84vx1csk+5yfEcDngMHqrO7ddclsdwpJ3nFupX3j+kTq4SNiterjOeFZLEGJAh+uqdmJkeDvJZYLLEkoZ4lAuMqZzEJgGGAiEHW9XOdoOLJ66oL7pkj9KSUU4qq4vhhuYuuJVgEnNXmwW/s9r1BqNSmt86vX/m2JaCHo7+AjoAtS+5nFGHc7Atift+PBl38z3pE30SAhxjqBW48jYb5rACVwpOKAElxIRjf1EhZF3oCFHxOzmaFp6Lo5B/+I1AOOoFrA6qAThfOmdxBYfTcNPfCgHAYt/eV708nR9J2JCucQqis52buSvcfgiIjPduJusdznnuuSMAASTJHTr7/bqkS5WicvEifcKV4hqy5Y0XguVLBWnxZGs0UCj1Z4mylwHA6MdpTK3DUGvUTog9FlgccHU94QZI/GnHSJl5+PNow2IOY4qNiPkWlimh7fPAVkpVio7j1t3b5brdieRPrFu63uTWC6fgIdVupQabPLFO18+fSp0sRlfNUnW/cPXXiNqpLWJdnUY/MvxaPdhDkeF/rYQv06teV5PLfe+mvNz89DbhzHuNHKr1XpEtf3A24e62TiO/Gue4AVSoLoFq1sqDVR7Rp5tQUXJxl0WpAcynjD0xHJqygM98yfdCcTIj0GjqKnqAEdDwO0PH7lamPzxIh6UgP5KwXy/eWqL6IQ8mjH3+naKas9Ygctj+D+EsAtpm6jyJYaB/q210PZq/I7eBrEGKsu4NbxifpZBRvM3qaOf6sU1gIJQ3uPSBi/imyh8H+FR7YJAIerUmCmG2gkixQ58pD35x4D2eEkX0ST6s9K0BdBhy6aBYTyfzVL/sqwPmPl98JKRFDILRL0MTL5Fs8e4yWwKD6GCeimsjBn8UtXDiDG/yJ7UX334fw3A5aBBdJgvEhNkPgW751zz/UQV8pGMnECYjUbaX1am/9wAS9ZW9/ug6gwAj0KIqDTGioCAbBO2EKDdZC9ij2ekoHO7Aoc0ijUmdjCs4u8JAC30uO9MhQd3Rnilz5l3Wm0wijXEKrLoFY+en5A8evExFVM5zF3zPJN6yutmlXL1BJBhelXYIz64i2g7cvoiXrAAtPEVcDpqAZzAAAAAAAEVYSUZWAAAATU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA5KGAAcAAAASAAAARKACAAQAAAABAAABK6ADAAQAAAABAAAA5gAAAABBU0NJSQAAAFNjcmVlbnNob3RYTVAgwAEAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MjMwPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjI5OTwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlVzZXJDb21tZW50PlNjcmVlbnNob3Q8L2V4aWY6VXNlckNvbW1lbnQ+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo=" width="299" height="230" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="which-strategies-can-we-adopt">Which strategies can we adopt?<a href="#which-strategies-can-we-adopt" class="hash-link" aria-label="Direct link to Which strategies can we adopt?" title="Direct link to Which strategies can we adopt?"></a></h2><ul><li><strong>Minification and Dead Code Elimination</strong>: These processes are often summed up as minifying or uglifying.</li><li><strong>Tree shaking</strong>: Tree shaking is dead code elimination on a project or library. Always try to use deps which support “tree shaking”, Bundlephobia could be your friend in this case.</li><li><strong>Code Splitting and Lazy Loading</strong>: Code splitting consists on taking a collection of modules and remove them from the main JS bundle. Lazy loading means we can load this newly created bundle later on.</li><li><strong>Replace/rewrite large dependencies</strong>: Consider replacing or rewriting libraries that are large in size where you might not need all of its functionalities (Moment.js for example).</li><li><strong>Feature module import</strong>: Check to see if you are using only a feature module of the library that can be imported alone without importing the whole library (Lodash for example).</li></ul><p><img loading="lazy" alt="Strategy" src="data:image/webp;base64,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" width="307" height="204" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="useful-tools-to-help-you-reducing-bundle-size">Useful tools to help you reducing bundle size<a href="#useful-tools-to-help-you-reducing-bundle-size" class="hash-link" aria-label="Direct link to Useful tools to help you reducing bundle size" title="Direct link to Useful tools to help you reducing bundle size"></a></h2><ul><li><strong>Lighthouse</strong>: automated tool for improving the performance, quality, and correctness of your web apps</li><li><strong>Bundlephobia</strong>: Bundlephobia helps you find the performance impact of npm packages</li><li><strong>Webpack Bundle Analyzer</strong>: analyzes your bundle</li><li><strong>VS Code</strong>: Import Cost plugin -> Display import/require package size in the editor</li></ul><p><img loading="lazy" alt="Tools" src="/assets/images/tools-91886b41cefeef7cc35b5cd21c43d2ba.webp" width="345" height="255" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion"></a></h2><p>Performance cannot be stripped down to a single metric such as bundle size. It would be great!
|
||
Unfortunately there is no single place to measure all of them.I think metrics like the Core Web Vitals and a general look at bundle size should be considered as a starting point.
|
||
You will cry... A lot... But don’t give up!</p><p><img loading="lazy" alt="The End" src="data:image/webp;base64,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" width="358" height="260" class="img_ev3q"></p></div><footer class="row docusaurus-mt-lg"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/javascript">javascript</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/bundle">bundle</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/bundle-size">bundle size</a></li></ul></div></footer></article><article class="margin-bottom--xl" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting"><header><h2 class="title_f1Hy" itemprop="headline"><a itemprop="url" href="/blog/prometheus-cardinality-issues">Prometheus Is Out Of Memory. Again.</a></h2><div class="container_mt6G margin-vert--md"><time datetime="2022-01-25T00:00:00.000Z" itemprop="datePublished">January 25, 2022</time></div><div class="margin-top--md margin-bottom--sm row"><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/smartinov" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/smartinov.png" alt="Stefan Martinov"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/smartinov" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Stefan Martinov</span></a></div><small class="avatar__subtitle" itemprop="description">Memelord</small></div></div></div></div></header><div class="markdown" itemprop="articleBody"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-annoyance">The Annoyance<a href="#the-annoyance" class="hash-link" aria-label="Direct link to The Annoyance" title="Direct link to The Annoyance"></a></h2><p>So, we've all been there. You go to your trusty grafana, search for some sweet metrics that you implemented and WHAM!
|
||
Prometheus returns us a 503, a trusty way of saying I'm not ready, and I'm probably going to die soon.
|
||
And since we're running in kubernetes I'm going to die soon, again and again.
|
||
And you're getting reports from your colleagues that prometheus is not responding.
|
||
And you can't ignore them anymore.</p><p><img loading="lazy" alt="Bummer." src="/assets/images/bummer-e80d471cba23d1ee83e8463187845893.webp" width="480" height="270" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-problem">The Problem<a href="#the-problem" class="hash-link" aria-label="Direct link to The Problem" title="Direct link to The Problem"></a></h2><p>All right, lets check what's happening to the little guy.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">kubectl get pods -n monitoring</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">prometheus-prometheus-kube-prometheus-prometheus-0 </span><span class="token number" style="color:rgb(247, 140, 108)">1</span><span class="token plain">/2 Running </span><span class="token number" style="color:rgb(247, 140, 108)">4</span><span class="token plain"> 5m</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>It seems like it's stuck in the running state, where the container is not yet ready.
|
||
Let's describe the deployment, to check out what's happening.</p><div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token key atrule">State</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Running │</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token key atrule">Started</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Wed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> 12 Jan 2022 15</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">12</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">49 +0100 │</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token key atrule">Last State</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Terminated │</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token key atrule">Reason</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> OOMKilled │</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token key atrule">Exit Code</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> 137 │</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token key atrule">Started</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Tue</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> 11 Jan 2022 17</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">14</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">41 +0100 │</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token key atrule">Finished</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain"> Wed</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> 12 Jan 2022 15</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">12</span><span class="token punctuation" style="color:rgb(199, 146, 234)">:</span><span class="token plain">47 +0100 │</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>So we see that the prometheus is in a running state waiting for the readiness probe to trigger, probably working on recovering from Write Ahead Log (WAL).
|
||
This could be an issue where prometheus is recovering from an error, or a restart and does not have enough memory to write everything in the WAL.
|
||
We could be running into an issue where we set the request/limits memory lower than the prometheus requires, and the kube scheduler keeps killing prometheus for wanting more memory.</p><p>For this case, we could give it more memory to work to see if it recovers. We should also analyze why the prometheus WAL is getting clogged up.</p><p>In essence, we want to check what has changed so that we suddenly have a high memory spike in our sweet, sweet environment.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-source">The Source<a href="#the-source" class="hash-link" aria-label="Direct link to The Source" title="Direct link to The Source"></a></h2><p><img loading="lazy" alt="Cardinality" src="/assets/images/cardinality-5f722655c50c25a6a91c53884ad19677.webp" width="501" height="500" class="img_ev3q"></p><p>A lot of prometheus issues revolve around cardinality.
|
||
Memory spikes that break your deployment? Cardinality.
|
||
Prometheus dragging its feet like it's Monday after the log4j (the second one ofc) zero day security breach? Cardinality.
|
||
Not getting that raise since you worked hard the past 16 years without wavering? You bet your ass it's cardinality.
|
||
So, as you can see much of life's problems can be accredited to cardinality.</p><p>In short cardinality of your metrics is the combination of all label values per metric.
|
||
For example, if our metric <code>http_request_total</code> had a label response code, and let's say we support 8 status codes, our cardinality starts off at 8.
|
||
For good measure we want to record the HTTP verb for the request. We support <code>GET POST PUT HEAD</code> which would put the cardinality to 4<!-- -->*<!-- -->8=<strong>32</strong>.
|
||
Now, if someone adds a URL to the metric label (<strong>!!VERY BAD IDEA!!</strong>, but bare with me now) and we have 2 active pages, we'd have a cardinality of 2<!-- -->*<!-- -->4<!-- -->*<!-- -->8=<strong>64</strong>.
|
||
But, imagine someone starts scraping your website for potential vulnerabilities. Imagine all the URLs that will appear, most likely only once.</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">mywebsite.com/admin.php</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">mywebsite.com/wp/admin.php</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">mywebsite.com/?utm_source=GUID</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This would blow up our cardinality to kingdom come. Like you will be out of memory faster than "<a href="https://www.reddit.com/r/ProgrammerHumor/comments/a483yz/those_javascript_devs/" target="_blank" rel="noopener noreferrer">a new super awesome Javascript gamechanger framework</a>" is born.
|
||
Or to quote user <a href="https://www.reddit.com/user/naveen17797/" target="_blank" rel="noopener noreferrer">naveen17797</a> <em>Scientists predict the number of js frameworks may exceed human population by 2020,at that point of time random string generators will be used to name those frameworks.</em></p><p>The point to this story is, be very mindful of how you use labels and cardinality in prometheus, since that will indeed have great impact on your prometheus performance.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-solution">The Solution<a href="#the-solution" class="hash-link" aria-label="Direct link to The Solution" title="Direct link to The Solution"></a></h2><p>Since this has never happened to me (never-ever) I found the following solution to be handy.
|
||
Since we can't get prometheus up and running to utilize PromQL to detect the potential issues, we have to find another way to detect high cardinality.
|
||
Therefore, we might want to get our hands dirty with some <code>kubectl exec -it -n monitoring pods/prometheus-prometheus-kube-prometheus-prometheus-0 -- sh</code>, and run the prometheus <code>tsdb</code> analysis too.</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">/prometheus $ promtool tsdb analyze </span><span class="token builtin class-name" style="color:rgb(255, 203, 107)">.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Which produced the result.</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">> Block ID: 01FT8E8YY4THHZ2S7C3G04GJMG</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">> Duration: 1h59m59.997s</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">> Series: 564171</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">> Label names: 285</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">> Postings (unique label pairs): 21139</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">> Postings entries (total label pairs): 6423664</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">> ...</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">> Highest cardinality metric names:</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">> 11340 haproxy_server_http_responses_total</span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain">> ...</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>We see the potential issue here, where the <code>haproxy_server_http_responses_total</code> metric is having a super-high cardinality which is growing.
|
||
We need to deal with it, so that our prometheus instance can breathe again. In this particular case, the solution was updating the haproxy.</p><p>... or burn it, up to you.</p><p><img loading="lazy" alt="Flame Thrower" src="/assets/images/flame-thrower-56bcf89132356ff53c03ca029d9d0746.webp" width="1440" height="1080" class="img_ev3q"></p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-further-reading">The Further Reading<a href="#the-further-reading" class="hash-link" aria-label="Direct link to The Further Reading" title="Direct link to The Further Reading"></a></h2><ol><li><a href="https://github.com/prometheus/prometheus/blob/main/tsdb/docs/format/wal.md" target="_blank" rel="noopener noreferrer">WAL Definition</a></li><li><a href="https://ganeshvernekar.com/blog/prometheus-tsdb-wal-and-checkpoint/" target="_blank" rel="noopener noreferrer">WAL & Checkpoints</a></li><li><a href="https://www.robustperception.io/using-tsdb-analyze-to-investigate-churn-and-cardinality" target="_blank" rel="noopener noreferrer">Using TSDB</a></li><li><a href="https://www.robustperception.io/which-are-my-biggest-metrics" target="_blank" rel="noopener noreferrer">Biggest Metrics</a></li><li><a href="https://www.robustperception.io/cardinality-is-key" target="_blank" rel="noopener noreferrer">Cardinality</a></li></ol></div><footer class="row docusaurus-mt-lg"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/prometheus">prometheus</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/cardinality">cardinality</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/devops">devops</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/ops">ops</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/k-8-s">k8s</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/oom">oom</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/memory">memory</a></li></ul></div></footer></article><article class="margin-bottom--xl" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting"><header><h2 class="title_f1Hy" itemprop="headline"><a itemprop="url" href="/blog/searching-for-search-engines">The never ending search a search engine 2022-01 edition</a></h2><div class="container_mt6G margin-vert--md"><time datetime="2022-01-20T00:00:00.000Z" itemprop="datePublished">January 20, 2022</time></div><div class="margin-top--md margin-bottom--sm row"><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/janhalfar" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/janhalfar.png" alt="Jan Halfar"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/janhalfar" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Jan Halfar</span></a></div><small class="avatar__subtitle" itemprop="description">foomo maintainer</small></div></div></div></div></header><div class="markdown" itemprop="articleBody"><p>While building this website and integrating <a href="https://docsearch.algolia.com" target="_blank" rel="noopener noreferrer">https://docsearch.algolia.com</a> and evaluating another solution by a large company in parallel I could not help to search github and the web for the current state of search engines and search related services.</p><p>Since I had done the same thing about a year ago, I was surprised to see how quickly things are moving atm.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="algolia">Algolia<a href="#algolia" class="hash-link" aria-label="Direct link to Algolia" title="Direct link to Algolia"></a></h2><p>I was blown away by the quality of <a href="https://www.algolia.com" target="_blank" rel="noopener noreferrer">https://www.algolia.com</a> and I wish it was open source, but I guess, we all have to make a living ;)</p><p>To see how awesome a web (search) interface can be check out <a href="https://www.lacoste.com/us/#query=red%20jackets%20for%20men" target="_blank" rel="noopener noreferrer">https://www.lacoste.com/us/#query=red%20jackets%20for%20men</a> </p><p>Apart from that the UI/UX of their backend tools is fantastic.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="elastic">Elastic<a href="#elastic" class="hash-link" aria-label="Direct link to Elastic" title="Direct link to Elastic"></a></h2><p>When it comes to <a href="https://www.elastic.com" target="_blank" rel="noopener noreferrer">https://www.elastic.com</a> I am a bit nervous about the future of the licensing, despite the fact, that I understand their motivation. At the same time the <a href="https://opensearch.org" target="_blank" rel="noopener noreferrer">https://opensearch.org</a> does not seem to be an ampty threat.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="typesenseorg">typesense.org<a href="#typesenseorg" class="hash-link" aria-label="Direct link to typesense.org" title="Direct link to typesense.org"></a></h2><p>I do not know, who was hiding under a rock, but I had not seen <a href="https://typesense.org" target="_blank" rel="noopener noreferrer">https://typesense.org</a> before and they certainly have a bold claim: <strong><em>"The Open Source Algolia Alternative" / "The Easier To Use ElasticSearch Alternative"</em></strong> </p><p>When looking at <a href="https://github.com/typesense/typesense/graphs/contributors" target="_blank" rel="noopener noreferrer">https://github.com/typesense/typesense/graphs/contributors</a> it seems, that Kishore Nallan has been working on this for a while. Unfourtunately I do not really see a lot of external contributions, C++ does not seem to attract a lot of contribution.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="meilisearch">MeiliSearch<a href="#meilisearch" class="hash-link" aria-label="Direct link to MeiliSearch" title="Direct link to MeiliSearch"></a></h2><p>This Rust project <a href="https://www.meilisearch.com/" target="_blank" rel="noopener noreferrer">https://www.meilisearch.com/</a> seems to be picking up speed and is definetly on the test short list. It is a fresh codebase with siginficant open source contributions and certainly will attract new developers with Rust and a modern architecture.</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="go-eco-system">Go eco system<a href="#go-eco-system" class="hash-link" aria-label="Direct link to Go eco system" title="Direct link to Go eco system"></a></h2><p>Obviously we are very interested in Go powered software and there are a few notable projects. ATM I do not see anything elastic or algolia like, that would be really mature. </p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="bleve--bluge">bleve / bluge<a href="#bleve--bluge" class="hash-link" aria-label="Direct link to bleve / bluge" title="Direct link to bleve / bluge"></a></h3><p><a href="https://github.com/mschoch" target="_blank" rel="noopener noreferrer">Marty Schoch</a> seems to be the man when it comes down to text indexing libraries in written in Go and bluge seems to be THE library, that is solid and modern, when implementing text search in your Go application.</p><p><a href="https://github.com/blevesearch/bleve" target="_blank" rel="noopener noreferrer">https://github.com/blevesearch/bleve</a>
|
||
<a href="https://github.com/blugelabs/bluge" target="_blank" rel="noopener noreferrer">https://github.com/blugelabs/bluge</a> // next iteration of bleve</p><h4 class="anchor anchorWithStickyNavbar_LWe7" id="projects-using-bluge">projects using bluge<a href="#projects-using-bluge" class="hash-link" aria-label="Direct link to projects using bluge" title="Direct link to projects using bluge"></a></h4><p>All bleeding edge afaik atm - but definitely good places to look at bluge usage</p><p><a href="https://github.com/prabhatsharma/zinc" target="_blank" rel="noopener noreferrer">https://github.com/prabhatsharma/zinc</a>
|
||
<a href="https://github.com/mosuka/phalanx" target="_blank" rel="noopener noreferrer">https://github.com/mosuka/phalanx</a></p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="look-ma-i-made-a-vector-database">Look ma I made a vector database<a href="#look-ma-i-made-a-vector-database" class="hash-link" aria-label="Direct link to Look ma I made a vector database" title="Direct link to Look ma I made a vector database"></a></h3><p>Gotta take a look at this one - will report later</p><p><a href="https://github.com/semi-technologies/weaviate" target="_blank" rel="noopener noreferrer">https://github.com/semi-technologies/weaviate</a></p></div><footer class="row docusaurus-mt-lg"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/search">search</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/search-engine">search-engine</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/backend">backend</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/go">go</a></li></ul></div></footer></article><article class="margin-bottom--xl" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting"><header><h2 class="title_f1Hy" itemprop="headline"><a itemprop="url" href="/blog/impact-of-3rd-party-scripts-on-performance">Impact of 3rd party scripts on performance</a></h2><div class="container_mt6G margin-vert--md"><time datetime="2022-01-20T00:00:00.000Z" itemprop="datePublished">January 20, 2022</time></div><div class="margin-top--md margin-bottom--sm row"><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/themre" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/themre.png" alt="Marko Trebižan"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/themre" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Marko Trebižan</span></a></div><small class="avatar__subtitle" itemprop="description">Frontend Dev</small></div></div></div></div></header><div class="markdown" itemprop="articleBody"><h2 class="anchor anchorWithStickyNavbar_LWe7" id="issue-with-performance">Issue with performance<a href="#issue-with-performance" class="hash-link" aria-label="Direct link to Issue with performance" title="Direct link to Issue with performance"></a></h2><p>When building an ecommerce site or an application where performance is a great deal for the users, you need to keep your application fast and responsive. Frontend developers have already many use-cases when the UI becomes laggy and this increases when 3rd party scripts are being included, such as Google Tag Manager or various Live chats (e.g. Intercom).</p><p>This does not only influences the users when using the site but also Lighthouse score gets lower which also influences page rankings. So the most naive and easy way for this is to defer loading of such scripts but when you need to get all the data from the start of the application, such tactic is not an option. So what else can we do?</p><h2 class="anchor anchorWithStickyNavbar_LWe7" id="partytown-to-the-rescue">Partytown to the rescue<a href="#partytown-to-the-rescue" class="hash-link" aria-label="Direct link to Partytown to the rescue" title="Direct link to Partytown to the rescue"></a></h2><p>Developers at BuilderIO created an library <a href="https://github.com/BuilderIO/partytown" target="_blank" rel="noopener noreferrer">Partytown</a> that would allow relocating resources from 3rd party scripts off the main thread.
|
||
We won't dive into specifics how it works, because they explain it nicely on their GitHub page.</p><p>In our stack we use <a href="https://nextjs.org/" target="_blank" rel="noopener noreferrer">Next.js</a> React framework and we will go through the basic steps that will allow us to include Partytown for Google Tag Manager.</p><h3 class="anchor anchorWithStickyNavbar_LWe7" id="setup">Setup<a href="#setup" class="hash-link" aria-label="Direct link to Setup" title="Direct link to Setup"></a></h3><p>Partytown script needs to be located inside our application and live on the same domain. Since we're using monorepo structure, we need to copy this script across all our frontend application. For that we used CopyPlugin webpack plugin in our Next.js config file:</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token plain">config</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token property-access">plugins</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">push</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token keyword" style="font-style:italic">new</span><span class="token plain"> </span><span class="token class-name" style="color:rgb(255, 203, 107)">CopyPlugin</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token literal-property property">patterns</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// we copy script from node_modules partytown package to `~partytown` folder in our package that serves static files</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token keyword module" style="font-style:italic">from</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">join</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">path</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">dirname</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token plain">require</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">resolve</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token string" style="color:rgb(195, 232, 141)">'@builder.io/partytown'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'lib'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// paths for SSR and client side rendering differ</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token literal-property property">to</span><span class="token operator" style="color:rgb(137, 221, 255)">:</span><span class="token plain"> path</span><span class="token punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token method function property-access" style="color:rgb(130, 170, 255)">join</span><span class="token punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token template-string interpolation">isServer </span><span class="token template-string interpolation operator" style="color:rgb(137, 221, 255)">?</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation string" style="color:rgb(195, 232, 141)">'..'</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation operator" style="color:rgb(137, 221, 255)">:</span><span class="token template-string interpolation"> </span><span class="token template-string interpolation string" style="color:rgb(195, 232, 141)">'.'</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string string" style="color:rgb(195, 232, 141)">/static/assets/</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"> </span><span class="token string" style="color:rgb(195, 232, 141)">'~partytown'</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">]</span><span class="token punctuation" style="color:rgb(199, 146, 234)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token punctuation" style="color:rgb(199, 146, 234)">;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Partytown's requirement is that it needs to know what script should it load into own web worker. For that we set script type to <code>text/partytown</code>. This will prevent script to load on initial load.</p><p>Inside <code>_document.tsx</code> we add this:</p><div class="language-javascript codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-javascript codeBlock_bY9V thin-scrollbar"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#bfc7d5"><span class="token operator" style="color:rgb(137, 221, 255)"><</span><span class="token maybe-class-name">Head</span><span class="token operator" style="color:rgb(137, 221, 255)">></span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// include Partytown and set custom path due to multiple frontends</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)"><</span><span class="token maybe-class-name">Partytown</span><span class="token plain"> lib</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token template-string interpolation function" style="color:rgb(130, 170, 255)">addTrailingSlash</span><span class="token template-string interpolation punctuation" style="color:rgb(199, 146, 234)">(</span><span class="token template-string interpolation keyword" style="font-style:italic">this</span><span class="token template-string interpolation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token template-string interpolation property-access">props</span><span class="token template-string interpolation punctuation" style="color:rgb(199, 146, 234)">.</span><span class="token template-string interpolation property-access">basePath</span><span class="token template-string interpolation punctuation" style="color:rgb(199, 146, 234)">)</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string string" style="color:rgb(195, 232, 141)">_next/static/assets/~partytown/</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> debug</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token boolean" style="color:rgb(255, 88, 116)">false</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token operator" style="color:rgb(137, 221, 255)">></span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token comment" style="color:rgb(105, 112, 152);font-style:italic">// tag 3rd party script with partytown type</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)"><</span><span class="token plain">script type</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token string" style="color:rgb(195, 232, 141)">"text/partytown"</span><span class="token plain"> src</span><span class="token operator" style="color:rgb(137, 221, 255)">=</span><span class="token punctuation" style="color:rgb(199, 146, 234)">{</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token template-string string" style="color:rgb(195, 232, 141)">https://www.googletagmanager.com/gtm.js?id=</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">${</span><span class="token template-string interpolation">id</span><span class="token template-string interpolation interpolation-punctuation punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token template-string template-punctuation string" style="color:rgb(195, 232, 141)">`</span><span class="token punctuation" style="color:rgb(199, 146, 234)">}</span><span class="token plain"> </span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token operator" style="color:rgb(137, 221, 255)">></span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"> </span><span class="token spread operator" style="color:rgb(137, 221, 255)">...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#bfc7d5"><span class="token plain"></span><span class="token operator" style="color:rgb(137, 221, 255)"><</span><span class="token operator" style="color:rgb(137, 221, 255)">/</span><span class="token maybe-class-name">Head</span><span class="token operator" style="color:rgb(137, 221, 255)">></span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg class="copyButtonIcon_y97N" viewBox="0 0 24 24"><path d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg class="copyButtonSuccessIcon_LjdS" viewBox="0 0 24 24"><path d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><h2 class="anchor anchorWithStickyNavbar_LWe7" id="results">Results<a href="#results" class="hash-link" aria-label="Direct link to Results" title="Direct link to Results"></a></h2><p>So now, does it work? We used one of our large Ecommerce sites to test the landing Lighthouse score. </p><p>This was before adding Partytown:</p><p><img loading="lazy" alt="Lighthouse before Partytown" src="/assets/images/lighthouse_before-dc68b4a70a257ec6284efc219a989c7e.jpg" width="800" height="842" class="img_ev3q"></p><p>Here you can see 2 critical things: almost 1s of total blocking time (TBT) and 9s of time to interactive (TTI). </p><p>After we added Partytown, we got this:</p><p><img loading="lazy" alt="Lighthouse after Partytown" src="/assets/images/lighthouse_after-252d381900343cee3782f1d9c3e27442.jpg" width="840" height="845" class="img_ev3q"></p><p>Time to interactive went from 9s to 6.1s which is almost 33% improvement and total blocking time was reduce by more than 50%! We were more than impressed how easy it was to improve our performances.</p><p>Side note: Both screenshots were compressed using <a href="https://squoosh.app/" target="_blank" rel="noopener noreferrer">Squoosh App</a>.</p><h1>Next steps</h1><p>After successful testing of Partytown for Google Tag Manager script, we are more than interested in trying it out on our other scripts. One important topic will be to test Partytown with other service-worker related libraries and how to use them together.</p></div><footer class="row docusaurus-mt-lg"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/frontend">frontend</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/performance">performance</a></li></ul></div></footer></article><article class="margin-bottom--xl" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting"><header><h2 class="title_f1Hy" itemprop="headline"><a itemprop="url" href="/blog/debugging-go-map-races-in-k8s">debugging Go map races in k8s</a></h2><div class="container_mt6G margin-vert--md"><time datetime="2022-01-19T00:00:00.000Z" itemprop="datePublished">January 19, 2022</time></div><div class="margin-top--md margin-bottom--sm row"><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/dreadl0ck" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/dreadl0ck.png" alt="Philipp Mieden"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/dreadl0ck" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Philipp Mieden</span></a></div><small class="avatar__subtitle" itemprop="description">MSc</small></div></div></div></div></header><div class="markdown" itemprop="articleBody"></div><footer class="row docusaurus-mt-lg"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/go">go</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/debugging">debugging</a></li><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/backend">backend</a></li></ul></div></footer></article><article class="margin-bottom--xl" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting"><header><h2 class="title_f1Hy" itemprop="headline"><a itemprop="url" href="/blog/welcome-back-2021">Relaunching foomo.org</a></h2><div class="container_mt6G margin-vert--md"><time datetime="2021-11-12T00:00:00.000Z" itemprop="datePublished">November 12, 2021</time></div><div class="margin-top--md margin-bottom--sm row"><div class="col col--6 authorCol_Hf19"><div class="avatar margin-bottom--sm"><a href="https://github.com/janhalfar" target="_blank" rel="noopener noreferrer" class="avatar__photo-link"><img class="avatar__photo" src="https://github.com/janhalfar.png" alt="Jan Halfar"></a><div class="avatar__intro" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><div class="avatar__name"><a href="https://github.com/janhalfar" target="_blank" rel="noopener noreferrer" itemprop="url"><span itemprop="name">Jan Halfar</span></a></div><small class="avatar__subtitle" itemprop="description">foomo maintainer</small></div></div></div></div></header><div class="markdown" itemprop="articleBody"><p>A few years ago we abandoned the previous version of <a href="https://www.foomo.org" target="_blank" rel="noopener noreferrer">https://www.foomo.org</a> as we did not want to maintain the old wordpress installation and the project was only living in README.md in the repos living under <a href="https://www.github.com/foomo" target="_blank" rel="noopener noreferrer">https://www.github.com/foomo</a> .</p><p>As things have grown over time we have decided to re-launch a website / cross project documentation.</p><p>So welcome back and enjoy the view to the past:</p><p><img loading="lazy" alt="blast from the past" src="/assets/images/blast-from-the-past-cb642ec62cf61aa0ff51dc863b482b57.png" width="2428" height="1888" class="img_ev3q"></p></div><footer class="row docusaurus-mt-lg"><div class="col"><b>Tags:</b><ul class="tags_jXut padding--none margin-left--sm"><li class="tag_QGVx"><a class="tag_zVej tagRegular_sFm0" href="/blog/tags/foomo">foomo</a></li></ul></div></footer></article><nav class="pagination-nav" aria-label="Blog list page navigation"></nav></main></div></div></div><footer class="footer"><div class="container container-fluid"><div class="row footer__links"><div class="col footer__col"><div class="footer__title">github</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://github.com/foomo" target="_blank" rel="noopener noreferrer" class="footer__link-item">https://github.com/foomo</a></li></ul></div><div class="col footer__col"><div class="footer__title">legal</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="/etc/imprint">Imprint</a></li></ul></div></div><div class="footer__bottom text--center"><div class="footer__copyright">© 2023 bestbytes</div></div></div></footer></div>
|
||
<script src="/assets/js/runtime~main.339c949d.js"></script>
|
||
<script src="/assets/js/main.4cf1833b.js"></script>
|
||
</body>
|
||
</html> |