热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AWSS3.NETClient高内存使用率

将AWSS3.NET客户端LOH分配减少98%内容问题发现为什么会出问题呢?推出最佳魔幻数字—81,920空闲的手还有一件事TLDR-给我好东西脚注问题

将AWS S3 .NET客户端LOH分配减少98%

内容

  • 问题发现
  • 为什么会出问题呢?
  • 推出最佳魔幻数字— 81,920
  • 空闲的手
  • 还有一件事
  • TLDR-给我好东西
  • 脚注

问题发现

我们在Codeweavers所做的一件事就是帮助人们找到他们的下一辆车。 通常,这涉及到客户看到他们要购买的汽车-我的意思是,您会在不看外观的情况下购买汽车吗? 持有这个责任该应用程序是为淫秽金额分配,时间GC上花费的,而像饼干怪兽吃得好...饼干一般吃RAM 最坏的罪犯。

我们不时地希望从生产环境中获取此应用程序的内存转储。 我们已经完成了足够的次数,以使我们执行的最常见诊断步骤自动化,并将其捆绑到一个称为ADA(自动转储分析)的小工具中。 如果你有兴趣,你可以找到的工具, 在这里 ,所有谈到本文中的代码在这里 。

我们运行的分析器之一是转储在大对象堆(LOH)上找到的所有byte []数组。 针对我们的8 GB内存转储运行该分析器之后,我们发现了数百个byte []数组,长度为131,096或131,186。 好吧,这很奇怪。 在Notepad ++中打开某些文件只会给我们带来很多随机字符。

我把科学方法丢到窗外一秒钟,我决定将所有转储的byte []数组重命名为* .jpg-嘿,现在有些文件现在显示缩略图! 经过仔细检查,大约50%的文件是图像。 其余50%都无法完全打开为图像。 在Notepad ++中打开少​​数非图像文件显示,它们在文件开头都有一行类似于此的行:-

0;chunk-signature=48ebf1394fcc452801d4ccebf0598177c7b31876e3fbcb7f6156213f931b261d

好的,这开始变得更有意义了。 长度为131,096的byte []数组是纯图像。 不是图像的byte []数组的长度为131,186,并在其余内容之前具有块签名行。 我猜想签名是内容的SHA256哈希。

在继续进行之前,值得确定该应用程序在图像处理方面的繁忙程度。 我们所有的图像处理都使用AWS SNS和SQS在整个服务器场中分布。 使用CloudWatch指标,我们可以轻松看到:

好了,所以相当繁忙。 值得注意的是,在进行任何以性能为中心的工作之前,请务必确定执行代码的频率和当前成本。 如果代码路径的成本很高(例如,花费二十秒钟),但是每天只命中一次,则不值得研究。 但是,如果相同的代码路径被击中很多(例如一天一百万次),那么绝对值得研究。

此时,我想到了两个罪魁祸首。 我们已经建立了有问题的应用程序来做很多图像处理。 但是有一些运动的部分和两种启动图像处理的方式:

  1. 图片被推送给我们
  2. 我们从SFTP提取图像

之后,我们转换图像,然后将其上传到AWS S3 。 在此阶段,我倾向于使用SFTP,因为它可能需要验证从服务器接收到的每个块。 但是,随着我的预感,我开始追逐野鹅,于是我无视我的直觉,便将大块签名插入了Google并粉碎了输入。 谷歌指出AWS S3是罪魁祸首 。 但这仅仅是理论,我们需要证明这一点。

如果我们上传相同的图像十次并使用dotTrace来查看LOH,则会看到一个有趣的模式:

每次我们在AWS S3 .NET客户端上调用PutObject时,看起来固定成本为0.3 MB。 这是一个问题,因为这意味着每次使用PutObject时,每次上载都要付出0.3 MB的高昂费用。 只想确认一下; 如果将上传次数从十次增加到一百次会发生什么?

是的,我们可以肯定地说,每次调用PutObject都会产生0.3 MB的昂贵分配。 更进一步,并使用ProcDump转储该过程:-

procdump64.exe -ma -64 AWS-S3.exe

通过ADA运行转储文件,我们看到有两组byte []数组具有完全相同的特性; 50%的长度为131,096,其他50%的长度为131,186。 重命名时,文件的一半是图像,文件的一半具有块签名起始行。 至此,我们可以确定,AWS S3 .NET客户端正在将byte []数组直接分配到LOH上。 那个问题。

为什么会出问题呢?

LOH是一个已收集但从未压缩的内存区域,尽管从现在开始可以进行.NET v4.5.1 压缩 ,但警告词对LOH的压缩非常昂贵。 每兆字节大约2.3毫秒 。 一条很好的经验法则是,短暂存在的物体不能进入LOH。

等于或大于85,000字节的对象直接进入LOH。 LOH的操作与其他内存区域大不相同。 其他内存区域会定期收集和压缩,这意味着您可以在垃圾收集器运行后将新对象添加到末尾。 而LOH会尝试将新分配的对象放入废弃对象遗留的剩余空间中。 如果新分配的对象的大小与可用空间完全相同或较小,则此方法很好用。 如果找不到空间,则LOH必须增长以容纳该对象。

