博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Blackfire进行PHP级性能优化
阅读量:2507 次
发布时间:2019-05-11

本文共 9778 字,大约阅读时间需要 32 分钟。

This article is part of a series on building a sample application — a multi-image gallery blog — for performance benchmarking and optimizations. (View the here.)

本文是构建用于性能基准测试和优化的示例应用程序(一个多图像画廊博客)系列文章的一部分。 (在此处查看 。)



Throughout the past few months, we’ve introduced Blackfire and ways in which it can be used to detect application performance bottlenecks. In this post, we’ll apply it to our freshly started project to try and find the low-points and low-hanging fruit which we can pick to improve our app’s performance.

在过去的几个月中,我们介绍了Blackfire及其用于检测应用程序性能瓶颈的方法。 在本文中,我们将其应用于新近启动的项目,以尝试找到可以提高应用程序性能的低点和低落的果实。

If you’re using (and you should be), Blackfire is already installed.

如果您正在使用 (应该如此),则已经安装了Blackfire。

While it’s useful to be introduced to Blackfire before diving into this, applying the steps in this post won’t require any prior knowledge; we’ll start from zero.

在深入探讨Blackfire很有用之前,应用本文中的步骤不需要任何先验知识; 我们将从零开始。

建立 (Setup)

The following are useful terms when evaluating graphs produced by Blackfire.

以下是评估Blackfire生成的图形时的有用术语。

  • Reference Profile: We usually need to run our first profile as a reference profile. This profile will be the performance baseline of our application. We can compare any profile with the reference, to measure the performance achievements.

    参考资料 :我们通常需要将第一个资料作为参考资料运行。 此配置文件将成为我们应用程序的性能基准。 我们可以将任何配置文件与参考进行比较,以衡量绩效。

  • Exclusive Time: The amount of time spent on a function/method to be executed, without considering the time spent for its external calls.

    独占时间 :不执行外部调用所花费的时间,花费在要执行的函数/方法上的时间。

  • Inclusive Time: The total time spent to execute a function including all the external calls.

    包含时间 :执行一个功能(包括所有外部调用)所花费的总时间。

  • Hot Paths: Hot Paths are the parts of our application that were most active during the profile. These could be the parts that consumed more memory or took more CPU time.

    热路径 :热路径是我们的应用程序中在配置文件中最活跃的部分。 这些可能是消耗更多内存或花费更多CPU时间的部分。

The first step is registering for an account at . The page will have the tokens and IDs which need to be placed into Homestead.yaml after cloning the project. There’s a placeholder for all those values at the bottom:

第一步是在注册帐户。 页面将具有克隆项目后需要放置到Homestead.yaml的令牌和ID。 所有这些值的底部都有一个占位符:

# blackfire:#     - id: foo#       token: bar#       client-id: foo#       client-token: bar

After uncommenting the rows and replacing the values, we need to install the .

取消注释行并替换值之后,我们需要安装 。

The Chrome companion is useful only when needing to trigger profiling manually — which will be the majority of your use cases. There are other integrations available as well, a full list of which can be found .

Chrome随播广告仅在需要手动触发配置文件时才有用-这将是您的大多数用例。 还可以使用其他集成,可以在找到其完整列表。

使用Blackfire进行优化 (Optimization with Blackfire)

We’ll test the home page: the landing page is arguably the most important part of any website, and if that takes too long to load, we’re guaranteed to lose our visitors. They’ll be gone before Google Analytics can kick in to register the bounce! We could test pages on which users add images, but read-only performance is far more important than write performance, so we’ll focus on the former.

我们将测试主页:登陆页面可以说是任何网站中最重要的部分,如果加载时间太长,我们肯定会失去访问者。 在Google Analytics(分析)可以注册反弹之前,它们将消失! 我们可以测试用户在其上添加图像的页面,但是只读性能远胜于写入性能,因此我们将重点放在前者上。

of the app loads all the galleries and sorts them by age.

的应用程序会加载所有图库,并按年龄对其进行排序。

Testing is simple. We open the page we want to benchmark, click the extension’s button in the browser, and select “Profile!”.

测试很简单。 我们打开要进行基准测试的页面,在浏览器中单击扩展程序的按钮,然后选择“配置文件!”。

Here’s the resulting graph:

这是结果图:

