Why does chrome Content Download take longer for cached resoures? - google-chrome

I am trying to make the page speed as fast as possible. The problem is that I have one file in particular that takes a long time to download (even if the size is 0 -> loaded from cache)
Here is how it looks without cache (first load):
And with cache:
I agree that the time has dropped by almost 50%, but why do I have a Content Download time from my local cache higher than the one from the server?
NOTE:
I am not sure if the times are explained the same in Safari, but it doesn't seem to take that long to get the file there.
Image from Safari Network tab:

After running tests on several projects and without any code or further breakdown of the content downloaded processes, here is the conclusion I've reached.
System threads set a priority level for each process they are assigned. When a file is stored in the cache then the download performance is, for the most part, dependent on the performance of the machine. If threads are bogged down then it can result in a slower content download than a download from a server. However, a download from a server is typically slower because of all of the processes involved in contacting, requesting, receiving and handling the download.
The advantage of cache is easily seen when handling slow connections and/or large files. For example, if there's 10+ seconds of waiting due to a slow connection then it's not ideal to load the full page more than once. It would take an incredibly slow system to justify sending that page twice.
Since browser cache removes the send/receive process, it is faster but it doesn't remove load times entirely. In this case, it happens to yield a higher load time in one category.
Side note: It seems odd to classify a file as content downloaded when reading it from the cache but it seems to be consistent amongst all of the projects I tested.

Related

How to optimize website for Chrome: waiting and download order of magnitude slower than other browsers

NB: since the answer to this could involve JavaScript or PHP programming, or general networking, or IT systems, I put it here, but if some mod thinks it's better suited for SuperUser or ServerFault, I won't object to it being moved.
I have a landing page to which I'm driving traffic through PPC. I've set up AWS CloudWatch to get RUM data, and the page is performing terribly — an average load time of 9.9s and max of 21.5!
I've done all of the "standard" optimization I can think of or research. The site is built with WordPress, running on Apache on an EC2 server. I've
Upgraded the EC2 instance to ensure I have enough memory
Written a custom plugin to filter out any other plugins that aren't explicitly used on the landing page in question
Customised my theme code so that it sets proper srcset and creates the correct image sizes on upload
Minified all the JS and CSS that I include through plugins or themes I've written
Put the site itself as a distribution to CloudFront
Installed the WP Super Cache plugin, and created a separate CDN distribution on CloudFront for it
Set appropriate cache control headers on CloudFront and told it to gzip everything
Put a facade in place of any videos
The site is blazing fast for me — "load" is less than 1 second. But my RUM says that's not the case for my users. So, I dug a little deeper. 70.2% of my visitors use Chrome, and 27.7% use other, of which almost 1/3rd are Android Browser — which as I understand it is just some sort of "Chrome Lite" — so nearly 80% of my visitors are using some Chrome variant.
Sure enough — if I load the page on Safari (to ensure nothing has expired on CloudFront), clear my browser cache, and reload the page, the first request shows a waiting time of 21.2ms, TTFB of 22.6ms, and download time of 4.8ms. The whole page shows that it's finished loading in 973ms.
Firefox is slightly slower, with the first request taking 100ms total, and the whole load about 1.75s — not blazing fast, but still within the understood "2 second" limit for good user experience.
On the other hand, for Chrome that same first request takes almost 570ms waiting and 208ms download. So, just the first request (which is 36k in size) takes almost as long to load in Chrome as the whole site takes in Safari. And that repeats for every single request, where both the waiting time and the download time are an order of magnitude slower on Chrome than on Safari (on the same device on the same network):
Whereas on Safari:
I would think "waiting" and "download" times would be primarily network driven, but I can repeat this all day long and the results are the same.
I might just assume that Chrome is not optimized for the Mac on which I'm running it, but, as I said, this all started with RUM data, so it's clearly not that. As much as I might like to, I obviously can't force all of my visitors to swap their Android devices for iPhones. Equally obviously, I can't have an average load time of 10 seconds.
So, why is my site so slow on Chrome? What else can I do to optimize this?
The landing page in question is here: https://www.chrisrichardson.info/lp/prague-b/
Note, a lot of the optimization I've done is for that page in particular, so other pages on the site might perform even worse, but I don't care about that, at least at the moment.
Hahahaha.
OK, just leaving this here for posterity's sake. The 10x latency was because Chrome had preserved in devtools from a previous session throttling to 3G. So, if you stumble upon this problem, check your throttling.
That still doesn't address my RUM issue, however, but I'll open that up as a different question.