它有助于像书架一样思考它; 在内存的其他区域中,不再使用的书籍被简单地扔掉,剩余的书籍被推到一起,所有新书都放在书架的尽头。

在不可能的LOH内,将丢弃书籍(对象),并记录该空间中曾经使用的页数(字节),并在下次将书分配到该书架时(LOH)它试图找到一个可以容纳那么多页面(字节)的空白空间。 如果书架无法容纳新分配的书(对象),则必须扩展书架以容纳新书(对象)。

垃圾收集器将从LOH收集死对象,与此同时,将新对象分配给LOH。 这可能导致长时间运行的应用程序出现生命周期的情况,其中LOH大小已增加到几GB(因为新对象无法容纳到现有的空白空间中),但实际上仅包含几个活动对象。 这称为LOH碎片。 在这种情况下,我们感到非常幸运,因为将其放入LOH的byte []数组有两种大小。 131,186和131,096。 这意味着,无论哪种大小的旧对象都死掉并被收集起来,新分配的对象恰好适合将其放入空白空间的大小。

好吧,回到有趣的东西。

推出最佳魔幻数字— 81,920

多亏了dotTrace,我们才能够准确地确定导致LOH碎片的原因。 它还向我们显示,每次调用PutObject的固定成本0.3 MB发生在ChunkedUploadWrapperStream的构造函数内部:

快速访问该文件在AWS-SDK-网库。 显示创建的两个byte []数组的长度至少为131,072:-

这就是为什么将这些byte []数组直接分配给LOH的原因,它们高于LOH阈值(85,000字节)。 此时,有几种可能的解决方案:

  1. 使用System.Buffers从byte []数组池中租用两个byte []数组
  2. 使用Microsoft.IO.RecycableMemoryStream并使用Stream的池直接对传入流进行操作
  3. 公开DefaultChunkSize,以便API的使用者可以自行设置
  4. 将DefaultChunkSize降低到低于LOH阈值的数字(85,000字节)

第一个和第二个解决方案可能是获得最大胜利的解决方案,但这将需要大量的请求,并引入了库维护者可能不希望的依赖项²。 第三种解决方案意味着图书馆的使用者必须了解该问题并将其设置为合理的数目,以避免分配LOH。 不,似乎第四种解决方案最有可能被接受,破坏现有功能的可能性也最小。

我们所需要的是一个低于85,000的数字,通常84,000之类的数字非常合适。 但是,在发现此问题的几周前,当我偶然发现这个宝石时,我正在参考参考源 (正在研究另一个问题):

Windows内存页的大小为4,096字节 ,因此选择低于LOH阈值(85,000字节)的倍数是完全有意义的。 是时候分叉,分支, 创建问题并提出拉取请求了 。

幸运的是,我们可以在本地进行更改³,看看有什么好处。 通过PutObject上传同一图像的一百次统计:-

空闲的手

在等待对我的请求请求进行审查的同时,我决定查阅AWS S3文档,偶然发现了预签名URL的概念。 听起来很有趣! 创建上传器的V2:-

上载相同文件一百次时,我们看到它具有以下统计信息:-

那真是太棒了,而我们实际上要做的就是阅读文档! 好吧,这是不对的,您的好处是可以阅读包含所有内容的摘要文章。 您在此处看到的工作是在一周的时间内完成的,介于两次客户工作之间。

使用GetPreSignedURL的一个小缺点是,如果修改了GetPreSignedUrlRequest并且未相应地修改WebRequest,则AWS将返回HTTP 403 Forbidden (例如,删除WebRequest上的XAmzAclHeader)。 这是因为客户端哈希和服务器哈希不再匹配。

还有一件事

多亏了我的上一篇文章,我才知道什么是书呆子狙击 -我对自己做了很多事情。 在此阶段,我感到对其他东西可以省掉有点头晕,我一直在看着LOH上剩余的0.4 MB。 同样,dotTrace将我们指向代码路径的方向,导致向LOH分配了0.4 MB:-

耶克斯, 那看起来很严肃 。 安静地退后一步,尝试不同的策略; 我们知道一个预签名的URL看起来像这样:

https://##bucket_name##.s3.##region_name##.amazonaws.com/##path##/##file_name##?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=##access_key##/20180613/##region_name##/s3/aws4_request&X-Amz-Date=20180613T233349Z&X-Amz-SignedHeaders=host;x-amz-acl&X-Amz-Signature=6bbcb0f802ad86022674e827d574b7a34a00ba76cd1411016c3581ba27fa5450

我们应该能够自行生成该URL,因为AWS非常友好地发布了其签名过程 。 在这一点上,我承认我已经准备好接受失败了,只是将0.4 MB留给了LOH。 我真的不喜欢的代码里姆斯我正要写可能消除剩余的0.4 MB将是值得的。

直到我发现我想要的例子为止。 我的工作量大大减少了; V3诞生了:

V3只是一个实验,旨在了解可能的情况,因为所获得的收益和维护的代码量不大,这并不是我们在生产代码中实际使用的东西。 预签名URL的发现是这里的主要优势:-

