Skip to content
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

Add profiling support #80

Open
macournoyer opened this issue Oct 9, 2020 · 6 comments
Open

Add profiling support #80

macournoyer opened this issue Oct 9, 2020 · 6 comments

Comments

@macournoyer
Copy link
Contributor

Right now, only Ruby Liquid has profiling. Profiling Liquid templates in production triggers Ruby Liquid to render the template, not Liquid::C. This is leading us on the wrong paths RE what to optimize.

I need to look at how other VMs are doing profiling with low overhead.

@dylanahsmith
Copy link
Contributor

Profiling Liquid templates in production

Is that something we are using? Since it doesn't look like we are using the profile: true Liquid::Tempate.parse option.

triggers Ruby Liquid to render the template, not Liquid::C. This is leading us on the wrong paths RE what to optimize.

Do you mean "us" as implementers of the liquid API? Since I believe we use stackprof for profiling our code in production. That will profile rendering with Liquid::C, although it won't show where the time is spent in the C code. For that purpose, we will want a sampling C profiler, which works like stackprof, but gets the C stack trace periodically instead of the ruby stack trace.

For development of liquid-c on MacOS, I've added a c_profile rake task that works with Xcode's instruments command (#62).

I need to look at how other VMs are doing profiling with low overhead.

We should also allow template authors to profile their liquid code.

A sampling profile works better for a single tenant use case, where it can be used across renders and capture. If we are just trying to profile a single render, then we may not collect enough samples. If we increase the sampling frequency to collect more samples, then we add more significant overhead. For local development, we render multiple times in a loop to collect enough samples with a sampling profiler, but naturally that redundant rendering is a significant overhead.

If we did want to implement a sampling profiler, then we could expose a stack of liquid source locations from the Liquid::Context that could be used by a sampler.

Another option would be to add instrumentation instructions to the VM code to collect timing information. That is essentially how the ruby liquid profiler works, however, we could do that more efficiently from C code. We would probably want to expose a different ruby API for it though.

@macournoyer
Copy link
Contributor Author

Is that something we are using? Since it doesn't look like we are using the profile: true Liquid::Tempate.parse option.

Yes, through the Theme Inspector that customers are using, and employees too.

Do you mean "us" as implementers of the liquid API? Since I believe we use stackprof for profiling our code in production. That will profile rendering with Liquid::C, although it won't show where the time is spent in the C code. For that purpose, we will want a sampling C profiler, which works like stackprof, but gets the C stack trace periodically instead of the ruby stack trace.

Sorry I meant "us" as the team I was working with debugging Liquid issues on a merchant site. But it could be merchants themselves, or theme designers.

For development of liquid-c on MacOS, I've added a c_profile rake task that works with Xcode's instruments command (#62).

Saw this! Very cool.

We should also allow template authors to profile their liquid code.

Yes, this is what I had in mind writing the issue. Template authors are currently optimizing their templates based on Liquid Ruby profilings.

@dylanahsmith
Copy link
Contributor

Ok, sorry that I missed that. We should definitely add support for this in that case.

I was concerned that it exposed the liquid parse tree nodes, but it looks like the node objects it exposes are Liquid::Profiler::Timing nodes. So I think we should be able to support it without too much trouble.

@macournoyer
Copy link
Contributor Author

macournoyer commented Oct 14, 2020

This is causing issues now in the Theme Inspector w/ Core. For eg. this flamegrapg use to be 6 levels deep:
Screen Shot 2020-10-13 at 2 32 41 PM

I'll try to carve out some time to fix this soon. But perhaps in the meantime we could disable Liquid::C for profiling requests?

@dylanahsmith
Copy link
Contributor

But perhaps in the meantime we could disable Liquid::C for profiling requests?

I thought the problem was with liquid-c mostly being disabled when profiling liquid. That happens automatically (

@disable_liquid_c_nodes ||= !Liquid::C.enabled || @template_options[:profile]
)

I'm not sure what affected the depth of the flamegraph

@macournoyer
Copy link
Contributor Author

macournoyer commented Oct 14, 2020

Found the issue. It's because section rendering logic doesn't set the profile option in the ParseContext: https://github.com/Shopify/storefront-renderer/blob/master/app/liquid/theme_render_context.rb#L265-L269. I don't understand how come it use to work before. I assume it's the same issue on Core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants