python性能解决_我们如何发现并解决Python代码中性能下降的问题

Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。

作者:Omer Lachish

最近,我们已经开始使用RQ库代替Celery库作为我们的任务运行引擎。第一阶段,我们只迁移了那些不直接进行查询工作的任务。这些任务包括发送电子邮件,确定哪些查询需要刷新、记录用户事件和其他维护工作。

在部署完成之后我们注意到,任务数量相同的情况下,与Celery库相比,RQ库需要更多的CPU去执行这些任务。我想我应该分享一下我是如何分析和解决这个问题的。

关于Celery库和RQ库的区别

Celery库和RQ库都有工作进程的概念,而且都使用分支来允许多种任务并行运行。当你启动一个Celery工作进程时,它会分到几个不同的进程,每个进程会自主地处理任务。使用RQ库,一个主进程将只会实例化一个子进程(称为“Worker Horse”),该子进程在执行完一个单独的任务后将会结束。当主进程从队列中提取另一项任务时,它将会派出一个新的Work Horse。

在RQ库中,通过使用更多的工作进程,即可实现与Celery相同的并行性。 但是,Celery库和RQ库之间存在着细微的区别:Celery进程在启动时会实例化多个子进程,并将其重用于多个任务。 而使用RQ库时,你必须给每一个任务分配进程。 两种方法都有优点和缺点,但这些内容不在本文讨论范围之内。

标杆分析法

在介绍任何内容之前,我想要确定一个基准,即一个工作容器处理1000项任务需要多长时间。我决定把重心放在record_event工作上,因为它是一种频繁的,轻量级的操作。我使用time命令来衡量性能,这里需要修改一下源代码:为了得出完成1000项任务所需的时间,我倾向于采用RQ库的burst模式,该模式在处理完作业后会退出流程。

我想避免测量那些被安排在基准测试时间段的任务。因此,在task/general.py中的record_event声明上方,通过将@job('default')替换为@job('benchmark'),可以将record_event移至一个名为benchmark的专用队列。

现在我们可以开始计时了。首先,我想查看一个进程启动和停止需要多长时间(没有任何工作)以便之后可以从任何结果中减去该时间:

2bde55c395f544888557636131fc295a.png

在我的计算机上,进程初始化需要14.7秒。我会记住这个时间。

然后,我将1000个虚拟的record_event任务添加进benchmark队列中:

39fe1e45871f473790dce2471070bc89.png

现在,运行相同的命令,看看处理1000项任务需要多长时间:

6a5929bec88e4f31905b93e9377863ac.png

减去14.7秒的启动时间,我们看到4个进程处理1000项任务需要102秒。现在,让我们尝试找出原因!为此,在进程工作的同时,我们将使用py_spy模块。

分析

让我们再增加1000项任务(因为上次的测试已经删除了所有任务),运行进程并同时监控它们所耗费的时间:

3122074069c94f55b69f820a849249bd.png

我知道,最后一条命令非常短。 理想情况下,出于可读性考虑,我会在每个“ &&”上都打断该命令,但是这些命令应该在同一个docker-compose exec worker bash session中按顺序运行。所以,以下是其功能的快速分析:在后台中,burst模式下,开启了4个进程。

