OSATE总线延迟的源码分析与模型修复——针对 Latency-case-study项目 端到端流延迟分析过程中空指针异常的解决

本文主要是介绍OSATE总线延迟的源码分析与模型修复——针对 Latency-case-study项目 端到端流延迟分析过程中空指针异常的解决,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、背景

 在文章AADL 端到端流延迟分析示例项目 Latency-case-study 简述的 “第八章 进行系统的端到端流延迟分析” 中,遇到了这样的一个问题:对分布式系统的端到端流延迟进行分析时,没有生成流延迟分析报告,并且错误日志提示,出现内部错误“空指针异常”。

上述文章给出的解决方案是使用旧版本的OSATE,但是这并未真正地解决问题。将OSATE项目的源代码下载,进行调试和分析,结果如下:

在涉及到总线的端到端延迟分析过程中,只将“在end to end flow中涉及的连接” 添加到指定数据结构connectionsToContributors。如果一个连接绑定到了某总线,却未在某个end to end flow中声明,那么该连接便不会添加到connectionsToContributors中,由此导致connectionsToContributors缺少关于该连接的数据,导致空指针异常。

本文在最后给出了修改后的代码,以下为详细内容:

二、问题回顾

对于Latency-case-study项目,在生成integration.software_distributed实例之后,启用流延迟分析,发现并未有任何报告被生成:

错误日志(Error Log)显示如下:

java.lang.NullPointerException: Cannot invoke "org.osate.analysis.flows.model.LatencyContributor.addSubContributor(org.osate.analysis.flows.model.LatencyContributor)" because "latencyContributor" is nullat org.osate.analysis.flows.FlowLatencyAnalysisSwitch.fillInQueuingTimes(FlowLatencyAnalysisSwitch.java:1465)at org.osate.analysis.flows.FlowLatencyAnalysisSwitch.invokeOnSOM(FlowLatencyAnalysisSwitch.java:1052)at org.osate.analysis.flows.handlers.CheckFlowLatency.analyzeInstanceModel(CheckFlowLatency.java:158)at org.osate.ui.handlers.AbstractInstanceOrDeclarativeModelReadOnlyHandler.analyzeInstanceModelInMode(AbstractInstanceOrDeclarativeModelReadOnlyHandler.java:126)at org.osate.ui.handlers.AbstractInstanceOrDeclarativeModelReadOnlyHandler.doAaxlAction(AbstractInstanceOrDeclarativeModelReadOnlyHandler.java:101)at org.osate.ui.handlers.AbstractInstanceOrDeclarativeModelModifyHandler.processAaxlAction(AbstractInstanceOrDeclarativeModelModifyHandler.java:58)at org.osate.ui.handlers.AbstractAaxlHandler.actionBody(AbstractAaxlHandler.java:181)at org.osate.ui.handlers.AaxlReadOnlyHandlerAsJob$ActionAsJob.runInWorkspace(AaxlReadOnlyHandlerAsJob.java:115)at org.eclipse.core.internal.resources.InternalWorkspaceJob.run(InternalWorkspaceJob.java:43)at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

可以看到,内部错误的主要原因是因为“ "latencyContributor" is null 

三、问题详细分析

为什么会产生空指针异常,接下来将自上而下地对问题进行分析:

在整个分析过程中,对于连接延迟的计算,涉及到了一个Map对象connectionsToContributors,其定义如下:(FlowLatencyAnalysisSwitch.java : line 111)

/** Map from (bus component, connection instance) -> latency contributor. We need this because the queuing latency is computed at the end of process* after all the transmission times are computed. So we add the queuing latency to this latency contributor for the connection instance* bound to the given bus. This may contain entries that in the end are not interesting because virtual buses can be bound to* other virtual buses that are eventually bound to real bus. We chases down all those layers.*/private final Map<Pair<ComponentInstance, ConnectionInstance>, LatencyContributor> connectionsToContributors = new HashMap<>();

在流延迟分析过程中,会将端到端流中的元素按照类型依次添加到对应的Map中(其中一个Map用来存储关于连接的组件,即上面提到的connectionsToContributors),代码如下:

(FlowLatencyAnalysisSwitch.java : mapFlowElementInstance() : line 187)

public LatencyReportEntry analyzeLatency(EndToEndFlowInstance etef, SystemOperationMode som,boolean asynchronousSystem) {LatencyReportEntry entry = new LatencyReportEntry(etef, som, asynchronousSystem, report.isMajorFrameDelay());for (FlowElementInstance fei : etef.getFlowElements()) {mapFlowElementInstance(etef, fei, entry);}// Issue 1148 moved this somewhere else// entry.finalizeReportEntry();return entry;
}

