性能优化是我们日常工作中很重要的一部分,主要有以下原因:
而并行优化在改善程序接口响应时间和吞吐量指标方面是个利器,所以本次结合前段时间做的一段长链路执行逻辑代码的优化,给大家讲讲程序并行优化的步骤及方法论。
一般是通过全链路监控、火焰图、自定义打点、生产报警等先找到耗时长的性能问题点,之后通过多线程并行化的方式达到优化程序响应时长和吞吐量的目的。
对问题点的执行链路进行分析,主要分几方面:
描述:具体业务任务继承接口 Runnable、Callable ,在调用 ExecutorService.submit 接口时,会提交任务到 ExecutorService 内部的一个任务队列中。同时,在 ExecutorService 内部还存在一个预先申请的线程池(Thread Pool),线程池中的线程会从任务队列中领取一个任务来执行。
优点:复用线程,减少线程创建销毁成本及减少请求时延
注意点:cpu密集型和io密集型任务应进行不同的线程池配置;为避免不同任务相互干扰重要业务最好独立使用线程池;不同线程之间要注意操作的有序和数据的可见性
描述:每个 Actor 代表的是可以被调度执行的轻量单元。如图中所示,Actor A 和 Actor C 在向 Actor B 发送消息时,所有消息会被底层框架发送到 Actor B 的 Mailbox 中,然后底层的 Akka 框架调度代码会触发 Actor B,来接收并执行消息的后续处理。这样,基于 Actor 模型的这套并发框架,首先就保证了消息可以被安全地在各个 Actor 之间传递,同时也保证了每个 Actor 实例可以串行处理接收到的所有消息。
优点:不需要关注多线程之间并发同步和数据一致性;轻量级高并发
注意点:actor任务粒度要小,避免承接太多业务逻辑;计算密集型任务更能发挥出AKKA的优势
描述:输入流 Flux 就是 Reactor 中典型的异步消息流,它代表了一个包含 0 个到 N 个的消息序列。另外,图中的 Rule 代表的是一个基于消息的处理逻辑或规则,输入流中的消息可以被中间多个处理逻辑组合连续加工之后,再生成一个包含 0 个到 N 个的输出消息流 Flux。
优点:rule采用pull处理消息,避免消息积压;异步非阻塞io,避免阻塞当前线程
注意点:函数式编程,会有一定的语法学习成本和理解成本;针对消息流处理的、基于 IO 密集型的异步交互场景比较有优势
多线程执行涉及到一系列细节问题,如共享变量可见性,执行顺序,结果的获取、后续操作的通知等,所以要结合需求使用一系列相关的并发工具类做多线程执行正确性的保障
一般通过jmeter、loadrunner等后端性能测试软件,不断对系统施加压力,并验证系统化处于或长期处于临界饱和阶段的稳定性以及性能指标,并试图找到系统处于临界状态时的主要瓶颈点。
注意点:
一般通过diff工具通过采集相同请求的响应对比判别是否影响业务;也可通过qa辅助构建针对改动的测试集去做验证
以我们前段时间进行的商品主数据下发消费能力调优进行举例说明整个优化过程:
主数据程序接收商品批量下发处理缓慢,触发下发积压报警
梳理各步骤对入参和保存时需要的变量的处理,分析各步骤相互依赖关系,是否可并行,进行执行过程优化调整。
商品主数据处理步骤分析:
出于团队知识栈及框架应用场景综合考虑,这里选择了线程池作为并发框架,并结合多io场景做了线程池参数配置。
/**
* io任务线程池
*/
public static ThreadPoolExecutor threadPoolExecutorForIO= new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),Runtime.getRuntime().availableProcessors()*2,1, TimeUnit.MINUTES,new ArrayBlockingQueue(2014),new ThreadPoolExecutor.CallerRunsPolicy());
这里使用CompletionService来获取多线程的执行结果,并进行结果归集。
CompletionService通过在线程结果完成时提交到阻塞队列,避免通过遍历future结果的方式导致先提交的任务耗时长造成的阻塞等待。
CountingExecutorCompletionService<Boolean> completionService= new CountingExecutorCompletionService(ExecutorCollector.threadPoolExecutorForIO);
//任务提交
completionService.submit(callableA);
//结果归集
boolean result=true;
for(int i = 0; i<completionService.getSubmittedTaskCount(); i++)
{
result&=completionService.take().get();
}
采用jmeter对两台相同配置的服务器(分别部署优化版本和原始版本)加压,观察服务负载情况
1)耗时和吞吐量异步版本要优于同步版本
异步版本耗时在80-100ms,同步版本耗时在120-160ms
异步版本吞吐量在17000/5分钟,同步版本吞吐量在15000/5分钟
2)cpu使用率异步版本略高一点,线程数异步版本比较高
线程数高的原因:用到了线程池,预置的核心线程数为逻辑核数64,因为涉及到io操作较多,最大线程数配成了128。
因为公司框架不支持http的diff,此处采用了自己抽检请求结果及qa协助走查和code review的方式保证业务结果的准确性
程序性能优化方法关系到方方面面,而多线程异步优化无疑是其中很重要的一种途径。它不光关系到并发框架的选择、多种线程工具类的使用,还关系到对整个处理链路的业务理解和编排分析。希望通过这一课可以帮大家理清相关的思路,作为日常优化工作的一个参考。
作者:京东物流 冯鸿儒
内容来源:京东云开发者社区
大家好,又见面了,我是你们的朋友全栈君。echo"************autostart,Begin...**************" #得到对应服务的进程号 str=`ps-ef|greplanguage-1.0-SNAPSHOT.jar|grep-v"grep"|awk'{print$2}'` #获取进程所在的目录 pwd=`ls-l/proc/${ str}|grep"cwd->"|grep-v"grep"|awk'{print$NF}'` echo"进程目录是:"$pwd kill-9$str if["$?"-eq0];then echo"killedpidis"$str echo"killsuccess" else echo"killfailed" fi nowDate=`date+"%Y-%m-%d"` #进入对应的目录,重
1.常见MON故障处理Monitor维护着Ceph集群的信息,如果Monitor无法正常提供服务,那整个Ceph集群就不可访问。一般来说,在实际运行中,CephMonitor的个数是2n+1(n>=0)个,在线上至少3个,只要正常的节点数>=n+1,Ceph的Paxos算法就能保证系统的正常运行。所以,当Monitor出现故障的时候,不要惊慌,冷静下来,一步一步地处理。1.1开始排障在遭遇Monitor故障时,首先回答下列几个问题:Mon进程在运行吗?我们首先要确保Mon进程是在正常运行的。很多人往往忽略了这一点。是否可以连接MonServer?有时候我们开启了防火墙,导致无法与Monitor的IP或端口进行通信。尝试使用ssh连接服务器,如果成功,再尝试用其他工具(如telnet,nc等)连接monitor的端口。ceph-s命令是否能运行并收到集群回复?如果答案是肯定的,那么你的集群已启动并运行着。你可以认为如果已经形成法定人数,monitors就只会响应status请求。如果ceph-s阻塞了,并没有收到集群的响应且输出了很多fault信息,很可能此时你的monito
.attr()与.removeAttr()attr()有4个表达式attr(传入属性名):获取属性的值attr(属性名,属性值):设置属性的值attr(属性名,函数值):设置属性的函数值attr(attributes):给指定元素设置多个属性值,即:{属性名一:“属性值一”,属性名二:“属性值二”,……}html(),text()和val().html(),.text()和.val()的差异总结:.html(),.text(),.val()三种方法都是用来读取选定元素的内容;只不过:.html()是用来读取元素的html内容(包括html标签).text()用来读取元素的纯文本内容,包括其后代元素.val()是用来读取表单元素的"value"值。.html()和.text()方法不能使用在表单元素上,而.val()只能使用在表单元素上;另外.html()方法使用在多个元素上时,只读取第一个元素;.val()方法和.html()相同,如果其应用在多个元素上时,只能读取第一个表单元素的"value"值,但是.text()和他们不一样,如果.text(
MySQL不常用的一个语法今天周会上,同事提到了一个业务问题,场景大概是这样的,业务方的需求是查询一条语句在不在,如果在就给出一个update语句,更新这条记录,如果不在,就给出一个insert语句,插入这条记录。逻辑大概是:result=select*fromtable; ifresult=0 inserttherecordintotable; else updatetherecord; 复制这样的操作乍一看没有什么问题,但是仔细分析分析,还是有些瓶颈的,目前来看,我能分析到的瓶颈有两个,其一:每次要执行2个SQL,效率比较差;其二:当我们在高并发的情况下跑这条语句,如果程序崩溃,不能保证操作的原子性。基于这个问题,同事提出了insert...onduplicatekeyupdate这个办法,而我的第一反应是replace方法,因为我之前从来没用过insert...onduplicatekey这个语法,所以专门把这两个语法研究了一下,下面简单分析下这两个语法:01insert...onduplicatekey方法首先我们看看这个语法的具体写法,我简单写一个例子,内容大致如下:1、首先
上一篇文章(ASTMatcher分析函数调用链(上))讲到ASTMatcher的原理以及创建,本文将详细介绍ASTMatcher获取函数调用链在iOSapp中的应用。一、ASTMatcher部分1、无消息调用的函数定义获取上篇中的ASTMatcher只能获取有消息调用的函数定义,那没有消息调用的函数定义就无法匹配到,所以无消息调用的函数定义也需要获取DeclarationMatcherAllFuncMatcher=objcMethodDecl( hasAncestor(objcImplementationDecl().bind("allClass")) ).bind("allSelector");复制同理也需要获取匹配节点2、category类的消息调用获取objcImplementationDecl()中并不包括category类,所以category类需要单独写Matcher匹配DeclarationMatcherCategoryFuncLinkMatcher=objcMethodDecl( hasAncestor(objcCategoryI
在CentOS7中,有三种定义的主机名:静态的(Statichostname)“静态”主机名也称为内核主机名,是系统在启动时从/etc/hostname自动初始化的主机名。瞬态的(Tansienthostname)“瞬态”主机名是在系统运行时临时分配的主机名,例如,通过DHCP或mDNS服务器分配。灵活的(Prettyhostname)“灵活”主机名也有人叫做“别名”主机名。 “灵活”主机名则允许使用自由形式(包括特殊/空白字符)的主机名,以展示给终端用户 “静态”主机名和“瞬态”主机名都遵从作为互联网域名同样的字符限制规则。查看主机名: 查看三种主机名:hostnamectl查看瞬态的主机名:hoetname查看当前Linux操作系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等):uname-a//查看到的是瞬态的(Tansienthostname) cat/etc/redhat-release//查看操作系统环境复制修改主机名: 方法一:临时有效 hostname主机名//只能临时修改的主机名,当重启机器后,主机名称又变回来了。hostnamexxx 方法二:
本文来自:酷壳--CoolShell地址:https://coolshell.cn/articles/4758.html如何写出无法维护的代码2011年06月03日 陈皓评论120条评论 124,691人阅读酷壳里有很多我觉得很不错的文章,但是访问量最大的却是那篇《6个变态的HelloWorld》,和它能在本站右边栏“全站热门”中出现的还有“如何加密源代码”,以及编程真难啊等这样的文章。可见本站的读者们的偏好,我也相信你们都是“身怀绝技”的程序员。所以,今天给大家推荐这篇文章,相信一定能触动大家的兴奋点。这篇文章的原文在这里(http://mindprod.com/jgloss/unmain.html),我看完后我想说——什么叫“创造力”,创造力就是——就算是要干一件烂事都能干得那么漂亮那么有创意的能力。什么叫“抓狂”,抓狂就是——以一种沉着老练的不屈不挠的一本正经的精神一点一点把你推向崩溃的边缘。我把文章节选了一些,也并没有完全翻译,简译一下,也加入了一些自己的调侃。对于有下面这些编程习惯的朋友,请大家对号入座。另外,维护程序的朋友们,你们死定了!!Ifbuildersbuiltbu
写给还是小白的你们,一起加油呀~可以这么理解Tomcat:开源的Web应用服务器,一般用于中小型系统和并发访问用户不是很多的情况下,是开发和调试JSP的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache服务器,可以利用它来响应HTML页面的访问请求。也就是说,Apache为HTML页面服务,而Tomcat实际上运行JSP页面和Servlet。另外,Tomcat和IIS等Web服务器一样,具有处理HTML页面的功能,另外它还有一个Servlet和JSP容器,独立的Servlet容器等是Tomcat的默认方式。下载地址:http://tomcat.apache.org/Tomcat的目录层次结构:bin存放启动和关闭Tomcat的脚本文件conf存放Tomcat服务器的各种配置文件lib存放Tomcat服务器和所有web应用程序需要访问的jar包logs存放Tomcat的日志文件temp存放Tomcat运行时产生的临时文件webapps当发布web应用程序时,通常把web应用程序的目录及文件放到这个目录下workTomcat将JSP生成的Servlet源文件和字节码文
传统的ID3和C4.5一般用于分类问题,其中ID3使用信息增益进行特征选择,即递归的选择分类能力最强的特征对数据进行分割,C4.5唯一不同的是使用信息增益比进行特征选择。特征A对训练数据D的信息增益g(D,A)=集合D的经验熵H(D)-特征A给定情况下D的经验条件熵H(D|A)特征A对训练数据D的信息增益比r(D,A)=g(D,A)/H(D)而CART(分类与回归)模型既可以用于分类、也可以用于回归,对于回归树(最小二乘回归树生成算法),需要寻找最优切分变量和最优切分点,对于分类树(CART生成算法),使用基尼指数选择最优特征。 install.packages("rpart")install.packages("rpart.plot")library(rpart);##rpart.control对树进行一些设置 ##xval是10折交叉验证 ##minsplit是最小分支节点数,这里指大于等于20,那么该节点会继续分划下去,否则停止 ##minbucket:叶子节点最小样本数 ##maxdepth:树的深度 ##cp全称为complexityp
1.论文信息标题:MitigatingNeuralNetworkOverconfidencewithLogitNormalization作者:HongxinWei,RenchunziXie,HaoCheng,LeiFeng,BoAn,YixuanLi6原文链接:https://arxiv.org/abs/2205.09310代码链接:https://github.com/hongxin001/logitnorm_ood2.介绍在我们的生活中,测试一个机器学习的分类器是否有效,一个标准是统计或者对抗检测(statisticallyoradversariallydetecting)测试样本与训练分布有足够的距离。在许多视觉的分类任务中,可以使用神经网络(DNNs)对样本内(In-Distribution)的类别进行精准分类。然而,确定预测不确定性仍然是一项困难的任务。而分类中通行的softmax这一归一化函数,在进行分类的神经网络中会产生“过度自信的结果”。即使若测试样本是ID数据中不存在的类别(Out-of-Distribution),softmax也会给这个陌生的东西计算出一个概率,而
大家好,又见面了,我是你们的朋友全栈君。 MYSQL中,常用的几种约束:约束类型:主键:primarykey外键:foreignkey唯一:unique非空:notnull自增:auto_increment默认值:default主键约束primarykey主键约束相当于唯一约束+非空约束的组合,主键约束列不允许重复,也不允许出现空值。每个表最多只允许一个主键,建立主键约束可以在列级别创建,也可以在表级别创建。当创建主键的约束时,系统默认会在所在的列和列组合上建立对应的唯一索引。基本模式:createtabletemp(idintprimarykey,namevarchar(20));组合模式:createtabletemp(idint,namevarchar(20),pwdvarchar(20),primarykey(id,name));1、创建库createdatabasetestcharsetutf8;可以加入ifnotexists判断是否重复建库在库名前面加入即可,建表也是如此2、创建表createtabletemp(idintprimarykeyauto_incrementno
1.接口描述接口请求域名:cdb.tencentcloudapi.com。 本接口(OpenDBInstanceGTID)用于开启云数据库实例的GTID,只支持版本为5.6以及以上的实例。 默认接口请求频率限制:20次/秒。 APIExplorer提供了在线调用、签名验证、SDK代码生成和快速检索接口等能力。您可查看每次调用的请求内容和返回结果以及自动生成SDK调用示例。 2.输入参数以下请求参数列表仅列出了接口请求参数和部分公共参数,完整公共参数列表见公共请求参数。 参数名称 必选 类型 描述 Action 是 String 公共参数,本接口取值:OpenDBInstanceGTID。 Version 是 String 公共参数,本接口取值:2017-03-20。 Region 是 String 公共参数,详见产品支持的地域列表。 InstanceId 是 String 实例ID,格式如:cdb-c1nl9rpv,与云数据库控制台页面中显示的实例ID相同。 3.输出参数 参数名称 类型 描述 AsyncRequestId St
12842357的倍数 基准时间限制:1秒空间限制:131072KB分值:5难度:1级算法题收藏 关注 给出一个数N,求1至N中,有多少个数不是2357的倍数。例如N=10,只有1不是2357的倍数。 Input 输入1个数N(1<=N<=10^18)。 Output 输出不是2357的倍数的数共有多少。 Input示例 10 Output示例 1 容斥原理:|AUBUC|=|A|+|B|+|C|-|ANB|-|BNC|-|CNA|+|ANBNC|; 正负号取决于集合的个数,奇数个集合为正,偶数个集合为负。 #include<map> #include<stack> #include<queue> #include<math.h> #include<vector> #include<string> #include<stdio.h> #include<iostream> #include<string.h> #include<algorit
100、-like表形容词,”像…一样“ 101、-ling表名词,”小东西或某种人“ 102、-ly①表形容词,通常加在名词后②表副词,通常放在形容词后 103、-ment①表名词,”行为或结果“②表示具体物 104、-most表形容词,”最…的“ 105、-ness表名词,”性质,状态“通常加在形容词后面 106、-o①表名词,”人,物或状态“②表名词,用于音乐术语 107、-on表名词,指人,物和一些物理学上的名词 108、-oon表名词,”人或物“ 109、-or表名词,”人或物器“,在一些词根前写成”-aotr“ 110、-ory①表形容词,”…的“②表名词,指场所等 111、-ose,表形容词,”多…的“ 112、-osity表名词,ose+ity组成,表示”多…的状态“ 113、-ot表名词,”…人” 114、-ous表形容词,通常放在一个完整的单词后,表示“…的” 115、-proof表形容词,“防…的” 116、-ress①表名词,指“女性“②表名词,指”物品“ 117、-ry表名词,通常放在一个完整的单词后面①表示”状态,性质“②表示”行业,学科“③表示集合名词④表
Quill是一个很流行的富文本编辑器,github上star大约21k: github:https://github.com/quilljs/quill/ 官网: https://quilljs.com/ 使用 <!--Includestylesheet--> <linkhref="https://cdn.quilljs.com/1.3.6/quill.snow.css"rel="stylesheet"> <!--Createtheeditorcontainer--> <divid="editor"> <p>HelloWorld!</p> <p>Someinitial<strong>bold</strong>text</p> <p><br></p> </div> <!--IncludetheQuilllibrary--> <scriptsrc="https://cdn.quilljs.c
微信张小龙简介: 伟大的、光荣的、正确的双料创始人。Foxmail创始人和微信创始人。 一般能成为“创始”,那肯定其产品在一段时间广受大家欢迎和使用,并深入用户心灵,在同行业内起到标杆作用。三者去一不可,1)受欢2)为用户着想3)标杆。 “创始”还不够,还得是人。一般像我这种货色天天弄篇水文,弄个电子读物,也只能自称“XX文章系列”撰写“者”。“者”和”人”区别很大,往往后者能被后世所记住,百年之后大家谈起某产品还会提起这个“人”。 我们来看篇新闻: 5月6日,腾讯公司宣布成立微信事业群(WeiXinGroup,简称WXG),张小龙出任微信事业群总裁。 据悉,微信事业群负责微信基础平台、微信开放平台,以及微信支付拓展、O2O等微信延伸业务的发展,并包括邮箱、通讯录等产品开发和运营,致力于打造微信大平台,为用户和合作伙伴创造更多价值 三个概念自我扫盲: 事业部:不多描述,简单来说我们可以理解为美国的联邦政府和各个州之间的关系。事业部在不违背公司的“宪法”情况下,可以自主管理其部门的产品经营,最关键的,其财务是独立核算的。 事业群:概念要比事业部广泛的多。事业群
1、namedtuple 定义一个namedtuple: namedtuple('数据类型名',[属性列表]) fromcollectionsimportnamedtuple Point=namedtuple('point',['x','y','z']) p1=Point(1,2,3) p2=Point(3,2,1) print(p1.x) print(p1.y) print(p1.z) print(p1) print(p2) card=namedtuple('card',['suits','number']) c1=card('黑桃',2) print(c1) print(c1.number) print((c1.suits))复制 2、队列 2.1队列 importqueue q=queue.Queue()#可以指定队列最大长度 forxinrange(30): q.put(x) print(q.get())#当没有值得时候,阻塞等待 print(q.qsize()) print(q.get())#当没有值得时候,阻塞等待 print(q.qsize()
栈的链表实现 LinkStack.h #ifndefLINKSTACK_H_ #defineLINKSTACK_H_ typedefintDataType;//自定义数据类型,假定为整型 structNode;//单链表结点类型 typedefstructNode*PNode;//结点指针类型 typedefstructNode//单链表结点结构 { DataTypeinfo;//结点数据域 PNodelink;//结点指针域 }Node; typedefstructLinkStack//链表栈定义 { PNodetop;//栈顶指针 }LinkStack; typedefstructLinkStack*PLinkStack;//链表栈的指针类型 //创建一个空栈 PLinkStackcreateEmptyStack(void); //判断栈是否为空栈 intisEmptyStack(PLinkStackstack); //进栈,成功返回1,失败返回0 intpush(PLinkStackstack,DataTypex); //出栈,成功返回1,失败返回0 intp
寄生组合式继承是集寄生式继承和组合继承的优点于一身,是基于类型继承最有效的方式复制 functionobject(o){ functionF(){}; F.prototype=o; returnnewF(); } functioninheritPrototype(subType,superType){ varprototype=object(superType.prototype); prototype.constructor=subType; subType.prototype=prototype; } functionSuperType(name){ this.name=name; this.colors=["red","yellow","green"]; } SuperType.prototype.sayName=function(){ alert(this.name) } functionSubType(name,age){ SuperType.call(this,name); this.age=age; } inheritPrototype(SubType,Sup