In fact, we can see here that the execution time inclusive to exclusive is 100% on the PDO execution. Specifically, this means that the whole dark pink part is spent inside this function and that this function in particular is not waiting for any other function. This is the function being waited on. Other method calls might have light pink bars far bigger than PDO’s, but those light pink parts are a sum of all the smaller light pink parts of depending functions, which means that looked at individually, those functions aren’t the problem. The dark ones need to be handled first; they are the priority.

实际上,我们在这里可以看到, 包括 PDO 在内独占执行时间为100%。 具体来说,这意味着整个深粉红色部分都用在此功能内,并且该功能尤其不用等待任何其他功能。 这是正在等待的功能。 其他方法调用的浅粉红色条可能比PDO大得多,但是这些浅粉红色部分是依赖函数的所有较小的浅粉红色部分的总和,这意味着单独查看这些功能不是问题。 黑暗的首先需要处理。 他们是优先事项。

Also, switching to RAM mode reveals that while the whole call used almost a whopping 40MB of RAM, the vast majority is in the Twig rendering, which makes sense: it is showing a lot of data, after all.

同样,切换到RAM模式表明,尽管整个调用几乎使用了40MB的RAM,但绝大部分是在Twig渲染中进行的,这很有意义:毕竟它正在显示大量数据。

RAM模式

In the diagram, hot paths have thick borders and generally indicate bottlenecks. Intensive nodes can be part of the hot path, but also be completely outside it. Intensive nodes are nodes a lot of time is spent in for some reason, and can be indicative of problems just as much.

在图中, 热路径的边界较粗,通常表示瓶颈。 密集节点可以是热路径的一部分,但也可以完全不在热路径之外。 密集型节点是出于某种原因而花费大量时间的节点,并且同样可以指示问题。

By looking at the most problematic methods and clicking around on relevant nodes, we can identify that PDOExecute is the most problematic bottleneck, while unserialize uses the most RAM relative to other methods. If we apply some detective work and follow the flow of methods calling each other, we’ll notice that both of these problems are caused by the fact that we’re loading the whole set of galleries on the home page. PDOExecute takes forever in memory and wall time to find them and sort them, and Doctrine takes ages and endless CPU cycles to turn them into renderable entities with unserialize to loop through them in a twig template. The solution seems simple — add pagination to the home page!

通过查看最有问题的方法并在相关节点上单击,我们可以确定PDOExecute是最有问题的瓶颈,而反unserialize相对于其他方法使用的RAM最多。 如果我们进行一些侦探工作并遵循彼此调用方法的流程,则会注意到这两个问题均是由于我们在主页上加载了整个图库集这一事实引起的。 PDOExecute会花费大量的内存和时间来查找它们并对其进行排序,而Doctrine则花费了很长时间和无休止的CPU周期将它们转换为可渲染的实体,并对其进行反unserialize以在twig模板中循环它们。 解决方案似乎很简单-在首页上添加分页!

By adding a PER_PAGE constant into the HomeController and setting it to something like 12, and then using that pagination constant in the fetching procedure, we block the first call to the newest 12 galleries:

通过向HomeController添加一个PER_PAGE常量并将其设置为12 ,然后在获取过程中使用该分页常量,我们可以阻止对最新的12个画廊的第一次调用:

$galleries = $this->em->getRepository(Gallery::class)->findBy([], ['createdAt' => 'DESC'], self::PER_PAGE);

We’ll trigger a lazy load when the user reaches the end of the page when scrolling, so we need to add some JS to the home view:

当用户滚动时到达页面末尾时,我们将触发延迟加载,因此我们需要向主视图中添加一些JS:

{% block javascripts %}    {
{ parent() }} {% endblock %}

Since annotations are being used for routes, it’s easy to just add a new method into the HomeController to lazily load our galleries when triggered:

由于注释用于路由,因此很容易在HomeController添加新方法以在触发时延迟加载画廊:

/** * @Route("/galleries-lazy-load", name="home.lazy-load") */public function homeGalleriesLazyLoadAction(Request $request){    $page = $request->get('page', null);    if (empty($page)) {        return new JsonResponse([            'success' => false,            'msg'     => 'Page param is required',        ]);    }    $offset = ($page - 1) * self::PER_PAGE;    $galleries = $this->em->getRepository(Gallery::class)->findBy([], ['createdAt' => 'DESC'], 12, $offset);    $view = $this->twig->render('partials/home-galleries-lazy-load.html.twig', [        'galleries' => $galleries,    ]);    return new JsonResponse([        'success' => true,        'data'    => $view,    ]);}