上述代码中,会遍历所有的端到端流etef(end to end flow),将每个端到端流fei(Flow Element Instance)作为参数传递给函数mapFlowElementInstance(etef, fei, entry),而该函数会间接调用processSamplingAndQueuingTimes(),从而根据端到端流的组成元素,向Map connectionsToContributors 中添加元素(只有在端到端流中声明的元素才会被添加),代码如下:(FlowLatencyAnalysisSwitch.java : processSamplingAndQueuingTimes():line 896)

	//通过下面函数获取总线的周期,对于周期性总线和非周期性总线,延迟的计算方式不同。double period = hasPeriod.contains(cc) ? PropertyUtils.getScaled(TimingProperties::getPeriod, boundBusOrRequiredClassifier, TimeUnits.MS).orElse(0.0)    :   0.0;// 如果是周期性总线,增加采样延迟,将排队延迟设为0if (period > 0) {// add sampling latency due to the protocol or bus being periodicLatencyContributor samplingLatencyContributor = new LatencyContributorComponent(boundBusOrRequiredClassifier, report.isMajorFrameDelay());samplingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.SAMPLED_PROTOCOL);samplingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.SAMPLED_PROTOCOL);samplingLatencyContributor.setSamplingPeriod(period);latencyContributor.addSubContributor(samplingLatencyContributor);// add queuing latency: always zero in this caseLatencyContributor queuingLatencyContributor = new LatencyContributorComponent(boundBusOrRequiredClassifier, report.isMajorFrameDelay());queuingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.QUEUED);queuingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.QUEUED);queuingLatencyContributor.setMinimum(0.0);queuingLatencyContributor.setMaximum(0.0);latencyContributor.addSubContributor(queuingLatencyContributor);} //如果是非周期性总线,需要在后续过程中计算排队延迟,将其存储于Map中else {/** Issue 1148** if "boundBus" is really a bound component instance, and not a required component classifier,* then we remember the bus as asynchronous. Later in fillInQueuingTimes() we go through this list,* and then find all the connection instances bound to this bus. For each connection,* we compute the sum of the max transmission times of the OTHER connections bound to the bus. This* we set as the worse case queuing time. (Best case is 0.)** We also remember the bus--connection pair that needs the queuing latency by storing its latency contributor.*/if (bindingConnection != null) {final ComponentInstance boundBus = (ComponentInstance) boundBusOrRequiredClassifier;/* Set the bus order and then add it to the ordered set */if (!busOrder.containsKey(boundBus)) {busOrder.put(boundBus, nextBusId++);asyncBuses.add(boundBus);}connectionsToContributors.put(new Pair<>(boundBus, bindingConnection), latencyContributor);}

根据上述代码:对于周期性总线和非周期性总线,其延迟的计算方式不同。

对于周期性总线,计算它的采样延迟,范围为[0, period]。

对于非周期性总线,其最小延迟为0,最大延迟按照绑定到该总线的其他连接的数据传输时间之和进行计算。

因此,对于端到端流延迟分析函数的调用代码,涉及到了一个名为 fillInQueuingTimes()的函数,其源码如下:(FlowLatencyAnalysisSwitch.java : fillInQueuingTimes():line 1412)

	private void fillInQueuingTimes(final SystemInstance system) {// Nothing to do if there are no asynchronous busesif (!asyncBuses.isEmpty()) {// Get all the connections bound to a bus and group them together by the bus they are bound tofinal Map<ComponentInstance, Set<ConnectionInstance>> sortedConnections = sortBoundConnections(system);/** Go through the list of all the asynchronous buses*/for (final NamedElement ne : asyncBuses) {// only proceed if it is a bus instance and not a classifier (from Required_Virtual_Bus_Class)if (ne instanceof ComponentInstance) {final ComponentInstance bus = (ComponentInstance) ne;// Get all the connections bound to that busfinal Set<ConnectionInstance> boundConnections = sortedConnections.getOrDefault(bus,Collections.emptySet());// Get all the transmission times and compute the totaldouble totalTime = 0.0;final Map<ConnectionInstance, Double> transmissionTimes = new HashMap<>();for (final ConnectionInstance ci : boundConnections) {final Double time = computedMaxTransmissionLatencies.getOrDefault(new Pair<ComponentInstance, ConnectionInstance>(bus, ci), 0.0);transmissionTimes.put(ci, time);totalTime += time;}/** Go through the list of connections again, and subtract the time associated* with the current connection to find the max waiting time for each connection.* (That each for each connection ci, we will have the sum of all the times* for the _other_ connections bound to same bus. This gives us the max* time that connection ci may have to wait to use the bus.)*/for (final ConnectionInstance ci : boundConnections) {final Double ciTime = transmissionTimes.get(ci);final double maxWaitingTime = totalTime - ciTime;// Finally we can stick this into the latency contributorfinal LatencyContributor latencyContributor = connectionsToContributors.get(new Pair<>(bus, ci));final LatencyContributor queuingLatencyContributor = new LatencyContributorComponent(bus,report.isMajorFrameDelay());queuingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.QUEUED);queuingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.QUEUED);queuingLatencyContributor.setMinimum(0.0);if (report.isDisableQueuingLatency()) {// Hide the queuing timequeuingLatencyContributor.setMaximum(0.0);queuingLatencyContributor.reportInfo("Ignoring queuing time of " + maxWaitingTime + "ms");} else {// Report the queuing timequeuingLatencyContributor.setMaximum(maxWaitingTime);}latencyContributor.addSubContributor(queuingLatencyContributor);// add the sampling latencyLatencyContributor samplingLatencyContributor = new LatencyContributorComponent(bus, report.isMajorFrameDelay());samplingLatencyContributor.setBestCaseMethod(LatencyContributorMethod.SAMPLED_PROTOCOL);samplingLatencyContributor.setWorstCaseMethod(LatencyContributorMethod.SAMPLED_PROTOCOL);samplingLatencyContributor.setSamplingPeriod(0.0);latencyContributor.addSubContributor(samplingLatencyContributor);}}}}}

在上述代码中,首先会获取一条总线上绑定的所有连接。

final Set<ConnectionInstance> boundConnections = sortedConnections.getOrDefault(bus,Collections.emptySet());

然后依次遍历每条连接,在Map connectionsToContributors中定位到这个连接并向其中添加延迟贡献。

final LatencyContributor latencyContributor = connectionsToContributors.get(new Pair<>(bus, ci));

......

latencyContributor.addSubContributor(queuingLatencyContributor);

异常出现的原因:如果一个连接没有被包含于某个端到端流,但是却被绑定到总线上,那么Map connectionsToContributors将不会添加此连接,故而在遍历绑定到总线的连接时,会出现空指针异常。

四、解决方案

修复此问题的方法有2种:

1. 完整地建模,声明系统中存在的所有端到端流,以保证不会有连接被遗漏。

2. 设定总线周期,避免排队延迟情况的出现(即绕过排队延迟计算)。

五、修复模型并测试

两种方案的代码如下:(在 integration.aadl 的 integration.software_distributed 部分)

system implementation integration.software_distributed extends integration.software_genericsubcomponentss1_cpu 	: processor latency_cs::platform::generic_cpu;s2_cpu 	: processor latency_cs::platform::generic_cpu;p_cpu 	: processor latency_cs::platform::generic_cpu;a_cpu 	: processor latency_cs::platform::generic_cpu;s_p_bus: bus latency_cs::platform::generic_bus;p_a_bus : bus latency_cs::platform::generic_bus;connectionsb0 : bus access s1_cpu.net <-> s_p_bus;b1 : bus access s2_cpu.net <-> s_p_bus;b2 : bus access p_cpu.net <-> s_p_bus;b3 : bus access p_cpu.net <-> p_a_bus;b4 : bus access a_cpu.net <-> p_a_bus;-- 为解决流延迟分析过程中出现的空指针异常而增添的代码---------------- 方法1.完整地建模,声明系统中存在的所有端到端流(在flows中声明)flowsetef2 : end to end flow s1.sensor_source -> c0 -> p.sink0; etef3 : end to end flow s2.sensor_source -> c1 -> p.sink1;-- ---------------------------------------------------------------properties-- 为解决流延迟分析过程中出现的空指针异常而增添的代码------------ 方法2.设定总线周期(在properties中设定)--	Period => 5ms applies to s_p_bus, p_a_bus;-- -----------------------------------------------------------actual_processor_binding => (reference (s1_cpu)) applies to s1;actual_processor_binding => (reference (s2_cpu)) applies to s2;actual_processor_binding => (reference (p_cpu)) applies to p;actual_processor_binding => (reference (a_cpu)) applies to a;actual_connection_binding => (reference (s_p_bus)) applies to c0;actual_connection_binding => (reference (s_p_bus)) applies to c1;actual_connection_binding => (reference (p_a_bus)) applies to c2;-- protocol that applies to the connectionsrequired_virtual_bus_class => (classifier (latency_cs::platform::generic_protocol)) applies to c0, c1, c2;
end integration.software_distributed;

1. 完整地建模,声明系统中存在的所有端到端流,实例化后进行分析:

成功生成流延迟分析报告:

报告内容如下所示:

2. 设定总线周期,避免排队延迟情况的出现

成功生成流延迟分析报告:

报告内容如下所示:

六、相关链接

 OSATE 开发者文档,展示了如何部署环境并拉取OSATE源码,如下:

Setting up an OSATE development environment — OSATE 2.13.0 documentation

OSATE 项目的源码也可以直接在github下载:

osate/osate2: Open Source AADL2 Tool Environment (github.com)

latency-case-study项目的源码也可以直接在github下载:

examples/latency-case-study at master · osate/examples (github.com)

 修改后的完整的项目代码可在此处下载。

【免费】latency-case-study项目修改版(资源-CSDN文库)

如有不当或错误之处,恳请您的指正,谢谢!!!

这篇关于OSATE总线延迟的源码分析与模型修复——针对 Latency-case-study项目 端到端流延迟分析过程中空指针异常的解决的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/326237

相关文章

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

如何解决线上平台抽佣高 线下门店客流少的痛点!

目前,许多传统零售店铺正遭遇客源下降的难题。尽管广告推广能带来一定的客流,但其费用昂贵。鉴于此,众多零售商纷纷选择加入像美团、饿了么和抖音这样的大型在线平台,但这些平台的高佣金率导致了利润的大幅缩水。在这样的市场环境下,商家之间的合作网络逐渐成为一种有效的解决方案,通过资源和客户基础的共享,实现共同的利益增长。 以最近在上海兴起的一个跨行业合作平台为例,该平台融合了环保消费积分系统,在短