被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的异步复制能力实现读写分离,这个方案目前应用比较广泛,这种技术对于以读为主的应用很有 ...
随机推荐
- Flutter Windows 桌面端支持进入稳定版
Flutter 创建伊始,我们就致力于打造一个能够构建精美的.可高度定制的.并且可以编译为机器码的跨平台应用解决方案,以充分发挥设备底层硬件的全部图形渲染能力.今天,Flutter 对 Windows ...
- Lesson6——Pandas Pandas描述性统计
1 简介 描述统计学(descriptive statistics)是一门统计学领域的学科,主要研究如何取得反映客观现象的数据,并以图表形式对所搜集的数据进行处理和显示,最终对数据的规律.特征做出综合 ...
- 报错:java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp
感谢原文作者:风起云淡- 原文链接:https://blog.csdn.net/shenguan777/article/details/78615521 异常分析: 在使用MySql时,如果数据库中有 ...
- 【Android珍藏】推荐10个炫酷的开源库【转】
感谢大佬:https://www.jianshu.com/p/d608f0228fd4 前言 技术群里面经常有人问到一些炫酷的UI效果实现方法,有时候我都是给一个相同或者相似效果的Github链接,有 ...
- where子句和having子句区别
感谢大佬:https://blog.csdn.net/XiaopinOo/article/details/78305008 where子句和having子句的区别: 1.where 不能放在grou ...
- redhat更改yum源及安装PHP环境
redhat更新yum源 删除同RHEL一同安装的yum源 rpm -qa|grep yum #查看本地yum yum list | wc -l #看个数 yum install pip #看现象 r ...
- 浅谈php web安全
首先,笔记不是web安全的专家,所以这不是web安全方面专家级文章,而是学习笔记.细心总结文章,里面有些是我们phper不易发现或者说不重视的东西.所以笔者写下来方便以后查阅.在大公司肯定有专门的we ...
- jdbc插入或查询数据库时间总是比实际时间少8小时原因
mysql插入数据库的时间总是有问题,比实际时间要早8小时.检查是jdbc连接的url中配置的时区有问题,原先是 jdbc.url=jdbc:mysql://47.**.**.**:3306/yeey ...
- JS字符串去替换元素再转换成数组
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11648074.html JS字符串替换不必要的元素, 然后去除多余的空格, 转换成数组: va ...
- Solution -「LOJ #141」回文子串 ||「模板」双向 PAM
\(\mathcal{Description}\) Link. 给定字符串 \(s\),处理 \(q\) 次操作: 在 \(s\) 前添加字符串: 在 \(s\) 后添加字符串: 求 \(s\ ...