比较方式 (Comparison)

Let’s now compare our upgraded app with the previous version by re-running the profiler.

现在,通过重新运行事件探查器,将升级后的应用程序与以前的版本进行比较。

Sure enough, our site uses 10 times less memory and loads much faster — maybe not in CPU time, as indicated by the stopwatch in the graph, but in impression. Reloading is now almost instant.

果然,我们的网站使用的内存减少了10倍,并且加载速度更快-可能不是CPU时间(如秒表所示),而是印象。 现在,重新加载几乎是即时的。

The graph now shows us that DebugClass is the most resource intensive method call.

现在,该图向我们显示DebugClass是最占用资源的方法调用。

DebugClass the most resource intensive method call

This happens because we’re in dev mode, and this class loader is generally much slower than the production one because it doesn’t heavily cache the classes. This is necessary so that changes done in the code can be immediately tested without having to clear APC cache or any other cache being used.

发生这种情况是因为我们处于开发模式,并且此类加载器通常比生产加载器慢得多,因为它不会大量缓存类。 这是必要的,以便可以立即测试代码中所做的更改,而不必清除APC缓存或正在使用的任何其他缓存。

If we switch to prod mode just for the purposes of this test, we’ll see a noticeable difference:

如果仅出于测试目的而切换到prod模式,我们将看到明显的不同:

结论 (Conclusion)

The speed of our app is now mind-boggling — a tiny 58ms to load the page, and no class loader in sight. Mind you, this is all happening in a VM with thousands of entries of dummy data. We can feel very optimistic about our app’s production state at this point: there’s little to no optimizations left on the home page; everything else can be classified as a micro-optimization.

现在,我们应用程序的速度令人难以置信-只需58毫秒即可加载页面,而且看不到类加载器。 请注意,这都是在具有数千个伪数据条目的VM中发生的。 此时,我们可以对我们的应用的生产状态感到非常乐观:首页上几乎没有优化,甚至没有优化。 其他所有内容都可以归类为微优化。

Re-running these performance tests regularly is important for any app’s development cycle, and integrating them into an app’s test pipeline, like a CD/CI flow, can be extremely helpful and productive. We’ll look at that option a little later, but it’s important to note that Blackfire’s premium subscription actually offers this very thing built in. !

定期重新运行这些性能测试对于任何应用程序的开发周期都很重要,并且将它们集成到应用程序的测试管道中(例如CD / CI流)可能会非常有帮助且富有成效。 我们来看看该选项稍晚一点,但要注意的是Blackfire的高级订阅实际上提供了这个建在非常的事是很重要的。 !

Right now, it’s important that we have Blackfire installed and available, and that it can serve us well in finding the bottlenecks and identifying new ones as we add more features into the mix. Welcome to the world of continuous performance testing!

目前,重要的一点是,我们已经安装并可用了Blackfire,并且在我们添加更多功能时,它可以很好地帮助我们发现瓶颈并确定新的瓶颈。 欢迎来到持续性能测试的世界!

翻译自:

转载地址:http://rtegb.baihongyu.com/

你可能感兴趣的文章
你可能使用了Spring最不推荐的注解方式
查看>>
(一)Hadoop 计算框架的特性
查看>>
实例对比 Julia, R, Python,谁是狼语言?
查看>>
volatile的用法
查看>>
java常见3种文件上传速度对比和文件上传方法详细代码
查看>>
SVD总结
查看>>
python基础教程(三)
查看>>
PL SQL Developer中文乱码
查看>>
字符串知识大全
查看>>
软件目录结构规范及堂兄弟文件引用
查看>>
H5 WebSocket通信和WCF支持WebSocket通信
查看>>
文件上传
查看>>
不能在此路径中使用此配置节。如果在父级别上锁定了该节,便会出现这种情况...
查看>>
Linux的IO性能监控工具iostat详解
查看>>
老杨聊架构:每个架构师都应该研究下康威定律
查看>>
1022: 锤子剪刀布
查看>>
百元买百鸡问题 ---穷举法
查看>>
[转]为什么不去读顶级会议上的论文
查看>>
Android模拟按键——源码环境下开发应用程序 ---编译jar(android可执行程序)
查看>>
Android Bluetooth HID实现详解
查看>>