• Resolved Michael Samson

    (@illuminice)


    Hi Raul,

    We spoke a little over a month ago in this thread:

    https://www.ads-software.com/support/topic/purging-the-fvm-cache-and-interaction-with-aws-cloudfront-cdn/

    I’ve been busy developing our platform over the past few weeks and had to turn my attention elsewhere for a while. Tonight I updated FVM and saw you made a lot of improvements (my compliments). I’ve been reviewing some of those and wanted to follow up with you.

    If you recall the last time we spoke I was concerned about the number of cache files. I had observed that the cache was creating separate files even though the pages had near identical requirements. This was occurring particularly with our profile pages which run on BuddyPress.

    This problem was never solved, and I just had to put it on hold until now. So tonight I updated the plugin and found that it was now inlining all of our css code. I saw the new inline options you added which were turned on by default.

    In the settings you recommend inlining of all css, but then say only if the files are small enough. We have some enormous css files, the largest of which is currently 609 KB (with over 15,000 lines). I found that the plugin was already inlining everything when I updated it, and so far I don’t see any issues on the site. So my first question is, should I allow the plugin to inline all css even if we have very large css files?

    My next question gets back to the original problem, about the cache growing exponentially in size. When we spoke last time you said the reason the cache was duplicating files was because the pages were slightly different, likely from inline css. If I am now allowing the plugin to inline all css, will this still have the same problem with the cache growing huge? Keep in mind that we are building a social media platform that will ultimately have millions upon millions of pages.

    I really like this plugin a lot and want to keep using it. But I also must be careful about this cache. The cache is being stored in the EFS (Elastic File System) in our AWS stack. This is necessary in order to centralize it in our load balanced environment. I need to be careful about the size of the cache because the storage costs of the EFS are quite expensive. We only keep files on the EFS that must be shared between all servers, which for the most part are a very few small files. The cache files from FVM are the exception, and this is why I want to find a way to minimize its impact.

    I may be asking the impossible here because all of our pages will be sightly different from one another, even though they are all sharing mostly the same css files. I’d greatly appreciate your insight and advice on this subject.

    P.S. I just wanted to note that the only files I currently see in the cache are in the /fvm/tmp/ directory. I assume this is normal when inlining all css.

    All my best,

    ~ Michael

