Distributed Profiling: How to identify and fix Performance Bottlenecks in a Microservices Architecture
Gain understanding of a decoupled application’s performance thanks to the recursive distributed profiling of microservices.
Maintaining the performance and flexibility of our applications can become increasingly challenging as they grow in complexity and scale.
This is largely due to the concept of monolithic architecture, where the entire application is built as a single, large, and unwieldy codebase, which can become a significant barrier to innovation and scalability.
But there’s a way to get around monolithic applications. By adopting a microservices architecture you can break down monoliths into smaller, more manageable components, each with a specific function.
And you can improve scalability, flexibility, and agility.
If you want to make that journey, I’d recommend you watch the keynote my colleague Shawna Spoor gave at Build Anything Together @SymfonyCon 2022: “From monolith to decoupled…wait, why is that one getting bigger?!?”
Distributed Profiling for decoupled applications
Yet, what about the performance optimization process in both cases?
Profiling a monolith allows for having a picture of the whole process. That’s indeed the initial reasoning for grouping every process together in the first place. But that doesn’t mean optimizing decoupled applications should be any harder.
Blackfire Distributed Profiling allows for the profiling of any service your application interacts with, the most common being other HTTP applications such as microservices. When profiling a script with Blackfire, all eligible HTTP or CLI services triggered by the main script are also profiled and generate Sub-Profiles.
Profile all the things, recursively!
And this is recursive. If those services are also relying on other web services, those will be profiled as well. It is required that all services run an architecture with Blackfire enabled. Also, Blackfire HTTP headers must be preserved on the services your application calls.
Blackfire Agents may even use different credentials, and can be linked to different Blackfire environments. The only requirement, in this case, is that the user who is profiling has access to the Blackfire environments, which are tied to the different agents.
A profile can also be propagated to applications written in all the languages that Blackfire supports, including PHP, Python, and GO. So, profiling your Python application relying on PHP and Go web services, themselves calling Python and PHP applications, will have sub-profiles triggered for all of those applications.
Give Distributed Profiling a try
book.b7e.io/cascade is an application making recursive HTTP calls that you can freely profile using the CLI. Let’s then trigger a profile and see what we can learn from it.
blackfire curl https://www.book.b7e.io/cascade/
As a side note, book.b7e.io is an application freely profilable by all. It is used within “PHP Code Performance Explained”, a book written by Fabien Potencier that can guide you in mastering Blackfire Profiler and test suite on a step-by-step basis—even if you are not a PHP developer.
Here is a public profile from Cascade. Clicking on the propagation tab lets you browse the different sub-profiles.
Assertions and recommendations for the profiles and the sub-profiles are also gathered in an unified scaffolded view:
Distributed profiling aims at helping you spot the root cause of your performance issue quickly. That one may not be located within your code, but within the services your application relies on. It is a convenient and powerful way to keep your decoupled applications as performant as needed.
Are you using distributed profiling? Give it a try, and tell us about your experience on Twitter and Reddit. We look forward to hearing from you. Even if you stick with monoliths 😀
Happy Distributed Performance Optimization!