被vector动态扩容给坑了!
大家好,我是东北码农。记录一下工作中事。
前几天,运维同事给我反馈了一个问题:
通过监控发现,线上的一个服务,业务线程时不时会出现卡顿,卡顿大约持续几秒。
我们做金融系统后台开发的,对性能要求很严格的,当然要查一查啦。
1、问题调查
1.1、top 日志
top中有内存和cpu信息,可以判断出卡顿时内存使用暴涨,但cpu使用没有下降。
应该是做了非常耗cpu和内存的操作,而不是等待什么。
1.2、代码分析
通过top的分析,结合代码分析,发现业务代码中有vector操作,每收到一个包都会建立索引。伪代码如下
vector<uint64_t> idx_;
void on_recv(pkg *h)
{
idx_.push_back(h->seq);
}
应该是vector动态扩容时,造成的卡顿。下面来验证一下。
2、vector
std::vector is a sequence container that encapsulates dynamic size arrays.
vector的底层实现是数组,在使用时采取动态扩容方式。
2.1、vector的size和capacity
vector有size和capacity两个属性,size是实际数量,capacity是容器当前容量。下面是cppreference中的解释:
- size:returns the number of elements。
- capacity:returns the number of elements that can be held in currently allocated storage。
2.2、扩容
下面写代码,观察一下vector何时会扩容,以及扩容时的开销。伪代码如下:在扩容时打印容量变化,以及耗时。
void test_vector()
{
vector<uint64_t> idxs;
uint64_t last_cap = 0;
for(int i = 0 ;i < 1200000000;i++)
{
auto begin = get_ns();
idxs.push_back(i);
auto cost = get_ns() - begin;
auto cap = idxs.capacity();
if(last_cap != cap || cost > 100*1000*1000)
{
printf("last_cap=%ju,cap=%ju,cost=%ju\n",last_cap,cap,cost/1000000);
last_cap = cap;
}
}
}
输出如下:
last_cap=0,cap=1,cost=0
last_cap=1,cap=2,cost=0
last_cap=2,cap=4,cost=0
last_cap=4,cap=8,cost=0
last_cap=8,cap=16,cost=0
last_cap=16,cap=32,cost=0
last_cap=32,cap=64,cost=0
last_cap=64,cap=128,cost=0
last_cap=128,cap=256,cost=0
last_cap=256,cap=512,cost=0
last_cap=512,cap=1024,cost=0
last_cap=1024,cap=2048,cost=0
last_cap=2048,cap=4096,cost=0
last_cap=4096,cap=8192,cost=0
last_cap=8192,cap=16384,cost=0
last_cap=16384,cap=32768,cost=0
last_cap=32768,cap=65536,cost=0
last_cap=65536,cap=131072,cost=0
last_cap=131072,cap=262144,cost=0
last_cap=262144,cap=524288,cost=1
last_cap=524288,cap=1048576,cost=1
last_cap=1048576,cap=2097152,cost=3
last_cap=2097152,cap=4194304,cost=6
last_cap=4194304,cap=8388608,cost=13
last_cap=8388608,cap=16777216,cost=25
last_cap=16777216,cap=33554432,cost=51
last_cap=33554432,cap=67108864,cost=102
last_cap=67108864,cap=134217728,cost=204
last_cap=134217728,cap=268435456,cost=407
last_cap=268435456,cap=536870912,cost=818
last_cap=536870912,cap=1073741824,cost=1633
last_cap=1073741824,cap=2147483648,cost=3372
可以看出,vector在2的n次幂都会扩容。重要节点是
- capacity :1.3亿~2.6亿-时间约400ms
- capacity :2.6亿~5.3亿-时间约800ms
- capacity :5.3亿~10.7亿-时间约1600ms
3、问题解决
问题找到了,解决就容易了。
vector有reserve接口,可以在程序启动时就扩容好,防止运行时动态扩容造成卡顿。
其实程序在启动时,已经调用reserve提前扩容了,但是近期国际局势不稳定,造成订单量飙升,所以reserve的量不足,需要重新估计一下。
- reserve:reserves storage
东北码农,全网同名,欢迎大家使用常用聊天软件关注、评论交流~
如果大家觉得有用,求点赞、转发~
谢谢你~
被vector动态扩容给坑了!的更多相关文章
- <实训|第十二天>用LVM对linux分区进行动态扩容
[root@localhost~]#序言在linux中,我们安装软件的途径一般有那些,你们知道吗?在linux中,如果你的磁盘空间不够用了,你知道如何来扩展磁盘吗?动态扩容不仅在工作中还是在其他方面都 ...
- ArrayList和Vector的扩容机制
ArrayList和Vector都是继承了相同的父类和实现了相同的接口.如下 public class Vector<E> extends AbstractList<E> im ...
- Arraylist动态扩容详解
ArrayList 概述 ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长. ArrayList不是线程安全的,只能用在单线程环境下. 实现了Serializable接口,因此它支 ...
- 转:用STL中的vector动态开辟二维数组
用STL中的vector动态开辟二维数组 源代码:#include <iostream>#include <vector>using namespace std;int mai ...
- Redis进阶实践之十二 Redis的Cluster集群动态扩容
一.引言 上一篇文章我们一步一步的教大家搭建了Redis的Cluster集群环境,形成了3个主节点和3个从节点的Cluster的环境.当然,大家可以使用 Cluster info 命令查看Cl ...
- LVM XFS增加硬盘分区容量最后一步的时候动态扩容报错
在我们lvextend扩容完之后,想动态扩容时出现错误.我们可以用以下命令来进行操作. 若不是xfs我们可以用resize2fs,这里报错了 [root@Mysql01-213-66 ~]# resi ...
- 一脸懵逼学习Hdfs---动态增加节点和副本数量管理(Hdfs动态扩容)
1:按照上篇博客写的,将各个进程都启动起来: 集群规划: 主机名 IP 安装的软件 运行的进程 master ...
- Linux LVM动态扩容
引用自: https://blog.csdn.net/u012439646/article/details/73380197 xfs_growfs /dev/centos/root 一.首先安 ...
- mysql动态扩容调研
MySQL动态扩容方案 目前可用方案 MySQL的复制: 一个Master数据库,多个Salve,然后利用MySQL的异步复制能力实现读写分离,这个方案目前应用比较广泛,这种技术对于以读为主的应用很有 ...
随机推荐
- Atcoder ARC-068
A 不难发现从 \(5\) 开始一直往 \(6\) 转再转回来是最优的,直接模拟即可. B 不难发现可以将多余部分直接贪心消去,最后必然会剩下两个或 \(1\) 个多余的数. 如果剩下两个,此时多余的 ...
- PHP中英文混合字符串处理
转载请注明来源:https://www.cnblogs.com/hookjc/ function cut_str($string, $sublen, $start = 0, $code = 'utf- ...
- cell重用
少数几个cell可不重用 NSString *CellIdentifier = [NSString stringWithFormat:@"MyCellID_%d",indexPat ...
- Redis 在 vivo 推送平台的应用与优化实践
一.推送平台特点 vivo推送平台是vivo公司向开发者提供的消息推送服务,通过在云端与客户端之间建立一条稳定.可靠的长连接,为开发者提供向客户端应用实时推送消息的服务,支持百亿级的通知/消息推送,秒 ...
- Lesson10——NumPy 迭代数组
NumPy 教程目录 NumPy 迭代数组 NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式. 迭代器最基本的任务的可以完成对数组元素的访问. Exa ...
- 1day漏洞反推技巧实战(3)
代码审计必备技能,github代码对比,写一笔: 搜索某开源组建漏洞,搜索出来某个版本rce: 通过消息得出:存在漏洞版本:1.10.10 ,修复漏洞版本1.10.11 去github寻找apache ...
- 【前端开发日记 】VSCODE被初始化之后重新设置的这些事
不知到什么插件的原因,导致我的vscode编辑器,在输入比如div的时候按tab不会识别成html标签,在设置了推荐词之后还是不好使,于是初始化了自己的编辑器设置 ,导致所有的插件和个性化设置都不见了 ...
- Kubernetes-三大开放接口-初见
目录 容器运行时接口CRI 历史 简介 架构 启用 CRI CRI 接口 当前支持的 CRI 后端 容器网络接口CNI 简介 接口定义 官方网络插件 接口参数 CNI 的特性 在 kubernetes ...
- mysql查询的时候没有加order by时的默认排序问题
有时候我们执行MySQL查询的时候,查询语句没有加order by,但是发现结果总是已经按照id排序好了的,难道MySQL就是为了好看给我们排序 如上图数据,是我查询了语句 SELECT * from ...
- suse 12 二进制部署 Kubernetets 1.19.7 - 第07章 - 部署kube-controller-manager组件
文章目录 1.7.部署kube-controller-manager 1.7.0.创建kube-controller-manager请求证书 1.7.1.生成kube-controller-manag ...