Viewing 7 replies - 1 through 7 (of 7 total)
  • Plugin Author Raul P.

    (@alignak)

    Hi Michael,

    The short answer is that you need to test how is the cache growing and where exactly are the differences ??

    Here’s some more info:

    a) FVM, primarily creates a unique hash name based on appending the “handles” names of the enqueued css/js files. Handles are defined when you enqueue your css and js files.
    https://developer.www.ads-software.com/reference/functions/wp_enqueue_script/

    b) WordPress uses dependencies, meaning that you can append inline data for both js and css files using wp_add_inline_script and wp_add_inline_style
    https://developer.www.ads-software.com/reference/functions/wp_add_inline_script/
    https://codex.www.ads-software.com/Function_Reference/wp_add_inline_style

    If there is any, FVM will minify and then create another hash out of that “unique” minified code, append it to the handles names and then hash the final, unique result again.

    c) If on any page, post, category, etc… any of the handles or inline css/js change, it will obviously have a new unique hash, thus creating a new cache file.

    d) FVM copies all css and js files it sees and first minifies them independently to an intermediate cache on the fvm/tmp directory. While checking for c) will collect a list of files (and inlined code) to be merged, and reuse any of the previously minified, independent files… so it minfies once and reuses those copies to create merged files.

    To evaluate you need to verify if each page is actually really creating new files per unique url or not, or if it’s just the name changing, or if it seems that there is unique css code on each page but in fact, there is a large number of slightly different number of unique inlined css files that sometimes, repeat on other urls.

    For example, let’s say that the inline css for a user profile that has filled 10 fields, has 10 classes inlined.
    Another user has filled 12 fields on his profile and he now has 12 classes inlined on his profile url.

    You need to check if all users that have filled the same exact amount and type of data, all share the same css or if, regardless of them being almost an exact copy of each other (except for the text or image), they still trigger a new css file, or css handle name.

    Create 2 profiles which are identical to each other, except on the information provided. Disable FVM and do a diff check on the saved html for any css or js name or content changes.

    If those 2 similar profiles share the same exact handle names and inline code, FVM will only generate 1 file for all. If it generates 2, something is changing (enable the debug mode on FVM and check your html for comments of what is being processed).

    If you only have 1 file generated by FVM, then that should be correct.
    It doesn’t matter if other profiles generate yet another css file, because now you know that similar profiles will share their css.

    If the data is similar, but the name changes… something is horribly wrong with whatever is generating that. It may be better to simply manually dequeue any generated css/js that is causing that, dump all code into a static file and enqueue it as a static file.

    https://developer.www.ads-software.com/themes/basics/including-css-javascript/

    When you inline all css, a couple of things happen after my updates.
    It now skips merging the css, although it still copies and minifies each css and it’s inlined data to a temporary directory, but this time instead of merging it first, it outputs the code directly into the theme.

    That means, if one of your css files change, or if one of it’s inlined code (children) changes, a new minified cache will be generated for that file only, instead of a new larger cache file every time.

    The cache will still grow, but at a slower rate… so your goal, is to make sure the css that is changing stays static and doesn’t change.
    You have to check where that different css code is coming from and instead of loading bits and pieces, remove that logic and have it all in one enqueued file instead.

    If each user is allowed to style it’s profile page, then you have to recode that functionality to output the personalized css code, not inlined as a child of the theme/plugin, but rather as another file (which could be a php file with some unique query string and some logic).
    You would then exclude that file from FVM so the rest of the files won’t change, and FVM stop detecting that change.

    Nevertheless, let me say that having unique cache on every profile is not good practice. You should have all possible css code in one css file and that’s it.

    In regard of inlining large css files, it usually doesn’t matter much because of gzip/brotli compression. Even if you inline 1 MB of CSS, that’s still probably going to be less than 256KB compressed (maybe).

    As a rule of thumb, I always inline css on the footer, then evaluate it the header can be inlined or not.

    How you decide if you should inline it or not… is with google pagespeed insights.
    You setup a cache plugin and try with and without inline, repeating the test a few times to make sure the html has been cached.

    If you have too much css in the header, pagespeed will start complaining about the time to first byte (it seems that someone at google doesn’t really understand what ttfb is… they probably meant to call it, prioritize visible content instead, but whatever).

    When you don’t inline, it will complain about the render blocking css instead.
    That’s why you look for the score before and after to decide which one to use.
    There will be a level where inlining will give you better score, but when it’s large enough, having it render blocking will be better.

    In regard of EFS… if I’m not mistaken, FVM works separately on each server if you want. You could define a “local” cache directory on FVM settings and have each server generate it’s files locally, per server.

    It gets the “latest version number” from the database, and the unique factor from the handles and inlined css/js code. If you use a local path instead of EFS, it will always check if the file exist or not, and if not it will create it again on each server.

    That should be fine, because the hash should be the same on all servers… and the only drawback, is that whenever you hit a server without a fvm cache, it will regenerate it again.

    Page cache… I’m not sure how you are using it, but if each server has its own cache, it will work.

    If instead, you use elastic to cache the html on memcached, then the referenced js/css file may not be there because there was no php request to trigger the regeneration.

    In that case, you could instead use Varnish and use it as a reverse proxy to the load balancer… it would hit whatever server, have FVM generate the file and then cache it on Varnish directly. Then it wouldn’t matter if other servers have the cache file or not, because when the next varnish cache is invalid, it would trigger any server php, which would then regenerate the file and repeat the process.

    Finally, if EFS is too expensive, you could create an s3 bucket and use it as a mounting point for the uploads/fvm directory (do not do this for the php files).
    https://cloud.netapp.com/blog/amazon-s3-as-a-file-system

    It will be slow(ish) creating them, but at least they will be available for everyone.

    I guess someday I’ll rewrite the plugin to make use of REDIS, Memcached… and then perhaps, something like AWS Elasticache or your own cache server can be used.
    It’s on the roadmap, for when I have time…

    Thread Starter Michael Samson

    (@illuminice)

    Hi Raul,

    Your responses are truly first rate! Thank you for such detailed information.

    I could speak at length about many parts of your response, but I’m going to just focus on what I need to know right now.

    I am really only concerned about three things…

    1. Improving page load time, efficiency, etc.
    2. Not keeping an unnecessarily large cache.
    3. Not breaking functionality with the optimizations.

    I agree with you that I will need to closely monitor the cache after we launch to see how it is growing in size, and what is contributing to that growth. On that note I have read your comments on this and will analyze the cache as we move forward.

    There is one key difference with regards to the cache when using all inline css vs. the combined files method. When the combined files were being created it was a concern because so many caches were created even for pages that should have been identical. I know there were reasons for that as we discussed. But the bottom line was it would have been a growing problem, literally.

    With the inlining of all css those combined files are completely eliminated. As you have described the css is basically collected for the page, minified using the tmp directory, and then inserted inline into the header/footer of the page. This leaves me wondering about cache footprint when inlining all css. On the surface it would seem that the cache would be a lot smaller because you only need a temporary cache to minify the content. However it does seem that the files in the temp directory do stay there, so this is not truly a dynamic process. Obviously the minified content is being saved to some extent so it can be reused without having to reprocess all that css.

    This is where I am curious to know if we will be better off in terms of cache size by using only inline styles. Your thoughts on this would be appreciated.

    Your comments about Google ranking and how it interprets the amount of inline css were interesting. I could see how Google may not like so much non-visual code being at the top of each page. It makes sense. But I am less worried right now about the rank, and more concerned with what improves our loading times and overall page efficiency. This is after all why I chose this plugin to begin with.

    About the EFS, it is better for us to stick with it then storing the cache data on the individual servers. The main reason for this is we have a truly stateless architecture for the individual servers and I want to keep it that way. I don’t like the idea of separate caches on the servers that differ from one another. This is exactly why we are using the EFS to centralize the little bit of dynamic data we do have. However, I do like you idea of taking advantage of a cache server/service such as AWS Elasticache. Our entire infrastructure is on AWS, so it wouldn’t be difficult for us to extend FVM to use something like that.

    Our platform is launching sometime in February, so we are still pretty early here to truly understand how FVM will behave when the site grows. Suffice to say this is something I will have to continue to monitor. At the moment I am liking the all inline css because it eliminates all those combined cache files. But I am not certain if this will remain a practical solution.

    Thank you again for your continued advice and support!

    ~ Michael

    Plugin Author Raul P.

    (@alignak)

    With the inlining of all css is on, merging is eliminated for css.
    That means, the initial impact is around 50% savings on the (css) cache size.

    In reality, savings will be more than that…

    There will be an invariable amount of css files that never change, so for those the cache is static and reused for all pages.
    That means, it will only trigger another cache file for a smaller, unique css file/inline it finds.

    Inlining css is a good option for eliminating render blocking scripts but watch out for the final html size after compression (the amount of data each user downloads per request).

    When you have external css files you can offload them to the cdn, but if you inline them, you cannot.

    That means, if your gzipped page with inline css is 250 Kb, 4 (simultaneous) requests per second will eat 1MB of bandwidth, 40 req/sec will eat 10MB (~100 Mbps) and 400 will eat 1Gbps.

    If on the other hand your gzipped html is 25KB and CSS is 225KB as an external file, the cdn will take the hit and your server can scale better.

    Nevertheless, wordpress can do at most 1 or 2 req per cpu core uncached… so make sure you consider a good cache strategy and amount of data to transfer.

    Score is directly correlated to speed… but pagespeed doesn’t consider scaling.

    Plugin Author Raul P.

    (@alignak)

    Also if you know which css is changing every time and causing the new cache generation, you could hack the plugin or use some hook to “echo” that inline css directly on the header, instead of enqueuing it. That way FVM won’t see it and thus, only merge the common files.

    Thread Starter Michael Samson

    (@illuminice)

    Hi Raul,

    Thanks again for the excellent response…

    There will be an invariable amount of css files that never change, so for those the cache is static and reused for all pages.
    That means, it will only trigger another cache file for a smaller, unique css file/inline it finds.

    I like the sound of this a lot, so that the same css is not cached over and over again. To be completely honest I really do not know how much inline/dynamic css we are dealing with. The site is so huge and complex, and this is just one aspect of it I have not examined yet. I should mention that I am the person behind all the custom css on the site. But there are likely dynamic processes going on that I am unaware of.

    Inlining css is a good option for eliminating render blocking scripts but watch out for the final html size after compression (the amount of data each user downloads per request).

    What is the easiest way to determine the final HTML size? I’ve never attempted that before. Would it be as simple as taking a View Source and saving it to a text file? That would include all the inlined css.

    When you have external css files you can offload them to the cdn, but if you inline them, you cannot.

    That is true. Even with the larger cache from the combined files, those files would all have been cached in the CDN, even though they were coming from the EFS as an origin.

    Nevertheless, wordpress can do at most 1 or 2 req per cpu core uncached… so make sure you consider a good cache strategy and amount of data to transfer.

    We’re not using any kind of server-side caching right now because the site has a great deal of dynamic content. It may be possible to cache our pages in some way, but it would be extremely complicated. I’ve had this on the back-burner for a long time now. Instead we focused on a client-side method of caching page content that allows our pages to run efficiently and not overload browsers. This is another topic entirely.

    Our site is extremely heavy in every aspect… media, nodes, scripts… it is very complex. I have been concerned about this from day one. We’ve made the site as efficient as we can, and it does load relatively fast considering what is being loaded and the sheer amounts of data. But suffice to say this is something I think about a lot.

    Let me ask you this, would you consider looking at our platform as a paid job to help us assess where/how we can improve things related to loading and efficiency? If this is something you’re open to we can connect directly via email. I rarely bring in people from the outside, but you may be the right person to look at this.

    ~ Michael

    Plugin Author Raul P.

    (@alignak)

    I would need to evaluate the site to give you my more in depth opinion.
    Reach me via fastvelocity.com contact form, with a reference to this post.

    As for html size, you can use the google chrome dev tools, under the network tab.
    Look at the first request, refresh if it’s not showing.
    https://prntscr.com/ltwhw5

    Thread Starter Michael Samson

    (@illuminice)

    Hi Raul,

    Having you evaluate the site is exactly what I have in mind. I’ll reach out to you on your contact form directly.

    That’s a nice trick in the Network tab there. I don’t use that tab very often and didn’t realize it gave you the document size like that. Very convenient. Our document size including all of the inlined css is 270 KB (for our home page). It’s worth noting that our pages (which are largely post/media grids) only initially load with 20 posts. We have a form of infinite scroll in place that loads the “cards” in batches of 20, and then caches any cards not currently in the viewport. That is the custom caching I referred to earlier.

    I’ll contact you now from your form and will reference this thread…

    Thanks for being open to talking more!

    ~ Michael

Viewing 7 replies - 1 through 7 (of 7 total)
  • The topic ‘Inlining All CSS and Overall Size of Cache on Large Site’ is closed to new replies.