同时,我的拉取请求已合并并发布在AWSSDK.Core的3.3.21.19版本中。 时间轴快速概述:-

  1. 2018–03–07 —在aws-sdk-net存储库上创建的问题
  2. 2018-03-13 —发送了拉取请求
  3. 2018-03-29 —合并请求请求
  4. 2018–03–29 —新版本的AWSSDK.Core已发布到NuGet

我喜欢开源。

TLDR-给我好东西

低于3.3.21.19的AWSSDK.Core版本导致在AWS S3 .NET客户端上每次PutObject调用的固定成本为0.3 MB。 此问题已在3.3.21.19及更高版本中得到纠正。 对于特别热的代码路径,值得探索在AWS S3 .NET客户端上使用GetPreSignedURL,因为在我们的上下文和用例中,LOH分配减少了98%。

找到我Twitter , LinkedIn或GitHub 。

脚注

¹另一个原因可能是WinDbg仍然吓到我了。

²话虽如此, 最近的一次对话已经开始利用.NET Core的优点。

³确保不像个人那样构建发布版本-好的,是我

本来在发表 dev.to

From: https://hackernoon.com/its-not-your-code-vol-i-c06fac8784df



推荐阅读
  • CTF竞赛中文件上传技巧与安全绕过方法深入解析
    CTF竞赛中文件上传技巧与安全绕过方法深入解析 ... [详细]
  • 您的数据库配置是否安全?DBSAT工具助您一臂之力!
    本文探讨了Oracle提供的免费工具DBSAT,该工具能够有效协助用户检测和优化数据库配置的安全性。通过全面的分析和报告,DBSAT帮助用户识别潜在的安全漏洞,并提供针对性的改进建议,确保数据库系统的稳定性和安全性。 ... [详细]
  • Spring Boot 中配置全局文件上传路径并实现文件上传功能
    本文介绍如何在 Spring Boot 项目中配置全局文件上传路径,并通过读取配置项实现文件上传功能。通过这种方式,可以更好地管理和维护文件路径。 ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 2018年9月21日,Destoon官方发布了安全更新,修复了一个由用户“索马里的海贼”报告的前端GETShell漏洞。该漏洞存在于20180827版本的某CMS中,攻击者可以通过构造特定的HTTP请求,利用该漏洞在服务器上执行任意代码,从而获得对系统的控制权。此次更新建议所有用户尽快升级至最新版本,以确保系统的安全性。 ... [详细]
  • 在 Ubuntu 中遇到 Samba 服务器故障时,尝试卸载并重新安装 Samba 发现配置文件未重新生成。本文介绍了解决该问题的方法。 ... [详细]
  • 开发日志:高效图片压缩与上传技术解析 ... [详细]
  • 本文介绍了如何使用 Node.js 和 Express(4.x 及以上版本)构建高效的文件上传功能。通过引入 `multer` 中间件,可以轻松实现文件上传。首先,需要通过 `npm install multer` 安装该中间件。接着,在 Express 应用中配置 `multer`,以处理多部分表单数据。本文详细讲解了 `multer` 的基本用法和高级配置,帮助开发者快速搭建稳定可靠的文件上传服务。 ... [详细]
  • 卓盟科技:动态资源加载技术的兼容性优化与升级 | Android 开发者案例分享
    随着游戏内容日益复杂,资源加载过程已不仅仅是简单的进度显示,而是连接玩家与开发者的桥梁。玩家对快速加载的需求越来越高,这意味着开发者需要不断优化和提升动态资源加载技术的兼容性和性能。卓盟科技通过一系列的技术创新,不仅提高了加载速度,还确保了不同设备和系统的兼容性,为用户提供更加流畅的游戏体验。 ... [详细]
  • 在Ubuntu系统中安装Android SDK的详细步骤及解决“Failed to fetch URL https://dlssl.google.com/”错误的方法
    在Ubuntu 11.10 x64系统中安装Android SDK的详细步骤,包括配置环境变量和解决“Failed to fetch URL https://dlssl.google.com/”错误的方法。本文详细介绍了如何在该系统上顺利安装并配置Android SDK,确保开发环境的稳定性和高效性。此外,还提供了解决网络连接问题的实用技巧,帮助用户克服常见的安装障碍。 ... [详细]
  • CSS3 @font-face 字体应用技术解析与实践
    在Web前端开发中,HTML教程和CSS3的结合使得网页设计更加多样化。长期以来,Web设计师受限于“web-safe”字体的选择。然而,CSS3中的`@font-face`规则允许从服务器端加载自定义字体,极大地丰富了网页的视觉效果。通过这一技术,设计师可以自由选择和使用各种字体,提升用户体验和页面美观度。本文将深入解析`@font-face`的实现原理,并提供实际应用案例,帮助开发者更好地掌握这一强大工具。 ... [详细]
  • 本文介绍了如何在iOS平台上使用GLSL着色器将YV12格式的视频帧数据转换为RGB格式,并展示了转换后的图像效果。通过详细的技术实现步骤和代码示例,读者可以轻松掌握这一过程,适用于需要进行视频处理的应用开发。 ... [详细]
author-avatar
matt
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有