- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
本文译自 Why I encountered Go memory fragmentation? How did I resolve it? ,作者通过分析golang的堆管理方式,解决了内存碎片的问题.
我们的团队正在搭建运行一个兼容Prometheus的内存时序数据库,该数据库有一个数据结构,称为"chunk"。每个chunk对应一个唯一键值标签对的4个小时的数据点,如:
{host="host1", env="production"}
可以将一个数据点认为是一个时间戳加数值的组合,一个chunk包含了4个小时的数据点。数据库同一时间只会保存每个(唯一标签对的)指标的8个chunk,且每4小时会对老的chunk进行清除。由于它是一个内存数据库,因此使用快照恢复逻辑来防止数据丢失.
通过观察内存使用发现,在数据库启动32~36小时之后,内存使用一直在增加:
一开始怀疑是内存泄露问题,因此通过每小时采集heap profile来对比内存使用差异,但此时并没有发现任何异常。一开始怀疑可能是chunks没有完全释放,如果长期持有未使用的对象,可能会导致该问题,但通过pprof并没有找到相关线索.
为什么使用的内存在增加,但总的堆使用却保持不变?
通过如下go memstats指标发现可能出现了内存碎片:
go_memstats_heap_inuse_bytes{…} - go_memstats_heap_alloc_bytes{…}
指标结果显示,堆申请的字节数要少于使用的字节数。这意味着有很多申请的空间没有被有效地利用。通常在chunks过期前的4小时内,该值会增加,但之后会逐步降低。然而在出问题的节点上,该值并没有降低.
我怀疑它可以为非重启节点使用过期的空间来处理新摄取的数据,但是由于内存碎片而不能为重启过的节点使用过期的空间(即使用恢复逻辑读取快照).
之后我将怀疑点转向了快照的恢复逻辑。快照实际上由chunks的字节构成,并放在文件中。在处理过程中会并行写chunk,因此chunk的顺序是随机的,这样可以提高写性能,而读操作则是从文件头按顺序读取的。因此可以想象,每4个小时,当某些零散chunk过期时,就会导致大量内存碎片.
下面是尝试的解决方式,即在将chunk写入文件之前会按照chunk的时间戳进行排序,这样就可以按照时间顺序来申请字节(恢复期间会从头部读取字节并分配内存),下面是修复后的申请方式:
经验证发现,问题并没有解决,且写操作性能严重降级.
至此需要理解Go是如何进行堆管理的。参考 golang-memory-allocation .
简单地说,Go运行时管理着大量 mspans ,每个 mspans 包含特定数目的连续8KB内存页,不同 msapns 有着不同的 size class (大小),size class决定了mspan中的对象的大小,用于适应不同大小的对象,降低内存浪费.
假设要申请100字节的对象,则需要选择112字节的size class( 参见列表 ).
通常每个chunk都有一个用于内部数据的字节数组,其创建方式为:
make([]byte, 0, 128)
Go中slice的大小并不是固定不变的,当slice的容量小于1024时会以2的倍数增加,当容量大于1024时,新slice的容量会变为原来的1.25倍。 (本文对这部分描述有误,此处纠正) ,在本场景中,大部分size-classes是固定的:
而目前恢复使用的chunk的为:
make([]byte, 0, actual chunk byte size)
这意味着摄取时采用的chunk size classes与恢复是采用的chunk size classes完全不同!恢复时使用未对齐mspan的实际chunk大小来保存数据,导致过期内存重复利用率不高,也导致mspan中出现了大量内存碎片:
最后作者,通过如下方式解决了该问题:
通过如上两种方式解决了该问题:
这里解释一下文中涉及的mstat的2个指标,更多参见 Exploring Prometheus Go client metrics :
- go_memstats_heap_alloc_bytes:为对象申请的堆内存,单位字节。该指标计算了所有GC没有释放的所有堆对象(可达的对象和不可达的对象)
- go_memstats_heap_inuse_bytes: in-use span中的字节数。 go_memstats_heap_inuse_bytes - go_memstats_heap_alloc_bytes 表示那些已申请但没有使用的堆内存。
最后此篇关于解决golang的内存碎片问题的文章就讲到这里了,如果你想了解更多关于解决golang的内存碎片问题的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我今天在这里看到了 Ayende 关于 NH 分片的文章 http://ayende.com/blog/4252/nhibernate-shards-progress-report .我第一次听说 N
我正在尝试使用 Scrapy 和 Cloudflare 抓取 URL,但我无法获得任何结果: 2018-07-09 22:14:00 [scrapy.core.engine] INFO: Spider
我用于调试日志的Graylog2服务器上存在一些磁盘问题。现在有未分配的分片: curl -XGET http://host:9200/_cat/shards graylog_292 1 p STAR
我正在做一个小机器人,它应该提供来自网站(ebay)的信息并使用 splinter 和 python 将其放入列表中。我的第一行代码: from splinter import Browser wit
我正在尝试通过 splinter 从模态框的下拉菜单中选择内容。我很容易找到这个下拉菜单,例如: (Pdb) dropdown = next(i for i in my_browser.find_by
我的 APC 总是达到 100% 碎片。我的 VPS 有 1GB 内存,APC 分配给它 256mb,但它只使用了 256mb 中平均 100mb(最大 150mb)的内存。 我必须重新启动 php-
所以我正在使用 python splinter library测试一个网络应用程序,当我检查一个元素是否存在并且我手动找到每个元素来操作它时,我遇到了一个问题。 问题是,当输入列表大于 4 项或更多时
我尝试从具有以下 html 代码的下拉列表中选择“本地主机”: Local Host ah005 这是我的 pyt
我正在使用 Spring 和 Thymeleaf 开发应用程序,我想知道如何使用 thymeleaf 片段。 Thymeleaf 与 JSP 的优点是我们不必运行应用程序来查看模板,但是,当我们将模板
我在 linux 上用 ping 做了一些测试,我有点好奇 DF 位和碎片是如何工作的。我一直在发送一些带有命令 -M do 的包和一些带有 -M dont 的包,我意识到即使发送小于 MTU 的包,
我尝试从原始 H264 视频数据创建片段 MP4,以便我可以在互联网浏览器的播放器中播放它。我的目标是创建实时流媒体系统,媒体服务器会将碎片化的 MP4 片段发送到浏览器。服务器将缓冲来自 Raspb
在 mongodb 中。如果你想构建一个有两个分片的生产系统,每个分片都是一个具有三个节点的副本集,你必须启动多少 mongod 进程? 为什么答案是9? 最佳答案 因为每个分片需要 3 个副本 x
我是 python 和 scrapy 的新手。我正在尝试遵循 Scrapy 教程,但我不明白 storage step 的逻辑. scrapy crawl spidername -o items.js
1、Sharding 的应用场景一般都那些? 当数据库中的数据量越来越大时,不论是读还是写,压力都会变得越来越大。试想,如果一张表中的数据量达到了千万甚至上亿级别的时候,不管是建索引,优化缓存等,
我正在通过以太网发送 2000 字节 JSON(以太网 MTU 1500 字节),因为我的数据包大于以太网 MTU,所以我的消息被分段,如您在下面的 Wireshark 捕获中看到的那样。现在我正在尝
我决定为我的文档实现以下 ID 策略,它将文档“类型”与 ID 结合起来: doc.id = "docType_" + Guid.NewGuid().ToString("n"); // create
是否可以编写 ip6tables 规则来阻止格式错误的 ipv6 分段数据包。这基本上是为了我们电器盒的ipv6认证。我们运行在:rhel 5.5 和内核:2.6.18-238.1.1.el5 我们目
有很多关于 .NET LOH 的可用信息,并且已经在各种文章中进行了解释。但是,似乎有些文章不够精确。 过时信息 在Brian Rasmussen's answer (2009), program m
我还有一个 Unresolved 问题 HERE关于一些可能涉及 LOH 碎片以及其他未知数的绝望内存问题。 我现在的问题是,公认的做事方式是什么?如果我的应用程序需要在 Visual C# 中完成,
经过 20 年的专业发展,我仍然发现自己对数据库性能的某些方面一无所知。这是那些时代之一。这里和其他地方有数以千计的关于表和索引碎片及其对性能影响的问题。我知道基本的注意事项,但有时似乎没有“好的”答
我是一名优秀的程序员,十分优秀!