What does Blink in-memory cache store?

Besides the browser cache, there are a few other ways browser cache data. For Chrome, there is another cache in the rendering engine Blink that stores images, styles, scripts and fonts (maybe more) in memory.
This cache is used for consecutive navigations on a site. Resources delivered from the Blink cache are tagged with (from memory cache) in the network tab. Resources served from the browser cache are tagged with (from disk cache).
My question is now, which resources are stored in and delivered from this very fast cache? From my tests, it varies a lot:
It works extremely well for images and script tag which are directly in the HTML.
It works sometimes for style (link) tags which are directly in the HTML. Sometimes it does not work (in the same browser with the same session).
It works almost never for script tags that are inserted into the HTML programmatically. Sometimes it works though.
One huge difference between disk cache hits and memory cache hits becomes visible in combination with Service Workers. Requests that are served by the in-memory cache cannot be observed in the Service Worker (because the cache comes before the Service Worker). Requests that are served by the disk cache pass through the Service Worker (since the Browser Cache lies behind Service Worker).
To show the explained behavior, I built a test page with all resource types: https://dm-clone-optimized.app.baqend.com/
You can navigate through the site with the links at the top and observe how the requests behave in the network tab and console. Every page loads the same resources.
After a bit of navigating (Chrome 70.0.3538.67), I get this behavior most of the time:
HTML is fetched from network
Script tags scripts.js and scripts2.js are from in-memory cache
Image tag logo.png is from in-memory as well
Style link tag styles.css is from disk cache :(
Programatically added script tag scripts2.js?id=1 is from disk cache as well :(
Sometimes though, I get really lucky and everything is served from in-memory cache:
I would love to understand how the Blink in-memory cache works and how I can tune my site to use it for all resources with appropriate cache control header.
---- edit ----
What concerns me the most is: Why are dynamically added scripts not cached at all? This has a noticeable impact on frameworks like require.js since they insert all dependencies as dynamically added script tags.
Blink in-memory cache works
Blink has four memory allocators
PartitionAlloc, Oilpan, tcmalloc, and system allocator
So the team working on Chrome Blink has removed tcmalloc and system allocators from Blink
Blink (PartitionAlloc+Oilpan) is the second largest consumer of renderer’s memory which consumes 10 - 20% in typical cases and retains some of the memory in Discardable, CC and V8
Inside Blink, the primary memory consumers are:
Large StringImpls (used by JavaScript source code)
shared buffers (used by Resources)
Vectors and HashTables
The recommendation is to: "identify caches that have an impact on Blink’s total memory and implement purgeMemory() only on them."
Reducing the size of (DOM object) won’t have an impact
Discarding caches won’t affect in most cases
They are working on getting rid of "DiscardableMemory" items which will help to do things like forcibly detaching all layout objects which in turn will release memory retained by the layout tree.
I believe it is a result of optimization in chrome, and they make it verbose to you.
The files are always go into disk cache. And they also goes into memory, and flushed very soon.
Chrome is smart enough to ask running process that do they still have a loaded copy of them in memory before seek on disk.
The step has a high hit rate, as those images/js are actively using for something.
You will not have any control how chrome manage TTL of them/capacity of memory could be used to keep blob hot. Chrome dev team doing quite a lots on dynamic tuning based on actual hardware capacity and system loading.
P.S. If you are asking for keep YOUR APP in memory. You are failing into Sun/Adobe way of evil: making their app DLL hot in memory(by tray icon/service) and slow everyone else down.
P.P.S. If it is the app end-user might want to use, use electron and follow Whatsapp/Slack/etc to build an app always running.

Chrome running out of memory

I've developed a Chrome Extension that cycles through approximately 1500-2000 pages to collect information from a website and push it onto my own server. I use a Chrome extension, as given the requirements it's much easier to configure than making and parsing from the server side.
The extension is used only for internal purposes and we trigger this job using the chrome.alarm API to run at 3:00 am every day. This alarm when triggers pops open a new tab and runs through the 1500-2000 pages. The problem is when we check in the morning we see the SNAP dialogue after the extension has cycled through about 1500 pages (approx 3/4). I'm presuming this is due to the memory demand placed on Chrome to maintain such an unusually large history?
My question is, what would be the best way to mitigate this? Presumably killing the tab and reopening (after x number of pages) would work but that would slow down the feed and require quite a bit of code re-factoring. Is there any way you can force Chrome to dump the history and would doing so free memory in the immediate session?
Just to add some context, I am running this on a extra small VM with only 1 GB of memory. I appreciate I could upgrade the VM but that really just defers the problem.
It's hard to make a solid recommendation without seeing your code, but here's something a bit more general:
The problem is likely the information that is being collected. It continues to build up in memory until you run out. You might consider saving the results to local storage using Chrome's unlimited storage capability. In manifest file:
"permissions": [
"unlimitedStorage"
],
What I would probably do is save to local storage after every page, or something similar, and then reset the array (or whatever you're using).
UPDATE
If indeed history is the problem, you could consider deleting it on the fly. This function will delete entries for a specific URL:
https://developer.chrome.com/extensions/history.html#method-deleteUrl

Chromium: is communicating with the page faster than communicating with a worker?

Suppose I've got the following parts in my system: Storage (S) and a number of Clients (C). The clients are separate Web Workers and I'm actually trying to emulate something like shared memory for them.
Right now I've got just one Client and it's communicating with the Storage pretty intensively. For the sake of testing it is spinning in a for-loop, requesting some information from the Storage and processing it (processing is really cheap).
It turns out that this is slow. I've checked the process list and noticed chrome --type=renderer eating lots of CPU, so I thought that it might be redrawing the page or doing some kind of DOM processing after each message, since the Storage is running in the page context. Ok, I've decided to try to move the Storage to a separate Worker so that the page is totally idle now and… ended up getting even worse performance—exactly twice slower (I've tried a Shared Worker and a Dedicated Worker with explicit MessageChannels with the same results).
So, here is my question: why sending a message from a Worker to another Worker is exactly twice slower than sending a message from a Worker to the page? Are they sending messages through the page? Is it “by design” or a bug? I was going to check the source code, but I'm afraid it's a bit too complex and, probably, someone is already familiar with this part of Chromium internals…
P.S. I'm testing in Chrome 27.0.1453.93 on Linux and Chrome 28.0.1500.20 on Windows.

html5 file system api - chrome hangs and crashes in multiple read and writes

I have a background thread(web worker) fetching heavy images from server and writing them to the file system synchronously.
At the same time, user needs to scroll through images which have been written already into the file system. So each time a scroll event is fired, a file is read from the file system asynchronously and displayed in the canvas. This process generates simultaneous reads and writes if a user scrolls through multiple images at once and hence causes the browser to hang and eventually crash. How can I be able to accomplish this without getting the browser to hang?
Please note: this is a wild guess on what is happening, one can never be 100% sure without knowing what actually your code does.
Chances are, your approach requires a lot of JS heap memory (e.g. you never cache images already read but re-read them discarding previous data.) Hangs may result from multiple full GC's in V8, and the eventual crash results from V8 running out of memory.
I suggest that you use Chrome Developer Tools' (Ctrl+Shift+I) Profiles panel and take a few heap snapshots before the tab crashes. Then you can compare them (the right SELECT in the bottom status bar, choose "Objects allocated between Snapshots 1 and 2") to see the if this hypothesis is right or not.