-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Share your Performance Wins! #41
Comments
Have spent about a week learning how different liquid structures perform. Just attacked our homepage for the last day, targeting low-hanging (no rewrite) stuff.
This is awesome so far, thank you. I was seriously considering a total rewrite the week before you released this because of how opaque our liquid was. |
@lukechadwick I'm more interested in finding out how on earth it was that high, to begin with! |
A combination of Bold and Swym snippet loops OG: https://screenshot.click/11-30-vi3qy-f7dwg.png Not necessarily the fault of Bold/Swym's apps, the general state of this theme was in pretty bad shape. A lot of app code scattered around from installs/uninstalls over time, and built on a pretty old version of Brooklyn. |
Fair enough. Thanks for sharing @lukechadwick. It's awesome the extension was able to help you so much! |
@lukechadwick We're in the same boat; even our numbers were similar. The liquid speedups were excellent but we learned that only about 1/10 visitors were triggering a liquid recompile. This was the real impact of refactoring from 12.5s compile time to 1.2s Blue is liquid compile time, averaging in 5 minute intervals. |
@tehaksbrid How did you determine that only 1/10 were triggering the liquid recompile? We've been seeing 50% of people getting CDN misses. What did you use to generate the graph you shared? Is the liquid compile time you're measuring the actual compile time or a close approximation metric like time to first byte? |
We sample performance metrics from all site visitors whose browsers support navigation timing level 2. That graph doesn't measure it directly, it's something like TTFB (specifically, the PerformanceNavigationTiming value of When plotting our homepage first loads, we found that 90% of users fell in a band 0.5-2s TTFB and the remainder showed the TTFB times we were expecting from liquid profiling. To me this was strong evidence that the template cache was succeeding. |
Went from ~5000ms down to 353ms. 😱 All by removing Locksmith app (on test site). Can't completely remove it from live site, but after a first pass of tidying up the app, live site went from 5052ms to 3811ms. Clearly more to do here. This may be a good argument for using the Shopify Plus wholesale channel! |
@susanlangenes i'm interested in this usecase with locksmith could you elaborate on what's blocking making changes in regards to locksmith? |
@tehaksbrid That is amazing! Even if only 1/10th of your visitors are triggering a liquid re-render, you prevented these visitors from experiencing 12.5 seconds wait on the page. @susanlangenes Thank you for identifying a liquid rendering impacting app! This is worth noting for wholesale shops |
@PaulNewton maybe? I personally wasn't involved in setting up Locksmith and this is my only client who uses it, so I don't know if it's a typical install. If you want to check it out, the site is slumberkins.com. What I think I see is that for every item in any linklist (navigation menus) Locksmith appears to be doing stuff.
Similar code exists for all navigation items in the header as well, which contains two versions of navigation (desktop and mobile). When I went through the theme and removed every instance of this type of code, that's when I got down to ~350ms. |
@susanlangenes @PaulNewton similar experience on several different stores, here's an example: Before: https://screenshot.click/21-31-9prk8-2r23q.png I think the main issue is that locksmith wraps it's code around so many different things (lock-smith has an autoinstall feature), including larger loops like collections and link-lists. This means the locksmith-variables snippet has to be rendered many times, which has it's own loops, variables and logic that add delay for each iteration. This tanks performance when you have a fairly long link list or collection, so I think the only solution is to remove lock-smith from non-sensitive snippets that it doesn't need to protect. |
@lukechadwick thank you for chiming in - I really didn't know what to make of this, but my experience seems to be matching yours, and I agree with your suggestion of stripping it down where it's not needed. |
@susanlangenes |
@lukechadwick For anyone where this is critical a possible alternate to explore is ajax loading the auth content; move the perf hit into perceptual speed with loaders,transitions, or on user interaction. Pull in the auth content from different page templates one set for what is "public" content and the other for serving authorized content(without a layout), or two themes one preinstall one post install. (meaning "public" is a blank surface serving nothing but basic presentation to avoid unauthorized access) Obviously that really only works if the theme is:
Though having 1&2 probably means it's all custom so no app like locksmith is being used anyway. |
@PaulNewton yeah I thought about an ajax solution for shops like this where it's necessary to have a lot of links. Or hey! Could throw a react app on top of it and away we go! Unfortunately there isn't budget for that at the moment. |
Hey crew! I wrote Locksmith. Performance is hard, when you're doing the kind of comprehensive checks that have to happen, to cover all the bases we're covering, without a cache mechanism available at the Liquid tag level. Having said that, there's gotta be a way to make this better. I feel you. I'm looking. And I'm glad the theme inspector is help you find the pain points - massively useful tool. In the meantime, when you identify a place where Locksmith's snippet is draining your performance and where it doesn't need to be there: add that theme asset to your Locksmith asset blacklist, available in your Locksmith account settings. Locksmith will strip itself out of that asset, when you do so. If you need to selectively re-add Locksmith to part of that asset, to protect something specific, use our guide on manual mode as a reference. If you're still having trouble, yes, [email protected] is the place to start. ❤️❤️ |
@isaacbowen that's very helpful! Thank you! |
@isaacbowen @wizardlyhel I have an update. After adding quite a few filenames to the Liquid asset blacklist in Locksmith (Settings > Advanced), our PDP went from 4496ms to 802ms. Homepage went from 2877ms to 470ms, and a custom holiday page template went from 3473ms to 749ms. This is a reasonable solution for my client because they typically only use Locksmith for early product releases to VIP groups where they lock a collection or product and give the VIP folks a direct link; there is never access through navigation or anywhere else on the site. Isaac, and everyone, thank you for taking the time to discuss this and help sort it out. We are thrilled to be able to keep Locksmith, AND have a very snappy site now! |
@susanlangenes Phenomenal. Excellent work! 👏 Thanks for letting us know; happy this approach worked well for you. :) |
While trying this tool to try to optimize our themes (started with our theme Warehouse), I figured out that actually, a lot of time was spent on... the header! It is true that our header has lot of feature, but it is one of the piece that is the most optimized in our code and where we cannot do a lot better in terms of Liquid code (each if/else break early, we only use simple condition...). It seems the time is actually spent on building the dropdown menu (iterating through menu.links, link.links and sub_link.links). This code cannot be optimized further on our end, but this lead me to think about something:
If that is indeed the case, this means there would be a huge possible improvement to be done on Shopify end by making sure to not eagerly load all the associated data of a menu. In overall I found that when trying to optimize themes (especially for themes with lot of features like ours), one main issue is that we do not have a lot of info on what is Shopify doing "under the hood". For instance if we have a link with a collection, does accessing the link will load the collection? If we iterate through the products of a collection, does accessing a property of the product will pre-load the variants... that kind of things! Having an advanced guide on how exactly the Liquid renderer works internally would help a lot. |
@bakura10 You are spot on with your points. At Shopify, we actually have no idea how external developers use liquid on themes and the different ways to work around the limitations of the platform. The purpose of this Chrome extension is to help you better analysis what is happing on your theme from the server level so that you can find ways to optimize and gain that web performance that you need. My hopes is that this knowledge is shared as we all aim to build for a better user experience. If you find some performance issue with any liquid drops, let us know (even better if you explain how you test it). You are right about |
Thanks for confirming! linklist was indeed my biggest surprise, I really didn't expect this to be an actual bottleneck in our theme's code. I suppose that we cannot do anything to optimize further this (it is not possible to hardcode the links in a theme). I hope there will be some improvement in that area :). |
Another two big bottleneck of our theme @wizardlyhel:
Basically, I have figured out that as soon as you start accessing product variants on collection page, the impact on performance is high! I would like to be able to build the collection pages without having to access any variant variable at all, but there are many limitation for now that prevent me to do that. |
Another very odd thing I have found: getting the product.price has a super big impact on performance. I have tried to set up a collection with several products all containing 100 variants to stress test it. Doing: {{product.title}} has nearly no impact on performance. However doing {{product.price}} triples the render time ! Not sure why, as it seems to be a product variable. |
@wizardlyhel will there be a wiki for this project or a separate place to make collaborative docs? Until then, Alternatively skip it in the main content and load it into a blank layout with only that content and load it with ajax separately on demand. Validating and Measuring Bottlenecks: |
I agree with that partially but I get the sense with theme perf shopify reaaally wants to see use cases,partner feedback,docs, etc. or seeing what partners build ontop of it.
It's been a while since I touched the warehouse theme. For inventory a UX approach could be a much healthier option, or temporary boost.
Isn't the liquid perf hit here because the theme fetches the entire page and not just the json endpoint? |
Hi @PaulNewton , Thank you for your replies.
Basically, what I am looking to do is, for each color, getting the first associated variant with this color, so I can add attribute such as the variant ID, changing the tile image to the variant image... But on collection pages that contains products with lot of variants, as soon as you access the product.variants performance are hit. With a collection page with 10 products each containing 100 variants, we already cross the 10s in render time. I have tried an approach yesterday that avoids getitng at all the "product.variants" drop, by fetching it dynamically in Ajax whenever someone click on a swatch. There is of course a small delay incur, but this allowed to reduce the render time for 10s to 2s for those heavy use cases. Which is why I suppose that accessing variants on collection page is something that should be avoided at all costs due to the performance impact. Does that make sense? :) |
Michaël, of course that makes sense (your last line) and of course, that is
exactly what my client wants right now. Oof.
I really appreciate your time and efforts at laying this out (everyone else
here, too).
Susan Langenes
Collage Creative <http://collagecreative.net> | 503.317.5825
…On Sun, May 31, 2020 at 7:05 PM Michaël Gallego ***@***.***> wrote:
Hi @PaulNewton <https://github.com/PaulNewton> ,
Thank you for your replies.
1.
Of course, as a theme developer, neither the approach of hardcoding
the menu nor loading it in Ajax for SEO reasons is a realistic workaround
for the menu. I suppose that for the specific case of linklists, we will
have no other choice than waiting that this is improved at Shopify level. I
will pass the message to the custom team department though, as they may
benefit from hardcoding links (although it honestly removes lot of
flexibility for the merchant, so I am not sure a lot of merchant will agree
with the fact they have to reach a development team whenever they want to
edit a link in the navigation).
2.
For the inventory, this does not remove the fact that to calculate the
"more than xx", you *will* need to iterate through variants. My
experience is that as soon as you access the product.variants drop, the
performance hit is incurred.
3.
For the color swatches, we are actually doing that in Liquid. Here is
a short snippet:
{%- for option in product.options_with_values -%}
{%- assign downcased_option = option.name | downcase -%}
{%- if color_label contains downcased_option -%}
{%- assign variant_option = 'option' | append: forloop.index -%}
{%- for value in option.values -%}
{%- assign downcased_value = value | downcase -%}
{%- for variant in product.variants -%}
{%- if variant[variant_option] == value -%}
{%- assign variant_for_value = variant -%}
{%- break -%}
{%- endif -%}
{%- endfor -%}
Basically, what I am looking to do is, for each color, getting the first
associated variant with this color, so I can add attribute such as the
variant ID, changing the tile image to the variant image...
But on collection pages that contains products with lot of variants, as
soon as you access the product.variants performance are hit. With a
collection page with 10 products each containing 100 variants, we already
cross the 10s in render time.
I have tried an approach yesterday that avoids getitng at all the
"product.variants" drop, by fetching it dynamically in Ajax whenever
someone click on a swatch. There is of course a small delay incur, but this
allowed to reduce the render time for 10s to 2s for those heavy use cases.
Which is why I suppose that accessing variants on collection page is
something that should be avoided at all costs due to the performance
impact. Does that make sense? :)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#41 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAWWUNIAUOC47E2A2KJCCHTRUMEHLANCNFSM4KOMOM3A>
.
|
That's an interesting idea
Stay tune on this
This is where we need to balance out the responsibilities of where should the render happen. Can we optimize for both the server and client end? For example, instead of iterating all 50 products on a single pagination, reduce this to 10 (number of products you can see above fold), and ajax load the rest - optimizing for time to first byte and first render timing. |
Interesting finding: product.featured_media is much more expensive than product.featured_image (about two times slower, which adds up on collection pages). |
Could someone explain to me how exactly this theme inspector tool can be utilized? I've downloaded the tool, accessed it through the Developer Tools under Inspect, but no cigar. It does not show up as an option. Any ideas on what's going wrong? Note: I'm not a developer. Just interested in improving Shopify site speed overall for my clients. |
I'm not sure where best to ask this and I feel another issue might be off-topic for this but what are we aiming for in terms of render time? I've been aiming for ~1k or less but I have no idea if that is still crazy high or even too low. Does anyone have any targets they try and strive for? |
@Tom-SUS You need to be a staff or a collaborator in order to run the profile. Since the Shopify tab isn't there, please make sure you are login with the Shopify icon in the top left of your screenshot. @dan-gamble Not really off-topic. I personally aim for about 200ms - 500ms page render. This is based on a past guideline that Google set for a "good" time-to-first-byte (TTFB) target. While it is no longer a main metric that Google use to determine a performing website, it is a good developer metric to aim for |
Hey @wizardlyhel, still no avail. I've logged in and now it's showing me an error message. I have this video for reference: https://www.loom.com/share/0169016289a54668a6d963a60c83f5ca |
@wizardlyhel thank you Helen. That's something much better to aim for, thank you :) |
mine is not a development store. but i am encountering the same problem as @Tom-SUS is having, just getting a "This page cannot be profiled" message..... :( any insight please @wizardlyhel ? |
I have logged in as Store Owner and also as staff, both did not work. |
anyone any idea please?
anyone any idea please? |
Have continued working on this since this tool was released. Am finishing up a total rewrite of our main store's theme. Overall 90% load time reduction (as measured by DCL) on every page and device/network tier. This tool has been indispensable. One mystery I've uncovered is anomalous document response times on pages with essentially no liquid. 200-800ms to respond with a 37kB document that consistently profiles to 20-30ms of liquid time. Serving the same document with the same code from our dev Plus store gives a consistent 70-120ms response. Traffic? IDK. Any insight on factors that impact response time outside liquid, @wizardlyhel? Sure would be nice to have a root service worker to bypass that TTFB entirely...😉😉 |
We would love to learn how you use this tool and solve your Liquid rendering issues. Comment below and tell us:
Tweet us your wins! @shopifydevs
The text was updated successfully, but these errors were encountered: