4种API性能恶化根因分析
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4种API性能恶化根因分析相关的知识,希望对你有一定的参考价值。
摘要:服务发生性能恶化时,需要投入大量人力分析性能异常根因,分析成本高,耗时长。我们提出了一种先在异常调用链内部分析候选根因,再在全局拓扑环境下对候选根因进行汇聚的二级分析方法,克服了调用链之间异常相互影响导致根因难以确定的问题,快速识别和定位恶化接口的根因。
本文分享自华为云社区《【AIOps专题】API性能恶化根因分析》,作者:DevAI。
背景介绍
当微服务系统发生性能恶化问题时,真正有问题的服务和与它相关的服务,都会出现指标异常以及发出告警。大量的告警让运维人员无法确定哪个服务才是恶化根因,只能逐个服务去检查,排除掉那些本身并没有异常的服务,定位成本高。自动化的恶化根因定位服务对于快速处理基于服务的系统恶化是非常重要的。
图例 调用链上的根因定位
基于长尾任务的性能恶化根因分析
一种常见的根因分析方法是将耗时长尾事件作为性能异常的根因事件。首先获得指定时间窗口内的恶化调用链,遍历接口恶化关联的多个调用链,选择耗时最长的一条;再基于耗时主导原则,对这条耗时最长的调用链找到耗时最长的调用事件,并将其作为恶化根因。这种方法的主要缺点在于,只考虑服务的耗时情况,认为根因只会发生在耗时最长的一条恶化调用链,对调用链结构异常、参数错误等导致的性能异常不具有识别能力;
基于单调用链拓扑的性能恶化根因分析
基于单调用链拓扑的性能恶化定位方法,首先从历史成功调用链数据中提炼正常调用链模板,对于每条待测用例,匹配最佳模板,再进行差异分析,最后排序推荐根因。这种根因分析方法仅着眼于根因在单条调用链上的影响因素,忽略了异常在调用链之间的相互影响以及调用链之间的差异。
基于恶化传播图的性能恶化根因分析
此方法针对目前相关性分析方法没有很好考虑到微服务动态位移的问题,设计新的异常评分算法以衡量微服务组件的恶化程度,构建恶化传播图;然后对传统随机游走算法进行优化。然而基于随机游走的方法都存在一个缺陷,即当系统中同时出现多个恶化时,服务可能会受到叠加影响,而导致定位的准确性下降。
基于拓扑汇聚的性能恶化根因分析方法
针对当前痛点,我们提出了一种基于拓扑汇聚的性能恶化根因分析方法,该方法最创新的特征是提出了一种先在异常调用链内部分析候选根因,再在全局拓扑环境下对候选根因进行汇聚的二级分析方法,综合利用了微服务场景下尽可能多的信息,并进行了综合汇聚和多指标评价,克服了调用链之间异常相互影响导致根因难以确定的问题,快速识别和定位恶化接口事件粒度的根因,减少了根因定位分析成本。方案主要包含两个模块,预处理模块和汇聚定位模块。
预处理模块通过输入时间窗口内的正常调用链数据,学习正常调用链模式并建立全局拓扑,包括三个部分:建立正常模板库、提取真实节点拓扑和维护反向可达性表。
汇聚定位模块首先对候选根因从三个维度进行分数计算,再根据汇聚公式对候选根因进行汇聚,包含三个维度的计算:链上得分的计算、链间得分的计算和拓扑得分的计算;再根据组合公式,得到最终的根因推荐分数,分数越高表示越有可能是根因。
总结
针对目前性能恶化定位成本高的问题,我们提出了一种先在异常调用链内部分析候选根因,再在全局拓扑环境下对候选根因进行汇聚的二级分析方法,并提出了一种计算三项得分的多维评价方法,综合考虑真实环境中的多种因素,以更准确更高效地推荐根因。
文章来自:PaaS技术创新Lab,PaaS技术创新Lab隶属于华为云,致力于综合利用软件分析、数据挖掘、机器学习等技术,为软件研发人员提供下一代智能研发工具服务的核心引擎和智慧大脑。我们将聚焦软件工程领域硬核能力,不断构筑研发利器,持续交付高价值商业特性!加入我们,一起开创研发新“境界”!
PaaS技术创新Lab主页链接:https://www.huaweicloud.com/lab/paas/home.html
JavaFX动画 - 性能恶化[重复]
【中文标题】JavaFX动画 - 性能恶化[重复]【英文标题】:JavaFX animation - deteriorating performance [duplicate] 【发布时间】:2017-12-04 17:39:39 【问题描述】:我创建了多个文本节点的动画。用户应该正在阅读从服务器接收到的文本。问题是几分钟(大约 5 分钟)后性能开始下降。从 60 fps 到 30 fps 及以下。因此,文本很难阅读。
编辑 2:
我创建了一个最小、完整且可验证的示例:
项目中有3个文件:
MainFxApp:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import java.util.List;
public class MainFxApp extends Application
@Override
public void start(Stage primaryStage)
Pane root = new Pane();
root.setStyle("-fx-background-color: black;");
MyAnimationTimer myAnimationTimer = new MyAnimationTimer((List<MyText>) (List<?>) root.getChildren());
MyText newText;
for (int i = 65; i < 85; i++)
newText = new MyText("" + ((char) i));
newText.setFill(Color.GREEN);
newText.setFont(Font.font(40));
myAnimationTimer.addNode(newText);
Scene scene = new Scene(root, 1200, 600);
primaryStage.setTitle("Performance test");
primaryStage.setScene(scene);
primaryStage.show();
myAnimationTimer.start();
public static void main(String[] args)
launch(args);
我的动画计时器:
import javafx.animation.AnimationTimer;
import javafx.application.Platform;
import javafx.scene.CacheHint;
import javafx.scene.Node;
import java.util.List;
public class MyAnimationTimer extends AnimationTimer
private List<MyText> nodes;
private double panelWidth;
private double panelHeight;
private double basicVelocity; // Distance per nanosecond
private long lastFrameTime;
private long timeCount = 0;
private int frameCount = 0;
MyAnimationTimer(List<MyText> nodes)
super();
this.nodes = nodes;
this.panelWidth = 1200;
this.panelHeight = 600;
this.setBasicVelocity();
@Override
public void start()
this.lastFrameTime = System.nanoTime();
super.start();
@Override
public void handle(long now)
long deltaT = now - lastFrameTime;
double deltaX = this.basicVelocity * deltaT;
for (MyText node : this.nodes)
node.setTranslateX(node.getTranslateX() + node.direction * deltaX);
if (node.getTranslateX() < 0)
node.direction = 1;
else if (node.getTranslateX() > 1200)
node.direction = -1;
this.lastFrameTime = now;
this.timeCount += deltaT;
this.frameCount++;
if (timeCount > 1000000000)
System.out.println(this.frameCount / (double) timeCount * 1000000000);
this.frameCount = 0;
this.timeCount = 0;
void addNode(final MyText node) // Not sure about the final thing
Platform.runLater(() ->
node.setCache(true);
node.setCacheHint(CacheHint.SPEED);
node.setTranslateY(panelHeight / 2);
double nodePositionX = panelWidth - 20;
if (nodes.size() >= 1)
Node lastNode = nodes.get(nodes.size() - 1);
double lastNodeEnd = lastNode.getTranslateX() + 50;
if (lastNodeEnd > nodePositionX)
nodePositionX = lastNodeEnd;
node.setTranslateX(nodePositionX);
nodes.add(node);
);
private void setBasicVelocity()
Platform.runLater(() ->
this.basicVelocity = ((panelWidth / 4) * 3 / (double) 5000 / 1000000.0);
);
我的文本:
import javafx.scene.text.Font;
import javafx.scene.text.Text;
class MyText extends Text
int direction = -1;
MyText(String text)
super(text);
this.setFont(new Font("Arial Regular", 40));
即使是这个简单的例子,性能下降也很明显。场景中有 20 个节点,fps 下降到 20 以下。我的 CPU 是 i5-4440 CPU (3.10GHz × 4)。这个问题出现在我测试过的每个平台上——JavaFX 8、JavaFX 9 和 Ubuntu 16.04。
编辑 3:
这个问题似乎只出现在 Linux 平台上。
但是,即使在 Windows 上,当我经常通过 Platform.runLater 方法访问 JavaFX 线程时,即使动画保持在 60fps,它也似乎并不流畅。有人知道如何改进吗?
谢谢,杨
【问题讨论】:
MyText 类在哪里? 您能看到资源监视器中消耗的任何资源吗?您使用的是什么操作系统? 对于我已经离开一周的迟到的回复,我深表歉意。我在编辑中添加了 MyText 源代码。我使用的是 Ubuntu 16.04,但我也在 Windows 10 上测试了代码,结果相同。 JavaFX 8 和 JavaFX 9 都出现此问题。当我启动应用程序时,动画以 60 fps 运行,所有 4 个线程的 CPU 消耗约为 20%。当问题发生时,每个线程的使用量大约为 50%,因此 CPU 时间消耗会显着增加。 我已经尝试了您的示例,但无法重现该问题,也看不到任何明显的问题,例如内存泄漏。如果出现性能问题,我将让应用程序运行一段时间并报告。 (Win 10,i5-4300U 2.50GHz)。 CPU 使用率 ~ 1.5%。使用 jdk_1.8.0_60 构建 内存消耗是否也增加了?你可以用-Dprism.verbose=true
运行吗?另外,看看这个问题:***.com/questions/40228866/…
【参考方案1】:
看起来您的 Linux 硬件加速在 JavaFX 渲染方面存在一些问题。我在具有类似功能的机器上没有遇到性能问题。
尝试在纯软件模式下运行您的代码:
java -Dprism.order=j2d -jar myfxapp.jar
【讨论】:
在这种情况下,它可能与此重复:***.com/questions/40228866/… 它确实解决了这个问题,它确实是@sillyfly 发布的线程的副本,我将这样标记它。谢谢以上是关于4种API性能恶化根因分析的主要内容,如果未能解决你的问题,请参考以下文章
基于网络拓扑及告警的故障根因定位系统实现及算法研究赛题需求分析
运营大规模HDFS集群必看:系统升级后,怎么性能反而恶化了?!