等待15秒(大致让它们完成启动。

安装py-spy模块。

运行rq-info命令,并且为其中一个进程进行分层控制。

在该控制过程中记录10秒中的活动情况并将其保存到profile.svg文件中。

结果如下火焰图所示:

557480556f3c4c37b6c5333a55e08ab3.png

从火焰图中,我注意到record_event在sqlalchemy.orm.configure_mappers中花费了很大一部分的执行时间,并且每次处理一项工作时这种情况都会出现。从它们的文档当中,我知道了:初始化到目前为止已构建的所有映射器的映射器间关系。

的确不需要在每一个分支上都发生这种事情。所以,我们可以在主进程当中一次性地初始化这些关系,避免在多个子进程当中重复性这些工作。

因此,在启动进程之前,我已经对sqlalchemy.org.configure_mappers()进行了调用,并再次进行了测试:

f63a095797c04f9d90a23a63cb0f89cd.png

如果我们减去14.7秒的启动时间,4个线程处理1000项任务的时间将从102秒减少到24.6秒。 比以前提高了4倍! 通过修复此程序,我们成功地将RQ生产资源减少了4倍,并保持了相同的吞吐量。

我认为,你应该记住,在单线程和多线程的情况下,应用的行为是有所不同的。如果每一项任务没有繁重的重复的工作要做,通常最好在分到多个线程之前进行一次。这些事情在测试和开发过程中不会出现,因此请确保您进行充分的测试并挖掘出任何会出现的性能问题。英文原文:https://blog.redash.io/how-we-spotted-and-fixed-a-performance-degradation-in-our-python-code/

译者:Lyx

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374324.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图灵机器人调用数据恢复_机器人也能撩妹?python程序员自制微信机器人,替他俘获女神芳心...

机器人也有感情还记得王传君饰演的《星语心愿之再爱》这部电影吗?王传君饰演的天才程序员“王鹏鹏”因工作原因不能陪伴照顾身在异地的女朋友“林亦男”,呆萌宅男“王鹏鹏”开发出一款以自己为原型的“王鹏鹏8.0”程序去陪伴异地恋的女友,后来…

Spark排错与优化

一. 运维 1. Master挂掉,standby重启也失效 Master默认使用512M内存,当集群中运行的任务特别多时,就会挂掉,原因是master会读取每个task的event log日志去生成spark ui,内存不足自然会OOM,可以在master的运行日志中看到…

在MySQL上使用带密码的GlassFish JDBC安全性

我在该博客上最成功的文章之一是有关在GlassFish上使用基于表单的身份验证来建立JDBC安全领域的文章 。 对这篇文章的一些评论使我意识到,要真正使它安全,应该做的还很多。 开箱即用的安全性 图片: TheKenChan ( CC BY-NC 2.0 &a…

利用python进行数据分析_利用python进行数据分析复现(1)

一直以来,都想学习python数据分析相关的知识,总是拖拖拉拉,包括这次这个分享也是。《利用python进行数据分析 第2版》是一次无意之间在简书上看到的一个分享,我决定将很详细。一直都想着可以复现一下。但总有理由&…

C语言代码规范(七)#define

#define 宏定义的使用 #define MAX(x, y) ( ((x) > (y)) ? (x) : (y) ) #define MIN(x, y) ( ((x) < (y)) ? (x) : (y) ) 在宏定义中要把参数用括号扩起来( ((x) > (y)) ? (x) : (y) )。 因为宏只是简单的文本替换&#xff0c;如果不注意&#xff0c;很容…

http 二进制_浅谈HTTP协议

HTTP一、HTTP协议http协议&#xff0c;是超文本传输协议&#xff0c;此协议是基于TCP/IP的协议&#xff0c;是互联网上应用最为广泛的一直网络协议是一种无状态协议&#xff0c;默认端口为80,。设计HTTP的最初目的是为了提供一种发布和接受HTML页面的方法。通过HTTP或者HTTPS协…

linux redis客户端_为什么单线程Redis能那么快?

我们通常说&#xff0c;Redis 是单线程&#xff0c;主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的&#xff0c;这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能&#xff0c;比如持久化、异步删除、集群数据同步等&#xff0c;其实是由额外的线…

C语言开发笔记(七)const和指针

const修饰变量是常用的&#xff0c;不容易犯错&#xff0c;而const和指针一起使用时很容易混淆。 (一)const int *p #include <stdio.h>int main(void) {int a 10;int b 20;const int *p &a;*p b;return 0; } const在int *的左侧&#xff0c;即指针指向内容为…

ubuntu php 无法执行exec_利用webhook使php项目自动部署

php中文网最新课程每日17点准时技术干货分享1.先来讲一下自动部署的原理&#xff0c;一般在我们push代码的时候&#xff0c;可以自动请求webhook中设置的url&#xff0c;完成一次请求与响应。那么只要我们设置的url地址请求的php文件内容是执行命令行git push命令&#xff0c;则…

C语言开发笔记(八)static

在C语言中&#xff0c;static有3个作用&#xff1a; &#xff08;1&#xff09;在函数体&#xff0c;一个被声明为静态的变量在这一函数体内被调用的过程中维持其值不变。 #include <stdio.h>void test(void) {static int i 0;printf("%d\n", i); }int main…

ppt修复无法读取_移动硬盘故障分析以及建议修复方法

移动硬盘中存储了大量的重要数据&#xff0c;一旦出现什么问题&#xff0c;会让人急得焦头烂额。换个硬盘倒是件小事&#xff0c;但其中资料、数据的丢失更令人懊恼。而在硬盘使用的过程中&#xff0c;由于使用者一时的不注意&#xff0c;往往就很容易造成意外的问题。接下来&a…

(原创)c#学习笔记04--流程控制01--布尔逻辑03--运算符优先级

转载于:https://www.cnblogs.com/wodehao0808/p/4896018.html

m.2接口和nvme区别_NVMe/SATA SSD有啥不一样?萌新怎么选

随着NAND技术的升级迭代&#xff0c;堆栈层数不断提高使得SSD单位容量成本不断下降&#xff0c;消费级市场基本已经成为了SSD的天下。目前主流的SSD大致有两种接口&#xff0c;分别是M.2和SATA两种类型。NVMe/SATA有啥区别SATA接口的SSD执行的AHCI协议标准&#xff0c;是目前较…

带有NetBeans 7.1 RC 2的WebLogic 12c快速入门

WebLogic服务器12c停运了几天。 它是针对“裸露”的Java开发人员的–花哨的Fusion Middleware东西将继续沿线升至12c。 因此&#xff0c;这基本上是我要运行的版本。 今天&#xff0c;我为您提供了一个最新的NetBeans 7.1&#xff08;RC 2&#xff09;和WebLogic的快速入门 &am…

python爬虫反爬机制_Python Scrapy突破反爬虫机制(项目实践)

对于 BOSS 直聘这种网站&#xff0c;当程序请求网页后&#xff0c;服务器响应内容包含了整个页面的 HTML 源代码&#xff0c;这样就可以使用爬虫来爬取数据。但有些网站做了一些“反爬虫”处理&#xff0c;其网页内容不是静态的&#xff0c;而是使用 JavaScript 动态加载的&…

自定义URL Scheme完全指南

iPhone / iOS SDK 最酷的特性之一就是应用将其自身”绑定”到一个自定义 URL scheme 上&#xff0c;该 scheme 用于从浏览器或其他应用中启动本应用。 注册自定义 URL Scheme 注册自定义 URL Scheme 的第一步是创建 URL Scheme — 在 Xcode Project Navigator 中找到并点击工程…

P6 音频格式—— AAC

目录 前言 01 AAC是什么&#xff1f; 02 为什么需要进行AAC进行音频压缩处理&#xff1f; 03 AAC的特点以及优势 04 AAC格式详解&#xff1a; 4.1. ADIF的数据结构&#xff1a; 4.1.1 ADIF Header具体的表格: 4.2. ADTS的结构&#xff08;重点&#xff09;&#xff1a; …

Android开发笔记——ListView模块、缓存及性能

ListView是Android开发中最常用的组件之一。本文将重点说明如何正确使用ListView&#xff0c;以及使用过程中可能遇到的问题。 ListView开发模块图片缓存可能遇到的问题一、ListView开发模块 从项目实践的角度来看&#xff0c;ListView适合“自底向上”的开发模式&#xff0c;即…

python实现excel筛选功能并输出_python如何实现excel按颜色筛选功能

离岛 2020-07-09 09:37 已采纳 不太了解具体需求&#xff0c;提供一些示例代码和思路供你参考&#xff1a; 整体思路&#xff1a;首先已知excel中的颜色值&#xff0c;根据编码实现颜色筛选的功能 示例&#xff1a; 1、首先安装pip install openpyxl 2、示例代码可以获取Excel中…

C学习杂记(七)extern声明可省略变量类型

工作三年&#xff0c;看C的书也不少。第一次知道extern可以省略变量类型。 b.c有一个全局变量unsigned int data_length&#xff0c;a.c想要调用它&#xff0c;通常使用: extern unsigned int data_length&#xff1b; 在声明时可以把外部变量类型去掉&#xff1a;extern da…