{"id":5851,"date":"2019-07-23T22:39:05","date_gmt":"2019-07-23T20:39:05","guid":{"rendered":"https:\/\/monodes.com\/predaelli\/?p=5851"},"modified":"2019-07-23T16:39:13","modified_gmt":"2019-07-23T14:39:13","slug":"web-bloat","status":"publish","type":"post","link":"https:\/\/monodes.com\/predaelli\/2019\/07\/23\/web-bloat\/","title":{"rendered":"Web bloat"},"content":{"rendered":"<h1><a href=\"https:\/\/danluu.com\/web-bloat\/\"><strong>Web bloat<\/strong><\/a><\/h1>\n<p>Some developer should learn this by heart!<\/p>\n<p><!--more--><\/p>\n<p><!--nextpage--><\/p>\n<blockquote><p><strong>Web bloat<\/strong><\/p>\n<hr \/>\n<p>A couple years ago, I took a road trip from Wisconsin to Washington and mostly stayed in rural hotels on the way. I expected the internet in rural areas too sparse to have cable internet to be slow, but I was still surprised that a large fraction of the web was inaccessible. Some blogs with lightweight styling were readable, as were pages by academics who hadn\u2019t updated the styling on their website since 1995. But very few commercial websites were usable (other than Google). When I measured my connection, I found that the bandwidth was roughly comparable to what I got with a 56k modem in the 90s. The latency and packetloss were significantly worse than the average day on dialup: latency varied between 500ms and 1000ms and packetloss varied between 1% and 10%. Those numbers are comparable to what I\u2019d see on dialup on a bad day.<\/p>\n<p>Despite my connection being only a bit worse than it was in the 90s, the vast majority of the web wouldn\u2019t load. Why shouldn\u2019t the web work with dialup or a dialup-like connection? It would be one thing if I tried to watch youtube and read pinterest. It\u2019s hard to serve videos and images without bandwidth. But my online interests are quite boring from a media standpoint. Pretty much everything I consume online is plain text, even if it happens to be styled with images and fancy javascript. In fact, I recently tried using w3m (a terminal-based web browser that, by default, doesn\u2019t support css, javascript, or even images) for a week and it turns out there are only two websites I regularly visit that don\u2019t really work in w3m (twitter and zulip, both fundamentally text based sites, at least as I use them)<sup id=\"fnref-M\" class=\"footnote-ref\"><a href=\"https:\/\/danluu.com\/web-bloat\/#fn:M\" rel=\"footnote\">1<\/a><\/sup>.<\/p>\n<p>More recently, I was reminded of how poorly the web works for people on slow connections when I tried to read a joelonsoftware post while using a flaky mobile connection. The HTML loaded but either one of the five CSS requests or one of the thirteen javascript requests timed out, leaving me with a broken page. Instead of seeing the article, I saw <a href=\"https:\/\/twitter.com\/danluu\/status\/823286780560437248\">three entire pages of sidebar, menu, and ads<\/a> before getting to the title because the page required some kind of layout modification to display reasonably. Pages are often designed so that they&#8217;re hard or impossible to read if some dependency fails to load. On a slow connection, it&#8217;s quite common for at least one depedency to fail. After refreshing the page twice, the page loaded as it was supposed to and I was able to read the blog post, a fairly compelling post on eliminating dependencies.<\/p>\n<p>Complaining that people don\u2019t care about performance like they used to and that we\u2019re letting bloat slow things down for no good reason is \u201cold man yells at cloud\u201d territory; I probably sound like that dude who complains that his word processor, which used to take 1MB of RAM, takes 1GB of RAM. Sure, that could be trimmed down, but there\u2019s a real cost to spending time doing optimization and even a $300 laptop comes with 2GB of RAM, so why bother? But it\u2019s not quite the same situation &#8212; it\u2019s not just nerds like me who care about web performance. When Microsoft looked at actual measured connection speeds, they found that <a href=\"https:\/\/blogs.microsoft.com\/on-the-issues\/2018\/12\/03\/the-rural-broadband-divide-an-urgent-national-problem-that-we-can-solve\/\">half of Americans don&#8217;t have broadband speed<\/a>. Heck, AOL had 2 million dial-up subscribers in 2015, just AOL alone. Outside of the U.S., there are even more people with slow connections. I recently chatted with Ben Kuhn, who spends a fair amount of time in Africa, about his internet connection:<\/p>\n<blockquote><p>I&#8217;ve seen ping latencies as bad as ~45 sec and packet loss as bad as 50% on a mobile hotspot in the evenings from Jijiga, Ethiopia. (I&#8217;m here now and currently I have 150ms ping with no packet loss but it&#8217;s 10am). There are some periods of the day where it ~never gets better than 10 sec and ~10% loss. The internet has gotten a lot better in the past ~year; it used to be that bad all the time except in the early mornings.<\/p>\n<p>\u2026<\/p>\n<p>Speedtest.net reports 2.6 mbps download, 0.6 mbps upload. I realized I probably shouldn&#8217;t run a speed test on my mobile data because bandwidth is really expensive.<\/p>\n<p>Our server in Ethiopia is has a fiber uplink, but it frequently goes down and we fall back to a 16kbps satellite connection, though I think normal people would just stop using the Internet in that case.<\/p><\/blockquote>\n<p>If you think <a href=\"https:\/\/1-minute-modem.branchable.com\/\">browsing on a 56k connection<\/a> is bad, try a 16k connection from Ethiopia!<\/p>\n<p>Everything we\u2019ve seen so far is anecdotal. Let\u2019s load some websites that programmers might frequent with a variety of simulated connections to get data on page load times. <a href=\"https:\/\/www.webpagetest.org\/\">webpagetest<\/a> lets us see how long it takes a web site to load (and why it takes that long) from locations all over the world. It even lets us simulate different kinds of connections as well as load sites on a variety of mobile devices. The times listed in the table below are the time until the page is \u201cvisually complete\u201d; as measured by webpagetest, that\u2019s the time until the above-the-fold content stops changing.<\/p>\n<div>\n<table id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03\" cellspacing=\"0\" align=\"center\">\n<thead>\n<tr>\n<th>URL<\/th>\n<th>Size<\/th>\n<th>C<\/th>\n<th colspan=\"8\">Load time in seconds<\/th>\n<\/tr>\n<tr>\n<th class=\"col_heading level0 col0\" colspan=\"1\"><\/th>\n<th class=\"col_heading level0 col1\" colspan=\"1\">MB<\/th>\n<th class=\"col_heading level0 col2\" colspan=\"1\"><\/th>\n<th class=\"col_heading level0 col3\" colspan=\"1\">FIOS<\/th>\n<th class=\"col_heading level0 col4\" colspan=\"1\">Cable<\/th>\n<th class=\"col_heading level0 col5\" colspan=\"1\">LTE<\/th>\n<th class=\"col_heading level0 col6\" colspan=\"1\">3G<\/th>\n<th class=\"col_heading level0 col7\" colspan=\"1\">2G<\/th>\n<th class=\"col_heading level0 col8\" colspan=\"1\">Dial<\/th>\n<th class=\"col_heading level0 col9\" colspan=\"1\">Bad<\/th>\n<th class=\"col_heading level0 col10\" colspan=\"1\">\ud83d\ude31<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col0\" class=\"data row0 col0\">http:\/\/bellard.org<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col1\" class=\"data row0 col1\">0.01<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col2\" class=\"data row0 col2\">5<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col3\" class=\"data row0 col3\">0.40<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col4\" class=\"data row0 col4\">0.59<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col5\" class=\"data row0 col5\">0.60<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col6\" class=\"data row0 col6\">1.2<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col7\" class=\"data row0 col7\">2.9<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col8\" class=\"data row0 col8\">1.8<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col9\" class=\"data row0 col9\">9.5<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row0_col10\" class=\"data row0 col10\">7.6<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col0\" class=\"data row1 col0\">http:\/\/danluu.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col1\" class=\"data row1 col1\">0.02<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col2\" class=\"data row1 col2\">2<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col3\" class=\"data row1 col3\">0.20<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col4\" class=\"data row1 col4\">0.20<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col5\" class=\"data row1 col5\">0.40<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col6\" class=\"data row1 col6\">0.80<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col7\" class=\"data row1 col7\">2.7<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col8\" class=\"data row1 col8\">1.6<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col9\" class=\"data row1 col9\">6.4<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col10\" class=\"data row1 col10\">7.6<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col0\" class=\"data row2 col0\">news.ycombinator.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col1\" class=\"data row2 col1\">0.03<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col2\" class=\"data row2 col2\">1<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col3\" class=\"data row2 col3\">0.30<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col4\" class=\"data row2 col4\">0.49<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col5\" class=\"data row2 col5\">0.69<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col6\" class=\"data row2 col6\">1.6<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col7\" class=\"data row2 col7\">5.5<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col8\" class=\"data row2 col8\">5.0<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col9\" class=\"data row2 col9\">14<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row2_col10\" class=\"data row2 col10\">27<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col0\" class=\"data row3 col0\">danluu.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col1\" class=\"data row3 col1\">0.03<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col2\" class=\"data row3 col2\">2<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col3\" class=\"data row3 col3\">0.20<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col4\" class=\"data row3 col4\">0.40<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col5\" class=\"data row3 col5\">0.49<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col6\" class=\"data row3 col6\">1.1<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col7\" class=\"data row3 col7\">3.6<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col8\" class=\"data row3 col8\">3.5<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col9\" class=\"data row3 col9\">9.3<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col10\" class=\"data row3 col10\">15<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col0\" class=\"data row4 col0\">http:\/\/jvns.ca<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col1\" class=\"data row4 col1\">0.14<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col2\" class=\"data row4 col2\">7<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col3\" class=\"data row4 col3\">0.49<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col4\" class=\"data row4 col4\">0.69<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col5\" class=\"data row4 col5\">1.2<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col6\" class=\"data row4 col6\">2.9<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col7\" class=\"data row4 col7\">10<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col8\" class=\"data row4 col8\">19<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col9\" class=\"data row4 col9\">29<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row4_col10\" class=\"data row4 col10\">108<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col0\" class=\"data row5 col0\">jvns.ca<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col1\" class=\"data row5 col1\">0.15<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col2\" class=\"data row5 col2\">4<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col3\" class=\"data row5 col3\">0.50<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col4\" class=\"data row5 col4\">0.80<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col5\" class=\"data row5 col5\">1.2<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col6\" class=\"data row5 col6\">3.3<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col7\" class=\"data row5 col7\">11<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col8\" class=\"data row5 col8\">21<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col9\" class=\"data row5 col9\">31<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row5_col10\" class=\"data row5 col10\">97<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col0\" class=\"data row6 col0\">fgiesen.wordpress.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col1\" class=\"data row6 col1\">0.37<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col2\" class=\"data row6 col2\">12<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col3\" class=\"data row6 col3\">1.0<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col4\" class=\"data row6 col4\">1.1<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col5\" class=\"data row6 col5\">1.4<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col6\" class=\"data row6 col6\">5.0<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col7\" class=\"data row6 col7\">16<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col8\" class=\"data row6 col8\">66<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col9\" class=\"data row6 col9\">68<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row6_col10\" class=\"data row6 col10\">FAIL<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col0\" class=\"data row7 col0\">google.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col1\" class=\"data row7 col1\">0.59<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col2\" class=\"data row7 col2\">6<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col3\" class=\"data row7 col3\">0.80<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col4\" class=\"data row7 col4\">1.8<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col5\" class=\"data row7 col5\">1.4<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col6\" class=\"data row7 col6\">6.8<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col7\" class=\"data row7 col7\">19<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col8\" class=\"data row7 col8\">94<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col9\" class=\"data row7 col9\">96<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row7_col10\" class=\"data row7 col10\">236<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col0\" class=\"data row8 col0\">joelonsoftware.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col1\" class=\"data row8 col1\">0.72<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col2\" class=\"data row8 col2\">19<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col3\" class=\"data row8 col3\">1.3<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col4\" class=\"data row8 col4\">1.7<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col5\" class=\"data row8 col5\">1.9<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col6\" class=\"data row8 col6\">9.7<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col7\" class=\"data row8 col7\">28<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col8\" class=\"data row8 col8\">140<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col9\" class=\"data row8 col9\">FAIL<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row8_col10\" class=\"data row8 col10\">FAIL<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col0\" class=\"data row9 col0\">bing.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col1\" class=\"data row9 col1\">1.3<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col2\" class=\"data row9 col2\">12<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col3\" class=\"data row9 col3\">1.4<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col4\" class=\"data row9 col4\">2.9<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col5\" class=\"data row9 col5\">3.3<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col6\" class=\"data row9 col6\">11<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col7\" class=\"data row9 col7\">43<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col8\" class=\"data row9 col8\">134<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col9\" class=\"data row9 col9\">FAIL<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row9_col10\" class=\"data row9 col10\">FAIL<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col0\" class=\"data row10 col0\">reddit.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col1\" class=\"data row10 col1\">1.3<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col2\" class=\"data row10 col2\">26<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col3\" class=\"data row10 col3\">7.5<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col4\" class=\"data row10 col4\">6.9<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col5\" class=\"data row10 col5\">7.0<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col6\" class=\"data row10 col6\">20<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col7\" class=\"data row10 col7\">58<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col8\" class=\"data row10 col8\">179<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col9\" class=\"data row10 col9\">210<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row10_col10\" class=\"data row10 col10\">FAIL<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col0\" class=\"data row11 col0\">signalvnoise.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col1\" class=\"data row11 col1\">2.1<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col2\" class=\"data row11 col2\">7<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col3\" class=\"data row11 col3\">2.0<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col4\" class=\"data row11 col4\">3.5<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col5\" class=\"data row11 col5\">3.7<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col6\" class=\"data row11 col6\">16<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col7\" class=\"data row11 col7\">47<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col8\" class=\"data row11 col8\">173<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col9\" class=\"data row11 col9\">218<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row11_col10\" class=\"data row11 col10\">FAIL<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col0\" class=\"data row12 col0\">amazon.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col1\" class=\"data row12 col1\">4.4<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col2\" class=\"data row12 col2\">47<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col3\" class=\"data row12 col3\">6.6<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col4\" class=\"data row12 col4\">13<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col5\" class=\"data row12 col5\">8.4<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col6\" class=\"data row12 col6\">36<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col7\" class=\"data row12 col7\">65<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col8\" class=\"data row12 col8\">265<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col9\" class=\"data row12 col9\">300<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row12_col10\" class=\"data row12 col10\">FAIL<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col0\" class=\"data row13 col0\">steve-yegge.blogspot.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col1\" class=\"data row13 col1\">9.7<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col2\" class=\"data row13 col2\">19<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col3\" class=\"data row13 col3\">2.2<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col4\" class=\"data row13 col4\">3.6<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col5\" class=\"data row13 col5\">3.3<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col6\" class=\"data row13 col6\">12<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col7\" class=\"data row13 col7\">36<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col8\" class=\"data row13 col8\">206<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col9\" class=\"data row13 col9\">188<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row13_col10\" class=\"data row13 col10\">FAIL<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col0\" class=\"data row14 col0\">blog.codinghorror.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col1\" class=\"data row14 col1\">23<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col2\" class=\"data row14 col2\">24<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col3\" class=\"data row14 col3\">6.5<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col4\" class=\"data row14 col4\">15<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col5\" class=\"data row14 col5\">9.5<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col6\" class=\"data row14 col6\">83<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col7\" class=\"data row14 col7\">235<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col8\" class=\"data row14 col8\">FAIL<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col9\" class=\"data row14 col9\">FAIL<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row14_col10\" class=\"data row14 col10\">FAIL<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>Each row is a website. For sites that support both plain HTTP as well as HTTPS, both were tested; URLs are HTTPS except where explicitly specified as HTTP. The first two columns show the amount of data transferred over the wire in MB (which includes headers, handshaking, compression, etc.) and the number of TCP connections made. The rest of the columns show the time in seconds to load the page on a variety of connections from fiber (FIOS) to less good connections. \u201cBad\u201d has the bandwidth of dialup, but with 1000ms ping and 10% packetloss, which is roughly what I saw when using the internet in small rural hotels. \u201c\ud83d\ude31\u201d simulates a 16kbps satellite connection from Jijiga, Ethiopia. Rows are sorted by the measured amount of data transferred.<\/p>\n<p>The timeout for tests was 6 minutes; anything slower than that is listed as FAIL. Pages that failed to load are also listed as FAIL. A few things that jump out from the table are:<\/p>\n<ol>\n<li>A large fraction of the web is unusable on a bad connection. Even on a good (0% packetloss, no ping spike) dialup connection, some sites won\u2019t load.<\/li>\n<li>Some sites will use a lot of data!<\/li>\n<\/ol>\n<h4 id=\"the-web-on-bad-connections\">The web on bad connections<\/h4>\n<p>As commercial websites go, Google is basically as good as it gets for people on a slow connection. On dialup, the 50%-ile page load time is a minute and a half. But at least it loads &#8212; when I was on a slow, shared, satellite connection in rural Montana, virtually no commercial websites would load at all. I could view websites that only had static content via Google cache, but the live site had no hope of loading.<\/p>\n<h4 id=\"some-sites-will-use-a-lot-of-data\">Some sites will use a lot of data<\/h4>\n<p>Although only two really big sites were tested here, there are plenty of sites that will use 10MB or 20MB of data. If you\u2019re reading this from the U.S., maybe you don\u2019t care, but if you\u2019re browsing from Mauritania, Madagascar, or Vanuatu, loading codinghorror once will cost you <a href=\"https:\/\/whatdoesmysitecost.com\/test\/170206_0G_2QG#gniCost\">more than 10% of the daily per capita GNI<\/a>.<\/p>\n<h4 id=\"page-weight-matters\">Page weight matters<\/h4>\n<p>Despite the best efforts of <a href=\"http:\/\/idlewords.com\/talks\/website_obesity.htm\">Maciej<\/a>, the meme that page weight doesn\u2019t matter keeps getting spread around. AFAICT, the top HN link of all time on web page optimization is to an article titled \u201cLudicrously Fast Page Loads &#8211; A Guide for Full-Stack Devs\u201d. At the bottom of the page, the author links to another one of his posts, titled \u201cPage Weight Doesn\u2019t Matter\u201d.<\/p>\n<blockquote><p>Usually, the boogeyman that gets pointed at is bandwidth: users in low-bandwidth areas (3G, developing world) are getting shafted. But the math doesn\u2019t quite work out. Akamai puts the global connection speed average at 3.9 megabits per second.<\/p><\/blockquote>\n<p>The \u201cludicrously fast\u201d guide fails to display properly on dialup or slow mobile connections because the images time out. On reddit, <a href=\"https:\/\/www.reddit.com\/r\/web_design\/comments\/3oppvo\/ludicrously_fast_page_loads_a_guide_for_fullstack\/\">it also fails under load<\/a>: &#8220;Ironically, that page took so long to load that I closed the window.&#8221;, &#8220;a lot of \u2026 gifs that do nothing but make your viewing experience worse&#8221;, &#8220;I didn&#8217;t even make it to the gifs; the header loaded then it just hung.&#8221;, etc.<\/p>\n<p>The flaw in the \u201cpage weight doesn\u2019t matter because average speed is fast\u201d is that if you average the connection of someone in my apartment building (which is wired for 1Gbps internet) and someone on 56k dialup, you get an average speed of 500 Mbps. That doesn\u2019t mean the person on dialup is actually going to be able to load a 5MB website. The average speed of 3.9 Mbps comes from a 2014 Akamai report, but it\u2019s just an average. If you look at Akamai\u2019s 2016 report, you can find entire countries where more than 90% of IP addresses are slower than that!<\/p>\n<p>Yes, there are a lot of factors besides page weight that matter, and yes it&#8217;s possible to create a contrived page that&#8217;s very small but loads slowly, as well as a huge page that loads ok because all of the weight isn&#8217;t blocking, but total page weight is still pretty decently correlated with load time.<\/p>\n<p>Since its publication, the &#8220;ludicrously fast&#8221; guide was updated with some javascript that only loads images if you scroll down far enough. That makes it look a lot better on webpagetest if you&#8217;re looking at the page size number (if webpagetest isn&#8217;t being scripted to scroll), but it&#8217;s a worse user experience for people on slow connections who want to read the page. If you&#8217;re going to read the entire page anyway, the weight increases, and you can no longer preload images by loading the site. Instead, if you&#8217;re reading, you have to stop for a few minutes at every section to wait for the images from that section to load. And that&#8217;s if you&#8217;re lucky and the javascript for loading images didn&#8217;t fail to load.<\/p>\n<h4 id=\"the-average-user-fallacy\">The average user fallacy<\/h4>\n<p>Just like many people develop with an average connection speed in mind, many people have a fixed view of who a user is. Maybe they think there are customers with a lot of money with fast connections and customers who won&#8217;t spend money on slow connections. That is, very roughly speaking, perhaps true on average, but sites don&#8217;t operate on average, they operate in particular domains. Jamie Brandon writes the following about his experience with Airbnb:<\/p>\n<blockquote><p>I spent three hours last night trying to book a room on airbnb through an overloaded wifi and presumably a satellite connection. OAuth seems to be particularly bad over poor connections. Facebook&#8217;s OAuth wouldn&#8217;t load at all and Google&#8217;s sent me round a &#8216;pick an account&#8217; -&gt; &#8216;please reenter you password&#8217; -&gt; &#8216;pick an account&#8217; loop several times. It took so many attempts to log in that I triggered some 2fa nonsense on airbnb that also didn&#8217;t work (the confirmation link from the email led to a page that said &#8216;please log in to view this page&#8217;) and eventually I was just told to send an email to account.disabled@airbnb.com, who haven&#8217;t replied.<\/p>\n<p>It&#8217;s particularly galling that airbnb doesn&#8217;t test this stuff, because traveling is pretty much the whole point of the site so they can&#8217;t even claim that there&#8217;s no money in servicing people with poor connections.<\/p><\/blockquote>\n<h4 id=\"what-about-tail-latency\">What about tail latency?<\/h4>\n<p>My original plan for this was post was to show 50%-ile, 90%-ile, 99%-ile, etc., tail load times. But the 50%-ile results are so bad that I don\u2019t know if there\u2019s any point to showing the other results. If you were to look at the 90%-ile results, you\u2019d see that most pages fail to load on dialup and the \u201cBad\u201d and \u201c\ud83d\ude31\u201d connections are hopeless for almost all sites.<\/p>\n<h4 id=\"http-vs-https\">HTTP vs HTTPs<\/h4>\n<div>\n<table id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03\" cellspacing=\"0\" align=\"center\">\n<thead>\n<tr>\n<th>URL<\/th>\n<th>Size<\/th>\n<th>C<\/th>\n<th colspan=\"8\">Load time in seconds<\/th>\n<\/tr>\n<tr>\n<th class=\"col_heading level0 col0\" colspan=\"1\"><\/th>\n<th class=\"col_heading level0 col1\" colspan=\"1\">kB<\/th>\n<th class=\"col_heading level0 col2\" colspan=\"1\"><\/th>\n<th class=\"col_heading level0 col3\" colspan=\"1\">FIOS<\/th>\n<th class=\"col_heading level0 col4\" colspan=\"1\">Cable<\/th>\n<th class=\"col_heading level0 col5\" colspan=\"1\">LTE<\/th>\n<th class=\"col_heading level0 col6\" colspan=\"1\">3G<\/th>\n<th class=\"col_heading level0 col7\" colspan=\"1\">2G<\/th>\n<th class=\"col_heading level0 col8\" colspan=\"1\">Dial<\/th>\n<th class=\"col_heading level0 col9\" colspan=\"1\">Bad<\/th>\n<th class=\"col_heading level0 col10\" colspan=\"1\">\ud83d\ude31<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col0\" class=\"data row1 col0\">http:\/\/danluu.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col1\" class=\"data row1 col1\">21.1<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col2\" class=\"data row1 col2\">2<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col3\" class=\"data row1 col3\">0.20<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col4\" class=\"data row1 col4\">0.20<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col5\" class=\"data row1 col5\">0.40<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col6\" class=\"data row1 col6\">0.80<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col7\" class=\"data row1 col7\">2.7<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col8\" class=\"data row1 col8\">1.6<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col9\" class=\"data row1 col9\">6.4<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row1_col10\" class=\"data row1 col10\">7.6<\/td>\n<\/tr>\n<tr>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col0\" class=\"data row3 col0\">https:\/\/danluu.com<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col1\" class=\"data row3 col1\">29.3<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col2\" class=\"data row3 col2\">2<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col3\" class=\"data row3 col3\">0.20<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col4\" class=\"data row3 col4\">0.40<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col5\" class=\"data row3 col5\">0.49<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col6\" class=\"data row3 col6\">1.1<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col7\" class=\"data row3 col7\">3.6<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col8\" class=\"data row3 col8\">3.5<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col9\" class=\"data row3 col9\">9.3<\/td>\n<td id=\"T_3d17f176_ecb9_11e6_bbf7_0cc47ac41d03row3_col10\" class=\"data row3 col10\">15<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>You can see that for a very small site that doesn\u2019t load many blocking resources, HTTPS is noticeably slower than HTTP, especially on slow connections. Practically speaking, this doesn\u2019t matter today because virtually no sites are that small, but if you design a web site as if people with slow connections actually matter, this is noticeable.<\/p>\n<h3 id=\"how-to-make-pages-usable-on-slow-connections\">How to make pages usable on slow connections<\/h3>\n<p>The long version is, to really understand what\u2019s going on, considering reading <a href=\"https:\/\/hpbn.co\/\">high-performance browser networking<\/a>, a great book on web performance that\u2019s avaiable for free.<\/p>\n<p>The short version is that most sites are so poorly optimized that someone who has no idea what they\u2019re doing can get a 10x improvement in page load times for a site whose job is to serve up text with the occasional image. When I started this blog in 2013, I used Octopress because Jekyll\/Octopress was the most widely recommended static site generator back then. A plain blog post with one or two images took 11s to load on a cable connection because the Octopress defaults included multiple useless javascript files in the header (for never-used-by-me things like embedding flash videos and delicious integration), which blocked page rendering. Just moving those javascript includes to the footer halved page load time, and <a href=\"https:\/\/danluu.com\/octopress-speedup\/\">making a few other tweaks decreased page load time by another order of magnitude<\/a>. At the time I made those changes, I knew nothing about web page optimization, other than what I heard during a 2-minute blurb on optimization from a 40-minute talk on how the internet works and I was able to get a 20x speedup on my blog in a few hours. You might argue that I\u2019ve now gone too far and removed too much CSS, but I got a 20x speedup for people on fast connections before making changes that affected the site\u2019s appearance (and the speedup on slow connections was much larger).<\/p>\n<p>That\u2019s normal. Popular themes for many different kinds of blogging software and CMSs contain anti-optimizations so blatant that any programmer, even someone with no front-end experience, can find large gains by just pointing <a href=\"https:\/\/www.webpagetest.org\/\">webpagetest<\/a> at their site and looking at the output.<\/p>\n<h3 id=\"what-about-browsers\">What about browsers?<\/h3>\n<p>While it&#8217;s easy to blame page authors because there&#8217;s a lot of low-hanging fruit on the page side, there&#8217;s just as much low-hanging fruit on the browser side. Why does my browser open up 6 TCP connections to try to download six images at once when I&#8217;m on a slow satellite connection? That just guarantees that all six images will time out! Even if I tweak the timeout on the client side, servers that are configured to protect against DoS attacks won&#8217;t allow long lived connections that aren&#8217;t doing anything. I can sometimes get some images to load by refreshing the page a few times (and waiting ten minutes each time), but why shouldn&#8217;t the browser handle retries for me? If you think about it for a few minutes, there are a lot of optimiztions that browsers could do for people on slow connections, but because they don&#8217;t, the best current solution for users appears to be: use w3m when you can, and then switch to a browser with ad-blocking when that doesn&#8217;t work. But why should users have to use two entirely different programs, one of which has a text-based interface only computer nerds will find palatable?<\/p>\n<h3 id=\"conclusion\">Conclusion<\/h3>\n<p>When I was at Google, someone told me a story about a time that \u201cthey\u201d completed a big optimization push only to find that measured page load times increased. When they dug into the data, they found that the reason load times had increased was that they got a lot more traffic from Africa after doing the optimizations. The team\u2019s product went from being unusable for people with slow connections to usable, which caused so many users with slow connections to start using the product that load times actually increased.<\/p>\n<p>Last night, at a presentation on the websockets protocol, Gary Bernhardt made the observation that the people who designed the websockets protocol did things like using a variable length field for frame length to save a few bytes. By contrast, if you look at the Alexa top 100 sites, almost all of them have a huge amount of slop in them; it\u2019s plausible that the total bandwidth used for those 100 sites is probably greater than the total bandwidth for all websockets connections combined. Despite that, if we just look at the three top 35 sites tested in this post, two send uncompressed javascript over the wire, two redirect the bare domain to the www subdomain, and two send a lot of extraneous information by not compressing images as much as they could be compressed without sacrificing quality. If you look at twitter, which isn\u2019t in our table but was mentioned above, they actually do <a href=\"https:\/\/twitter.com\/danluu\/status\/705815510479302656\">an anti-optimization where, if you upload a PNG which isn\u2019t even particularly well optimized, they\u2019ll re-encode it as a jpeg which is larger and has visible artifacts<\/a>!<\/p>\n<p>\u201cUse bcrypt\u201d has become the mantra for a reasonable default if you\u2019re not sure what to do when storing passwords. The web would be a nicer place if \u201cuse webpagetest\u201d caught on in the same way. It\u2019s not always the best tool for the job, but it sure beats the current defaults.<\/p>\n<h3 id=\"appendix-experimental-caveats\">Appendix: experimental caveats<\/h3>\n<p>The above tests were done by repeatedly loading pages via a private webpagetest image in AWS west 2, on a c4.xlarge VM, with simulated connections on a first page load in Chrome with no other tabs open and nothing running on the VM other than the webpagetest software and the browser. This is unrealistic in many ways.<\/p>\n<p>In relative terms, this disadvantages sites that have a large edge presence. When I was in rural Montana, I ran some tests and found that I had noticeably better latency to Google than to basically any other site. This is not reflected in the test results. Furthermore, this setup means that pages are nearly certain to be served from a CDN cache. That shouldn&#8217;t make any difference for sites like Google and Amazon, but it reduces the page load time of less-trafficked sites that aren&#8217;t &#8220;always&#8221; served out of cache. For example, when I don&#8217;t have a post trending on social media, between 55% and 75% of traffic is served out of a CDN cache, and when I do have something trending on social media, it&#8217;s more like 90% to 99%. But the test setup means that the CDN cache hit rate during the test is likely to be &gt; 99% for my site and other blogs which aren&#8217;t so widely read that they&#8217;d normally always have a cached copy available.<\/p>\n<p>All tests were run assuming a first page load, but it\u2019s entirely reasonable for sites like Google and Amazon to assume that many or most of their assets are cached. Testing first page load times is perhaps reasonable for sites with a traffic profile like mine, where much of the traffic comes from social media referrals of people who\u2019ve never visited the site before.<\/p>\n<p>A c4.xlarge is a fairly powerful machine. Today, most page loads come from mobile and even the fastest mobile devices aren\u2019t as fast as a c4.xlarge; most mobile devices are much slower than the fastest mobile devices. Most desktop page loads will also be from a machine that\u2019s slower than a c4.xlarge. Although the results aren\u2019t shown, I also ran a set of tests using a t2.micro instance: for simple sites, like mine, the difference was negligible, but for complex sites, like Amazon, page load times were as much as 2x worse. As you might expect, for any particular site, the difference got smaller as the connection got slower.<\/p>\n<p>As Joey Hess pointed out, many dialup providers attempt to do compression or other tricks to reduce the effective weight of pages and none of these tests take that into account.<\/p>\n<p>Firefox, IE, and Edge often have substantially different performance characteristics from Chrome. For that matter, different versions of Chrome can have different performance characteristics. I just used Chrome because it\u2019s the most widely used desktop browser, and running this set of tests took over a full day of VM time with a single-browser.<\/p>\n<p>The simulated bad connections add a constant latency and fixed (10%) packetloss. In reality, poor connections have highly variable latency with peaks that are much higher than the simulated latency and periods of much higher packetloss than can last for minutes, hours, or days. Putting \ud83d\ude31 at the rightmost side of the table may make it seem like the worst possible connection, but packetloss can get much worse.<\/p>\n<p>Similarly, while codinghorror happens to be at the bottom of the page, it&#8217;s nowhere to being the slowest loading page. Just for example, I originally considered including slashdot in the table but it was so slow that it caused a significant increase in total test run time because it timed out at six minutes so many times. Even on FIOS it takes 15s to load by making a whopping 223 requests over 100 TCP connections despite weighing in at &#8220;only&#8221; 1.9MB. Amazingly, slashdot also pegs the CPU at 100% for 17 entire seconds while loading on FIOS. In retrospect, this might have been a good site to include because it&#8217;s pathologically mis-optimized sites like slashdot that allow the &#8220;page weight doesn&#8217;t matter&#8221; meme to sound reasonable.<\/p>\n<p>The websites compared don&#8217;t do the same thing. Just looking at the blogs, some blogs put entire blog entries on the front page, which is more convenient in some ways, but also slower. Commercial sites are even more different &#8212; they often can&#8217;t reasonably be static sites and have to have relatively large javascrit payloads in order to work well.<\/p>\n<h3 id=\"appendix-irony\">Appendix: irony<\/h3>\n<p>The main table in this post is almost 50kB of HTML (without compression or minification); that\u2019s larger than everything else in this post combined. That table is curiously large because I used a library (pandas) to generate the table instead of just writing a script to do it by hand, and as we know, the default settings for most libraries generate a massive amount of bloat. It didn\u2019t even save time because every single built-in time-saving feature that I wanted to use was buggy, which forced me to write all of the heatmap\/gradient\/styling code myself anyway! Due to laziness, I left the pandas table generating scaffolding code, resulting in a table that looks like it\u2019s roughly an order of magnitude larger than it needs to be.<\/p>\n<p>This isn&#8217;t a criticism of pandas. Pandas is probably quite good at what it&#8217;s designed for; it&#8217;s just not designed to produce slim websites. The CSS class names are huge, which is reasonable if you want to avoid accidental name collisions for generated CSS. Almost every <code class=\"\" data-line=\"\">td<\/code>, <code class=\"\" data-line=\"\">th<\/code>, and <code class=\"\" data-line=\"\">tr<\/code> element is tagged with a redundant <code class=\"\" data-line=\"\">rowspan=1<\/code> or <code class=\"\" data-line=\"\">colspan=1<\/code>, which is reasonable for generated code if you don&#8217;t care about size. Each cell has its own CSS class, even though many cells share styling with other cells; again, this probably simplified things on the code generation. Every piece of bloat is totally reasonable. And unfortunately, there&#8217;s no tool that I know of that will take a bloated table and turn it into a slim table. A pure HTML minifier can&#8217;t change the class names because it doesn&#8217;t know that some external CSS or JS doesn&#8217;t depend on the class name. An HTML minifier could theoretically determine that different cells have the same styling and merge them, except for the aforementioned problem with potential but non-existent external depenencies, but that&#8217;s beyond the capability of the tools I know of.<\/p>\n<p>For another level of ironic, consider that while I think of a 50kB table as bloat, this page is 12kB when gzipped, even with all of the bloat. Google&#8217;s AMP currently has &gt; 100kB of blocking javascript that has to load before the page loads! There&#8217;s no reason for me to use AMP pages because AMP is slower than my current setup of pure HTML with a few lines of embedded CSS and the occasional image, but, as a result, I&#8217;m penalized by Google (relative to AMP pages) for not &#8220;accelerating&#8221; (deccelerating) my page with AMP.<\/p>\n<p><small> Thanks to Leah Hanson, Jason Owen, and Lindsey Kuper for comments\/corrections <\/small><\/p>\n<div class=\"footnotes\">\n<hr \/>\n<ol>\n<li id=\"fn-M\">excluding internal Microsoft stuff that\u2019s required for work. Many of the sites are IE only and don\u2019t even work in edge. I didn\u2019t try those sites in w3m but I doubt they\u2019d work! In fact, I doubt that even half of the non-IE specific internal sites would work in w3m. <a class=\"footnote-return\" href=\"https:\/\/danluu.com\/web-bloat\/#fnref:M\"><sup>[return]<\/sup><\/a><\/li>\n<\/ol>\n<\/div>\n<div class=\"np\"><a href=\"https:\/\/danluu.com\/startup-options\/\">\u2190 Options v. cash<\/a> <a href=\"https:\/\/danluu.com\/hn-comments\/\">HN: the good parts \u2192<\/a><\/div>\n<div class=\"np\"><a href=\"https:\/\/danluu.com\/\">Archive<\/a> <a href=\"https:\/\/www.patreon.com\/danluu\">Support this site (patreon)<\/a> <a href=\"https:\/\/danluu.com\/about\/\">About<\/a> <a href=\"https:\/\/twitter.com\/danluu\">Twitter<\/a> <a href=\"https:\/\/danluu.com\/atom.xml\" rel=\"alternate\" type=\"application\/rss+xml\">RSS<\/a><\/div>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p class=\"excerpt\">Web bloat Some developer should learn this by heart!<\/p>\n<p class=\"more-link-p\"><a class=\"more-link\" href=\"https:\/\/monodes.com\/predaelli\/2019\/07\/23\/web-bloat\/\">Read more &rarr;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"link","meta":{"inline_featured_image":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-5851","post","type-post","status-publish","format-link","hentry","category-senza-categoria","post_format-post-format-link"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6daft-1wn","jetpack-related-posts":[{"id":5753,"url":"https:\/\/monodes.com\/predaelli\/2019\/06\/17\/computer-latency-1977-2017\/","url_meta":{"origin":5851,"position":0},"title":"Computer latency: 1977-2017","author":"Paolo Redaelli","date":"2019-06-17","format":false,"excerpt":"Computer latency: 1977-2017 Computer latency: 1977-2017 I've had this nagging feeling that the computers I use today feel slower than the computers I used as a kid. As a rule, I don\u2019t trust this kind of feeling because human perception has been shown to be unreliable in empirical studies, so\u2026","rel":"","context":"In &quot;Senza categoria&quot;","block_context":{"text":"Senza categoria","link":"https:\/\/monodes.com\/predaelli\/category\/senza-categoria\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":13846,"url":"https:\/\/monodes.com\/predaelli\/2025\/08\/13\/ai-bloat-in-browser-blowing-up-cpu-and-drains-battery\/","url_meta":{"origin":5851,"position":1},"title":"AI &#8216;Bloat&#8217; in browser blowing up CPU and drains battery","author":"Paolo Redaelli","date":"2025-08-13","format":false,"excerpt":"Slashdot tells us that a new \"AI-bloat feature\" of Firefox 141 blows up CPU and energy usage referring a neowin.net article that luckily offers an easy solution: disabling it. Here's how: you can disable them through the browser's advanced settings. Head to about:config in a new tab, accept the risk\u2026","rel":"","context":"In &quot;Tricks&quot;","block_context":{"text":"Tricks","link":"https:\/\/monodes.com\/predaelli\/category\/documentations\/tricks\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":763,"url":"https:\/\/monodes.com\/predaelli\/2015\/10\/31\/how-to-differentiate-between-an-average-and-a-good-programmer\/","url_meta":{"origin":5851,"position":2},"title":"How to differentiate between an Average and a Good Programmer?","author":"Paolo Redaelli","date":"2015-10-31","format":false,"excerpt":"\u00a0How to differentiate between an Average and a Good Programmer? \u00a0 Oh my! It's so true! javarevisited looks like a really good programming blog as I found gems like\u00ab10 Articles Every Programmer Must Read \u00bb among What Every Programmer Should Know about Memory What Every Computer Scientist Should Know About\u2026","rel":"","context":"In &quot;Senza categoria&quot;","block_context":{"text":"Senza categoria","link":"https:\/\/monodes.com\/predaelli\/category\/senza-categoria\/"},"img":{"alt_text":"Being a good programmer is 3% talent, 97% not being distracted by the Internet","src":"https:\/\/i0.wp.com\/monodes.com\/predaelli\/wp-content\/uploads\/sites\/4\/2015\/10\/Being%2Ba%2BProgrammer.jpg?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":11099,"url":"https:\/\/monodes.com\/predaelli\/2024\/01\/06\/how-standard-ebooks-serves-millions-of-requests-per-month-with-a-2gb-vps-or-a-paean-to-the-classic-web-alex-cabal\/","url_meta":{"origin":5851,"position":3},"title":"How Standard Ebooks serves millions of requests per month with a 2GB VPS; or, a paean to the classic web &#8211; Alex Cabal","author":"Paolo Redaelli","date":"2024-01-06","format":false,"excerpt":"Source: How Standard Ebooks serves millions of requests per month with a 2GB VPS; or, a paean to the classic web - Alex Cabal Standard Ebooks is a project that takes transcriptions of public domain literature, like the kind typically available at Project Gutenberg, and creates beautiful, modern ebooks out\u2026","rel":"","context":"In &quot;Senza categoria&quot;","block_context":{"text":"Senza categoria","link":"https:\/\/monodes.com\/predaelli\/category\/senza-categoria\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":13146,"url":"https:\/\/monodes.com\/predaelli\/2025\/04\/19\/aevitanda\/","url_meta":{"origin":5851,"position":4},"title":"\u00c6vitanda","author":"Paolo Redaelli","date":"2025-04-19","format":false,"excerpt":"per installare il Certificato Sectigo (2023, valido per 3 annni) per certificare il software ho dovuto usare Edge in modalit\u00e0 Internet Explorer.... Davide Costa su commentando un pezzo ironico su Vita da informatici Credo metter\u00f2 codesta \"Sectigo\" sulla lista delle organizzazioni da evitare\u2026 in latino \u00e6vitanda perch\u00e9 usare liste di\u2026","rel":"","context":"In &quot;Web&quot;","block_context":{"text":"Web","link":"https:\/\/monodes.com\/predaelli\/category\/web\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3599,"url":"https:\/\/monodes.com\/predaelli\/2017\/12\/27\/basilisk-web-browser\/","url_meta":{"origin":5851,"position":5},"title":"Basilisk web browser","author":"Paolo Redaelli","date":"2017-12-27","format":"link","excerpt":"This Basilisk web browser\u00a0will be a boon for all those people who need to still use Java and Flash based websites: Full support for JavaScript's ECMAscript 6 standard for modern web browsing. Support for all NPAPI plugins (Unity, Silverlight, Flash, Java, authentication plugins, etc.). Support for XUL\/Overlay Mozilla-style extensions. Experimental\u2026","rel":"","context":"In &quot;Software Libero&quot;","block_context":{"text":"Software Libero","link":"https:\/\/monodes.com\/predaelli\/category\/software\/software-libero\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/posts\/5851","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/comments?post=5851"}],"version-history":[{"count":0,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/posts\/5851\/revisions"}],"wp:attachment":[{"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/media?parent=5851"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/categories?post=5851"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/monodes.com\/predaelli\/wp-json\/wp\/v2\/tags?post=5851"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}