Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MindSpore
mindinsight
提交
6433fbb8
M
mindinsight
项目概览
MindSpore
/
mindinsight
通知
8
Star
4
Fork
2
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
M
mindinsight
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
“8b67a4d1a1c015f8c68562699b1ce5604efdfe42”上不存在“src/query/git@gitcode.net:qq_37101384/tdengine.git”
提交
6433fbb8
编写于
6月 18, 2020
作者:
P
ph
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
UI add profiling minddata page(2nd commit)
上级
83c104c4
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
858 addition
and
68 deletion
+858
-68
mindinsight/ui/src/locales/zh-cn.json
mindinsight/ui/src/locales/zh-cn.json
+123
-32
mindinsight/ui/src/services/request-service.js
mindinsight/ui/src/services/request-service.js
+79
-0
mindinsight/ui/src/views/train-manage/operator.vue
mindinsight/ui/src/views/train-manage/operator.vue
+3
-4
mindinsight/ui/src/views/train-manage/profiling-dashboard.vue
...insight/ui/src/views/train-manage/profiling-dashboard.vue
+469
-28
mindinsight/ui/src/views/train-manage/profiling.vue
mindinsight/ui/src/views/train-manage/profiling.vue
+184
-4
未找到文件。
mindinsight/ui/src/locales/zh-cn.json
浏览文件 @
6433fbb8
...
@@ -9,7 +9,6 @@
...
@@ -9,7 +9,6 @@
"dataError"
:
"获取到的数据异常"
,
"dataError"
:
"获取到的数据异常"
,
"regIllegal"
:
"请输入正确的检索条件"
,
"regIllegal"
:
"请输入正确的检索条件"
,
"stayTuned"
:
"敬请期待"
,
"stayTuned"
:
"敬请期待"
,
"select"
:
"请选择"
,
"select"
:
"请选择"
,
"search"
:
"请搜索"
,
"search"
:
"请搜索"
,
"enter"
:
"请输入"
,
"enter"
:
"请输入"
,
...
@@ -72,7 +71,7 @@
...
@@ -72,7 +71,7 @@
"unhide"
:
"取消隐藏"
,
"unhide"
:
"取消隐藏"
,
"hideData"
:
"条数据"
,
"hideData"
:
"条数据"
,
"totalHide"
:
"本页共隐藏{n}条数据"
,
"totalHide"
:
"本页共隐藏{n}条数据"
,
"mustExist"
:
"必选项"
,
"mustExist"
:
"必选项"
,
"remarkValidation"
:
"备注为英文字母、数字、中文、下划线、中划线、点的组合,长度范围为[1,128]字符"
,
"remarkValidation"
:
"备注为英文字母、数字、中文、下划线、中划线、点的组合,长度范围为[1,128]字符"
,
"changeSuccess"
:
"修改成功"
,
"changeSuccess"
:
"修改成功"
,
"metricLabel"
:
"Metric"
,
"metricLabel"
:
"Metric"
,
...
@@ -142,7 +141,6 @@
...
@@ -142,7 +141,6 @@
"isDelete"
:
"是否删除当前阈值"
,
"isDelete"
:
"是否删除当前阈值"
,
"noData"
:
"无"
"noData"
:
"无"
},
},
"images"
:
{
"images"
:
{
"titleText"
:
"图像"
,
"titleText"
:
"图像"
,
"tagSelectTitle"
:
"标签选择"
,
"tagSelectTitle"
:
"标签选择"
,
...
@@ -232,43 +230,137 @@
...
@@ -232,43 +230,137 @@
"path"
:
"路径"
,
"path"
:
"路径"
,
"number"
:
"卡编号"
,
"number"
:
"卡编号"
,
"distribution"
:
"分布图"
,
"distribution"
:
"分布图"
,
"queueEmptyRatio"
:
"队列空比例"
,
"queueEmptyRatio"
:
"队列空比例
:
"
,
"queueFullRatio"
:
"队列满比例"
,
"queueFullRatio"
:
"队列满比例
:
"
,
"dataQueueDis"
:
"数据队列分布图"
,
"dataQueueDis"
:
"数据队列分布图"
,
"operatorTimeConAnalysis"
:
"算子耗时分析"
,
"operatorTimeConAnalysis"
:
"算子耗时分析"
,
"timeConStastic"
:
"耗时统计"
,
"timeConStastic"
:
"耗时统计"
,
"avgCost"
:
"平均总耗时"
,
"avgCost"
:
"平均总耗时
:
"
,
"getCost"
:
"平均取数据耗时"
,
"getCost"
:
"平均取数据耗时
:
"
,
"pushCost"
:
"平均
push耗时
"
,
"pushCost"
:
"平均
推送数据耗时:
"
,
"lterationGap"
:
"迭代间隙"
,
"lterationGap"
:
"迭代间隙"
,
"lterationTail"
:
"迭代拖尾"
,
"lterationTail"
:
"迭代拖尾"
,
"propertion"
:
"占比"
,
"propertion"
:
"占比"
,
"minddataTitle"
:
"数据准备详情"
,
"title"
:
"迭代间隙流程分析"
,
"title"
:
"迭代间隙流程分析"
,
"dataDeal"
:
"数据处理"
,
"dataDeal"
:
"数据处理"
,
"dataQueue"
:
"数据队列"
,
"dataQueue"
:
"数据队列"
,
"errorTip"
:
"个step出现异常"
,
"errorTip"
:
"个step出现异常"
,
"pipelineError"
:
"Pipeline异常step"
,
"smartHelper"
:
"小助手"
,
"deviceQueueError"
:
"device_queue_op异常step"
,
"suggestions"
:
"优化建议"
,
"getNextError"
:
"get_next异常step"
,
"common-profiler_tutorial"
:
{
"smartHelper"
:
"小助手"
,
"desc"
:
"如何使用Profiler进行性能分析"
,
"suggestions"
:
"优化建议"
,
"anchor"
:
[
"stepSelect"
:
"Step选择"
,
"desc"
"curCard"
:
"当前卡片"
,
],
"stepTrace"
:
"迭代轨迹"
,
"url"
:
[
"mindData"
:
"数据准备"
,
"https://www.mindspore.cn/tutorial/zh-CN/master/advanced_use/visualization_tutorials.html"
"timeLine"
:
"时间线"
,
]
"rankOfOperator"
:
"算子耗时统计排名"
,
},
"stepTraceDetail"
:
"迭代轨迹详情"
,
"step_trace-proposer_type_label"
:
{
"viewDetail"
:
"查看详情"
,
"desc"
:
"迭代轨迹性能优化参考建议"
"stepNum"
:
"耗时step数"
,
},
"iterGapTimeLabel"
:
"迭代间隙时长"
,
"step_trace-iter_interval"
:
{
"iterGapRateLabel"
:
"迭代间隙占比"
,
"desc"
:
"在开启图模式和数据集下沉模式后,如果平均迭代间隙时间大于{n1}ms,则数据处理至计算图执行之间的流程可能存在优化空间。"
"fpBpTimeLabel"
:
"FP+BP时长"
,
},
"fpBpRateLabel"
:
"FP+BP占比"
,
"common-proposer_type_label"
:
{
"tailTimeLabel"
:
"迭代拖尾时长"
,
"desc"
:
"性能分析与优化指导"
"tailRateLabel"
:
"迭代拖尾占比"
,
},
"minddata_pipeline-proposer_type_label"
:
{
"desc"
:
"Minddata pipeline性能优化建议"
},
"minddata_pipeline-general"
:
{
"desc"
:
"Pipeline中的算子{n1}可能存在性能瓶颈,请用户重点关注。"
},
"minddata_pipeline-dataset_op"
:
{
"desc"
:
"对于算子{n1},用户可以尝试调整num_parallel_workers参数。"
},
"minddata_pipeline-generator_op"
:
{
"desc"
:
"对于算子{n1},用户可以尝试调整num_parallel_workers参数或优化训练脚本,如果性能没有得到优化,可以尝试替换为MindRecordDataset算子。"
},
"minddata_pipeline-map_op"
:
{
"desc"
:
"对于算子{n1},用户可以尝试调整num_parallel_workers参数,如果使用的是Python的算子,可以尝试优化训练脚本。"
},
"minddata_pipeline-batch_op"
:
{
"desc"
:
"对于算子{n1},用户可以尝试增加prefetch_size大小。"
},
"minddata_warning_op"
:
{
"desc"
:
"经过上述判断,算子{n1}可能存在优化空间。"
},
"minddata-proposer_type_label"
:
{
"desc"
:
"数据处理性能分析"
},
"minddata_device_queue"
:
{
"desc"
:
"主机侧队列为空比例{n1}/{n2},为满比例{n3}/{n4}。"
},
"minddata_get_next_queue"
:
{
"desc"
:
"芯片侧队列为空比例{n1}/{n2}。"
},
"millisecond"
:
"ms"
,
"stepSelect"
:
"Step选择"
,
"curCard"
:
"当前卡片"
,
"stepTrace"
:
"迭代轨迹"
,
"mindData"
:
"数据准备"
,
"timeLine"
:
"时间线"
,
"rankOfOperator"
:
"算子耗时统计排名"
,
"stepTraceDetail"
:
"迭代轨迹详情"
,
"viewDetail"
:
"查看详情"
,
"stepNum"
:
"耗时step数"
,
"iterGapTimeLabel"
:
"迭代间隙时长"
,
"iterGapRateLabel"
:
"迭代间隙占比"
,
"fpBpTimeLabel"
:
"前向+反向时长"
,
"fpBpRateLabel"
:
"前向+反向占比"
,
"tailTimeLabel"
:
"迭代拖尾时长"
,
"tailRateLabel"
:
"迭代拖尾占比"
,
"operatorDetail"
:
"算子详情"
,
"operatorDetail"
:
"算子详情"
,
"times"
:
"次"
"times"
:
"次"
,
"queueStep"
:
"队列step分布图"
,
"queueInfo"
:
"迭代间隙"
,
"pipeline"
:
"数据处理"
,
"pipelineTopTitle"
:
"算子间队列平均使用率"
,
"pipelineMiddleTitle"
:
"算子间队列关系"
,
"deviceQueueOp"
:
"数据发送"
,
"deviceQueueOpTip"
:
"数据发送算子"
,
"getNext"
:
"取数据算子"
,
"connectorQuene"
:
"主机队列"
,
"getData"
:
"数据获取"
,
"opTotalTime"
:
"算子执行总时间:"
,
"streamNum"
:
"执行流数量:"
,
"opNum"
:
"算子数目:"
,
"opTimes"
:
"算子执行总次数:"
,
"features"
:
"功能介绍:"
,
"iterationInfo"
:
"迭代轨迹展示的是每个step从上个迭代开始至该step结束的耗时信息,主体时间分为3部分:迭代间隙、前向+反向、迭代拖尾。"
,
"iterationGapInfo"
:
"主要负责从数据队列中读取数据,如果该部分耗时较长,建议前往数据处理部分进一步分析;"
,
"fpbpTitle"
:
"前向反向"
,
"fpbpInfo"
:
"执行网络中的前向算子以及反向算子,承载了一个step主要的计算工作,如果该部分耗时较长,建议前往算子统计或时间线中进一步分析;"
,
"iterativeTailingTitle"
:
"迭代拖尾"
,
"iterativeTailingInfo"
:
"主要在多卡场景下执行参数聚合参数更新操作,如果该部分耗时较长,建议查看all_reduce耗时以及并行情况。"
,
"statistics"
:
"统计信息:"
,
"totalTime"
:
"总耗时:"
,
"totalSteps"
:
"总step数:"
,
"fpbpTimeRatio"
:
"前向+反向耗时占比:"
,
"iterationGapTimeRatio"
:
"迭代间隙耗时占比:"
,
"iterativeTailingTimeRatio"
:
"迭代拖尾耗时占比:"
,
"dataProcess"
:
"该图展示了数据处理阶段的流程,数据通过数据处理阶段存入主机队列,再通过数据传输阶段存入芯片侧的数据队列,最终由数据传输算子get_next发送给前向训练使用。"
,
"dataProcessInfo"
:
"综合分析该阶段的流程,通过判断主机队列和数据队列为空的情况就可以初步判断可能出现性能异常的阶段。"
,
"analysisOne"
:
"1、如果迭代间隙较长,并且芯片侧的数据队列部分batch为空,那么可能由于数据处理和数据传输阶段导致的性能异常,参考2,反之则定位数据传输算子get_next内部问题;"
,
"analysisTwo"
:
"2、如果通过1定位为数据处理、数据传输阶段异常,则查看主机队列情况,如果大概率为空,则可能为数据处理阶段导致异常,如果大概率不为空,则可能数据传输阶段异常;"
,
"higherAnalysis"
:
"注:可结合下方算子耗时进行高阶分析"
,
"chipInfo"
:
"芯片侧数据队列为空比例:"
,
"hostIsEmpty"
:
"主机侧队列为空比例:"
,
"hostIsFull"
:
"主机侧队列为满比例:"
,
"operatorInfo"
:
"{msg1}、{msg2}算子信息"
,
"workersNum"
:
"使用线程数"
,
"queueDeepChartTitle"
:
"{msg}队列深度折线图"
,
"sampleInterval"
:
"采样间隔"
,
"deep"
:
"深度"
,
"queueTip1"
:
"队列为满比例:"
,
"queueTip2"
:
"队列为空比例:"
,
"totalCapacity"
:
"总容量"
,
"averageCapacity"
:
"平均使用容量"
,
"stepTraceMessage"
:
"当前FP和BP为自动选点,如不合乎预期,请自行修改。"
,
"FPMessage"
:
"FP起始算子:"
,
"BPMessage"
:
"BP终止算子:"
},
},
"components"
:
{
"components"
:
{
"summaryTitle"
:
"训练选择"
,
"summaryTitle"
:
"训练选择"
,
...
@@ -299,7 +391,6 @@
...
@@ -299,7 +391,6 @@
"50542215"
:
"查询参数错误"
,
"50542215"
:
"查询参数错误"
,
"50542216"
:
"Summary日志文件未找到"
,
"50542216"
:
"Summary日志文件未找到"
,
"50542217"
:
"Summary日志路径错误"
,
"50542217"
:
"Summary日志路径错误"
,
"50542218"
:
"筛选参数错误"
,
"50542218"
:
"筛选参数错误"
"50546102"
:
"step_id取值错误"
}
}
}
}
\ No newline at end of file
mindinsight/ui/src/services/request-service.js
浏览文件 @
6433fbb8
...
@@ -176,6 +176,14 @@ export default {
...
@@ -176,6 +176,14 @@ export default {
},
},
});
});
},
},
// get data of helper
queryDataOfProfileHelper
(
params
)
{
return
axios
({
method
:
'
get
'
,
url
:
'
/v1/mindinsight/profile/summary/propose
'
,
params
:
params
,
});
},
// query training trace
// query training trace
queryTrainingTrace
(
params
)
{
queryTrainingTrace
(
params
)
{
return
axios
({
return
axios
({
...
@@ -197,4 +205,75 @@ export default {
...
@@ -197,4 +205,75 @@ export default {
},
},
});
});
},
},
queryTimeline
(
params
)
{
return
axios
({
method
:
'
get
'
,
url
:
'
/v1/mindinsight/profile/timeline
'
,
params
:
params
,
headers
:
{
ignoreError
:
true
,
},
});
},
queryTimlineInfo
(
params
)
{
return
axios
({
method
:
'
get
'
,
url
:
'
v1/mindinsight/profile/timeline-summary
'
,
params
:
params
,
headers
:
{
ignoreError
:
true
,
},
});
},
queryOpQueue
(
params
)
{
return
axios
({
method
:
'
post
'
,
url
:
'
v1/mindinsight/profile/minddata-pipeline/op-queue
'
,
params
:
params
.
params
,
data
:
params
.
body
,
headers
:
{
ignoreError
:
true
,
},
});
},
queryQueue
(
params
)
{
return
axios
({
method
:
'
get
'
,
url
:
'
v1/mindinsight/profile/minddata-pipeline/queue
'
,
params
:
params
,
headers
:
{
ignoreError
:
true
,
},
});
},
queryProcessSummary
(
params
)
{
return
axios
({
method
:
'
get
'
,
url
:
'
v1/mindinsight/profile/process_summary
'
,
params
:
params
,
headers
:
{
ignoreError
:
true
,
},
});
},
queueInfo
(
params
)
{
return
axios
({
method
:
'
get
'
,
url
:
'
v1/mindinsight/profile/queue_info
'
,
params
:
params
,
headers
:
{
ignoreError
:
true
,
},
});
},
minddataOp
(
params
)
{
return
axios
({
method
:
'
get
'
,
url
:
'
v1/mindinsight/profile/minddata_op
'
,
params
:
params
,
headers
:
{
ignoreError
:
true
,
},
});
},
};
};
mindinsight/ui/src/views/train-manage/operator.vue
浏览文件 @
6433fbb8
...
@@ -146,13 +146,12 @@
...
@@ -146,13 +146,12 @@
</el-tab-pane>
</el-tab-pane>
<el-tab-pane
label=
"AI CPU"
<el-tab-pane
label=
"AI CPU"
class=
"cpu-tab"
class=
"cpu-tab"
name=
"cpu"
name=
"cpu"
>
v-if=
"false"
>
<div
class=
"cl-profiler-top"
<div
class=
"cl-profiler-top"
v-if=
"cpuCharts.data.length"
>
v-if=
"cpuCharts.data.length"
>
<div>
<div>
<span
class=
"profiler-title"
>
<span
class=
"profiler-title"
>
{{ $t('operator.operator
Type
Statistics') }}
{{ $t('operator.operatorStatistics') }}
</span>
</span>
</div>
</div>
<div
class=
"cl-profiler-echarts"
>
<div
class=
"cl-profiler-echarts"
>
...
...
mindinsight/ui/src/views/train-manage/profiling-dashboard.vue
浏览文件 @
6433fbb8
...
@@ -25,11 +25,33 @@ limitations under the License.
...
@@ -25,11 +25,33 @@ limitations under the License.
:class=
"
{disabled:svg.noData
&&
svg.data.length === 0}">
{{
$t
(
'
profiling.viewDetail
'
)
}}
:class=
"
{disabled:svg.noData
&&
svg.data.length === 0}">
{{
$t
(
'
profiling.viewDetail
'
)
}}
<i
class=
"el-icon-d-arrow-right"
></i></button>
<i
class=
"el-icon-d-arrow-right"
></i></button>
</div>
</div>
<div
class=
"tip-icon"
<div
class=
"tip-icon"
>
v-show=
"false"
>
<el-tooltip
placement=
"bottom"
<el-tooltip
content=
""
placement=
"top"
effect=
"light"
>
effect=
"light"
>
<div
slot=
"content"
class=
"tooltip-container"
>
<div>
{{
$t
(
"
profiling.features
"
)
}}
</div>
<div>
{{
$t
(
'
profiling.iterationInfo
'
)
}}
</div>
<div>
<span>
{{
$t
(
'
profiling.queueInfo
'
)
}}
</span>
<span>
{{
$t
(
'
profiling.iterationGapInfo
'
)
}}
</span>
</div>
<div>
<span>
{{
$t
(
'
profiling.fpbpTitle
'
)
}}
</span>
<span>
{{
$t
(
'
profiling.fpbpInfo
'
)
}}
</span>
</div>
<div>
<span>
{{
$t
(
'
profiling.iterativeTailingTitle
'
)
}}
</span>
<span>
{{
$t
(
'
profiling.iterativeTailingInfo
'
)
}}
</span>
</div>
<br
/>
<div>
{{
$t
(
'
profiling.statistics
'
)
}}
</div>
<div>
{{
$t
(
'
profiling.totalTime
'
)
}}
<span>
{{
totalTime
}}{{
$t
(
'
profiling.millisecond
'
)
}}
</span></div>
<div>
{{
$t
(
'
profiling.totalSteps
'
)
}}
<span>
{{
totalSteps
}}
</span></div>
<div>
{{
$t
(
'
profiling.fpbpTimeRatio
'
)
}}
<span>
{{
fpAndBp
}}
</span></div>
<div>
{{
$t
(
'
profiling.iterationGapTimeRatio
'
)
}}
<span>
{{
iterationInterval
}}
</span></div>
<div>
{{
$t
(
'
profiling.iterativeTailingTimeRatio
'
)
}}
<span>
{{
tail
}}
</span></div>
</div>
<i
class=
"el-icon-info"
></i>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</el-tooltip>
</div>
</div>
...
@@ -78,19 +100,144 @@ limitations under the License.
...
@@ -78,19 +100,144 @@ limitations under the License.
<div
class=
"minddata"
>
<div
class=
"minddata"
>
<div
class=
"title-wrap"
>
<div
class=
"title-wrap"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.mindData
'
)
}}
</div>
<div
class=
"title"
>
{{
$t
(
'
profiling.mindData
'
)
}}
</div>
<div
class=
"view-detail"
<div
class=
"view-detail"
>
v-if=
"false"
>
<button
@
click=
"viewDetail('minddata')"
<button
@
click=
"viewDetail('minddata')"
>
{{
$t
(
'
profiling.viewDetail
'
)
}}
:disabled=
"processSummary.noData"
:class=
"
{disabled:processSummary.noData}">
{{
$t
(
'
profiling.viewDetail
'
)
}}
<i
class=
"el-icon-d-arrow-right"
></i></button>
<i
class=
"el-icon-d-arrow-right"
></i></button>
</div>
</div>
<div
class=
"tip-icon"
>
<el-tooltip
placement=
"bottom"
effect=
"light"
>
<div
slot=
"content"
class=
"tooltip-container"
>
<div>
{{
$t
(
"
profiling.features
"
)
}}
</div>
<div>
{{
$t
(
'
profiling.dataProcess
'
)
}}
</div>
<div>
{{
$t
(
'
profiling.dataProcessInfo
'
)
}}
</div>
<div>
{{
$t
(
'
profiling.analysisOne
'
)
}}
</div>
<div>
{{
$t
(
'
profiling.analysisTwo
'
)
}}
</div>
<div
v-show=
"deviceInfoShow||queueInfoShow"
>
{{
$t
(
'
profiling.higherAnalysis
'
)
}}
</div>
<br
/>
<div
v-show=
"deviceInfoShow||queueInfoShow"
>
{{
$t
(
'
profiling.statistics
'
)
}}
</div>
<div
v-show=
"queueInfoShow"
>
{{
$t
(
'
profiling.chipInfo
'
)
}}
<span>
{{
queueInfoEmptyNum
}}
/
{{
queueInfoTotalNum
}}
</span>
</div>
<div
v-show=
"deviceInfoShow"
>
<div>
{{
$t
(
'
profiling.hostIsEmpty
'
)
}}
<span>
{{
deviceInfoEmptyNum
}}
/
{{
deviceInfoTotalNum
}}
</span>
</div>
<div>
{{
$t
(
'
profiling.hostIsFull
'
)
}}
<span>
{{
deviceInfoFullNum
}}
/
{{
deviceInfoTotalNum
}}
</span>
</div>
</div>
</div>
<i
class=
"el-icon-info"
></i>
</el-tooltip>
</div>
</div>
<div
class=
"pipeline-container"
v-show=
"!processSummary.noData"
>
<div
class=
"cell-container data-process"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.pipeline
'
)
}}
</div>
</div>
<div
class=
"queue-container"
>
<div
class=
"img"
>
<div
class=
"edge"
>
<img
src=
"@/assets/images/data-flow.png"
alt=
""
/>
</div>
<div
class=
"icon"
>
<img
src=
"@/assets/images/queue.svg"
alt=
""
clickKey=
"connector_queue"
/>
</div>
<div
class=
"edge"
>
<img
src=
"@/assets/images/data-flow.png"
alt=
""
/>
</div>
</div>
<div
class=
"title"
>
{{
$t
(
'
profiling.connectorQuene
'
)
}}
</div>
<div
class=
"description"
>
<div
class=
"item"
v-if=
"processSummary.device.empty || processSummary.device.empty === 0"
>
{{
$t
(
'
profiling.queueTip2
'
)
}}
<span
class=
"num"
>
{{
processSummary
.
device
.
empty
}}
/
{{
processSummary
.
device
.
total
}}
</span>
</div>
<div
class=
"item"
v-if=
"processSummary.device.full || processSummary.device.full === 0"
>
{{
$t
(
'
profiling.queueTip1
'
)
}}
<span
class=
"num"
>
{{
processSummary
.
device
.
empty
}}
/
{{
processSummary
.
device
.
total
}}
</span>
</div>
</div>
</div>
<div
class=
"cell-container device_queue_op"
clickKey=
"device_queue_op"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.deviceQueueOp
'
)
}}
</div>
<div
class=
"content"
>
{{
$t
(
'
profiling.deviceQueueOpTip
'
)
}}
| TDT
</div>
</div>
<div
class=
"queue-container"
v-if=
"processSummary.count === 6"
>
<div
class=
"img"
>
<div
class=
"edge"
>
<img
src=
"@/assets/images/data-flow.png"
alt=
""
/>
</div>
<div
class=
"icon"
>
<img
src=
"@/assets/images/queue.svg"
clickKey=
"data_queue"
alt=
""
/>
</div>
<div
class=
"edge"
>
<img
src=
"@/assets/images/data-flow.png"
alt=
""
/>
</div>
</div>
<div
class=
"title"
>
{{
$t
(
'
profiling.dataQueue
'
)
}}
</div>
<div
class=
"description"
>
<div
class=
"item"
v-if=
"processSummary.get_next.empty || processSummary.get_next.empty === 0"
>
{{
$t
(
'
profiling.queueTip2
'
)
}}
<span
class=
"num"
>
{{
processSummary
.
get_next
.
empty
}}
/
{{
processSummary
.
get_next
.
total
}}
</span>
</div>
<div
class=
"item"
v-if=
"processSummary.get_next.full || processSummary.get_next.full === 0"
>
{{
$t
(
'
profiling.queueTip1
'
)
}}
<span
class=
"num"
>
{{
processSummary
.
get_next
.
empty
}}
/
{{
processSummary
.
get_next
.
total
}}
</span>
</div>
</div>
</div>
<div
class=
"cell-container get-next"
clickKey=
"get_next"
v-if=
"processSummary.count === 6"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.getData
'
)
}}
</div>
</div>
</div>
<div
class=
"coming-soon-content"
>
<div
class=
"coming-soon-container"
>
<img
:src=
"require('@/assets/images/coming-soon.png')"
/>
<p
class=
'coming-soon-text'
>
{{
$t
(
"
public.stayTuned
"
)
}}
</p>
</div>
</div>
<div
class=
"image-noData"
v-if=
"processSummary.noData"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
<p>
{{
$t
(
"
public.noData
"
)
}}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -140,18 +287,35 @@ limitations under the License.
...
@@ -140,18 +287,35 @@ limitations under the License.
<div
class=
"time-line"
>
<div
class=
"time-line"
>
<div
class=
"title-wrap"
>
<div
class=
"title-wrap"
>
<div
class=
"title"
>
{{
$t
(
'
profiling.timeLine
'
)
}}
</div>
<div
class=
"title"
>
{{
$t
(
'
profiling.timeLine
'
)
}}
</div>
<div
class=
"view-detail"
<div
class=
"view-detail"
>
v-show=
"false"
>
<button
@
click=
"toPerfetto()"
<a
@
click=
"toPerfetto()"
>
{{
$t
(
'
profiling.viewDetail
'
)
}}
<i
class=
"el-icon-d-arrow-right"
></i></a>
:disabled=
"perfetto.waiting"
:class=
"
{disabled:perfetto.waiting}">
{{
$t
(
'
profiling.viewDetail
'
)
}}
<i
class=
"el-icon-d-arrow-right"
></i></button>
</div>
</div>
</div>
<div
class=
"timeline-info"
v-if=
"!timelineInfo.noData"
>
<div
class=
"info-line"
>
<span>
{{
$t
(
'
profiling.opTotalTime
'
)
}}
</span><span>
{{
timelineInfo
.
totalTime
}}
ms
</span>
</div>
</div>
<div
class=
"coming-soon-content"
>
<div
class=
"info-line"
>
<div
class=
"coming-soon-container"
>
<span>
{{
$t
(
'
profiling.streamNum
'
)
}}
</span><span>
{{
timelineInfo
.
streamNum
}}
</span>
<img
:src=
"require('@/assets/images/coming-soon.png')"
/>
</div>
<p
class=
'coming-soon-text'
>
<div
class=
"info-line"
>
{{
$t
(
"
public.stayTuned
"
)
}}
<span>
{{
$t
(
'
profiling.opNum
'
)
}}
</span><span>
{{
timelineInfo
.
opNum
}}
</span></div>
</p>
<div
class=
"info-line"
>
<span>
{{
$t
(
'
profiling.opTimes
'
)
}}
</span><span>
{{
timelineInfo
.
opTimes
+
$t
(
'
profiling.times
'
)
}}
</span>
</div>
</div>
<div
class=
"image-noData"
v-if=
"timelineInfo.noData"
>
<div>
<img
:src=
"require('@/assets/images/nodata.png')"
alt=
""
/>
</div>
</div>
<p>
{{
$t
(
"
public.noData
"
)
}}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
...
@@ -164,6 +328,18 @@ import CommonProperty from '../../common/common-property';
...
@@ -164,6 +328,18 @@ import CommonProperty from '../../common/common-property';
export
default
{
export
default
{
data
()
{
data
()
{
return
{
return
{
fpAndBp
:
'
--
'
,
iterationInterval
:
'
--
'
,
totalSteps
:
'
--
'
,
totalTime
:
'
--
'
,
tail
:
'
--
'
,
queueInfoShow
:
false
,
deviceInfoShow
:
false
,
queueInfoEmptyNum
:
'
--
'
,
queueInfoTotalNum
:
'
--
'
,
deviceInfoEmptyNum
:
'
--
'
,
deviceInfoTotalNum
:
'
--
'
,
deviceInfoFullNum
:
'
--
'
,
svg
:
{
svg
:
{
data
:
[],
data
:
[],
svgPadding
:
20
,
svgPadding
:
20
,
...
@@ -193,6 +369,33 @@ export default {
...
@@ -193,6 +369,33 @@ export default {
topN
:
[],
topN
:
[],
colorList
:
[
'
#6C92FA
'
,
'
#6CBFFF
'
,
'
#4EDED2
'
,
'
#7ADFA0
'
,
'
#A6DD82
'
],
colorList
:
[
'
#6C92FA
'
,
'
#6CBFFF
'
,
'
#4EDED2
'
,
'
#7ADFA0
'
,
'
#A6DD82
'
],
},
},
perfetto
:
{
url
:
'
https://ui.perfetto.dev/#!
'
,
data
:
null
,
delay
:
5000
,
waiting
:
true
,
},
timelineInfo
:
{
totalTime
:
0
,
streamNum
:
0
,
opNum
:
0
,
opTimes
:
0
,
noData
:
true
,
},
processSummary
:
{
noData
:
true
,
count
:
6
,
device
:
{
empty
:
0
,
full
:
0
,
total
:
0
,
},
get_next
:
{
empty
:
0
,
full
:
0
,
total
:
0
,
},
},
};
};
},
},
mounted
()
{
mounted
()
{
...
@@ -231,10 +434,47 @@ export default {
...
@@ -231,10 +434,47 @@ export default {
},
},
methods
:
{
methods
:
{
init
()
{
init
()
{
this
.
queryTimeline
();
this
.
queryTrainingTrace
();
this
.
queryTrainingTrace
();
this
.
getProccessSummary
();
this
.
initPieChart
();
this
.
initPieChart
();
window
.
addEventListener
(
'
resize
'
,
this
.
resizeTrace
,
false
);
window
.
addEventListener
(
'
resize
'
,
this
.
resizeTrace
,
false
);
},
},
getProccessSummary
()
{
const
params
=
{
train_id
:
this
.
trainingJobId
,
profile
:
this
.
summaryPath
,
device_id
:
this
.
currentCard
,
};
RequestService
.
queryProcessSummary
(
params
).
then
((
resp
)
=>
{
if
(
resp
&&
resp
.
data
)
{
const
data
=
JSON
.
parse
(
JSON
.
stringify
(
resp
.
data
));
this
.
processSummary
.
count
=
Object
.
keys
(
data
).
length
;
this
.
dealProcess
(
data
);
// 芯片侧
if
(
resp
.
data
.
get_next_queue_info
)
{
this
.
queueInfoShow
=
true
;
this
.
queueInfoEmptyNum
=
resp
.
data
.
get_next_queue_info
.
summary
.
empty_batch_count
;
this
.
queueInfoTotalNum
=
resp
.
data
.
get_next_queue_info
.
summary
.
total_batch
;
}
// 主机侧
if
(
resp
.
data
.
device_queue_info
)
{
this
.
deviceInfoShow
=
true
;
this
.
deviceInfoEmptyNum
=
resp
.
data
.
device_queue_info
.
summary
.
empty_batch_count
;
this
.
deviceInfoTotalNum
=
resp
.
data
.
device_queue_info
.
summary
.
total_batch
;
this
.
deviceInfoFullNum
=
resp
.
data
.
device_queue_info
.
summary
.
full_batch_count
;
}
}
else
{
this
.
dealProcess
(
null
);
}
});
},
viewDetail
(
path
)
{
viewDetail
(
path
)
{
this
.
$router
.
push
({
this
.
$router
.
push
({
path
,
path
,
...
@@ -250,13 +490,15 @@ export default {
...
@@ -250,13 +490,15 @@ export default {
option
.
tooltip
=
{
option
.
tooltip
=
{
trigger
:
'
item
'
,
trigger
:
'
item
'
,
formatter
:
(
params
)
=>
{
formatter
:
(
params
)
=>
{
return
`
${
params
.
marker
}
${
params
.
data
.
name
}
${
params
.
percent
}
%`
;
return
`
${
params
.
data
.
name
}
<br>
${
params
.
marker
}
${
params
.
percent
}
%`
;
},
},
confine
:
true
,
extraCssText
:
'
white-space:normal; word-break:break-word;
'
,
};
};
option
.
series
=
[
option
.
series
=
[
{
{
type
:
'
pie
'
,
type
:
'
pie
'
,
center
:
[
'
5
0%
'
,
'
50
%
'
],
center
:
[
'
5
5%
'
,
'
55
%
'
],
data
:
this
.
pieChart
.
data
,
data
:
this
.
pieChart
.
data
,
radius
:
'
50%
'
,
radius
:
'
50%
'
,
lable
:
{
lable
:
{
...
@@ -370,6 +612,19 @@ export default {
...
@@ -370,6 +612,19 @@ export default {
setTimeout
(()
=>
{
setTimeout
(()
=>
{
this
.
dealTraceData
();
this
.
dealTraceData
();
},
100
);
},
100
);
if
(
res
.
data
.
summary
)
{
this
.
fpAndBp
=
res
.
data
.
summary
.
fp_and_bp
;
this
.
iterationInterval
=
res
.
data
.
summary
.
iteration_interval
;
this
.
totalSteps
=
res
.
data
.
summary
.
total_steps
;
this
.
totalTime
=
res
.
data
.
summary
.
total_time
;
this
.
tail
=
res
.
data
.
summary
.
tail
;
}
else
{
this
.
fpAndBp
=
'
--
'
;
this
.
iterationInterval
=
'
--
'
;
this
.
totalSteps
=
'
--
'
;
this
.
totalTime
=
'
--
'
;
this
.
tail
=
'
--
'
;
}
}
else
{
}
else
{
document
.
querySelector
(
'
#trace
'
).
style
.
height
=
'
0px
'
;
document
.
querySelector
(
'
#trace
'
).
style
.
height
=
'
0px
'
;
this
.
svg
.
noData
=
true
;
this
.
svg
.
noData
=
true
;
...
@@ -568,6 +823,85 @@ export default {
...
@@ -568,6 +823,85 @@ export default {
}
}
return
new
Uint8Array
(
arr
);
return
new
Uint8Array
(
arr
);
},
},
toPerfetto
()
{
if
(
this
.
perfetto
.
data
)
{
const
popupwin
=
window
.
open
(
this
.
perfetto
.
url
);
setTimeout
(()
=>
{
const
params
=
{
perfetto
:
{
title
:
''
,
buffer
:
this
.
perfetto
.
data
,
},
};
if
(
popupwin
)
{
popupwin
.
postMessage
(
params
,
this
.
perfetto
.
url
);
}
},
this
.
perfetto
.
delay
);
}
else
{
this
.
perfetto
.
waiting
=
true
;
}
},
queryTimeline
()
{
const
params
=
{
dir
:
this
.
relativePath
,
device_id
:
this
.
currentCard
,
};
RequestService
.
queryTimlineInfo
(
params
)
.
then
((
res
)
=>
{
if
(
res
&&
res
.
data
)
{
this
.
timelineInfo
.
noData
=
false
;
this
.
timelineInfo
.
totalTime
=
res
.
data
.
total_time
.
toFixed
(
4
);
this
.
timelineInfo
.
streamNum
=
res
.
data
.
num_of_streams
;
this
.
timelineInfo
.
opNum
=
res
.
data
.
num_of_ops
;
this
.
timelineInfo
.
opTimes
=
res
.
data
.
op_exe_times
;
}
else
{
this
.
timelineInfo
.
noData
=
true
;
}
})
.
catch
(()
=>
{
this
.
timelineInfo
.
noData
=
true
;
});
this
.
perfetto
.
waiting
=
true
;
RequestService
.
queryTimeline
(
params
).
then
((
res
)
=>
{
if
(
res
&&
res
.
data
)
{
this
.
perfetto
.
data
=
this
.
stringToUint8Array
(
JSON
.
stringify
(
res
.
data
),
);
this
.
perfetto
.
waiting
=
false
;
}
});
},
dealProcess
(
data
)
{
this
.
processSummary
.
device
=
{
empty
:
0
,
full
:
0
,
total
:
0
,
};
this
.
processSummary
.
get_next
=
{
empty
:
0
,
full
:
0
,
total
:
0
,
};
this
.
processSummary
.
noData
=
true
;
if
(
data
)
{
if
(
data
.
device_queue_info
&&
data
.
device_queue_info
.
summary
)
{
this
.
processSummary
.
device
=
{
empty
:
data
.
device_queue_info
.
summary
.
empty_batch_count
,
full
:
data
.
device_queue_info
.
summary
.
full_batch_count
,
total
:
data
.
device_queue_info
.
summary
.
total_batch
,
};
}
if
(
data
.
get_next_queue_info
&&
data
.
get_next_queue_info
.
summary
)
{
this
.
processSummary
.
get_next
=
{
empty
:
data
.
get_next_queue_info
.
summary
.
empty_batch_count
,
full
:
data
.
get_next_queue_info
.
summary
.
full_batch_count
,
total
:
data
.
get_next_queue_info
.
summary
.
total_batch
,
};
}
this
.
processSummary
.
noData
=
false
;
}
},
},
},
destroyed
()
{
destroyed
()
{
window
.
removeEventListener
(
'
resize
'
,
this
.
resizeTrace
,
false
);
window
.
removeEventListener
(
'
resize
'
,
this
.
resizeTrace
,
false
);
...
@@ -576,13 +910,20 @@ export default {
...
@@ -576,13 +910,20 @@ export default {
};
};
</
script
>
</
script
>
<
style
lang=
"scss"
>
<
style
lang=
"scss"
>
.el-tooltip-popper
{
max-width
:
500px
;
}
.tooltip-container
{
line-height
:
20px
;
padding
:
10px
;
}
.pro-router-wrap
{
.pro-router-wrap
{
height
:
100%
;
height
:
100%
;
&
>
div
{
&
>
div
{
float
:
left
;
float
:
left
;
height
:
100%
;
height
:
100%
;
&
>
div
{
&
>
div
{
border
:
1px
solid
#
ddd
;
border
:
1px
solid
#
eee
;
border-radius
:
4px
;
border-radius
:
4px
;
}
}
.title-wrap
{
.title-wrap
{
...
@@ -594,8 +935,9 @@ export default {
...
@@ -594,8 +935,9 @@ export default {
}
}
.tip-icon
{
.tip-icon
{
float
:
right
;
float
:
right
;
margin-right
:
1
8
px
;
margin-right
:
1
0
px
;
font-size
:
20px
;
font-size
:
20px
;
color
:
#6c7280
;
.el-icon-warning
{
.el-icon-warning
{
cursor
:
pointer
;
cursor
:
pointer
;
&
:hover::before
{
&
:hover::before
{
...
@@ -650,7 +992,7 @@ export default {
...
@@ -650,7 +992,7 @@ export default {
}
}
}
}
.pro-router-left
{
.pro-router-left
{
width
:
calc
(
100%
-
35
0px
);
width
:
calc
(
100%
-
40
0px
);
padding-right
:
15px
;
padding-right
:
15px
;
.step-trace
{
.step-trace
{
height
:
45%
;
height
:
45%
;
...
@@ -667,10 +1009,101 @@ export default {
...
@@ -667,10 +1009,101 @@ export default {
}
}
.minddata
{
.minddata
{
height
:
calc
(
55%
-
15px
);
height
:
calc
(
55%
-
15px
);
.pipeline-container
{
width
:
100%
;
padding
:
20px
20px
;
height
:
calc
(
100%
-
52px
);
display
:
flex
;
font-size
:
0
;
align-items
:
baseline
;
.cell-container
{
width
:
20%
;
padding
:
20px
0
;
border
:
2px
solid
transparent
;
.title
{
font-size
:
14px
;
line-height
:
20px
;
padding
:
0
0
0
20px
;
font-weight
:
bold
;
}
.content
{
padding
:
10px
20px
0px
20px
;
font-size
:
12px
;
}
}
.data-process
{
background-color
:
#e3f8eb
;
.title
{
border-left
:
2px
solid
#00a5a7
;
}
}
.device_queue_op
{
background-color
:
#e1f2ff
;
.title
{
border-left
:
2px
solid
#6cbfff
;
}
}
.get-next
{
background-color
:
#fef4dd
;
.title
{
border-left
:
2px
solid
#fdca5a
;
}
}
.queue-container
{
width
:
20%
;
position
:
relative
;
.img
{
width
:
100%
;
height
:
24px
;
margin-top
:
30px
;
.edge
{
width
:
calc
(
50%
-
40px
);
display
:
inline-block
;
vertical-align
:
middle
;
img
{
width
:
100%
;
}
}
.icon
{
padding
:
0
20px
;
display
:
inline-block
;
vertical-align
:
middle
;
img
{
padding
:
3px
;
border
:
2px
solid
transparent
;
}
}
}
.title
{
text-align
:
center
;
font-size
:
14px
;
margin-top
:
10px
;
font-weight
:
bold
;
}
.description
{
position
:
absolute
;
font-size
:
12px
;
line-height
:
12px
;
white-space
:
nowrap
;
overflow
:
hidden
;
width
:
100%
;
text-align
:
center
;
.item
{
font-size
:
12px
;
line-height
:
16px
;
white-space
:
normal
;
.num
{
color
:
#07a695
;
}
}
}
}
}
}
}
}
}
.pro-router-right
{
.pro-router-right
{
width
:
35
0px
;
width
:
40
0px
;
.op-time-consume
{
.op-time-consume
{
height
:
calc
(
60%
-
15px
);
height
:
calc
(
60%
-
15px
);
margin-bottom
:
15px
;
margin-bottom
:
15px
;
...
@@ -728,6 +1161,14 @@ export default {
...
@@ -728,6 +1161,14 @@ export default {
.time-line
{
.time-line
{
height
:
40%
;
height
:
40%
;
overflow
:
hidden
;
overflow
:
hidden
;
.timeline-info
{
width
:
100%
;
height
:
calc
(
100%
-
54px
);
padding-left
:
36px
;
}
.info-line
{
line-height
:
30px
;
}
}
}
}
}
.op-time-content
{
.op-time-content
{
...
...
mindinsight/ui/src/views/train-manage/profiling.vue
浏览文件 @
6433fbb8
...
@@ -24,7 +24,8 @@ limitations under the License.
...
@@ -24,7 +24,8 @@ limitations under the License.
<label>
{{
$t
(
'
profiling.curCard
'
)
}}
</label>
<label>
{{
$t
(
'
profiling.curCard
'
)
}}
</label>
<el-select
v-model=
"curDashboardInfo.curCardNum"
<el-select
v-model=
"curDashboardInfo.curCardNum"
class=
"card-select"
class=
"card-select"
:placeholder=
"$t('public.select')"
>
:placeholder=
"$t('public.select')"
@
change=
"selectValueChange"
>
<el-option
v-for=
"item in CardNumArr"
<el-option
v-for=
"item in CardNumArr"
:key=
"item.value"
:key=
"item.value"
:label=
"item.value + $t('operator.card')"
:label=
"item.value + $t('operator.card')"
...
@@ -35,6 +36,8 @@ limitations under the License.
...
@@ -35,6 +36,8 @@ limitations under the License.
<div
class=
"helper-title"
>
<div
class=
"helper-title"
>
{{
$t
(
"
profiling.smartHelper
"
)
}}
{{
$t
(
"
profiling.smartHelper
"
)
}}
</div>
</div>
<div
class=
"suggested-title"
>
{{
$t
(
"
profiling.suggestions
"
)
}}
</div>
<div
id=
"helper-tips"
></div>
</div>
</div>
<div
class=
"collapse-btn"
<div
class=
"collapse-btn"
:class=
"
{collapse:collapse}"
:class=
"
{collapse:collapse}"
...
@@ -58,6 +61,16 @@ import RequestService from '../../services/request-service';
...
@@ -58,6 +61,16 @@ import RequestService from '../../services/request-service';
export
default
{
export
default
{
data
()
{
data
()
{
return
{
return
{
tipsArrayList
:
[
'
step_trace-iter_interval
'
,
'
minddata_pipeline-general
'
,
'
minddata_pipeline-dataset_op
'
,
'
minddata_pipeline-generator_op
'
,
'
minddata_pipeline-map_op
'
,
'
minddata_pipeline-batch_op
'
,
'
minddata_warning_op
'
,
],
moreParameter
:
[
'
minddata_device_queue
'
,
'
minddata_get_next_queue
'
],
CardNumArr
:
[],
CardNumArr
:
[],
collapse
:
false
,
collapse
:
false
,
curDashboardInfo
:
{
curDashboardInfo
:
{
...
@@ -85,6 +98,12 @@ export default {
...
@@ -85,6 +98,12 @@ export default {
this
.
curDashboardInfo
.
query
.
path
=
''
;
this
.
curDashboardInfo
.
query
.
path
=
''
;
this
.
$message
.
error
(
this
.
$t
(
'
trainingDashboard.invalidId
'
));
this
.
$message
.
error
(
this
.
$t
(
'
trainingDashboard.invalidId
'
));
}
}
this
.
getDataOfProfileHelper
();
},
selectValueChange
()
{
const
helperDiv
=
document
.
getElementById
(
'
helper-tips
'
);
helperDiv
.
innerHTML
=
''
;
this
.
getDataOfProfileHelper
();
},
},
getDeviceList
()
{
getDeviceList
()
{
const
params
=
{
const
params
=
{
...
@@ -110,6 +129,124 @@ export default {
...
@@ -110,6 +129,124 @@ export default {
})
})
.
catch
(()
=>
{});
.
catch
(()
=>
{});
},
},
getDataOfProfileHelper
()
{
const
params
=
{
train_id
:
this
.
curDashboardInfo
.
query
.
id
,
profile
:
this
.
curDashboardInfo
.
query
.
dir
,
device_id
:
this
.
curDashboardInfo
.
curCardNum
.
toString
()
?
this
.
curDashboardInfo
.
curCardNum
.
toString
()
:
'
0
'
,
};
RequestService
.
queryDataOfProfileHelper
(
params
)
.
then
((
resp
)
=>
{
if
(
resp
&&
resp
.
data
)
{
const
dataKeys
=
Object
.
keys
(
resp
.
data
);
const
helperDiv
=
document
.
getElementById
(
'
helper-tips
'
);
helperDiv
.
innerHTML
=
''
;
dataKeys
.
forEach
((
item
)
=>
{
if
(
!
this
.
tipsArrayList
.
includes
(
item
)
&&
!
this
.
moreParameter
.
includes
(
item
)
&&
resp
.
data
[
item
]
)
{
this
.
$t
(
`profiling`
)[
item
]
=
resp
.
data
[
item
];
}
if
(
item
.
endsWith
(
'
type_label
'
))
{
const
divDom
=
document
.
createElement
(
'
div
'
);
divDom
.
setAttribute
(
'
class
'
,
'
suggested-items-style
'
);
divDom
.
innerHTML
=
`<div class="helper-icon"></div>
<div class="helper-container-title">
${
this
.
$t
(
`profiling`
)[
item
].
desc
}
</div>`
;
helperDiv
.
appendChild
(
divDom
);
}
else
if
(
this
.
tipsArrayList
.
includes
(
item
))
{
const
divDom
=
document
.
createElement
(
'
div
'
);
divDom
.
setAttribute
(
'
class
'
,
'
content-style
'
);
const
content
=
`
${
this
.
$t
(
`profiling`
)[
item
].
desc
}
`
.
replace
(
`{n1}`
,
resp
.
data
[
item
][
0
],
);
divDom
.
innerHTML
=
`<div class="content-icon el-icon-caret-right"></div>
<div class="helper-content-style">
${
content
}
</div>`
;
helperDiv
.
appendChild
(
divDom
);
}
else
if
(
item
===
'
minddata_device_queue
'
)
{
const
deviceEmpty
=
resp
.
data
[
'
minddata_device_queue
'
][
0
]
>=
0
?
resp
.
data
[
'
minddata_device_queue
'
][
0
]
:
'
--
'
;
const
deviceTotal
=
resp
.
data
[
'
minddata_device_queue
'
][
1
]
>=
0
?
resp
.
data
[
'
minddata_device_queue
'
][
1
]
:
'
--
'
;
const
deviceFull
=
resp
.
data
[
'
minddata_device_queue
'
][
2
]
>=
0
?
resp
.
data
[
'
minddata_device_queue
'
][
2
]
:
'
--
'
;
const
divDom
=
document
.
createElement
(
'
div
'
);
divDom
.
setAttribute
(
'
class
'
,
'
content-style
'
);
const
content
=
`
${
this
.
$t
(
`profiling`
)[
item
].
desc
}
`
.
replace
(
`{n1}`
,
deviceEmpty
)
.
replace
(
`{n2}`
,
deviceTotal
)
.
replace
(
`{n3}`
,
deviceFull
)
.
replace
(
`{n4}`
,
deviceTotal
);
divDom
.
innerHTML
=
`<div class="content-icon el-icon-caret-right"></div>
<div class="helper-content-style">
${
content
}
</div>`
;
helperDiv
.
appendChild
(
divDom
);
}
else
if
(
item
===
'
minddata_get_next_queue
'
)
{
const
getNextEmpty
=
resp
.
data
[
'
minddata_get_next_queue
'
][
0
]
>=
0
?
resp
.
data
[
'
minddata_get_next_queue
'
][
0
]
:
'
--
'
;
const
getNextTotal
=
resp
.
data
[
'
minddata_get_next_queue
'
][
1
]
>=
0
?
resp
.
data
[
'
minddata_get_next_queue
'
][
1
]
:
'
--
'
;
const
divDom
=
document
.
createElement
(
'
div
'
);
divDom
.
setAttribute
(
'
class
'
,
'
content-style
'
);
const
content
=
`
${
this
.
$t
(
`profiling`
)[
item
].
desc
}
`
.
replace
(
`{n1}`
,
getNextEmpty
)
.
replace
(
`{n2}`
,
getNextTotal
);
divDom
.
innerHTML
=
`<div class="content-icon el-icon-caret-right"></div>
<div class="helper-content-style">
${
content
}
</div>`
;
helperDiv
.
appendChild
(
divDom
);
}
else
if
(
this
.
$t
(
`profiling`
)[
item
].
anchor
)
{
if
(
this
.
$t
(
`profiling`
)[
item
].
anchor
.
length
===
1
)
{
const
divDom
=
document
.
createElement
(
'
div
'
);
divDom
.
setAttribute
(
'
class
'
,
'
content-style
'
);
divDom
.
innerHTML
=
`<div class="content-icon el-icon-caret-right"></div>
<div class="helper-content-style">
<a href="
${
this
.
$t
(
`profiling`
)[
item
].
url
[
0
]}
">
${
this
.
$t
(
`profiling`
)[
item
].
desc
}
</a></div>`
;
helperDiv
.
appendChild
(
divDom
);
}
else
{
const
divDom
=
document
.
createElement
(
'
div
'
);
divDom
.
setAttribute
(
'
class
'
,
'
content-style
'
);
const
anchorList
=
this
.
$t
(
`profiling`
)[
item
].
anchor
;
const
anchorContent
=
this
.
$t
(
`profiling`
)[
item
].
desc
;
for
(
let
i
=
0
;
i
<
anchorList
.
length
;
i
++
)
{
const
desc
=
anchorContent
.
relpace
(
anchorList
[
i
],
`<a href="
${
this
.
$t
(
`profiling`
)[
item
].
url
[
i
]}
">
${
anchorList
[
i
]}
</a>`
,
);
anchorContent
=
desc
;
}
divDom
.
innerHTML
=
`<div class="content-icon el-icon-caret-right">
</div><div class="helper-content-style">
${
anchorContent
}
</div>`
;
helperDiv
.
appendChild
(
divDom
);
}
}
else
{
const
divDom
=
document
.
createElement
(
'
div
'
);
divDom
.
setAttribute
(
'
class
'
,
'
content-style
'
);
divDom
.
innerHTML
=
`
${
this
.
$t
(
`profiling`
)[
item
].
desc
}
`
;
helperDiv
.
appendChild
(
divDom
);
}
});
}
})
.
catch
(()
=>
{});
},
backToDdashboard
()
{
backToDdashboard
()
{
this
.
$router
.
push
({
this
.
$router
.
push
({
path
:
'
/profiling/profiling-dashboard
'
,
path
:
'
/profiling/profiling-dashboard
'
,
...
@@ -171,6 +308,49 @@ export default {
...
@@ -171,6 +308,49 @@ export default {
cursor
:
pointer
;
cursor
:
pointer
;
}
}
}
}
.helper-container-title
{
display
:
inline-block
;
padding
:
0
6px
;
}
.helper-icon
{
display
:
inline-block
;
width
:
6px
;
height
:
6px
;
margin-top
:
6px
;
border-radius
:
3px
;
background-color
:
#00a5a7
;
}
.suggested-title
{
font-weight
:
bold
;
margin-bottom
:
20px
;
font-size
:
16px
;
}
.container-bottom
{
margin-bottom
:
16px
;
}
.suggested-items-style
{
display
:
flex
;
font-weight
:
bold
;
margin-bottom
:
6px
;
margin-top
:
10px
;
}
.helper-content-style
{
margin-left
:
6px
;
line-height
:
20px
;
word-break
:
break-all
;
text-overflow
:
ellipsis
;
overflow
:
hidden
;
display
:
-
webkit-box
;
-webkit-box-orient
:
vertical
;
-webkit-line-clamp
:
8
;
}
}
.content-icon
{
color
:
#00a5a7
;
padding-top
:
3px
;
}
.content-style
{
display
:
flex
;
}
}
.collapse-btn
{
.collapse-btn
{
position
:
absolute
;
position
:
absolute
;
...
@@ -185,7 +365,7 @@ export default {
...
@@ -185,7 +365,7 @@ export default {
text-align
:
center
;
text-align
:
center
;
background-image
:
url('../../assets/images/collapse-left.svg')
;
background-image
:
url('../../assets/images/collapse-left.svg')
;
}
}
.collapse-btn.collapse
{
.collapse-btn.collapse
{
background-image
:
url('../../assets/images/collapse-right.svg')
;
background-image
:
url('../../assets/images/collapse-right.svg')
;
}
}
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录