我如何将软件系统的性能提高35,000%( 三 )


Donation.all.includes(:donor)

我如何将软件系统的性能提高35,000%

文章插图
> Finding the hidden N+1 queries reduced our response times, sometimes drastically.
 
低效的代码在代码中有很多实例,它们在不需要时执行资源密集型的工作 。
转向更快的库一些可用的库非常慢 。
对于序列化,在序列化较大的集合时,使用更快的库(例如oj)可以大大提高性能 。
流媒体我们处理了很多Excel电子表格以及其他批量数据报告和上传 。最初编写了大量代码,首先将整个电子表格加载到内存中,然后对其进行操作,这可能会占用大量时间,CPU和内存 。
许多先前的现有代码试图在不真正了解手头问题的情况下变得聪明和优化 。这些解决方案通常可以通过将整个工作表加载到内存中并将其推入内存高速缓存中来工作,这会导致重大问题,因为工作表仍在内存中 。它解决了使问题恶化的症状,而不是原因 。
我不得不重写大量代码及其算法来支持流传输,以最大程度地减少内存和CPU占用空间 。这样一来,算法和代码就不必加载整个电子表格,这对加快处理速度具有重要作用 。
将集合遍历移动到数据库当数据库可以轻松地处理它时,有很多代码可以在应用程序中执行操作 。示例包括遍历数千条记录以添加一些内容,而不是计算数据库中的总和,或者急于加载整个文档以访问单个字段 。
我进行的一个特定代码优化涉及用一个总数据库查询替换耗时数秒并运行多个查询的长时间运行的计算 。
有问题的查询是拉出每一个捐赠的用户,遍历每条记录,从该用户那里拉相关的标签(例如,"学生","校友"等),将它们全部合并,然后减少结果 放入一组不同的标签中
它看起来像下面的样子:
def get_unique_tagsall_tags = []@cause.donations.each{|donation| donation.cause.account.tags.each{|cause_tag| all_tags << tag if donation.tags.include?(tag.value)}}unique_tags = []all_tags.each{|tag| unique_tags << tag unless unique_tags.include?(tag)}end隐藏在广告系列页面呈现生命周期最深处的此代码在每次单个请求时都被调用 。
我如何将软件系统的性能提高35,000%

文章插图
> Much of the page time spent loading the campaign page was spent in the database (brown).
 
对于只有几个标签的较小捐赠天数,这不是问题,也绝不是问题 。但是,那一年的新情况是,我们的一些大客户在捐赠当天上传了成千上万个不同的标签 。
我将该逻辑移到单个聚合查询中,如下所示,结果是瞬时的:
我如何将软件系统的性能提高35,000%

文章插图
> A code optimization I did reduced the load time of most campaign pages to 447ms, down from 2500ms.
 
背景有些事情不需要立即在网络请求中发生-诸如发送电子邮件之类的事情可能会延迟几秒钟,或者完全由系统的其他部分处理 。
这被称为"背景",它会移动本应逐步执行的操作并使它们平行 。
如果您可以使请求周期的一部分异步进行,则意味着响应将更快地返回给用户,从而减少了使用的资源 。
我提供了对核心生命周期无关紧要的所有内容的背景信息:电子邮件发送,上传,报告生成等 。
资产最小化事实证明,我们的许多前端资产并未经过压缩或优化 。这是一个相当容易的更改,将这些资产的加载时间缩短了多达70% 。
我们有一个部署脚本,可以将前端资产推送到AWS S3 。我要做的就是生成并上传压缩的压缩版本,同时告诉S3通过设置内容编码和内容类型来提供gzip 。
如下所示的Webpack配置将执行此操作:
plugins.push(new CompressionPlugin({test: /.(js|css)$/,}));let s3Plugin = new S3Plugin({s3Options: {accessKeyId: <ACCESS_KEY_ID>,secretAccessKey: <SECRET_ACCESS_KEY>,region: <REGION>},s3UploadOptions: {Bucket: <BUCKET>,asset: '[path][query]',ContentEncoding(fileName) {if (/.gz/.test(fileName)) { return 'gzip' }}, ContentType(fileName) {if (/.css/.test(fileName)) { return 'text/css' }if (/.js/.test(fileName)) { return 'text/JAVAscript' }}},});plugins.push(s3Plugin);内存泄漏我花了大量时间来寻找内存泄漏,当我们开始使用交换内存时,内存泄漏极大地降低了性能(诅咒您,R14错误) 。
在寻找导致泄漏的实际原因时,我们做了传统的"以特定频率重启服务器"创可贴 。我积极地调整了设置:我们更改了垃圾收集时间,交换了序列化程序库,甚至将ruby垃圾收集器更改为jemalloc


推荐阅读