diff --git a/ide/src/base-ui/select/LitSelect.ts b/ide/src/base-ui/select/LitSelect.ts index da9d3e108939c3e05f5f15476b50fb2f00c5b4bd..61311ebed751bfdc734123c25a49a287ada5dca9 100644 --- a/ide/src/base-ui/select/LitSelect.ts +++ b/ide/src/base-ui/select/LitSelect.ts @@ -459,6 +459,13 @@ export class LitSelect extends BaseElement { if (this.hasAttribute('disabled')) { return; } + // @ts-ignore + if (this.selectInputEl.value.length > 0) { + // @ts-ignore + this.selectInputEl.placeholder = this.selectInputEl.value; + // @ts-ignore + this.selectInputEl.value = ''; + } if (this.hasAttribute('show-search')) { // @ts-ignore this.selectSearchEl.style.display = 'flex'; // @ts-ignore @@ -475,57 +482,57 @@ export class LitSelect extends BaseElement { // @ts-ignore this.selectInputEl.onkeydown = (ev: KeyboardEvent): void => { ev.stopPropagation(); - if (this.hasAttribute('tabselect')) { - // @ts-ignore - this.selectInputEl.readOnly = true; - } else { - // @ts-ignore - if (ev.key === 'Backspace') { - if (this.isMultiple()) { - // @ts-ignore - let tag = this.selectMultipleRootEl.lastElementChild.previousElementSibling; - if (tag) { - this.querySelector(`lit-select-option[value=${tag.value}]`)?.removeAttribute('selected'); - tag.remove(); - if (this.shadowRoot!.querySelectorAll('.tag').length === 0) { - // @ts-ignore - this.selectInputEl.style.width = 'auto'; // @ts-ignore - this.selectInputEl.placeholder = this.defaultPlaceholder; - } - } - } else { - this.clear(); - this.dispatchEvent(new CustomEvent('onClear', { detail: ev })); //向外派发清理事件 - } // @ts-ignore - } else if (ev.key === 'Enter') { - if (!this.canInsert) { - let filter = [...this.querySelectorAll('lit-select-option')].filter( - // @ts-ignore - (a: unknown) => a.style.display !== 'none' - ); - if (filter.length > 0) { - // @ts-ignore - this.selectInputEl.value = filter[0].textContent; // @ts-ignore - this.selectInputEl.placeholder = filter[0].textContent; - this.blur(); + if (this.hasAttribute('tabselect')) { + // @ts-ignore + this.selectInputEl.readOnly = true; + } else { + // @ts-ignore + if (ev.key === 'Backspace') { + if (this.isMultiple()) { // @ts-ignore - this.value = filter[0].getAttribute('value'); - this.dispatchEvent( - new CustomEvent('change', { - detail: { - selected: true, - value: filter[0].getAttribute('value'), - text: filter[0].textContent, - }, - }) + let tag = this.selectMultipleRootEl.lastElementChild.previousElementSibling; + if (tag) { + this.querySelector(`lit-select-option[value=${tag.value}]`)?.removeAttribute('selected'); + tag.remove(); + if (this.shadowRoot!.querySelectorAll('.tag').length === 0) { + // @ts-ignore + this.selectInputEl.style.width = 'auto'; // @ts-ignore + this.selectInputEl.placeholder = this.defaultPlaceholder; + } + } + } else { + this.clear(); + this.dispatchEvent(new CustomEvent('onClear', { detail: ev })); //向外派发清理事件 + } // @ts-ignore + } else if (ev.key === 'Enter') { + if (!this.canInsert) { + let filter = [...this.querySelectorAll('lit-select-option')].filter( + // @ts-ignore + (a: unknown) => a.style.display !== 'none' ); - } - }// @ts-ignore - } else if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { - // @ts-ignore - ev.preventDefault(); + if (filter.length > 0) { + // @ts-ignore + this.selectInputEl.value = filter[0].textContent; // @ts-ignore + this.selectInputEl.placeholder = filter[0].textContent; + this.blur(); + // @ts-ignore + this.value = filter[0].getAttribute('value'); + this.dispatchEvent( + new CustomEvent('change', { + detail: { + selected: true, + value: filter[0].getAttribute('value'), + text: filter[0].textContent, + }, + }) + ); + } + }// @ts-ignore + } else if (ev.key === '0' && ev.target.value.length === 1 && ev.target.value === '0') { + // @ts-ignore + ev.preventDefault(); + } } - } }; } diff --git a/ide/src/base-ui/slicer/lit-slicer.ts b/ide/src/base-ui/slicer/lit-slicer.ts index e9a1bc3875fcc3bbfadc31d03e72158269d2db74..86f9061f009ae0108d4c16781f8f7d909f912dbb 100644 --- a/ide/src/base-ui/slicer/lit-slicer.ts +++ b/ide/src/base-ui/slicer/lit-slicer.ts @@ -153,6 +153,8 @@ export class LitSlicerTrack extends HTMLElement { ) { previousElementSibling!.style.width = preWidth + e1.pageX - preX + 'px'; nextElementSibling!.style.width = nextWidth + preX - e1.pageX + 'px'; + } else { + this.draging = false; } } }; diff --git a/ide/src/doc/funDetail.json b/ide/src/doc/funDetail.json index e9a08eb4d55c5dd87b5b44d714e5454c582bf3f0..9bca062d7de50c4c2c854a08c75c02118d17a341 100644 --- a/ide/src/doc/funDetail.json +++ b/ide/src/doc/funDetail.json @@ -31,12 +31,6 @@ "EN": "this is an english translate for CN", "flag": "0" }, - { - "slice": "FlushLayoutTask", - "CN": "组件的布局,这一块可以确认是什么组件在创建或者复用", - "EN": "this is an english translate for CN", - "flag": "0" - }, { "slice": "CreateTaskMeasure", "CN": "组件的测量。这一块可以确认是什么组件在创建", @@ -49,12 +43,6 @@ "EN": "this is an english translate for CN", "flag": "0" }, - { - "slice": "JSAnimation", - "CN": "如果FlushVsync下面出现这个trace点,说明触发了ArkUI的动效,例如使用了属性动画animation属性或者显示动画animateTo。可以排查一下代码看一下这种场景是否需要触发这个动画,有时候会因为组件的刷新而出现该动画的冗余绘制", - "EN": "this is an english translate for CN", - "flag": "0" - }, { "slice": "BuildRecyle", "CN": "如果出现这个trace说明,这个组件是走复用逻辑的。当前如果组件节点较多,也会导致组件复用的时候耗时比较长导致丢帧。", @@ -186,6 +174,378 @@ "CN": "触发了shader编译,需要通过与之shader来避免。shader缓存是业界通用方案,在动效前几次执行的时候会概率性出现,用于创建该场景的着色器并将其缓存,以使之后的操作可以直接复用原有的着丝琪,从而提升系统的性能。但shader编译耗时太长导致RS侧丢帧造成动效卡顿", "EN": "this is an english translate for CN", "flag": "0" + }, + { + "slice": "OnVsyncEvent now", + "CN": "收到Vsync信号,渲染流程开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "UITaskScheduler::FlushTask", + "CN": "刷新UI界面,包括布局、渲染和动画等", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "FlushMessages", + "CN": "发送消息通知图形侧进行渲染", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "FlushRenderTask", + "CN": "总渲染任务执行", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Layout", + "CN": "节点布局", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "FrameNode::RenderTask", + "CN": "单个渲染任务执行", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ListLayoutAlgorithm::MeasureListItem:", + "CN": "计算列表项的布局尺寸", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ListLayoutAlgorithm::MeasureListItemGroup:", + "CN": "计算列表ListItemGroup项的布局尺寸", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "HandleDragStart, id:", + "CN": "拖拽开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "HandleDragUpdate, mainDelta", + "CN": "拖拽中", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "HandleDragEnd, mainPosition:", + "CN": "拖拽结束", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Scrollable friction animation start,", + "CN": "抛滑动画开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Scrollable friction animation finish, id:", + "CN": "抛滑动画结束", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "StopFrictionAnimation, id:", + "CN": "关闭抛滑动画", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Scrollable spring animation start, start:", + "CN": "过界回弹动画开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Scrollable spring animation finish, id:", + "CN": "过界回弹动画结束", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Scrollable spring animation update, start:", + "CN": "更新过界回弹动画开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "StopSpringAnimation, id:", + "CN": "关闭过界回弹动画", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Scroll snap animation start, start:", + "CN": "Scroll的限位动画开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Scroll snap animation finish, id:", + "CN": "Scroll的限位动画结束", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "List start snap animation, start:", + "CN": "List的限位动画开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "List snap animation finish, id:", + "CN": "List的限位动画结束", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "StopSnapAnimation isSnapAnimationStop_:", + "CN": "关闭限位动画", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "APP_LIST_FLING", + "CN": "滑动阶段(包括所有的拖拽,抛滑、回弹、滚动控制器动画)", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "TRAILING_ANIMATION id:", + "CN": "动画的拖尾阶段", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "HandleTouchDown, panDirection:", + "CN": "手指按下", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "HandleTouchUp, isDragging_:", + "CN": "手指抬起(新增)", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "HandleTouchCancel, id:", + "CN": "取消手势", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ScrollAbort, no OnScrollStart, id:", + "CN": "ScrollAbort为true,触发OnScrollStart失败,(一般出现在抛滑后调用滚动控制器启动滚动动画)", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "OnScrollStart, id:", + "CN": "触发OnScrollStart成功", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ScrollAbort, no OnScrollStop, id:", + "CN": "ScrollAbort为true,触发OnScrollStop失败(一般出现在抛滑后调用滚动控制器启动滚动动画)", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "OnScrollStop, id:", + "CN": "触发OnScrollStop成功", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ScrollBy, offset:", + "CN": "滚动控制器触发ScrollBy", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ScrollTo with animation, position:", + "CN": "滚动控制器触发带动画的ScrollTo", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ScrollTo without animation, position:", + "CN": "滚动控制器触发不带动画的ScrollTo", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ScrollPage with animation, position", + "CN": "滚动控制器触发带动画的Scrollpage", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ScrollPage without animation, position:", + "CN": "滚动控制器触发不带动画的Scrollpage", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Fling, flingVelocity:", + "CN": "滚动控制器触发惯性滚动", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Scroll ScrollToEdge scrollEdgeType:", + "CN": "Scroll触发ScrollEdge", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ScrollToEdge scrollEdgeType:", + "CN": "滚动控制器触发的ScrollEdge", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ScrollToIndex, index:", + "CN": "滚动控制器触发ScrollToIndex", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "CUSTOM_ANIMATOR_SCROLLER_ANIMATION", + "CN": "滚动控制器触发ScrollTo滑动动画", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "HandleScroll, initOffset:", + "CN": "嵌套滚动处理偏移量", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "HandleScrollVelocity, IsOutOfBoundary:", + "CN": "嵌套滚动中处理离手速度", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "HandleOverScroll, IsOutOfBoundary:", + "CN": "离手时处理过界滚动", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "SCROLLER_FIX_VELOCITY_ANIMATION", + "CN": "控制器触发按固定速度滚动到边缘", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "CheckRestartSpring, sizeDiminished is true, do ProcessSpringUpdate, id:", + "CN": "回弹动画期间组件大小被修改导致触发回弹更新动画", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "CheckRestartSpring, do ProcessScrollOver, id:", + "CN": "在静态场景下因组件大小修改原因导致组件处于过界状态,触发回弹动画恢复到未过界状态", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ListItemGroup:", + "CN": "设置lane的ListItemGroup列表布局", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "ListItem:", + "CN": "设置lane的列表布局", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "change direction in spring animation and start fling animation, distance::", + "CN": "过界回弹动效中出现方向改变,并启动抛滑动效", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "scrollPause set true to stop ProcessScrollMotion, canOverScroll:", + "CN": "抛滑动效期间达成停止条件从而关闭抛滑动效,并触发结束回调(一般出现在快速抛滑过界的场景)", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Tabs.onChange index ", + "CN": "tabs页面切换后", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Tabs/Swiper drag start", + "CN": "跟手拖拽开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Tabs/Swiper drag end", + "CN": "跟手拖拽结束", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Tabs/Swiper start property animation, X:", + "CN": "属性动画开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Tabs/Swiper finish property animation, X: ", + "CN": "属性动画结束", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Tabs/Swiper start spring animation", + "CN": "回弹动画开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Tabs/Swiper finish spring animation, offset:", + "CN": "回弹动画结束", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Tabs/Swiper start translate animation", + "CN": "自定义属性动画开始", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "Tabs/Swiper finish translate animation", + "CN": "自定义属性动画结束", + "EN": "this is an english translate for CN", + "flag": "0" + }, + { + "slice": "FlushVsync", + "CN": "刷新视图同步事件,包括记录帧信息、刷新任务、绘制渲染上下文、处理用户输入", + "EN": "this is an english translate for CN", + "flag": "0" } ] } \ No newline at end of file diff --git a/ide/src/doc/md/quickstart_app_startup.md b/ide/src/doc/md/quickstart_app_startup.md index f6f20762c06cd131637f983f63682c46d60dd55b..f16c4d98a2a69096b8e1c775e131f77ab6bb553a 100644 --- a/ide/src/doc/md/quickstart_app_startup.md +++ b/ide/src/doc/md/quickstart_app_startup.md @@ -17,7 +17,7 @@ App startup 的泳道图展示: ![GitHub Logo](../../figures/appstartup/appstartuprow.jpg) -应用启动包括六个阶段,分别是 Process Creating(应用进程创建阶段)、Application Launching(加载应用阶段)、UI Ability Launching(加载 UI Ability)、UI Ability OnForeground(应用进入前台)、First Frame - APP Phase(首帧渲染提交-应用)、First Frame - Render Phase(首帧渲染提交-Render Service)。每个阶段的 Slice 上都会显示出该阶段的时延。 +应用启动包括八个阶段,分别是ProcessTouchEvent(处理点击事件阶段)、StartUIAbilityBySCB(SCB发送请求阶段)、LoadAbility(AMS加载Ability阶段) 、Application Launching(加载应用阶段)、UI Ability Launching(加载UI Ability)、UI Ability OnForeground(应用进入前台)、First Frame - APP Phase(首帧渲染提交-应用)、First Frame - Render Phase(首帧渲染提交-Render Service)。每个阶段的Slice上都会显示出该阶段的时延。 ### App startup 泳道图点选功能 diff --git a/ide/src/doc/quickstart_app_startup.html b/ide/src/doc/quickstart_app_startup.html index fc3a13a3ef9a855b331bd8f5990fe70fc00351ef..0d5dc3e95c42d9888471590ea63e2c59e4ae2b43 100644 --- a/ide/src/doc/quickstart_app_startup.html +++ b/ide/src/doc/quickstart_app_startup.html @@ -811,10 +811,10 @@ App startup:配置项的总开关。解析时请打开对应的Flags标记(Dis
GitHub Logo
- 应用启动包括六个阶段,分别是Process Creating(应用进程创建阶段)、Application Launching(加载应用阶段)、UI Ability - Launching(加载UI Ability)、UI Ability OnForeground(应用进入前台)、First Frame - APP - Phase(首帧渲染提交-应用)、First Frame - Render Phase(首帧渲染提交-Render - Service)。每个阶段的Slice上都会显示出该阶段的时延。 + 应用启动包括八个阶段,分别是ProcessTouchEvent(处理点击事件阶段)、StartUIAbilityBySCB(SCB发送请求阶段)、 + LoadAbility(AMS加载Ability阶段) 、Application Launching(加载应用阶段)、UI Ability Launching(加载UI Ability)、 + UI Ability OnForeground(应用进入前台)、First Frame - APP Phase(首帧渲染提交-应用)、First Frame - Render Phase(首帧渲染提交-Render Service)。 + 每个阶段的Slice上都会显示出该阶段的时延。

App startup泳道图点选功能

diff --git a/ide/src/doc/quickstart_extensions.html b/ide/src/doc/quickstart_extensions.html index 647ab76b2e0d33902b20a73e346befa42ef7b857..c9e47bf43f7ead26f630e1d50304de5d0c260141 100644 --- a/ide/src/doc/quickstart_extensions.html +++ b/ide/src/doc/quickstart_extensions.html @@ -811,7 +811,7 @@ 在hi-smart-perf-host-extend目录下,找到stop.bat文件,右键选择以管理员身份运行,即可关闭扩展服务。

- 备注:当前扩展服务版本为1.0.1,如果本地存在以其他方式安装的非正式版本,请手动关闭扩展服务,并重新按照该指导安装 + 备注:当前扩展服务版本为1.0.2,如果本地存在以其他方式安装的非正式版本,请手动关闭扩展服务,并重新按照该指导安装

diff --git a/ide/src/figures/appstartup/appstartuprow.jpg b/ide/src/figures/appstartup/appstartuprow.jpg index fd4352512879725ee74f7271855b3beafd1d6798..26eb17eb85e77351cb9767f8249ef8ac95a74aa9 100644 Binary files a/ide/src/figures/appstartup/appstartuprow.jpg and b/ide/src/figures/appstartup/appstartuprow.jpg differ diff --git a/ide/src/trace/SpApplication.ts b/ide/src/trace/SpApplication.ts index 62e1e7d2cb93e7c789f1a75184924715bc0a8655..a793515bc35ddca9dae9ddd704b6891ca2439c58 100644 --- a/ide/src/trace/SpApplication.ts +++ b/ide/src/trace/SpApplication.ts @@ -2534,12 +2534,11 @@ export class SpApplication extends BaseElement { clearInterval(timer); }, 4000); // 存入缓存 - await caches.open(`${fileName}`).then(async (cache) => { - let headers = new Headers(); - headers.append('Content-type', 'application/octet-stream'); - headers.append('Content-Transfer-Encoding', 'binary'); - return cache.put(`${fileName}`, new Response(reqBufferDB, { status: 200 })); - }); + const blob = new Blob([reqBufferDB]); + const response = new Response(blob) + caches.open('DB-file').then(cache => { + return cache.put(`/${fileName}`, response); + }) }, 'download-db' ); diff --git a/ide/src/trace/bean/BoxSelection.ts b/ide/src/trace/bean/BoxSelection.ts index c0509abc106216a806db6d59b903ae373f794ada..f4ae309f879d3efed4bdce8a48efdc20ad184402 100644 --- a/ide/src/trace/bean/BoxSelection.ts +++ b/ide/src/trace/bean/BoxSelection.ts @@ -1346,6 +1346,7 @@ export class SelectionData { maxDuration: number = 0; maxDurationFormat: string = ''; occurrences: number = 0; + selfTime: number = 0; state: string = ''; trackId: number = 0; delta: string = ''; diff --git a/ide/src/trace/bean/PerfAnalysis.ts b/ide/src/trace/bean/PerfAnalysis.ts new file mode 100644 index 0000000000000000000000000000000000000000..1f73a5a16ba464ddefe9a500646980d9e62aff29 --- /dev/null +++ b/ide/src/trace/bean/PerfAnalysis.ts @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class PerfFunctionAsmParam { + totalCount: number = 0; + functionName: string = ""; + vaddrList: Array = []; +} + +export class FormattedAsmInstruction { + selfcount:number = 0; + percent:number = 0; + addr: number = 0; + instruction: string = ''; + sourceLine: string = ''; +} + +export class OriginAsmInstruction { + addr:string = ''; + instruction:string = ''; + sourceLine: string = ''; +} + +export class PerfFunctionAsmShowUpData { + addr: number = 0; + instruction: string = ''; + selfCount: number = 0; + percent: number = 0; +} + diff --git a/ide/src/trace/component/SpAdvertisement.ts b/ide/src/trace/component/SpAdvertisement.ts index 83922144ba6618109f450e3fe79f05f98f7e06c6..4428fca6e57a68c7cc6b6635ad11652270c690d8 100644 --- a/ide/src/trace/component/SpAdvertisement.ts +++ b/ide/src/trace/component/SpAdvertisement.ts @@ -54,9 +54,11 @@ export class SpAdvertisement extends BaseElement { this.message = resp.data.data; localStorage.setItem('message', this.message); let parts = this.message.split(';'); - let linkInfo = parts[2].match(/链接:([^\s]+)/)![1] || ''; - let link = `${parts[1]}`; - let finalString = `${parts[0]}
${link}`; + let registrationLinkInfo = (parts[2].match(/报名链接:([^\s]+)/) || [])[1] || ''; + let onlineMeetingLinkInfo = (parts[3].match(/线上会议链接:([^\s]+)/) || [])[1] || ''; + let registrationLink = `报名链接`; + let onlineMeetingLink = `线上会议链接`; + let finalString = `${parts[0]}
${parts[1]}
${registrationLink}   ${onlineMeetingLink}
${parts[4]}`; this.noticeEl!.innerHTML = `

${finalString}

`; if (publish) { if (resp.data.data !== publish) { diff --git a/ide/src/trace/component/SpAiAnalysisPage.html.ts b/ide/src/trace/component/SpAiAnalysisPage.html.ts index de484aaff9a0cd4f8f33ab43659be67b46368b54..24ede5f22d8178afcdc645354ba50b95141e3711 100644 --- a/ide/src/trace/component/SpAiAnalysisPage.html.ts +++ b/ide/src/trace/component/SpAiAnalysisPage.html.ts @@ -74,12 +74,12 @@ export const SpAiAnalysisPageHtml = ` 诊断报告 - + - + - +
@@ -135,11 +135,11 @@ export const SpAiAnalysisPageHtml = ` display: flex; justify-content: center; align-items: center; - width: 320px; + width: 90%; height: 50%; position: absolute; top: 23%; - left: 44%; + left: 45%; transform: translateX(-50%); background-color: sky-blue; } diff --git a/ide/src/trace/component/SpAiAnalysisPage.ts b/ide/src/trace/component/SpAiAnalysisPage.ts index ee8c489955fbb2f698b208c090fbf8c5e67f72ce..05d3b7a1de4ed17ba3a42663639ebd8e46712cbf 100644 --- a/ide/src/trace/component/SpAiAnalysisPage.ts +++ b/ide/src/trace/component/SpAiAnalysisPage.ts @@ -51,6 +51,10 @@ export class SpAiAnalysisPage extends BaseElement { private startTimeEl: HTMLSpanElement | null | undefined; private endTimeEl: HTMLSpanElement | null | undefined; private contentsTable: LitTable | null | undefined; + private chatBar: HTMLDivElement | null | undefined; + private reportDetails: HTMLDivElement | null | undefined; + private showPageFlag: string = 'chat'; + private tipContentArr: Array = []; private question: string = ''; private token: string = ''; // 是否点击了新建聊天 @@ -62,6 +66,7 @@ export class SpAiAnalysisPage extends BaseElement { private isNodata: boolean = true; private md: unknown; private isResultBack: boolean = true; + private timerId: unknown = undefined; static startTime: number = 0; static endTime: number = 0; activeTime: Element | undefined | null; @@ -80,12 +85,12 @@ export class SpAiAnalysisPage extends BaseElement { typographer: true }); let aiAssistant = document.querySelector('body > sp-application')!.shadowRoot!.querySelector('#sp-ai-analysis'); - let chatBar = this.shadowRoot?.querySelector('.chatBar'); + this.chatBar = this.shadowRoot?.querySelector('.chatBar'); let closeBtn = document.querySelector('body > sp-application')!.shadowRoot!.querySelector('#sp-ai-analysis')!.shadowRoot!.querySelector('div.rightTabBar > lit-icon')!.shadowRoot!.querySelector('#icon'); this.askQuestion = this.shadowRoot?.querySelector('.ask_question'); this.reportBar = this.shadowRoot?.querySelector('.report'); this.q_a_window = this.shadowRoot?.querySelector('.q_a_window'); - let reportDetails = this.shadowRoot?.querySelector('.report_details'); + this.reportDetails = this.shadowRoot?.querySelector('.report_details'); this.contentWindow = this.shadowRoot?.querySelector('.ask_question'); this.tipsContainer = this.shadowRoot?.querySelector('.tipsContainer'); this.inputEl = this.shadowRoot?.querySelector('.inputText'); @@ -109,6 +114,57 @@ export class SpAiAnalysisPage extends BaseElement { this.endTimeEl = this.shadowRoot?.querySelector('.endTime'); this.endTimeEl!.innerHTML = getTimeString(TraceRow.range?.endNS!); + let rightBarGroup: any = [ + { + barName: '聊天', + barEl: this.chatBar, + imgEl: this.chatImg, + barFlag: 'chat', + img: 'img/talk.png', + activeImg: 'img/talk_active.png', + showPage: this.askQuestion, + isMustLoadedTrace: false + }, + { + barName: '诊断', + barEl: this.reportBar, + imgEl: this.reportImg, + barFlag: 'detect', + img: 'img/report.png', + activeImg: 'img/report_active.png', + showPage: this.reportDetails, + isMustLoadedTrace: true + } + ] + + // 给右边栏添加点击事件 + rightBarGroup.forEach((barItem: any, index: number) => { + barItem.barEl.addEventListener('click', (ev: Event) => { + if (barItem.isMustLoadedTrace && !SpApplication.isTraceLoaded) { + let importTraceTips = '请先导入trace,再使用诊断功能'; + this.tipContentArr = ['chat']; + this.abnormalPageTips(importTraceTips, '', 4000, this.tipContentArr); + return; + } + // this.tipsContent!.style.display = this.isNodata && barItem.barFlag === 'detect' ? 'flex' : 'none'; + this.tipsContainer!.style.display = 'none'; + this.showPageFlag = barItem.barFlag; + barItem.imgEl.src = barItem.activeImg; + barItem.barEl.classList.add('active'); + barItem.showPage.style.display = 'block'; + if (this.tipContentArr.indexOf(barItem.barFlag) > -1) { + this.tipsContainer!.style.display = 'flex'; + } + for (let i = 0; i < rightBarGroup.length; i++) { + if (i !== index) { + rightBarGroup[i].barEl.classList.remove('active'); + rightBarGroup[i].imgEl.src = rightBarGroup[i].img; + rightBarGroup[i].showPage.style.display = 'none'; + } + } + }) + }) + // 发送消息图标点击事件 this.sendImg?.addEventListener('click', () => { this.sendMessage(); @@ -187,15 +243,6 @@ export class SpAiAnalysisPage extends BaseElement { this.tipsContainer!.style.display = 'none'; this.tipsContent!.style.display = 'none'; this.downloadBtn!.style.display = 'none'; - // 没有登陆,弹窗提示,退出逻辑 - if (!WebSocketManager.getInstance()?.isReady()) { - this.tipsContent!.style.display = 'flex'; - let guideSrc = `https://${window.location.host.split(':')[0]}:${window.location.port - }/application/?action=help_27`; - let linkNodeTips = `未连接,请启动本地扩展程序再试![指导]`; - this.abnormalPageTips(linkNodeTips, '', 4000); - return; - } // 清空诊断报告的内容 this.reportContent = ''; // 隐藏诊断按钮 @@ -205,58 +252,37 @@ export class SpAiAnalysisPage extends BaseElement { this.initiateDiagnosis(); } else { // 首次诊断 - WebSocketManager.getInstance()!.registerMessageListener(TypeConstants.DIAGNOSIS_TYPE, this.webSocketCallBack); + WebSocketManager.getInstance()!.registerMessageListener(TypeConstants.DIAGNOSIS_TYPE, this.webSocketCallBack, this.eventCallBack); // 看缓存中有没有db,没有的话拿一个进行诊断并存缓存 let fileName = sessionStorage.getItem('fileName'); - caches.match(`${fileName}.db`).then(async (res) => { - if (!res) { - this.cacheDb(fileName); + await caches.match(`/${fileName}.db`).then(response => { + if (response) { + response.blob().then(blob => { + const reader = new FileReader(); + reader.readAsArrayBuffer(blob); + reader.onloadend = () => { + const dbBuffer = reader.result; + // @ts-ignore + const reqBufferDB = new Uint8Array(dbBuffer); + // 使用uint8Array + WebSocketManager.getInstance()!.sendMessage( + TypeConstants.DIAGNOSIS_TYPE, + TypeConstants.SENDDB_CMD, + reqBufferDB + ); + }; + }); } else { - WebSocketManager.getInstance()!.sendMessage( - TypeConstants.DIAGNOSIS_TYPE, - TypeConstants.SENDDB_CMD, - new TextEncoder().encode(await res!.text()) - ); + // 如果缓存中没有,从网络获取并存储 + this.cacheDb(fileName); } - }); + }) }; // 点击一键诊断时先挂载loading this.loadingItem = this.loading('style="position:absolute;top:45%;left:45%;z-index:999"'); this.draftList?.appendChild(this.loadingItem!); }); - // 侧边栏诊断点击事件 *************优化,考虑多个按钮 - this.reportBar!.addEventListener('click', () => { - if (!SpApplication.isTraceLoaded) { - let importTraceTips = '请先导入trace,再使用诊断功能'; - this.abnormalPageTips(importTraceTips, '', 4000); - return; - } - this.reportImg!.src = 'img/report_active.png'; - this.chatImg!.src = 'img/talk.png'; - this.reportBar!.classList.add('active'); - chatBar!.classList.remove('active'); - //@ts-ignore - this.askQuestion!.style.display = 'none'; - //@ts-ignore - reportDetails!.style.display = 'block'; - this.tipsContent!.style.display = this.isNodata ? 'flex' : 'none'; - this.tipsContainer!.style.display = 'none'; - }); - - // 侧边栏聊天点击事件 - chatBar!.addEventListener('click', () => { - this.reportImg!.src = 'img/report.png'; - this.chatImg!.src = 'img/talk_active.png'; - this.reportBar!.classList.remove('active'); - chatBar!.classList.add('active'); - //@ts-ignore - this.askQuestion!.style.display = 'block'; - //@ts-ignore - reportDetails!.style.display = 'none'; - this.tipsContainer!.style.display = 'none'; - }); - // 监听表格目录row点击事件,跳转至对应问题行 this.contentsTable!.addEventListener('row-click', (evt) => { // @ts-ignore @@ -487,13 +513,14 @@ export class SpAiAnalysisPage extends BaseElement { // @ts-ignore return { ...item, id: index + 1 }; }); + let tbody = this.contentsTable!.shadowRoot!.querySelector('.table') as HTMLElement; + tbody.style.height = 30 + 25 * source.length + 'px'; + tbody.style.maxHeight = TBODY_HEIGHT + 'px'; this.contentsTable!.recycleDataSource = source; } connectedCallback(): void { super.connectedCallback(); - let tbody = this.contentsTable!.shadowRoot!.querySelector('.table') as HTMLElement; - tbody.style.height = TBODY_HEIGHT + 'px'; } async getToken(isChat?: boolean): Promise { @@ -509,8 +536,12 @@ export class SpAiAnalysisPage extends BaseElement { } //控制页面异常场景的显示 - abnormalPageTips(tipStr: string, imgSrc: string, setTimeoutTime: number): void { - this.tipsContainer!.style.display = 'flex'; + abnormalPageTips(tipStr: string, imgSrc: string, setTimeoutTime: number, flag: Array): void { + // 清除延时器,防止弹窗重叠互相影响 + if (this.timerId) { + // @ts-ignore + clearTimeout(this.timerId); + } this.tipsContainer!.innerHTML = ''; if (imgSrc !== '') { let mixedTipsBox = document.createElement('div'); @@ -523,15 +554,20 @@ export class SpAiAnalysisPage extends BaseElement { mixedTipsBox.appendChild(mixedImg); mixedTipsBox.appendChild(mixedText); this.tipsContainer!.appendChild(mixedTipsBox); + this.tipsContainer!.style.display = 'none'; } else { let textTipsBox = document.createElement('div'); textTipsBox.className = 'textTips'; textTipsBox!.innerHTML = tipStr; this.tipsContainer!.appendChild(textTipsBox); } + if (flag.indexOf(this.showPageFlag) > -1) { + this.tipsContainer!.style.display = 'flex'; + } if (setTimeoutTime) { setTimeout(() => { - this.tipsContainer!.style.display = 'none'; + this.timerId = this.tipsContainer!.style.display = 'none'; + this.tipContentArr = []; }, setTimeoutTime); } } @@ -553,7 +589,7 @@ export class SpAiAnalysisPage extends BaseElement { timeList: Array ): void { SpStatisticsHttpUtil.askAi({ - token: this.token, + token: this.token, // @ts-ignore question: dataList[i].description + ',请问该怎么优化?', collection: '' @@ -562,7 +598,7 @@ export class SpAiAnalysisPage extends BaseElement { }).catch((error) => { this.appendMsg(dataList, i, suggestonDiv, timeList, error); }); - this.draftList!.appendChild(itemDiv!); + this.draftList!.insertBefore(itemDiv!, this.loadingItem!); itemDiv!.style.animation = 'opcityliner 3s'; } @@ -613,18 +649,11 @@ export class SpAiAnalysisPage extends BaseElement { (reqBufferDB: Uint8Array) => { WebSocketManager.getInstance()!.sendMessage(TypeConstants.DIAGNOSIS_TYPE, TypeConstants.SENDDB_CMD, reqBufferDB); // 存入缓存 - caches.open(`${fileName}.db`).then((cache) => { - let headers = new Headers(); - headers.append('Content-Type', 'application/octet-stream'); - headers.append('Content-Transfer-Encoding', 'binary'); - return cache - .put( - `${fileName}.db`, - new Response(reqBufferDB, { - status: 200, - }) - ); - }); + const blob = new Blob([reqBufferDB]); + const response = new Response(blob) + caches.open('DB-file').then(cache => { + return cache.put(`/${fileName}.db`, response); + }) }, 'download-db' ); @@ -651,10 +680,11 @@ export class SpAiAnalysisPage extends BaseElement { this.isNodata = true; this.draftList!.innerHTML = ''; this.contentsTable!.style.display = 'none'; - let textStr = '服务异常'; + let textStr = '服务异常,请重新导trace!'; let imgsrc = 'img/no-report.png'; this.tipsContent!.style.display = 'none'; - this.abnormalPageTips(textStr, imgsrc, 0); + this.tipContentArr = ['detect']; + this.abnormalPageTips(textStr, imgsrc, 0, this.tipContentArr); this.draftBtn!.style.display = 'inline-block'; } if (this.isJsonString(jsonRes.resultMessage)) { @@ -667,9 +697,11 @@ export class SpAiAnalysisPage extends BaseElement { let textStr = '当前未诊断出问题'; let imgsrc = 'img/no-report.png'; this.tipsContent!.style.display = 'none'; - this.abnormalPageTips(textStr, imgsrc, 0); + this.tipContentArr = ['detect']; + this.abnormalPageTips(textStr, imgsrc, 0, this.tipContentArr); this.draftBtn!.style.display = 'inline-block'; } else { + this.tipContentArr = []; SpStatisticsHttpUtil.generalRecord('AI_statistic', 'large_model_detect', ['1']); this.isNodata = false; // 整理数据,渲染数据 @@ -679,6 +711,16 @@ export class SpAiAnalysisPage extends BaseElement { } } + // eventCallBack + eventCallBack = async (result: string) => { + this.draftList!.innerHTML = ''; + this.tipsContent!.style.display = 'flex'; + this.tipContentArr = ['detect']; + // @ts-ignore + this.abnormalPageTips(this.getStatusesPrompt()[result].prompt, '', 4000, ['detect']); + this.draftBtn!.style.display = 'inline-block'; + } + // 发起诊断 initiateDiagnosis(): void { let requestBodyObj = { @@ -719,6 +761,35 @@ export class SpAiAnalysisPage extends BaseElement { return true; } + // 获取提示语 + getStatusesPrompt(): unknown { + let guideSrc = `https://${window.location.host.split(':')[0]}:${window.location.port + }/application/?action=help_27`; + return { + unconnected: { + prompt: `未连接,请启动本地扩展程序再试![指导]` + },// 重连 + connected: { + prompt: '扩展程序连接中,请稍后再试!' + }, // 中间 + logined: { + prompt: '扩展程序连接中,请稍后再试!' + }, // 中间 + loginFailedByLackSession: { + prompt: '当前所有会话都在使用中,请释放一些会话再试!' + }, // 重连 + upgrading: { + prompt: '扩展程序连接中,请稍后再试!' + }, // 中间 + upgradeSuccess: { + prompt: '扩展程序已完成升级,重启中,请稍后再试!' + }, // 重连 + upgradeFailed: { + prompt: '刷新页面触发升级,或卸载扩展程序重装!' + },// 重连 + } + } + initHtml(): string { return SpAiAnalysisPageHtml; } diff --git a/ide/src/trace/component/SpRecordConfigModel.ts b/ide/src/trace/component/SpRecordConfigModel.ts index 01cb2789b1bd4be3f82dcbeb7e5e1bea036fb028..3c9703764a97cab02c57832731fba4a1b41aa63b 100644 --- a/ide/src/trace/component/SpRecordConfigModel.ts +++ b/ide/src/trace/component/SpRecordConfigModel.ts @@ -512,7 +512,7 @@ export function createNativePluginConfig( if (spAllocations!.appProcess !== '' && spAllocations!.startSamp) { let nativeConfig = initNativePluginConfig(spAllocations, selectVersion); let maxProcessSize = 4; - if (selectVersion !== undefined && selectVersion !== '3.2') { + if (selectVersion !== undefined && selectVersion !== '3.2' && selectVersion !=='unknown') { nativeConfig.callframeCompress = true; nativeConfig.recordAccurately = spAllocations!.record_accurately; nativeConfig.offlineSymbolization = spAllocations!.offline_symbolization; @@ -552,7 +552,7 @@ function initNativePluginConfig(spAllocations: SpAllocations, selectVersion: str let appProcess = spAllocations!.appProcess; let processName = ''; let processId = ''; - if (spAllocations!.startup_mode && selectVersion !== '3.2') { + if (spAllocations!.startup_mode && selectVersion !== '3.2'&& selectVersion !=='unknown') { processName = appProcess; } else { if (appProcess.indexOf('(') !== -1) { diff --git a/ide/src/trace/component/SpRecordTrace.ts b/ide/src/trace/component/SpRecordTrace.ts index 158bcd66d46bd3ae0775acd122cffe68923adac1..e428c237f1c41d03a7058217cd66384b6dca2bc1 100644 --- a/ide/src/trace/component/SpRecordTrace.ts +++ b/ide/src/trace/component/SpRecordTrace.ts @@ -81,7 +81,7 @@ export class SpRecordTrace extends BaseElement { public static selectVersion: string | null; public static isVscode = false; public static cancelRecord = false; - static supportVersions = ['3.2', '4.0+', '5.0+']; + static supportVersions = ['unknown','3.2', '4.0+', '5.0+']; public deviceSelect: HTMLSelectElement | undefined; public deviceVersion: HTMLSelectElement | undefined; private _menuItems: Array | undefined; @@ -196,10 +196,10 @@ export class SpRecordTrace extends BaseElement { let option = document.createElement('option'); option.className = 'select'; if (typeof dev.serialNumber === 'string') { - optionNum++; - option.value = dev.serialNumber; - option.textContent = dev!.serialNumber ? dev!.serialNumber!.toString() : 'hdc Device'; - this.deviceSelect!.appendChild(option); + optionNum++; + option.value = dev.serialNumber; + option.textContent = dev!.serialNumber ? dev!.serialNumber!.toString() : 'hdc Device'; + this.deviceSelect!.appendChild(option); if (dev.serialNumber === sn) { option.selected = true; this.recordButton!.hidden = false; @@ -501,7 +501,19 @@ export class SpRecordTrace extends BaseElement { // @ts-ignore HdcDeviceManager.findDevice().then((usbDevices): void => { log(usbDevices); - this.refreshDeviceList(usbDevices.serialNumber); + HdcDeviceManager.connect(usbDevices.serialNumber).then((res) => { + if (res) { + this.refreshDeviceList(usbDevices.serialNumber); + } else { + this.recordButton!.hidden = true; + this.disconnectButton!.hidden = true; + this.devicePrompt!.innerText = 'Device not connected'; + this.hintEl!.innerHTML = DEVICE_NOT_CONNECT; + if (!this.showHint) { + this.showHint = true; + } + } + }) }); } }; @@ -577,6 +589,7 @@ export class SpRecordTrace extends BaseElement { disconnectButtonClickEvent = (): void => { // --------------我修改的 + this.setDeviceVersionSelect('unknown') let index = this.deviceSelect!.selectedIndex; if (index !== -1 && this.deviceSelect!.options.length > 0) { for (let i = 0; i < this.deviceSelect!.options.length; i++) { @@ -648,7 +661,7 @@ export class SpRecordTrace extends BaseElement { private nativeMemoryHideBySelectVersion(): void { let divConfigs = this.spAllocations?.shadowRoot?.querySelectorAll('.version-controller'); if (divConfigs) { - if (SpRecordTrace.selectVersion !== '3.2') { + if (SpRecordTrace.selectVersion !== '3.2' && SpRecordTrace.selectVersion !=='unknown') { for (let divConfig of divConfigs) { divConfig!.style.zIndex = '1'; } @@ -669,11 +682,11 @@ export class SpRecordTrace extends BaseElement { SpRecordTrace.supportVersions.forEach((supportVersion) => { let option = document.createElement('option'); option.className = 'select'; - option.selected = supportVersion === '4.0+'; - option.textContent = `OpenHarmony-${supportVersion}`; + option.selected = supportVersion === 'unknown'; + option.textContent = supportVersion === 'unknown'? 'unknown' : `OpenHarmony-${supportVersion}`; option.setAttribute('device-version', supportVersion); this.deviceVersion!.append(option); - SpRecordTrace.selectVersion = '4.0+'; + SpRecordTrace.selectVersion = 'unknown'; this.nativeMemoryHideBySelectVersion(); }); } @@ -794,7 +807,7 @@ export class SpRecordTrace extends BaseElement { this.MenuItemEbpfHtml = th; } this.menuGroup!.appendChild(th); - if (item.title === 'Ark Ts') { + if (item.title === 'Ark Ts') { this.menuGroup!.removeChild(th); } }); @@ -901,7 +914,7 @@ export class SpRecordTrace extends BaseElement { this.buildMenuItem('Ark Ts', 'file-config', this.spArkTs!), this.buildMenuItem('FFRT', 'file-config', this.spFFRTConfig!), this.buildMenuItem('Hilog', 'realIntentionBulb', this.spHiLog!), - this.buildMenuItem('Xpower', 'externaltools', this.spXPower!), + this.buildMenuItem('Xpower', 'externaltools', this.spXPower!), ]; } diff --git a/ide/src/trace/component/SpSystemTrace.event.ts b/ide/src/trace/component/SpSystemTrace.event.ts index 60d590885880114f545c48289fcae3e1a4efb754..f86ac41f82063f6a984b0f88ae77ed9e0c40f98f 100644 --- a/ide/src/trace/component/SpSystemTrace.event.ts +++ b/ide/src/trace/component/SpSystemTrace.event.ts @@ -418,11 +418,7 @@ function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRo } }) .catch((e): void => { }); - // @ts-ignore - if (entry && entry.dur && (entry.startTime! || entry.startTs)) { - // @ts-ignore - SpAiAnalysisPage.selectChangeListener(entry.startTime || entry.startTs, (entry.startTime! || entry.startTs) + entry.dur); - } + SpAiAnalysisPage.selectChangeListener(TraceRow.range?.startNS!, TraceRow.range?.endNS!); } export default function spSystemTraceOnClickHandler( sp: SpSystemTrace, @@ -621,7 +617,6 @@ export function spSystemTraceDocumentOnMouseOut(sp: SpSystemTrace, ev: MouseEven } export function spSystemTraceDocumentOnKeyPress(this: unknown, sp: SpSystemTrace, ev: KeyboardEvent): void { - SpSystemTrace.isKeyUp = false; if (!sp.loadTraceCompleted || SpSystemTrace.isAiAsk) { return; } @@ -771,6 +766,10 @@ export function spSystemTraceDocumentOnMouseUp(sp: SpSystemTrace, ev: MouseEvent if (!sp.loadTraceCompleted || !sp.mouseEventEnable) { return; } + //@ts-ignore + if ((window as unknown).isSheetMove) { + return; + } if (sp.isWASDKeyPress()) { ev.preventDefault(); ev.stopPropagation(); @@ -786,10 +785,6 @@ export function spSystemTraceDocumentOnMouseUp(sp: SpSystemTrace, ev: MouseEvent } TraceRow.isUserInteraction = false; sp.rangeSelect.isMouseDown = false; - //@ts-ignore - if ((window as unknown).isSheetMove) { - return; - } if (sp.isMouseInSheet(ev)) { return; } @@ -804,7 +799,6 @@ export function spSystemTraceDocumentOnKeyUp(sp: SpSystemTrace, ev: KeyboardEven if (SpSystemTrace.isAiAsk) { return; } - SpSystemTrace.isKeyUp = true; if (sp.times.size > 0) { for (let timerId of sp.times) { clearTimeout(timerId); diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index ec193b177c6aac326e4ecc00cc536a291268abac..8a3481eedea6ac35c37d441b3d7037edf58144c5 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -154,7 +154,6 @@ type SlicesTimeAlias = SlicesTime | undefined | null; @element('sp-system-trace') export class SpSystemTrace extends BaseElement { mouseCurrentPosition = 0; - static isKeyUp: boolean = true; offsetMouse = 0; static isMouseLeftDown = false; static scrollViewWidth = 0; @@ -600,7 +599,7 @@ export class SpSystemTrace extends BaseElement { ) ); } - if (!TraceRow.rangeSelectObject && !this.isSlectStruct()) { + if (!TraceRow.rangeSelectObject) { SpAiAnalysisPage.selectChangeListener(TraceRow.range?.startNS!, TraceRow.range?.endNS!); } //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知 @@ -899,7 +898,7 @@ export class SpSystemTrace extends BaseElement { // @ts-ignore context!.moveTo(x0!, y0!); // @ts-ignore - if (SpSystemTrace.isKeyUp || curveDrawList.length < 90) { + if (curveDrawList.length < 90) { // @ts-ignore for (let i = 0; i < curveDrawList.length - 1; i++) { // @ts-ignore @@ -912,7 +911,7 @@ export class SpSystemTrace extends BaseElement { // @ts-ignore context.closePath(); // @ts-ignore - } else if (!SpSystemTrace.isKeyUp && curveDrawList.length >= 90) { + } else if (curveDrawList.length >= 90) { let x; let y; // @ts-ignore @@ -1106,7 +1105,7 @@ export class SpSystemTrace extends BaseElement { // 一直按着回车键的时候执行搜索功能 continueSearch = (ev: KeyboardEvent): void => { - if(!this.keyboardEnable){ + if (!this.keyboardEnable) { return; } if (ev.key === 'Enter') { @@ -1658,14 +1657,14 @@ export class SpSystemTrace extends BaseElement { let startParentRow = startRow ? this.shadowRoot?.querySelector>(`trace-row[row-id='${startRow.rowParentId}'][folder]`) : this.shadowRoot?.querySelector>( `trace-row[row-id='${pid}'][folder]` ); - if (startParentRow && startParentRow.expansion){ - let filterRow = startParentRow?.childrenList.filter((item)=>item.rowId === tid)[0]; - !filterRow && startParentRow?.childrenList.forEach((i)=>{ - if(i.rowId === 'sameThreadProcess'){// @ts-ignore - filterRow = startParentRow?.childrenList.concat(i.childrenList).filter((item)=>item.rowId === String(tid))[0]; + if (startParentRow && startParentRow.expansion) { + let filterRow = startParentRow?.childrenList.filter((item) => item.rowId === tid)[0]; + !filterRow && startParentRow?.childrenList.forEach((i) => { + if (i.rowId === 'sameThreadProcess') {// @ts-ignore + filterRow = startParentRow?.childrenList.concat(i.childrenList).filter((item) => item.rowId === String(tid))[0]; // @ts-ignore startParentRow = filterRow!.parentRowEl!; - } + } }); } const expansionFlag = this.collectionHasThread(startRow); diff --git a/ide/src/trace/component/chart/SpPerfOutputDataChart.ts b/ide/src/trace/component/chart/SpPerfOutputDataChart.ts index 5a3f79c2077f95478b05e6ed6998ac49d7b54d03..5c2330c68942315458f938a9c3616e3fd8cc3f9f 100644 --- a/ide/src/trace/component/chart/SpPerfOutputDataChart.ts +++ b/ide/src/trace/component/chart/SpPerfOutputDataChart.ts @@ -44,7 +44,7 @@ export class SpPerfOutputDataChart { this.dur = 3000000000; } // @ts-ignore - this.perfOutputArr = perfOutputData[0].name.split(':')[2].split(','); + this.perfOutputArr = perfOutputData[0].name.includes(':') ? perfOutputData[0].name.split(':')[2].includes(',') ? perfOutputData[0].name.split(':')[2].split(',') : [] : []; // @ts-ignore let endTime: number = perfOutputData[0].ts; this.startTime = endTime - window.recordStartNS - this.dur!; diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index aae578e1b8f9c65d5dbbc7c644344a626b7357f1..0dbe92d48bf6dfc88a4df968fa6f5ddecc3f9691 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -95,6 +95,20 @@ import { PerfToolStruct } from '../../../database/ui-worker/ProcedureWorkerPerfT import { GpuCounterStruct } from '../../../database/ui-worker/ProcedureWorkerGpuCounter'; import { TabPaneGpuCounter } from '../sheet/gpu-counter/TabPaneGpuCounter'; import { TabPaneSliceChild } from '../sheet/process/TabPaneSliceChild'; +import { TabPerfFuncAsm } from '../sheet/hiperf/TabPerfFuncAsm'; +import { XpowerStatisticStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerStatistic'; +import { XpowerAppDetailStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerAppDetail'; +import { XpowerWifiStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerWifi'; +import { TabPaneXpowerStatisticCurrentData } from '../sheet/xpower/TabPaneXpowerStatisticCurrentData'; +import { XpowerThreadInfoStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerThreadInfo'; +import { TabPaneXpowerThreadInfoSelection } from '../sheet/xpower/TabPaneXpowerThreadInfoSelection'; +import { TabPaneXpowerGpuFreqSelection } from '../sheet/xpower/TabPaneXpowerGpuFreqSelection'; +import { XpowerGpuFreqStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerGpuFreq'; +import {WebSocketManager} from "../../../../webSocket/WebSocketManager"; +import {Constants, TypeConstants} from "../../../../webSocket/Constants"; +import { PerfFunctionAsmParam } from '../../../bean/PerfAnalysis'; +import { info,error } from '../../../../log/Log'; + @element('trace-sheet') export class TraceSheet extends BaseElement { @@ -119,6 +133,9 @@ export class TraceSheet extends BaseElement { private optionsDiv: LitPopover | undefined | null; private optionsSettingTree: LitTree | undefined | null; private tabPaneHeight: string = ''; + private enc = new TextEncoder(); + private dec = new TextDecoder(); + private REQ_BUF_SIZE = 1024 * 1024; static get observedAttributes(): string[] { return ['mode']; @@ -207,17 +224,22 @@ export class TraceSheet extends BaseElement { this.perfAnalysisListener(evt); }); // @ts-ignore + this.getComponentByID('box-perf-analysis')?.addFunctionRowClickEventListener(this.functionAnalysisListener.bind(this)); + // @ts-ignore this.getComponentByID('box-native-statistic-analysis')?.addEventListener('row-click', (e: MouseEvent) => { this.nativeAnalysisListener(e); }); // @ts-ignore - this.getComponentByID('box-io-tier-statistics-analysis')?.addEventListener('row-click', (evt: MouseEvent) => { - // @ts-ignore - if (evt.detail.button === 2 && evt.detail.tableName) { - let pane = this.getPaneByID('box-io-calltree'); - this.litTabs!.activeByKey(pane.key); + this.getComponentByID('box-io-tier-statistics-analysis')?.addEventListener( + 'row-click', + (evt: MouseEvent) => { + // @ts-ignore + if (evt.detail.button === 2 && evt.detail.tableName) { + let pane = this.getPaneByID('box-io-calltree'); + this.litTabs!.activeByKey(pane.key); + } } - }); + ); // @ts-ignore this.getComponentByID('box-virtual-memory-statistics-analysis')?.addEventListener( 'row-click', @@ -269,7 +291,7 @@ export class TraceSheet extends BaseElement { }); // @ts-ignore this.getComponentByID('box-thread-states')?.addEventListener('td-click', (evt: unknown) => { - this.tdClickHandler(evt); + this.tdClickHandler(evt, false); }); // @ts-ignore this.getComponentByID('box-slices')?.addEventListener('td-click', (evt: unknown) => { @@ -285,6 +307,29 @@ export class TraceSheet extends BaseElement { } } + private functionAnalysisListener(evt: unknown, vaddrList: Array): void { + // @ts-ignore + this.currentPaneID = "box-perf-analysis"; + //隐藏除了当前Tab页的其他Tab页 + this.shadowRoot!.querySelectorAll("lit-tabpane").forEach( + (it): boolean => + it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false) + ); + let pane = this.getPaneByID("tab-perf-func-asm"); //通过Id找到需要展示的Tab页 + pane.closeable = true; + pane.hidden = false; + // @ts-ignore + pane.tab = evt.tableName; //设置Tab页标题 + let param = new PerfFunctionAsmParam(); + param.vaddrList = vaddrList; + // @ts-ignore + param.functionName = evt.tableName; + // @ts-ignore + param.totalCount = evt.count; + (pane.children.item(0) as TabPerfFuncAsm)!.data = param; + this.litTabs!.activeByKey(pane.key); //显示key值(sheetconfig里面对应的index是一个数字)对应的Tab页 + } + private nativeAnalysisListener(e: MouseEvent): void { //@ts-ignore if (e.detail.button === 2 && e.detail.tableName) { @@ -385,17 +430,19 @@ export class TraceSheet extends BaseElement { this.initNavElements(tabsPackUp!, borderTop, initialHeight); this.exportBt = this.shadowRoot?.querySelector('#export-btn'); tabsOpenUp!.onclick = (): void => { - this.tabs!.style.height = `${window.innerHeight - this.search!.offsetHeight - this.timerShaft!.offsetHeight - borderTop - }px`; + this.tabs!.style.height = `${ + window.innerHeight - this.search!.offsetHeight - this.timerShaft!.offsetHeight - borderTop + }px`; let litTabpane: NodeListOf | undefined | null = this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane'); litTabpane!.forEach((node: HTMLDivElement): void => { - node!.style.height = `${window.innerHeight - + node!.style.height = `${ + window.innerHeight - this.search!.offsetHeight - this.timerShaft!.offsetHeight - this.navRoot!.offsetHeight - borderTop - }px`; + }px`; initialHeight.node = node!.style.height; }); initialHeight.tabs = this.tabs!.style.height; @@ -427,9 +474,6 @@ export class TraceSheet extends BaseElement { let that = this; // 节点挂载时给Tab面板绑定鼠标按下事件 this.nav!.onmousedown = (event): void => { - if (SpSystemTrace.isKeyUp === false) { - return; - } // @ts-ignore (window as unknown).isSheetMove = true; // 获取所有标签页的节点数组 @@ -494,7 +538,7 @@ export class TraceSheet extends BaseElement { // 只要没有移动到边界区域都会进入该条件 that.navRoot!.offsetHeight <= newHeight && that.search!.offsetHeight + that.timerShaft!.offsetHeight + borderTop + that.spacer!.offsetHeight <= - window.innerHeight - newHeight + window.innerHeight - newHeight ) { that.tabs!.style.height = `${newHeight}px`; litTabpane!.style.height = `${newHeight - that.navRoot!.offsetHeight}px`; @@ -509,19 +553,21 @@ export class TraceSheet extends BaseElement { window.innerHeight - newHeight ) { // 该条件在面板高度置顶时触发 - that.tabs!.style.height = `${window.innerHeight - + that.tabs!.style.height = `${ + window.innerHeight - that.search!.offsetHeight - that.timerShaft!.offsetHeight - borderTop - that.spacer!.offsetHeight - }px`; - litTabpane!.style.height = `${window.innerHeight - + }px`; + litTabpane!.style.height = `${ + window.innerHeight - that.search!.offsetHeight - that.timerShaft!.offsetHeight - that.navRoot!.offsetHeight - borderTop - that.spacer!.offsetHeight - }px`; + }px`; tabsPackUp!.name = 'down'; } that.tabPaneHeight = litTabpane!.style.height; @@ -535,7 +581,7 @@ export class TraceSheet extends BaseElement { private importClickEvent(): void { let importFileBt: HTMLInputElement | undefined | null = - this.shadowRoot?.querySelector('#import-file'); + this.shadowRoot?.querySelector('#import-file'); importFileBt!.addEventListener('change', (event): void => { let files = importFileBt?.files; if (files) { @@ -546,30 +592,127 @@ export class TraceSheet extends BaseElement { if (fileList.length > 0) { importFileBt!.disabled = true; window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Import So File' }); - threadPool.submit( - 'upload-so', - '', - fileList, - (res: unknown) => { - importFileBt!.disabled = false; // @ts-ignore - if (res.result === 'ok') { - window.publish(window.SmartEvent.UI.UploadSOFile, {}); - } else { - // @ts-ignore - const failedList = res.failedArray.join(','); - window.publish(window.SmartEvent.UI.Error, `parse so file ${failedList} failed!`); - } - }, - 'upload-so' - ); + this.uploadSoOrAN(fileList).then(r => + threadPool.submit( + 'upload-so', + '', + fileList, + (res: unknown) => { + importFileBt!.disabled = false; // @ts-ignore + if (res.result === 'ok') { + window.publish(window.SmartEvent.UI.UploadSOFile, {}); + } else { + // @ts-ignore + const failedList = res.failedArray.join(','); + window.publish(window.SmartEvent.UI.Error, `parse so file ${failedList} failed!`); + } + }, + 'upload-so' + )).finally(() => { + fileList.length = 0; + }) } - fileList.length = 0; } importFileBt!.files = null; importFileBt!.value = ''; }); } + private async uploadSoOrAN(fileList: Array): Promise { + if (fileList) { + fileList.sort((a, b) => b.size - a.size); + await this.uploadAllFiles(fileList); + } + } + + + // 上传文件 + private async uploadAllFiles(fileList: Array): Promise { + // 创建一个副本,避免修改原始的 fileList + const filesToUpload = [...fileList]; + + for (let i = 0; i < filesToUpload.length; i++) { + const file = filesToUpload[i]; + try { + await this.uploadSingleFile(file); + info(`File ${file.name} uploaded successfully.`); + } catch (err) { + error(`Failed to upload file: ${file.name}, error: `, err); + } + } + info(`All files have been uploaded.`); + } + + + private uploadSingleFile = async (file: File | null): Promise => { + if (file) { + let writeSize = 0; + let wsInstance = WebSocketManager.getInstance(); + const fileName = file.name; + let bufferIndex = 0; + + // 定义一个 ACK 回调函数的等待机制 + const waitForAck = (): Promise => { + return new Promise((resolve, reject) => { + wsInstance!.registerCallback(TypeConstants.DISASSEMBLY_TYPE, onAckReceived); + // 定义超时定时器 + const timeout = setTimeout(() => { + // 超时后注销回调并拒绝 Promise + wsInstance!.unregisterCallback(TypeConstants.DISASSEMBLY_TYPE, onAckReceived); + reject(new Error('等待 ACK 超时:文件 ${fileName},索引 ${bufferIndex})')); + }, 10000); + function onAckReceived(cmd: number, result: Uint8Array) { + const decoder = new TextDecoder(); + const jsonString = decoder.decode(result); + let jsonRes = JSON.parse(jsonString); + if (cmd === Constants.DISASSEMBLY_SAVE_BACK_CMD) { + if (jsonRes.fileName === fileName && jsonRes.bufferIndex === bufferIndex) { + wsInstance!.unregisterCallback(TypeConstants.DISASSEMBLY_TYPE, onAckReceived) + clearTimeout(timeout); + if (jsonRes.resultCode == 0) { + bufferIndex++; + // 当收到对应分片的 ACK 时,resolve Promise,继续上传下一个分片 + resolve(); + }else{ + // 上传失败,拒绝 Promise 并返回 + reject(new Error(`Upload failed for file: ${fileName}, index: ${jsonRes.bufferIndex})`)); + } + } + } + } + }); + }; + + while (writeSize < file.size) { + let sliceLen = Math.min(file.size - writeSize, this.REQ_BUF_SIZE); + let blob: Blob | null = file.slice(writeSize, writeSize + sliceLen); + let buffer: ArrayBuffer | null = await blob.arrayBuffer(); + let data: Uint8Array | null = new Uint8Array(buffer); + + const dataObject = { + file_name: fileName, + buffer_index: bufferIndex, + buffer_size: sliceLen, + total_size: file.size, + is_last: writeSize + sliceLen >= file.size, + buffer: Array.from(data), + }; + + + const dataString = JSON.stringify(dataObject); + const textEncoder = new TextEncoder(); + const encodedData = textEncoder.encode(dataString); + wsInstance!.sendMessage(TypeConstants.DISASSEMBLY_TYPE, Constants.DISASSEMBLY_SAVE_CMD, encodedData); + writeSize += sliceLen; + // 等待服务器端确认当前分片的 ACK + await waitForAck(); + data = null; + buffer = null; + blob = null; + } + } + }; + private exportClickEvent(): void { this.exportBt!.onclick = (): void => { let currentTab = this.getTabpaneByKey(this.litTabs?.activekey!); @@ -580,7 +723,17 @@ export class TraceSheet extends BaseElement { let table2 = Array.from( (currentTab.firstChild as BaseElement).shadowRoot?.querySelectorAll('lit-table') || [] ); - let tables = [...table1, ...table2]; + let componentTopTable = undefined; + if ( + (currentTab.firstChild as BaseElement).shadowRoot?.querySelector('#tb-counter') && + ((currentTab.firstChild as BaseElement).shadowRoot?.querySelector('#tb-counter')?.firstChild as BaseElement) + ) { + componentTopTable = ((currentTab.firstChild as BaseElement).shadowRoot?.querySelector('#tb-counter') + ?.firstChild as BaseElement)!.shadowRoot?.querySelectorAll('lit-table'); + } + + let table3 = Array.from(componentTopTable || []); + let tables = [...table1, ...table2, ...table3]; for (let table of tables) { if (!table.hasAttribute('hideDownload')) { @@ -683,11 +836,30 @@ export class TraceSheet extends BaseElement { this.displayTab('current-selection').setHangData(data, sp, scrollCallback); displayClockData = (data: ClockStruct): Promise => this.displayTab('current-selection').setClockData(data); - displayDmaFenceData = (data: DmaFenceStruct, rowData: unknown): void =>//展示tab页内容 + displayDmaFenceData = ( + data: DmaFenceStruct, + rowData: unknown + ): void => //展示tab页内容 // @ts-ignore this.displayTab('current-selection').setDmaFenceData(data, rowData); displayXpowerData = (data: XpowerStruct): Promise => this.displayTab('current-selection').setXpowerData(data); + displayXpowerDisplayData = (data: XpowerAppDetailStruct): Promise => + this.displayTab('current-selection').setXpowerDisplayData(data); + displayXpowerWifiPacketsData = (data: XpowerWifiStruct): Promise => + this.displayTab('current-selection').setXpowerWifiPacketsData(data); + displayXpowerBytesWifiData = (data: XpowerWifiStruct): Promise => + this.displayTab('current-selection').setXpowerWifiBytesData(data); + displayXpowerStatisticData = (data: XpowerStatisticStruct): void => + this.displayTab( + 'box-xpower-statistic-current-data' + ).setXpowerStatisticCurrentData(data); + displayXpowerThreadInfoData = (dataList: Array): void => { + this.displayTab('box-xpower-thread-info-selection').setThreadInfoData(dataList); + }; + displayXpowerGpuFreqData = (dataList: Array): void => { + this.displayTab('box-xpower-gpu-freq-selection').setGpuFreqData(dataList); + }; displayPerfToolsData = (data: PerfToolStruct): void => this.displayTab('current-selection').setPerfToolsData(data); displayIrqData = (data: IrqStruct): void => @@ -728,9 +900,15 @@ export class TraceSheet extends BaseElement { data: FuncStruct, scrollCallback: Function, callback?: (data: Array, str: string, binderTid: number) => void, - distributedCallback?: (dataList: FuncStruct[]) => void, + distributedCallback?: (dataList: FuncStruct[]) => void ): Promise => - this.displayTab(...names).setFunctionData(data, threadName, scrollCallback, callback, distributedCallback); + this.displayTab(...names).setFunctionData( + data, + threadName, + scrollCallback, + callback, + distributedCallback + ); displayCpuData = ( data: CpuStruct, callback: ((data: WakeupBean | null) => void) | undefined = undefined, @@ -932,10 +1110,9 @@ export class TraceSheet extends BaseElement { ]; }; displayUserPlugin = (selectData: unknown): void => { - this.displayTab("tab-pane-userplugin").data = selectData; + this.displayTab('tab-pane-userplugin').data = selectData; }; - displayGpuCounterData = (data: GpuCounterStruct): void => { this.displayTab('box-gpu-counter').data = data; }; @@ -1126,32 +1303,32 @@ export class TraceSheet extends BaseElement { window.publish(window.SmartEvent.UI.ShowBottomTab, { show: show, delta: delta }); } - tdClickHandler(e: unknown): void { + tdClickHandler(e: unknown, isDependCpu?: boolean): void { // @ts-ignore this.currentPaneID = e.target.parentElement.id; //隐藏除了当前Tab页的其他Tab页 this.shadowRoot!.querySelectorAll('lit-tabpane').forEach((it): boolean => it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false) - );//todo:看能不能优化 - let pane = this.getPaneByID('box-cpu-child');//通过Id找到需要展示的Tab页 - pane.closeable = true;//关闭的ican显示 + ); //todo:看能不能优化 + let pane = this.getPaneByID('box-cpu-child'); //通过Id找到需要展示的Tab页 + pane.closeable = true; //关闭的ican显示 pane.hidden = false; this.litTabs!.activeByKey(pane.key); //显示key值对应的Tab页 // @ts-ignore - pane.tab = e.detail.tabTitle ? e.detail.tabTitle : Utils.transferPTSTitle(e.detail.title);//设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串 + pane.tab = e.detail.tabTitle ? e.detail.tabTitle : Utils.transferPTSTitle(e.detail.title); //设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串 let param = new BoxJumpParam(); param.traceId = this.selection!.traceId; param.leftNs = this.selection!.leftNs; param.rightNs = this.selection!.rightNs; - param.cpus = this.selection!.cpus; + param.cpus = isDependCpu ? this.selection!.cpus : []; // @ts-ignore param.state = e.detail.summary ? '' : e.detail.state; // @ts-ignore param.processId = e.detail.summary ? this.selection.processIds : e.detail.pid; // @ts-ignore param.threadId = e.detail.summary ? this.selection.threadIds : e.detail.tid; - param.isJumpPage = true;// @ts-ignore - param.currentId = e.target.parentElement.id;//根据父Tab页的标题,确认子Tab页的dur是否需要处理 + param.isJumpPage = true; // @ts-ignore + param.currentId = e.target.parentElement.id; //根据父Tab页的标题,确认子Tab页的dur是否需要处理 (pane.children.item(0) as TabPaneBoxChild).data = param; } @@ -1163,20 +1340,20 @@ export class TraceSheet extends BaseElement { this.shadowRoot!.querySelectorAll('lit-tabpane').forEach((it): boolean => it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false) ); - let pane = this.getPaneByID('box-slice-child');//通过Id找到需要展示的Tab页 + let pane = this.getPaneByID('box-slice-child'); //通过Id找到需要展示的Tab页 pane.closeable = true; pane.hidden = false; this.litTabs!.activeByKey(pane.key); //显示key值(sheetconfig里面对应的index是一个数字)对应的Tab页 // @ts-ignore - pane.tab = e.detail.tabTitle;//设置Tab页标题 + pane.tab = e.detail.tabTitle; //设置Tab页标题 let param = new SliceBoxJumpParam(); param.traceId = this.selection!.traceId; param.leftNs = this.selection!.leftNs; param.rightNs = this.selection!.rightNs; param.processId = this.selection!.processIds; - param.threadId = this.selection!.funTids;//@ts-ignore2 - param.name = e.detail.allName ? e.detail.allName : [e.detail.name];//@ts-ignore2 - param.isJumpPage = true;// @ts-ignore + param.threadId = this.selection!.funTids; //@ts-ignore2 + param.name = e.detail.allName ? e.detail.allName : [e.detail.name]; //@ts-ignore2 + param.isJumpPage = true; // @ts-ignore param.isSummary = e.detail.allName ? true : false; (pane.children.item(0) as TabPaneSliceChild).data = { param: param, selection: this.selection }; } diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index f1d1af535ec72fc69aaa0d005bbdf98d010094f1..b948e0e7bc45a7a343135a4ce6881fd6a00c2284 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -127,9 +127,6 @@ import { TabPaneHiSysEventSummary } from '../sheet/hisysevent/TabPaneHiSysEventS import { TabPaneBinders } from '../sheet/binder/TabPaneBinders'; import { TabPaneGpufreq } from '../sheet/gpufreq/TabPaneGpufreqUsage'; import { TabPaneSampleInstruction } from '../sheet/bpftrace/TabPaneSampleInstruction'; -import { TabPaneSampleInstructionDistributions } from '../sheet/bpftrace/TabPaneSampleInstructionDistributions'; -import { TabPaneSampleInstructionTotalTime } from '../sheet/bpftrace/TabPaneSampleInstructionSelectionTotalTime'; -import { TabPaneSampleInstructionSelection } from '../sheet/bpftrace/TabPaneSampleInstructionSelection'; import { TabPaneDataCut } from '../sheet/TabPaneDataCut'; import { TabPaneGpuCounterSelection } from '../sheet/gpu-counter/TabPaneGpuCounterSelection'; import { TabPaneGpuCounter } from '../sheet/gpu-counter/TabPaneGpuCounter'; @@ -139,6 +136,7 @@ import { TabPanePerfAsync } from '../sheet/hiperf/TabPerfAsyncList'; import { TabPaneUserPlugin } from '../sheet/userPlugin/TabPaneUserPlugin'; import { TabPaneDmaFence } from '../sheet/dma-fence/TabPaneDmaFenceSelect'; import { TabPaneSliceChild } from '../sheet/process/TabPaneSliceChild'; +import { TabPerfFuncAsm } from '../sheet/hiperf/TabPerfFuncAsm' export let tabConfig: { [key: string]: { @@ -699,21 +697,6 @@ export let tabConfig: { require: (param: SelectionParam) => param.threadIds.length > 0 || (param.clockMapData.size > 0 && param.clockMapData.has('gpufreq Frequency') === true), }, - 'box-sample-instruction-selection': { - title: 'Data Selection', - type: TabPaneSampleInstructionSelection, - require: (param: SelectionParam) => param.sampleData.length > 0, - }, - 'box-sample-instruction-distribution-selection': { - title: 'Data Distribution', - type: TabPaneSampleInstructionDistributions, - require: (param: SelectionParam) => param.sampleData.length > 0, - }, - 'box-sample-instruction-totaltime-selection': { - title: 'Total Duration', - type: TabPaneSampleInstructionTotalTime, - require: (param: SelectionParam) => param.sampleData.length > 0, - }, 'box-sample-instruction': { title: 'Data Flow', type: TabPaneSampleInstruction, @@ -750,4 +733,8 @@ export let tabConfig: { title: '', type: TabPaneSliceChild, }, + 'tab-perf-func-asm': { + title: '', + type: TabPerfFuncAsm, + } }; diff --git a/ide/src/trace/component/trace/search/Search.ts b/ide/src/trace/component/trace/search/Search.ts index 03c14b4251aabae0c5002551266fa3dbc9bb33b2..517c8df9d2e44bf3cc0bc944bac41ae54126e893 100644 --- a/ide/src/trace/component/trace/search/Search.ts +++ b/ide/src/trace/component/trace/search/Search.ts @@ -248,18 +248,15 @@ export class LitSearch extends BaseElement { this.searchBlurListener(); }); this.search!.addEventListener('keyup', (e: KeyboardEvent) => { - SpSystemTrace.isKeyUp = true; this._retarge_index!.value = ''; this.searchKeyupListener(e); }); //阻止事件冒泡 this.search!.addEventListener('keydown', (e: KeyboardEvent) => { - SpSystemTrace.isKeyUp = false; e.stopPropagation(); }); this.search!.addEventListener('keypress', (e: KeyboardEvent) => { - SpSystemTrace.isKeyUp = false; e.stopPropagation(); }); this.shadowRoot?.querySelector('#arrow-left')?.addEventListener('click', (): void => { @@ -283,12 +280,10 @@ export class LitSearch extends BaseElement { this.keyUpListener(); //阻止事件冒泡 this.shadowRoot?.querySelector("input[name='retarge_index']")?.addEventListener('keydown', (e: unknown) => { - SpSystemTrace.isKeyUp = false; // @ts-ignore e.stopPropagation(); }); this.shadowRoot?.querySelector("input[name='retarge_index']")?.addEventListener('keypress', (e: unknown) => { - SpSystemTrace.isKeyUp = false; // @ts-ignore e.stopPropagation(); }); @@ -359,7 +354,6 @@ export class LitSearch extends BaseElement { this._retarge_index!.value = ''; }, 2000); } - SpSystemTrace.isKeyUp = true; // @ts-ignore e.target.blur(); } diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrent.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrent.ts index 414e019954bb51418f3ac970fc3b7a17989bd8cb..54762cc97657fa4d4dfbb6a4c08e32657bad9c6e 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrent.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrent.ts @@ -210,7 +210,6 @@ export class TabPaneCurrent extends BaseElement { tr[i].querySelector('#text-input')!.value = this.slicesTimeList[i - 1].text; // // 点击色块修改颜色 tr[i].querySelector('#text-input')?.addEventListener('keyup', (event: unknown) => { - SpSystemTrace.isKeyUp = true; if ( // @ts-ignore this.tableDataSource[i].startTime === this.slicesTimeList[i - 1].startTime && diff --git a/ide/src/trace/component/trace/sheet/TabPaneFilter.ts b/ide/src/trace/component/trace/sheet/TabPaneFilter.ts index 65238dded8f956fbfa29465fc563c8f88c0e8406..161ce9adf3a85b502d606fd89aa969d629155782 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneFilter.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneFilter.ts @@ -403,7 +403,7 @@ export class TabPaneFilter extends BaseElement { if (thirdList) { this.setAttribute('third', ''); } - thtml += ``; + thtml += `` if (thirdList) { if (thirdTitle !== '') { thtml += `${thirdTitle}`; @@ -714,7 +714,6 @@ export class TabPaneFilter extends BaseElement { this.value = this.value.replace(/\D/g, ''); }; e.addEventListener('keyup', (event: unknown): void => { - SpSystemTrace.isKeyUp = true; // @ts-ignore event.stopPropagation(); // @ts-ignore diff --git a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionDistributions.ts b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionDistributions.ts deleted file mode 100644 index ef58348a3bd6b0a674a8410688370001152b9626..0000000000000000000000000000000000000000 --- a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionDistributions.ts +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { BaseElement, element } from '../../../../../base-ui/BaseElement'; -import { SelectionParam } from '../../../../bean/BoxSelection'; -import { debounce } from '../../../Utils'; -const paddingLeft = 100; -const paddingBottom = 15; -const xStep = 50; // x轴间距 -const barWidth = 2; // 柱子宽度 - -@element('tab-sample-instructions-distrubtions-chart') -export class TabPaneSampleInstructionDistributions extends BaseElement { - private instructionChartEle: HTMLCanvasElement | undefined | null; - private ctx: CanvasRenderingContext2D | undefined | null; - private onReadableData: Array = []; - private hintContent = ''; //悬浮框内容 - private floatHint!: HTMLDivElement | undefined | null; //悬浮框 - private canvasScrollTop = 0; // tab页上下滚动位置 - private isUpdateCanvas = false; - private cacheData: Array = []; - private canvasX = -1; // 鼠标当前所在画布x坐标 - private canvasY = -1; // 鼠标当前所在画布y坐标 - private startX = 0; // 画布相对于整个界面的x坐标 - private startY = 0; // 画布相对于整个界面的y坐标 - private hoverBar: unknown; - private isChecked: boolean = false; - private xCount = 0; //x轴刻度个数 - private xMaxValue = 0; //x轴上数据最大值 - private xSpacing = 50; //x轴间距 - private xAvg = 0; //根据xMaxValue进行划分 用于x轴上刻度显示 - private yAvg = 0; //根据yMaxValue进行划分 用于y轴上刻度显示 - - initHtml(): string { - return ` - - -
- `; - } - - initElements(): void { - this.instructionChartEle = this.shadowRoot?.querySelector('#instruct-chart-canvas'); - this.ctx = this.instructionChartEle?.getContext('2d'); - this.floatHint = this.shadowRoot?.querySelector('#float_hint'); - } - - set data(SampleParam: SelectionParam) { - // @ts-ignore - this.onReadableData = SampleParam.sampleData[0].property; - this.calInstructionRangeCount(this.isChecked); - } - - connectedCallback(): void { - super.connectedCallback(); - this.parentElement!.onscroll = () => { - this.canvasScrollTop = this.parentElement!.scrollTop; - this.hideTip(); - }; - this.instructionChartEle!.onmousemove = (e): void => { - if (!this.isUpdateCanvas) { - this.updateCanvasCoord(); - } - this.canvasX = e.clientX - this.startX; - this.canvasY = e.clientY - this.startY + this.canvasScrollTop; - this.onMouseMove(); - }; - this.instructionChartEle!.onmouseleave = () => { - this.hideTip(); - }; - document.addEventListener('sample-popver-change', (e: unknown) => { - // @ts-ignore - const select = Number(e.detail.select); - this.isChecked = Boolean(select); - this.calInstructionRangeCount(this.isChecked); - }); - this.listenerResize(); - } - - /** - * 更新canvas坐标 - */ - updateCanvasCoord(): void { - if (this.instructionChartEle instanceof HTMLCanvasElement) { - this.isUpdateCanvas = this.instructionChartEle.clientWidth !== 0; - if (this.instructionChartEle.getBoundingClientRect()) { - const box = this.instructionChartEle.getBoundingClientRect(); - const D = this.parentElement!; - this.startX = box.left + Math.max(D.scrollLeft, document.body.scrollLeft) - D.clientLeft; - this.startY = box.top + Math.max(D.scrollTop, document.body.scrollTop) - D.clientTop + this.canvasScrollTop; - } - } - } - - /** - * 获取鼠标悬停的函数 - * @param nodes - * @param canvasX - * @param canvasY - * @returns - */ - searchDataByCoord(nodes: unknown, canvasX: number, canvasY: number): void | null { - // @ts-ignore - for (let i = 0; i < nodes.length; i++) { - // @ts-ignore - const element = nodes[i]; - if (this.isContains(element, canvasX, canvasY)) { - return element; - } - } - return null; - } - - /** - * 鼠标移动 - */ - onMouseMove(): void { - const lastNode = this.hoverBar; - //查找鼠标所在的node - const searchResult = this.searchDataByCoord(this.cacheData, this.canvasX, this.canvasY); - if (searchResult) { - this.hoverBar = searchResult; - //鼠标悬浮的node未改变则不需重新渲染文字 - if (searchResult !== lastNode) { - this.updateTipContent(); - } - this.showTip(); - } else { - this.hideTip(); - this.hoverBar = undefined; - } - } - - /** - * 隐藏悬浮框 - */ - hideTip(): void { - if (this.floatHint) { - this.floatHint.style.display = 'none'; - this.instructionChartEle!.style.cursor = 'default'; - } - } - - /** - * 显示悬浮框 - */ - showTip(): void { - this.floatHint!.innerHTML = this.hintContent; - this.floatHint!.style.display = 'block'; - this.instructionChartEle!.style.cursor = 'pointer'; - let x = this.canvasX; - let y = this.canvasY - this.canvasScrollTop; - //右边的函数悬浮框显示在左侧 - if (this.canvasX + this.floatHint!.clientWidth > (this.instructionChartEle!.clientWidth || 0)) { - x -= this.floatHint!.clientWidth - 1; - } else { - x += 20; - } - //最下边的函数悬浮框显示在上方 - y -= this.floatHint!.clientHeight - 1; - this.floatHint!.style.transform = `translate(${x}px, ${y}px)`; - } - - /** - * 更新悬浮框内容 - * @returns - */ - updateTipContent(): void { - const hoverNode = this.hoverBar; - if (!hoverNode) { - return; - } - const detail = hoverNode!; - this.hintContent = ` - ${ - // @ts-ignore - detail.instruct}
- ${ - // @ts-ignore - parseFloat(detail.heightPer)} - `; - } - - /** - * 判断鼠标当前在那个函数上 - * @param frame - * @param x - * @param y - * @returns - */ - isContains(point: unknown, x: number, y: number): boolean { - // @ts-ignore - return x >= point.x && x <= point.x + 2 && point.y <= y && y <= point.y + point.height; - } - - /** - * 统计onReadable数据各指令的个数 - * @param isCycles - */ - calInstructionRangeCount(isCycles: boolean) { - if (this.onReadableData.length === 0) return; - this.cacheData.length = 0; - const count = this.onReadableData.length; - let instructions = {}; - if (isCycles) { - // @ts-ignore - instructions = this.onReadableData.reduce((pre: unknown, current: unknown) => { - // @ts-ignore - (pre[`${Math.ceil(current.cycles)}`] = pre[`${Math.ceil(current.cycles)}`] || []).push(current); - return pre; - }, {}); - } else { - // @ts-ignore - instructions = this.onReadableData.reduce((pre: unknown, current: unknown) => { - // @ts-ignore - (pre[`${Math.ceil(current.instructions)}`] = pre[`${Math.ceil(current.instructions)}`] || []).push(current); - return pre; - }, {}); - } - this.ctx!.clearRect(0, 0, this.instructionChartEle!.width, this.instructionChartEle!.height); - this.instructionChartEle!.width = this.clientWidth; - - this.xMaxValue = - Object.keys(instructions) - .map((i) => Number(i)) - .reduce((pre, cur) => Math.max(pre, cur), 0) + 10; - const yMaxValue = Object.values(instructions).reduce( - // @ts-ignore - (pre: number, cur: unknown) => Math.max(pre, Number((cur.length / count).toFixed(2))), - 0 - ); - this.yAvg = Number(((yMaxValue / 5) * 1.5).toFixed(2)) || yMaxValue; - const height = this.instructionChartEle!.height; - const width = this.instructionChartEle!.width; - this.drawLineLabelMarkers(width, height, isCycles); - this.drawBar(instructions, height, count); - } - - /** - * 绘制柱状图 - * @param instructionData - * @param height - * @param count - */ - drawBar(instructionData: unknown, height: number, count: number): void { - const yTotal = Number((this.yAvg * 5).toFixed(2)); - const interval = Math.floor((height - paddingBottom) / 6); - // @ts-ignore - for (const x in instructionData) { - const xNum = Number(x); - const xPosition = xStep + (xNum / (this.xCount * this.xAvg)) * (this.xCount * this.xSpacing) - barWidth / 2; - // @ts-ignore - const yNum = Number((instructionData[x].length / count).toFixed(3)); - const percent = Number((yNum / yTotal).toFixed(2)); - const barHeight = (height - paddingBottom - interval) * percent; - this.drawRect(xPosition, height - paddingBottom - barHeight, barWidth, barHeight); - // @ts-ignore - const existX = this.cacheData.find((i) => i.instruct === x); - if (!existX) { - this.cacheData.push({ - instruct: x, - x: xPosition, - y: height - paddingBottom - barHeight, - height: barHeight, - heightPer: parseFloat((yNum * 100).toFixed(2)), - }); - } else { - // @ts-ignore - existX.x = xPosition; - } - } - } - - /** - * 绘制x y轴 - * @param width - * @param height - * @param isCycles - */ - drawLineLabelMarkers(width: number, height: number, isCycles: boolean) { - this.ctx!.font = '12px Arial'; - this.ctx!.lineWidth = 1; - this.ctx!.fillStyle = '#333'; - this.ctx!.strokeStyle = '#ccc'; - if (isCycles) { - this.ctx!.fillText('cycles数(1e5)', width - paddingLeft + 10, height - paddingBottom); - } else { - this.ctx!.fillText('指令数(1e5)', width - paddingLeft + 10, height - paddingBottom); - } - - //绘制x轴 - this.drawLine(xStep, height - paddingBottom, width - paddingLeft, height - paddingBottom); - //绘制y轴 - this.drawLine(xStep, 5, xStep, height - paddingBottom); - //绘制标记 - this.drawMarkers(width, height); - } - - /** - * 绘制横线 - * @param x - * @param y - * @param X - * @param Y - */ - drawLine(x: number, y: number, X: number, Y: number) { - this.ctx!.beginPath; - this.ctx!.moveTo(x, y); - this.ctx!.lineTo(X, Y); - this.ctx!.stroke(); - this.ctx!.closePath(); - } - - /** - * 绘制x y轴刻度 - * @param width - * @param height - */ - drawMarkers(width: number, height: number) { - this.xCount = 0; - //绘制x轴锯齿 - let serrateX = 50; - let y = height - paddingBottom; - const clientWidth = width - paddingLeft - 50; - if (clientWidth > this.xMaxValue) { - this.xSpacing = Math.floor(clientWidth / 20); - this.xAvg = Math.ceil(this.xMaxValue / 20); - } else { - this.xSpacing = Math.floor(clientWidth / 10); - this.xAvg = Math.ceil(this.xMaxValue / 10); - } - while (serrateX <= clientWidth) { - this.xCount++; - serrateX += this.xSpacing; - this.drawLine(serrateX, y, serrateX, y + 5); - } - //绘制x轴刻度 - this.ctx!.textAlign = 'center'; - for (let i = 0; i <= this.xCount; i++) { - const x = xStep + i * this.xSpacing; - this.ctx!.fillText(`${i * this.xAvg}`, x, height); - } - //绘制y轴刻度 - this.ctx!.textAlign = 'center'; - const yPadding = Math.floor((height - paddingBottom) / 6); - for (let i = 0; i < 6; i++) { - if (i === 0) { - this.ctx!.fillText(`${i}%`, 30, y); - } else { - const y = height - paddingBottom - i * yPadding; - this.drawLine(xStep, y, width - paddingLeft, y); - this.ctx!.fillText(`${parseFloat((i * this.yAvg).toFixed(2)) * 100}%`, 30, y); - } - } - } - - /** - * 监听页面size变化 - */ - listenerResize(): void { - new ResizeObserver( - debounce(() => { - if (this.instructionChartEle!.getBoundingClientRect()) { - const box = this.instructionChartEle!.getBoundingClientRect(); - const element = this.parentElement!; - this.startX = box.left + Math.max(element.scrollLeft, document.body.scrollLeft) - element.clientLeft; - this.startY = - box.top + Math.max(element.scrollTop, document.body.scrollTop) - element.clientTop + this.canvasScrollTop; - this.calInstructionRangeCount(this.isChecked); - } - }, 100) - ).observe(this.parentElement!); - } - /** - * 绘制方块 - * @param x - * @param y - * @param X - * @param Y - */ - drawRect(x: number, y: number, X: number, Y: number) { - this.ctx!.beginPath(); - this.ctx!.rect(x, y, X, Y); - this.ctx!.fill(); - this.ctx!.closePath(); - } -} diff --git a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelection.ts b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelection.ts deleted file mode 100644 index 96b91294e8c01e8455ee8e0135f240d43c45fed6..0000000000000000000000000000000000000000 --- a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelection.ts +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { BaseElement, element } from '../../../../../base-ui/BaseElement'; -import { SelectionParam } from '../../../../bean/BoxSelection'; -import { Rect, drawString } from '../../../../database/ui-worker/ProcedureWorkerCommon'; -import { ColorUtils } from '../../base/ColorUtils'; -import { SampleStruct } from '../../../../database/ui-worker/ProcedureWorkerBpftrace'; -import { SpApplication } from '../../../../SpApplication'; - -const SAMPLE_STRUCT_HEIGHT = 30; -const Y_PADDING = 4; - -@element('tab-sample-instruction-selection') -export class TabPaneSampleInstructionSelection extends BaseElement { - private instructionEle: HTMLCanvasElement | undefined | null; - private ctx: CanvasRenderingContext2D | undefined | null; - private textEle: HTMLSpanElement | undefined | null; - private instructionArray: Array = []; - private instructionData: Array = []; - private isUpdateCanvas = false; - private canvasX = -1; // 鼠标当前所在画布x坐标 - private canvasY = -1; // 鼠标当前所在画布y坐标 - private startX = 0; // 画布相对于整个界面的x坐标 - private startY = 0; // 画布相对于整个界面的y坐标 - private hintContent = ''; //悬浮框内容 - private floatHint: HTMLDivElement | undefined | null; //悬浮框 - private canvasScrollTop = 0; // tab页上下滚动位置 - private hoverSampleStruct: unknown | undefined; - private isChecked: boolean = false; - private maxDepth = 0; - - initHtml(): string { - return ` - -
- -
-
- 指令数数据流 -
-
- `; - } - - initElements(): void { - this.instructionEle = this.shadowRoot?.querySelector('#instruct-select-canvas'); - this.textEle = this.shadowRoot?.querySelector('.headline'); - this.ctx = this.instructionEle?.getContext('2d'); - this.floatHint = this.shadowRoot?.querySelector('#select_float_hint'); - } - - set data(SampleParam: SelectionParam) { - this.hoverSampleStruct = undefined; - this.instructionData = SampleParam.sampleData; - this.getAvgInstructionData(this.instructionData); - queueMicrotask(() => { - this.updateCanvas(this.clientWidth); - this.drawInstructionData(this.isChecked); - }); - } - - connectedCallback(): void { - super.connectedCallback(); - this.parentElement!.onscroll = () => { - this.canvasScrollTop = this.parentElement!.scrollTop; - this.hideTip(); - }; - this.instructionEle!.onmousemove = (e): void => { - if (!this.isUpdateCanvas) { - this.updateCanvasCoord(); - } - this.canvasX = e.clientX - this.startX; - this.canvasY = e.clientY - this.startY + this.canvasScrollTop; - this.onMouseMove(); - }; - this.instructionEle!.onmouseleave = () => { - this.hideTip(); - }; - document.addEventListener('sample-popver-change', (e: unknown) => { - // @ts-ignore - const select = Number(e.detail.select); - this.hoverSampleStruct = undefined; - this.isChecked = Boolean(select); - this.drawInstructionData(this.isChecked); - }); - this.listenerResize(); - } - - /** - * 初始化窗口大小 - * @param newWidth - */ - updateCanvas(newWidth?: number): void { - if (this.instructionEle instanceof HTMLCanvasElement) { - this.instructionEle.style.width = `${100}%`; - this.instructionEle.style.height = `${(this.maxDepth + 1) * SAMPLE_STRUCT_HEIGHT}px`; - if (this.instructionEle.clientWidth === 0 && newWidth) { - this.instructionEle.width = newWidth; - } else { - this.instructionEle.width = this.instructionEle.clientWidth; - } - this.instructionEle.height = (this.maxDepth + 1) * SAMPLE_STRUCT_HEIGHT; - } - } - - /** - * 鼠标移动 - */ - onMouseMove(): void { - const lastNode = this.hoverSampleStruct; - //查找鼠标所在的node - const searchResult = this.searchDataByCoord(this.instructionArray!, this.canvasX, this.canvasY); - if (searchResult) { - this.hoverSampleStruct = searchResult; - //鼠标悬浮的node未改变则不需重新渲染文字 - if (searchResult !== lastNode) { - this.updateTipContent(); - this.ctx!.clearRect(0, 0, this.instructionEle!.width, this.instructionEle!.height); - this.ctx!.beginPath(); - for (const key in this.instructionArray) { - // @ts-ignore - for (let i = 0; i < this.instructionArray[key].length; i++) { - // @ts-ignore - const cur = this.instructionArray[key][i]; - this.draw(this.ctx!, cur); - } - } - this.ctx!.closePath(); - } - this.showTip(); - } else { - this.hideTip(); - this.hoverSampleStruct = undefined; - } - } - - /** - * 隐藏悬浮框 - */ - hideTip(): void { - if (this.floatHint) { - this.floatHint.style.display = 'none'; - } - } - - /** - * 显示悬浮框 - */ - showTip(): void { - this.floatHint!.innerHTML = this.hintContent; - this.floatHint!.style.display = 'block'; - let x = this.canvasX; - let y = this.canvasY - this.canvasScrollTop; - //右边的函数悬浮框显示在左侧 - if (this.canvasX + this.floatHint!.clientWidth > this.instructionEle!.clientWidth || 0) { - x -= this.floatHint!.clientWidth - 1; - } else { - x += 30; - } - //最下边的函数悬浮框显示在上方 - y -= this.floatHint!.clientHeight - 1; - this.floatHint!.style.transform = `translate(${x}px, ${y}px)`; - } - - /** - * 更新悬浮框内容 - * @returns - */ - updateTipContent(): void { - const hoverNode = this.hoverSampleStruct; - if (!hoverNode) { - return; - } - // @ts-ignore - this.hintContent = `${hoverNode.detail}(${hoverNode.name})
- ${ - // @ts-ignore - this.isChecked ? hoverNode.hoverCycles : hoverNode.hoverInstructions} - - `; - } - - /** - * 设置绘制所需的坐标及宽高 - * @param sampleNode - * @param instructions - * @param x - */ - setSampleFrame(sampleNode: SampleStruct, instructions: number, x: number): void { - if (!sampleNode.frame) { - sampleNode.frame! = new Rect(0, 0, 0, 0); - } - sampleNode.frame!.x = x; - sampleNode.frame!.y = sampleNode.depth! * SAMPLE_STRUCT_HEIGHT; - sampleNode.frame!.width = instructions; - sampleNode.frame!.height = SAMPLE_STRUCT_HEIGHT; - } - - /** - * 判断鼠标当前在那个函数上 - * @param frame - * @param x - * @param y - * @returns - */ - isContains(frame: unknown, x: number, y: number): boolean { - // @ts-ignore - return x >= frame.x && x <= frame.x + frame.width && frame.y <= y && y <= frame.y + frame.height; - } - - /** - * 绘制 - * @param isCycles - */ - drawInstructionData(isCycles: boolean): void { - this.isChecked ? (this.textEle!.innerText = 'cycles数据流') : (this.textEle!.innerText = 'instructions数据流'); - const clientWidth = this.instructionEle!.width; - //将数据转换为层级结构 - const instructionArray = this.instructionData - // @ts-ignore - .filter((item: unknown) => (isCycles ? item.cycles : item.instructions)) - .reduce((pre: unknown, cur: unknown) => { - // @ts-ignore - (pre[`${cur.depth}`] = pre[`${cur.depth}`] || []).push(cur); - return pre; - }, {}); - // @ts-ignore - for (const key in instructionArray) { - // @ts-ignore - for (let i = 0; i < instructionArray[key].length; i++) { - // @ts-ignore - const cur = instructionArray[key][i]; - //第一级节点直接将宽度设置为容器宽度 - if (key === '0') { - this.setSampleFrame(cur, clientWidth, 0); - } else { - //获取上一层级节点数据 - // @ts-ignore - const preList = instructionArray[Number(key) - 1]; - //获取当前节点的父节点 - const parentNode = preList.find((node: SampleStruct) => node.name === cur.parentName); - //计算当前节点下指令数之和 用于计算每个节点所占的宽度比 - const total = isCycles - // @ts-ignore - ? instructionArray[key] - // @ts-ignore - .filter((i: unknown) => i.parentName === parentNode.name) - .reduce((pre: number, cur: SampleStruct) => pre + cur.cycles!, 0) - // @ts-ignore - : instructionArray[key] - // @ts-ignore - .filter((i: unknown) => i.parentName === parentNode.name) - .reduce((pre: number, cur: SampleStruct) => pre + cur.instructions!, 0); - const curWidth = isCycles ? cur.cycles : cur.instructions; - const width = Math.floor(parentNode.frame.width * (curWidth / total)); - if (i === 0) { - this.setSampleFrame(cur, width, parentNode.frame.x); - } else { - // @ts-ignore - const preNode = instructionArray[key][i - 1]; - preNode.parentName === parentNode.name - ? this.setSampleFrame(cur, width, preNode.frame.x + preNode.frame.width) - : this.setSampleFrame(cur, width, parentNode.frame.x); - } - } - } - } - // @ts-ignore - this.instructionArray = instructionArray; - - this.ctx!.clearRect(0, 0, this.instructionEle!.width, this.instructionEle!.height); - this.ctx!.beginPath(); - // @ts-ignore - for (const key in instructionArray) { - // @ts-ignore - for (let i = 0; i < instructionArray[key].length; i++) { - // @ts-ignore - const cur = instructionArray[key][i]; - this.draw(this.ctx!, cur); - } - } - this.ctx!.closePath(); - } - - /** - * 更新canvas坐标 - */ - updateCanvasCoord(): void { - if (this.instructionEle instanceof HTMLCanvasElement) { - this.isUpdateCanvas = this.instructionEle.clientWidth !== 0; - if (this.instructionEle.getBoundingClientRect()) { - const box = this.instructionEle.getBoundingClientRect(); - const D = document.documentElement; - this.startX = box.left + Math.max(D.scrollLeft, document.body.scrollLeft) - D.clientLeft; - this.startY = box.top + Math.max(D.scrollTop, document.body.scrollTop) - D.clientTop + this.canvasScrollTop; - } - } - } - - /** - * 获取鼠标悬停的函数 - * @param nodes - * @param canvasX - * @param canvasY - * @returns - */ - searchDataByCoord(nodes: unknown, canvasX: number, canvasY: number): void | null { - // @ts-ignore - for (const key in nodes) { - // @ts-ignore - for (let i = 0; i < nodes[key].length; i++) { - // @ts-ignore - const cur = nodes[key][i]; - if (this.isContains(cur.frame, canvasX, canvasY)) { - return cur; - } - } - } - return null; - } - - /** - * 绘制方法 - * @param ctx - * @param data - */ - draw(ctx: CanvasRenderingContext2D, data: SampleStruct) { - let spApplication = document.getElementsByTagName('sp-application')[0]; - if (data.frame) { - ctx.globalAlpha = 1; - ctx.fillStyle = - ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.name || '', data.depth!, ColorUtils.FUNC_COLOR.length)]; - const textColor = - ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.name || '', data.depth!, ColorUtils.FUNC_COLOR.length)]; - ctx.lineWidth = 0.4; - // @ts-ignore - if (this.hoverSampleStruct && data.name == this.hoverSampleStruct.name) { - if (spApplication.dark) { - ctx.strokeStyle = '#fff'; - } else { - ctx.strokeStyle = '#000'; - } - } else { - if (spApplication.dark) { - ctx.strokeStyle = '#000'; - } else { - ctx.strokeStyle = '#fff'; - } - } - ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, SAMPLE_STRUCT_HEIGHT - Y_PADDING); - ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, SAMPLE_STRUCT_HEIGHT - Y_PADDING); - ctx.fillStyle = ColorUtils.funcTextColor(textColor); - drawString(ctx, `${data.detail}(${data.name})`, 5, data.frame, data); - } - } - - /** - * 统计框选指令数的平均值 - * @param instructionData - * @returns - */ - getAvgInstructionData(instructionData: Array): unknown { - // @ts-ignore - const length = instructionData[0].property.length; - // @ts-ignore - const knowData = instructionData.filter((instruction) => instruction.name.indexOf('unknown') < 0); - knowData.forEach((instruction) => { - // @ts-ignore - if (instruction.property.length > 0) { - // @ts-ignore - const totalInstruction = instruction.property.reduce( - (pre: number, cur: SampleStruct) => pre + Math.ceil(cur.instructions!), - 0 - ); - // @ts-ignore - const totalCycles = instruction.property.reduce( - (pre: number, cur: SampleStruct) => pre + Math.ceil(cur.cycles!), - 0 - ); - // @ts-ignore - instruction.instructions = Math.ceil(totalInstruction / length) || 1; - // @ts-ignore - instruction.cycles = Math.ceil(totalCycles / length) || 1; - // @ts-ignore - instruction.hoverInstructions = Math.ceil(totalInstruction / length); - // @ts-ignore - instruction.hoverCycles = Math.ceil(totalCycles / length); - // @ts-ignore - this.maxDepth = Math.max(this.maxDepth, instruction.depth); - } - }); - // @ts-ignore - const unknownData = instructionData.filter((instruction) => instruction.name.indexOf('unknown') > -1); - let instructionSum = 0; - let cyclesSum = 0; - let hoverInstructionsSum = 0; - let hoverCyclesSum = 0; - unknownData.forEach((unknown) => { - instructionSum = 0; - cyclesSum = 0; - hoverInstructionsSum = 0; - hoverCyclesSum = 0; - // @ts-ignore - for (const key in unknown.children) { - // @ts-ignore - const child = instructionData.find((instruction) => instruction.name === key); - // @ts-ignore - instructionSum += child.instructions ?? 0; - // @ts-ignore - cyclesSum += child.cycles ?? 0; - // @ts-ignore - hoverInstructionsSum += child.hoverInstructions ?? 0; - // @ts-ignore - hoverCyclesSum += child.hoverCycles ?? 0; - } - // @ts-ignore - unknown.instructions = instructionSum; - // @ts-ignore - unknown.cycles = cyclesSum; - // @ts-ignore - unknown.hoverInstructions = hoverInstructionsSum; - // @ts-ignore - unknown.hoverCycles = hoverCyclesSum; - }); - return instructionData; - } - - /** - * 监听页面size变化 - */ - listenerResize(): void { - new ResizeObserver(() => { - if (this.instructionEle!.getBoundingClientRect()) { - const box = this.instructionEle!.getBoundingClientRect(); - const element = document.documentElement; - this.startX = box.left + Math.max(element.scrollLeft, document.body.scrollLeft) - element.clientLeft; - this.startY = - box.top + Math.max(element.scrollTop, document.body.scrollTop) - element.clientTop + this.canvasScrollTop; - } - }).observe(this.parentElement!); - } -} diff --git a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelectionTotalTime.ts b/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelectionTotalTime.ts deleted file mode 100644 index 5015f1577dda5c6a174cf04710baa115ad28c31e..0000000000000000000000000000000000000000 --- a/ide/src/trace/component/trace/sheet/bpftrace/TabPaneSampleInstructionSelectionTotalTime.ts +++ /dev/null @@ -1,399 +0,0 @@ -/* - * Copyright (C) 2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { BaseElement, element } from '../../../../../base-ui/BaseElement'; -import { SelectionParam } from '../../../../bean/BoxSelection'; -import { debounce } from '../../../Utils'; - -const paddingLeft = 100; -const paddingBottom = 15; -const xStart = 50; // x轴起始位置 -const barWidth = 2; // 柱子宽度 -const millisecond = 1_000_000; - -@element('tab-sample-instructions-totaltime-selection') -export class TabPaneSampleInstructionTotalTime extends BaseElement { - private instructionChartEle: HTMLCanvasElement | undefined | null; - private ctx: CanvasRenderingContext2D | undefined | null; - private cacheData: Array = []; - private canvasX = -1; // 鼠标当前所在画布x坐标 - private canvasY = -1; // 鼠标当前所在画布y坐标 - private startX = 0; // 画布相对于整个界面的x坐标 - private startY = 0; // 画布相对于整个界面的y坐标 - private hoverBar: unknown; - private onReadableData: Array = []; - private hintContent = ''; //悬浮框内容 - private floatHint: HTMLDivElement | undefined | null; //悬浮框 - private canvasScrollTop = 0; // tab页上下滚动位置 - private isUpdateCanvas = false; - private xCount = 0; //x轴刻度个数 - private xMaxValue = 0; //x轴上数据最大值 - private xSpacing = 50; //x轴间距 - private xAvg = 0; //根据xMaxValue进行划分 用于x轴上刻度显示 - private yAvg = 0; //根据yMaxValue进行划分 用于y轴上刻度显示 - - initHtml(): string { - return ` - - -
- `; - } - - initElements(): void { - this.instructionChartEle = this.shadowRoot?.querySelector('#instruct-chart-canvas'); - this.ctx = this.instructionChartEle?.getContext('2d'); - this.floatHint = this.shadowRoot?.querySelector('#float_hint'); - } - - set data(SampleParam: SelectionParam) { - // @ts-ignore - this.onReadableData = SampleParam.sampleData[0].property; - this.calInstructionRangeCount(); - } - - connectedCallback(): void { - super.connectedCallback(); - this.parentElement!.onscroll = () => { - this.canvasScrollTop = this.parentElement!.scrollTop; - this.hideTip(); - }; - this.instructionChartEle!.onmousemove = (e): void => { - if (!this.isUpdateCanvas) { - this.updateCanvasCoord(); - } - this.canvasX = e.clientX - this.startX; - this.canvasY = e.clientY - this.startY + this.canvasScrollTop; - this.onMouseMove(); - }; - this.instructionChartEle!.onmouseleave = () => { - this.hideTip(); - }; - this.listenerResize(); - } - - /** - * 更新canvas坐标 - */ - updateCanvasCoord(): void { - if (this.instructionChartEle instanceof HTMLCanvasElement) { - this.isUpdateCanvas = this.instructionChartEle.clientWidth !== 0; - if (this.instructionChartEle.getBoundingClientRect()) { - const box = this.instructionChartEle.getBoundingClientRect(); - const D = this.parentElement!; - this.startX = box.left + Math.max(D.scrollLeft, document.body.scrollLeft) - D.clientLeft; - this.startY = box.top + Math.max(D.scrollTop, document.body.scrollTop) - D.clientTop + this.canvasScrollTop; - } - } - } - - /** - * 获取鼠标悬停的函数 - * @param nodes - * @param canvasX - * @param canvasY - * @returns - */ - searchDataByCoord(nodes: unknown, canvasX: number, canvasY: number):unknown { - // @ts-ignore - for (let i = 0; i < nodes.length; i++) { - // @ts-ignore - const element = nodes[i]; - if (this.isContains(element, canvasX, canvasY)) { - return element; - } - } - return null; - } - - /** - * 鼠标移动 - */ - onMouseMove(): void { - const lastNode = this.hoverBar; - //查找鼠标所在的node - const searchResult = this.searchDataByCoord(this.cacheData, this.canvasX, this.canvasY); - if (searchResult) { - this.hoverBar = searchResult; - //鼠标悬浮的node未改变则不需重新渲染文字 - if (searchResult !== lastNode) { - this.updateTipContent(); - } - this.showTip(); - } else { - this.hideTip(); - this.hoverBar = undefined; - } - } - - /** - * 隐藏悬浮框 - */ - hideTip(): void { - if (this.floatHint) { - this.floatHint.style.display = 'none'; - this.instructionChartEle!.style.cursor = 'default'; - } - } - - /** - * 显示悬浮框 - */ - showTip(): void { - this.floatHint!.innerHTML = this.hintContent; - this.floatHint!.style.display = 'block'; - this.instructionChartEle!.style.cursor = 'pointer'; - let x = this.canvasX; - let y = this.canvasY - this.canvasScrollTop; - //右边的函数悬浮框显示在左侧 - if (this.canvasX + this.floatHint!.clientWidth > (this.instructionChartEle!.clientWidth || 0)) { - x -= this.floatHint!.clientWidth - 1; - } else { - x += 30; - } - //最下边的函数悬浮框显示在上方 - y -= this.floatHint!.clientHeight - 1; - this.floatHint!.style.transform = `translate(${x}px, ${y}px)`; - } - - /** - * 更新悬浮框内容 - */ - updateTipContent(): void { - const hoverNode = this.hoverBar; - if (!hoverNode) { - return; - } - const detail = hoverNode!; - // @ts-ignore - this.hintContent = ` ${detail.instruct}
${parseFloat( - // @ts-ignore - detail.heightPer - )} `; - } - - /** - * 判断鼠标当前在那个函数上 - * @param frame - * @param x - * @param y - * @returns - */ - isContains(point: unknown, x: number, y: number): boolean { - // @ts-ignore - return x >= point.x && x <= point.x + 2 && point.y <= y && y <= point.y + point.height; - } - - /** - * 统计onReadable数据各指令数个数 - */ - calInstructionRangeCount() { - if (this.onReadableData.length === 0) return; - this.cacheData.length = 0; - const count = this.onReadableData.length; - const onReadableData = this.onReadableData; - const instructionArray = onReadableData.reduce((pre: unknown, current: unknown) => { - // @ts-ignore - const dur = parseFloat(((current.end - current.begin) / millisecond).toFixed(1)); - // @ts-ignore - (pre[dur] = pre[dur] || []).push(current); - return pre; - }, {}); - this.ctx!.clearRect(0, 0, this.instructionChartEle!.width, this.instructionChartEle!.height); - this.instructionChartEle!.width = this.clientWidth; - - this.xMaxValue = - // @ts-ignore - Object.keys(instructionArray) - .map((i) => Number(i)) - .reduce((pre, cur) => Math.max(pre, cur), 0) + 5; // @ts-ignore - const yMaxValue = Object.values(instructionArray).reduce( - // @ts-ignore - (pre: number, cur: unknown) => Math.max(pre, Number((cur.length / count).toFixed(2))), - 0 - ); - this.yAvg = Number(((yMaxValue / 5) * 1.5).toFixed(2)); - const height = this.instructionChartEle!.height; - const width = this.instructionChartEle!.width; - this.drawLineLabelMarkers(width, height); - this.drawBar(instructionArray, height, count); - } - - /** - * 绘制柱状图 - * @param instructionData - * @param height - * @param count - */ - drawBar(instructionData: unknown, height: number, count: number): void { - const yTotal = Number((this.yAvg * 5).toFixed(2)); - const interval = Math.floor((height - paddingBottom) / 6); // @ts-ignore - for (const x in instructionData) { - const xNum = Number(x); - const xPosition = xStart + (xNum / (this.xCount * this.xAvg)) * (this.xCount * this.xSpacing) - barWidth / 2; // @ts-ignore - const yNum = Number((instructionData[x].length / count).toFixed(3)); - const percent = Number((yNum / yTotal).toFixed(2)); - const barHeight = (height - paddingBottom - interval) * percent; - this.drawRect(xPosition, height - paddingBottom - barHeight, barWidth, barHeight); // @ts-ignore - const existX = this.cacheData.find((i) => i.instruct === x); - if (!existX) { - this.cacheData.push({ - instruct: x, - x: xPosition, - y: height - paddingBottom - barHeight, - height: barHeight, - heightPer: parseFloat((yNum * 100).toFixed(2)), - }); - } else { - // @ts-ignore - existX.x = xPosition; - } - } - } - - /** - * 绘制x y轴 - * @param width - * @param height - */ - drawLineLabelMarkers(width: number, height: number) { - this.ctx!.font = '12px Arial'; - this.ctx!.lineWidth = 1; - this.ctx!.fillStyle = '#333'; - this.ctx!.strokeStyle = '#ccc'; - - this.ctx!.fillText('时长 / ms', width - paddingLeft, height - paddingBottom); - - //绘制x轴 - this.drawLine(xStart, height - paddingBottom, width - paddingLeft, height - paddingBottom); - //绘制y轴 - this.drawLine(xStart, 5, xStart, height - paddingBottom); - //绘制标记 - this.drawMarkers(width, height); - } - - /** - * 绘制横线 - * @param x - * @param y - * @param X - * @param Y - */ - drawLine(x: number, y: number, X: number, Y: number) { - this.ctx!.beginPath; - this.ctx!.moveTo(x, y); - this.ctx!.lineTo(X, Y); - this.ctx!.stroke(); - this.ctx!.closePath(); - } - - /** - * 绘制x y轴刻度 - * @param width - * @param height - */ - drawMarkers(width: number, height: number) { - this.xCount = 0; - //绘制x轴锯齿 - let serrateX = 50; - let yHeight = height - paddingBottom; - const clientWidth = width - paddingLeft - 50; - if (clientWidth > this.xMaxValue) { - this.xSpacing = Math.floor(clientWidth / 20); - this.xAvg = Math.ceil(this.xMaxValue / 20); - } else { - this.xSpacing = Math.floor(clientWidth / 10); - this.xAvg = Math.ceil(this.xMaxValue / 10); - } - while (serrateX <= clientWidth) { - this.xCount++; - serrateX += this.xSpacing; - this.drawLine(serrateX, yHeight, serrateX, yHeight + 5); - } - //绘制x轴刻度 - this.ctx!.textAlign = 'center'; - for (let i = 0; i <= this.xCount; i++) { - const x = xStart + i * this.xSpacing; - this.ctx!.fillText(`${i * this.xAvg}`, x, height); - } - //绘制y轴刻度 - this.ctx!.textAlign = 'center'; - const yPadding = Math.floor((height - paddingBottom) / 6); - for (let i = 0; i < 6; i++) { - const y = height - paddingBottom - i * yPadding; - if (i === 0) { - this.ctx!.fillText(`${i}%`, 30, y); - } else { - this.drawLine(xStart, y, width - paddingLeft, y); - this.ctx!.fillText(`${parseFloat((i * this.yAvg).toFixed(2)) * 100}%`, 30, y); - } - } - } - - /** - * 监听页面size变化 - */ - listenerResize(): void { - new ResizeObserver( - debounce(() => { - if (this.instructionChartEle!.getBoundingClientRect()) { - const box = this.instructionChartEle!.getBoundingClientRect(); - const element = this.parentElement!; - this.startX = box.left + Math.max(element.scrollLeft, document.body.scrollLeft) - element.clientLeft; - this.startY = - box.top + Math.max(element.scrollTop, document.body.scrollTop) - element.clientTop + this.canvasScrollTop; - this.calInstructionRangeCount(); - } - }, 100) - ).observe(this.parentElement!); - } - /** - * 绘制方块 - * @param x - * @param y - * @param X - * @param Y - */ - drawRect(x: number, y: number, X: number, Y: number) { - this.ctx!.beginPath(); - this.ctx!.rect(x, y, X, Y); - this.ctx!.fill(); - this.ctx!.closePath(); - } -} diff --git a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts index 2624391dfdc16fbd417ac696609b6a7cdbeb40af..5ebfd694c26b04df7577530872cb8496779895eb 100644 --- a/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts +++ b/ide/src/trace/component/trace/sheet/cpu/TabPaneFrequencySample.ts @@ -281,7 +281,7 @@ export class TabPaneFrequencySample extends BaseElement { return; } // @ts-ignore - let includeData = initFreqResult.findIndex((a) => a.ts >= leftStartNs); + let includeData = initFreqResult.findIndex((a) => a.ts > leftStartNs); if (includeData !== 0) { initFreqResult = initFreqResult.slice( includeData === -1 ? initFreqResult.length - 1 : includeData - 1, diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts index a2ae261cdba15d205e08991700d8f764185a55ad..5763fa5b006d144b60cff31a4210dcf4c0a28b90 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts @@ -25,6 +25,8 @@ import { LitCheckBox } from '../../../../../base-ui/checkbox/LitCheckBox'; import { initSort } from '../SheetUtils'; import { TabpanePerfProfile } from './TabPerfProfile'; import { TabPanePerfAnalysisHtml } from './TabPanePerfAnalysis.html'; +import { WebSocketManager } from '../../../../../webSocket/WebSocketManager'; +import { Constants, TypeConstants } from '../../../../../webSocket/Constants'; @element('tabpane-perf-analysis') export class TabPanePerfAnalysis extends BaseElement { @@ -64,6 +66,13 @@ export class TabPanePerfAnalysis extends BaseElement { private tableArray: NodeListOf | undefined | null; private isComplete: boolean = true; private currentSelectionParam: SelectionParam | undefined | null; + private vaddrList: Array = []; + private selectedTabProcessId: number = 0; + private selectedTabThreadId: number = 0; + private selectedTabfileName: string = ''; + private clickFuncVaddrList: Array = []; + private functionListener!: Function | undefined | null; + private currentSoName: string = ''; set data(val: SelectionParam) { if (val === this.currentSelection) { @@ -201,6 +210,7 @@ export class TabPanePerfAnalysis extends BaseElement { this.addRowClickEventListener(this.perfTableProcess!, this.perfProcessLevelClickEvent.bind(this)); this.addRowClickEventListener(this.perfTableThread!, this.perfThreadLevelClickEvent.bind(this)); this.addRowClickEventListener(this.perfTableSo!, this.perfSoLevelClickEvent.bind(this)); + this.addRowClickEventListener(this.tableFunction!, this.functionClickEvent.bind(this)); } private addRowClickEventListener(table: LitTable, clickEvent: Function): void { @@ -336,25 +346,25 @@ export class TabPanePerfAnalysis extends BaseElement { tip: (perfObj): string => { return `
Process:${ - // @ts-ignore - perfObj.obj.tableName - }
+ // @ts-ignore + perfObj.obj.tableName + }
Sample Count:${ - // @ts-ignore - perfObj.obj.count - }
+ // @ts-ignore + perfObj.obj.count + }
Percent:${ - // @ts-ignore - perfObj.obj.percent - }%
+ // @ts-ignore + perfObj.obj.percent + }%
Event Count:${ - // @ts-ignore - perfObj.obj.eventCount - }
+ // @ts-ignore + perfObj.obj.eventCount + }
Percent:${ - // @ts-ignore - perfObj.obj.eventPercent - }%
+ // @ts-ignore + perfObj.obj.eventPercent + }% `; }, @@ -403,6 +413,8 @@ export class TabPanePerfAnalysis extends BaseElement { // @ts-ignore this.processName = it.tableName; this.perfAnalysisPie?.hideTip(); + // @ts-ignore + this.selectedTabProcessId = it.pid; } private threadPieChart(val: SelectionParam): void { @@ -474,6 +486,8 @@ export class TabPanePerfAnalysis extends BaseElement { // @ts-ignore this.threadName = it.tableName; this.perfAnalysisPie?.hideTip(); + // @ts-ignore + this.selectedTabThreadId = it.tid; } private initPerfAnalysisPieConfig(): void { @@ -541,6 +555,8 @@ export class TabPanePerfAnalysis extends BaseElement { private perfSoLevelClickEvent(it: unknown): void { this.reset(this.tableFunction!, true); this.showAssignLevel(this.tableFunction!, this.perfTableSo!, 3, this.functionData); + // @ts-ignore + this.currentSoName = it.tableName; this.getHiperfFunction(it); let title = ''; if (this.processName.length > 0) { @@ -556,6 +572,33 @@ export class TabPanePerfAnalysis extends BaseElement { } this.titleEl!.textContent = title; this.perfAnalysisPie?.hideTip(); + // @ts-ignore + this.selectedTabfileName = it.tableName; + } + + private functionClickEvent(it: unknown) { + this.clickFuncVaddrList = this.vaddrList.filter((item: unknown) => { + // @ts-ignore + return item.process_id === this.selectedTabProcessId && + // @ts-ignore + item.thread_id === this.selectedTabThreadId && + // @ts-ignore + item.libName === this.selectedTabfileName && + // @ts-ignore + item.symbolName === it.tableName + }) + if (this.clickFuncVaddrList.length > 0) { + const textEncoder = new TextEncoder(); + const queryData = { + elf_name: this.currentSoName, //@ts-ignore + vaddr: this.clickFuncVaddrList[0].vaddrInFile, //@ts-ignore + func: it.tableName + }; + const dataString = JSON.stringify(queryData); + const encodedData = textEncoder.encode(dataString); + WebSocketManager.getInstance()?.sendMessage(TypeConstants.DISASSEMBLY_TYPE, Constants.DISASSEMBLY_QUERY_CMD, encodedData); + } + this.functionListener!(it, this.clickFuncVaddrList); } private sortByColumn(): void { @@ -1080,7 +1123,7 @@ export class TabPanePerfAnalysis extends BaseElement { // @ts-ignore other.percent = ((other.count / this.sumCount!) * 100).toFixed(2); // @ts-ignore - other.eventCount += res[i].eventCount; + other.eventCount += res[i].eventCount; // @ts-ignore other.eventPercent = ((other.eventCount / this.sumEventCount!) * 100).toFixed(2); } @@ -1111,6 +1154,15 @@ export class TabPanePerfAnalysis extends BaseElement { this.progressEL!.loading = false; this.getHiperfProcess(val); }); + const args = [ + { + funcName: 'getVaddrToFile', + funcArgs: [val], + }, + ]; + procedurePool.submitWithName('logic0', 'perf-vaddr', args, undefined, (results: Array) => { + this.vaddrList = results; + }) } private getDataByWorker(val: SelectionParam, handler: Function): void { @@ -1152,6 +1204,10 @@ export class TabPanePerfAnalysis extends BaseElement { }).observe(this.parentElement!); } + public addFunctionRowClickEventListener(clickEvent: Function): void { + this.functionListener = clickEvent; + } + initHtml(): string { return TabPanePerfAnalysisHtml; } diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.html.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.html.ts new file mode 100644 index 0000000000000000000000000000000000000000..278d486871acc8eac2708857fb4617a920f0a862 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.html.ts @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const TabPerfFuncAsmHtml = ` + +
+
+
+
Function Name:
+
Total Count:
+
.text Section File Off:
+
+
+ + + + + + + + +
+
+`; diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.ts new file mode 100644 index 0000000000000000000000000000000000000000..7b07fb176549acb145f660b2a763105cffc90be6 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.ts @@ -0,0 +1,278 @@ +import { TabPerfFuncAsmHtml } from "./TabPerfFuncAsm.html"; +import { BaseElement, element } from "../../../../../base-ui/BaseElement"; +import { LitTable } from "../../../../../base-ui/table/lit-table"; +import { + FormattedAsmInstruction, + PerfFunctionAsmParam, + OriginAsmInstruction, +} from "../../../../bean/PerfAnalysis"; +import { WebSocketManager } from "../../../../../webSocket/WebSocketManager"; +import { Constants, TypeConstants } from "../../../../../webSocket/Constants"; + +@element("tab-perf-func-asm") +export class TabPerfFuncAsm extends BaseElement { + private assmblerTable: LitTable | null | undefined; + private loadingElement: HTMLElement | null | undefined; + private functionName: string = ""; + private totalCount: number = 0; + private functionNameElement: HTMLDivElement | null | undefined; + private totalCountElement: HTMLDivElement | null | undefined; + private textFileOffElement: HTMLDivElement | null | undefined; + private errorMessageElement: HTMLDivElement | null | undefined; + private funcBaseAddr: bigint = BigInt(0); + // Key: offset; Value: selfcount + private funcSampleMap: Map = new Map(); + private showUpData: FormattedAsmInstruction[] = []; + private originalShowUpData: FormattedAsmInstruction[] = []; + private formattedAsmIntructionArray: FormattedAsmInstruction[] = []; + private resizeObserver: ResizeObserver | null = null; + + initHtml(): string { + return TabPerfFuncAsmHtml; + } + + initElements(): void { + this.assmblerTable = this.shadowRoot!.querySelector( + "#perf-function-asm-table" + ); + this.loadingElement = + this.shadowRoot!.querySelector("#loading"); + this.functionNameElement = + this.shadowRoot!.querySelector("#function-name"); + this.totalCountElement = + this.shadowRoot!.querySelector("#total-count"); + this.textFileOffElement = + this.shadowRoot!.querySelector("#text-file-off"); + this.textFileOffElement!.style.display = 'none'; + this.errorMessageElement = this.shadowRoot!.querySelector("#error-message"); + + this.assmblerTable!.style.display = "grid"; + + this.assmblerTable!.itemTextHandleMap.set("addr", (value: unknown) => { + return `0x${(value as number).toString(16)}`; + }); + + this.assmblerTable!.itemTextHandleMap.set("selfcount", (value: unknown) => { + return (value as number) === 0 ? "" : (value as number).toString(); + }); + + this.assmblerTable!.itemTextHandleMap.set("percent", (value: unknown) => { + return (value as number) === 0 ? "" : (value as number).toString(); + }); + + this.assmblerTable!.itemTextHandleMap.set("instruction", (value: unknown) => { + return (value as string) === "" ? "INVALID" : (value as string); + }); + + this.assmblerTable!.itemTextHandleMap.set("sourceLine", (value: unknown) => { + return (value as string) || ""; + }); + + this.assmblerTable!.addEventListener("column-click", ((evt: Event) => { + const {key, sort} = (evt as CustomEvent).detail; + if (key === "selfcount") { + if (sort === 0) { + this.assmblerTable!.recycleDataSource = this.originalShowUpData; + this.assmblerTable!.reMeauseHeight(); + } else { + this.showUpData.sort((a, b) => { + return sort === 1 + ? a.selfcount - b.selfcount + : b.selfcount - a.selfcount; + }); + this.assmblerTable!.recycleDataSource = this.showUpData; + this.assmblerTable!.reMeauseHeight(); + } + } else if (key === "percent") { + if (sort === 0) { + this.assmblerTable!.recycleDataSource = this.originalShowUpData; + this.assmblerTable!.reMeauseHeight(); + } else { + this.showUpData.sort((a, b) => { + return sort === 1 ? a.percent - b.percent : b.percent - a.percent; + }); + this.assmblerTable!.recycleDataSource = this.showUpData; + this.assmblerTable!.reMeauseHeight(); + } + } + }) as EventListener); + } + + private updateTitle(): void { + if (this.functionName) { + this.functionNameElement!.innerHTML = `Function Name: ${this.functionName}`; + this.totalCountElement!.innerHTML = `Total Count: ${this.totalCount}`; + } + } + + private showLoading(): void { + if (this.loadingElement) { + this.loadingElement.removeAttribute("hidden"); + } + } + + private hideLoading(): void { + if (this.loadingElement) { + this.loadingElement.setAttribute("hidden", ""); + } + } + + private showError(message: string): void { + if (this.errorMessageElement) { + this.errorMessageElement.textContent = message; + this.errorMessageElement.style.display = 'block'; + } + } + + private hideError(): void { + if (this.errorMessageElement) { + this.errorMessageElement.style.display = 'none'; + } + } + + set data(data: PerfFunctionAsmParam) { + if (this.functionName === data.functionName || data.functionName === undefined) { + return; + } + + (async () => { + try { + this.clearData(); + this.functionName = data.functionName; + this.totalCount = data.totalCount; + this.updateTitle(); + this.showLoading(); + // @ts-ignore + const vaddrInFile = data.vaddrList[0].vaddrInFile; + // 1. 先转成 BigInt + // 2. 用 asUintN 转成无符号64位 + // 3. 如果需要用作数值运算,再转回 Number + this.funcBaseAddr = BigInt.asUintN(64, BigInt(vaddrInFile)); + // 1. 计算采样数据 + this.calculateFuncAsmSapleCount(data.vaddrList); + // 2. 等待汇编指令数据 + let callback: (cmd: number, e: Uint8Array) => void; + + await Promise.race([ + new Promise((resolve, reject) => { + callback = (cmd: number, e: Uint8Array) => { + try { + + if (cmd === Constants.DISASSEMBLY_QUERY_BACK_CMD) { + const result = JSON.parse(new TextDecoder().decode(e)); + if (result.resultCode === 0) { + if (result.anFileOff) { + this.textFileOffElement!.innerHTML = `.text Section File Off ${result.anFileOff}`; + this.textFileOffElement!.style.display = 'block'; + } else { + this.textFileOffElement!.style.display = 'none'; + } + this.formatAsmInstruction(JSON.parse(result.resultMessage)); + this.calcutelateShowUpData(); + resolve(); + } else { + reject(new Error(`Failed with code: ${result.resultCode}`)); + } + } else { + reject(new Error(`Unexpected command: ${cmd}`)); + } + WebSocketManager.getInstance()?.unregisterCallback(TypeConstants.DISASSEMBLY_TYPE, callback); + } catch (error) { + WebSocketManager.getInstance()?.unregisterCallback(TypeConstants.DISASSEMBLY_TYPE, callback); + reject(error); + } + }; + + WebSocketManager.getInstance()?.registerCallback(TypeConstants.DISASSEMBLY_TYPE, callback); + }), + new Promise((_, reject) => setTimeout(() => { + WebSocketManager.getInstance()?.unregisterCallback(TypeConstants.DISASSEMBLY_TYPE, callback); + reject(new Error('Request timeout')); + }, 20000)) + ]); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; + this.showError(`Error: can't get assembly code because ${errorMessage}, show sample list without assembly code`); + this.calcutelateErrorShowUpData(); + } finally { + this.showUpData = [...this.originalShowUpData]; + this.assmblerTable!.recycleDataSource = this.showUpData; + this.assmblerTable!.reMeauseHeight(); + this.hideLoading(); + } + })(); + } + + private calcutelateErrorShowUpData(): void { + this.funcSampleMap.forEach((selfCount, offsetToVaddr) => { + this.originalShowUpData.push({ + selfcount: selfCount, + percent: Math.round((selfCount / this.totalCount) * 10000) / 100, + // 地址计算也使用 BigInt + addr: Number(BigInt.asUintN(64, this.funcBaseAddr + BigInt(offsetToVaddr))), + instruction: '', + sourceLine: '' + }) + }) + } + + private calculateFuncAsmSapleCount(vaddrList: Array): void { + vaddrList.forEach(item => { + // @ts-ignore + const count = this.funcSampleMap.get(item.offsetToVaddr) || 0; + // @ts-ignore + this.funcSampleMap.set(item.offsetToVaddr, count + 1); + }); + } + + private formatAsmInstruction(originAsmInstruction: Array) { + this.formattedAsmIntructionArray = originAsmInstruction.map(instructs => ({ + selfcount: 0, + percent: 0, + addr: parseInt(instructs.addr, 16), + instruction: instructs.instruction, + sourceLine: instructs.sourceLine + }) as FormattedAsmInstruction); + } + + + private clearData(): void { + this.hideError(); + this.funcSampleMap.clear(); + this.showUpData = []; + this.originalShowUpData = []; + this.formattedAsmIntructionArray = []; + this.assmblerTable!.recycleDataSource = []; + } + + private calcutelateShowUpData(): void { + this.funcSampleMap.forEach((selfCount, offsetToVaddr) => { + let instructionPosition = offsetToVaddr / 4; + this.formattedAsmIntructionArray[instructionPosition].selfcount = selfCount; + this.formattedAsmIntructionArray[instructionPosition].percent = Math.round((selfCount / this.totalCount) * 10000) / 100; + }) + this.originalShowUpData = this.formattedAsmIntructionArray; + } + + public connectedCallback(): void { + super.connectedCallback(); + // 初始化 ResizeObserver + this.resizeObserver = new ResizeObserver(() => { + if (this.assmblerTable && this.parentElement) { + this.assmblerTable.style.height = `${this.parentElement.clientHeight - 50}px`; + this.assmblerTable!.reMeauseHeight(); + } + }); + this.resizeObserver.observe(this.parentElement!); + } + + public disconnectedCallback(): void { + super.disconnectedCallback(); + + // 断开 ResizeObserver + if (this.resizeObserver) { + this.resizeObserver.disconnect(); + this.resizeObserver = null; + } + } +} \ No newline at end of file diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts index 91a16eacd7b2962359cedc84c591134660c6b3b7..d24f40db02679573fb45eba4275dbe3f89f74c08 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.ts @@ -111,8 +111,13 @@ export class TabpanePerfProfile extends BaseElement { this.perfProfilerFilter!.initializeFilterTree(true, true, true); this.perfProfilerFilter!.filterValue = ''; this.perfProfileProgressEL!.loading = true; // @ts-ignore - this.perfProfileLoadingPage.style.visibility = 'visible'; // @ts-ignore - this.getDataByWorkAndUpDateCanvas(perfProfilerSelection); + this.perfProfileLoadingPage.style.visibility = 'visible'; + const newPerfProfilerSelection = Object.fromEntries(// @ts-ignore + Object.entries(perfProfilerSelection).filter(([key, value]) => + !['clockMapData', 'xpowerMapData', 'hangMapData'].includes(key) + ) + ) as Partial;// @ts-ignore + this.getDataByWorkAndUpDateCanvas(newPerfProfilerSelection); } getDataByWorkAndUpDateCanvas(perfProfilerSelection: SelectionParam): void { diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts index bf838087eeb3f4a740fadcc74c51f6e9515c02a9..0752fed98003aa8372814492c0e3e9802658a0c9 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMemory.ts @@ -135,7 +135,20 @@ export class TabPaneNMemory extends BaseElement { this.tblData!.recycleDataSource = []; this.setNmMemoryLoading(false); if (results.length > 0) { - results.forEach((item) => { + let isTwoArray: boolean = results.some(item => { + return Array.isArray(item); + }) + let dataList: unknown = []; + if (isTwoArray) { + results.forEach(v => { + // @ts-ignore + dataList = dataList.concat(v); + }) + } else { + dataList = results; + } + // @ts-ignore + dataList.forEach((item) => { //@ts-ignore let tmpNumber = item.addr.split('x'); //@ts-ignore diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSliceChild.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSliceChild.ts index 1e3cdfa833b19d02e85764875750521472b260e9..65b1ddcdfb6e78b3d7ff52e76941b6b56a0a34a0 100644 --- a/ide/src/trace/component/trace/sheet/process/TabPaneSliceChild.ts +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSliceChild.ts @@ -18,7 +18,7 @@ import { LitTable } from '../../../../../base-ui/table/lit-table'; import { SelectionData, SelectionParam, SliceBoxJumpParam } from '../../../../bean/BoxSelection'; import { Utils } from '../../base/Utils'; import { resizeObserver } from '../SheetUtils'; -import { getTabDetails, getGhDetails, getSfDetails } from '../../../../database/sql/Func.sql'; +import { getTabDetails, getGhDetails, getSfDetails, getParentDetail, getFuncChildren } from '../../../../database/sql/Func.sql'; @element('box-slice-child') export class TabPaneSliceChild extends BaseElement { @@ -120,14 +120,46 @@ export class TabPaneSliceChild extends BaseElement { return promises; }; this.sliceChildTbl!.loading = true; - Promise.all([result1(), result2(), result3()]).then(res => { + Promise.all([result1(), result2(), result3()]).then(async res => { this.sliceChildTbl!.loading = false; let result: unknown = (res[0] || []).concat(res[1] || []).concat(res[2] || []); this.sliceChildTbl!.loading = false; // @ts-ignore if (result.length !== null && result.length > 0) { + let funcIdArr: Array = []; + let minStartTS = Infinity; + let maxEndTS = -Infinity; + // @ts-ignore + let parentDetail: [{ startTS: number, endTS: number, depth: number, id: number, name: string }] = await getParentDetail(val.param.processId, val.param.threadId, val.param.leftNs, val.param.rightNs); + + // @ts-ignore + parentDetail.forEach(item => { + funcIdArr.push(item.id); + if (item.depth === 0) { + if (item.startTS < minStartTS) { + minStartTS = item.startTS; + } + if (item.endTS > maxEndTS) { + maxEndTS = item.endTS; + } + } + }); + + let FuncChildrenList = await getFuncChildren(funcIdArr, val.param.processId, val.param.threadId, minStartTS, maxEndTS, true); + let childDurMap = new Map(); + FuncChildrenList.forEach((it: any) => { + if (!childDurMap.has(it.parentId)) { + childDurMap.set(it.parentId, it.duration); + } else { + let dur = childDurMap.get(it.parentId) + dur += it.duration + childDurMap.set(it.parentId, dur!); + } + }); // @ts-ignore result.map((e: unknown) => { + // @ts-ignore + e.selfTime = childDurMap.has(e.id) ? (e.duration - childDurMap.get(e.id)) / 1000000 : e.duration / 1000000; // @ts-ignore e.startTime = Utils.getTimeString(e.startNs); // @ts-ignore @@ -179,6 +211,8 @@ export class TabPaneSliceChild extends BaseElement { + +
`; } diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts index 49509b0b0d2dc5b485a73057b1655775752dd3ba..21adc2c47233eb2c5b50d4d86b1f3955f2bb4d38 100644 --- a/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSlices.ts @@ -20,7 +20,7 @@ import { SpSystemTrace } from '../../../SpSystemTrace'; import { TraceRow } from '../../base/TraceRow'; import { LitSearch } from '../../search/Search'; import { resizeObserver } from '../SheetUtils'; -import { getTabSlicesAsyncFunc, getTabSlicesAsyncCatFunc } from '../../../../database/sql/Func.sql'; +import { getTabSlicesAsyncFunc, getTabSlicesAsyncCatFunc, getParentDetail, getFuncChildren } from '../../../../database/sql/Func.sql'; import { getTabSlices } from '../../../../database/sql/ProcessThread.sql'; import { FuncStruct } from '../../../../database/ui-worker/ProcedureWorkerFunc'; import { Utils } from '../../base/Utils'; @@ -147,13 +147,45 @@ export class TabPaneSlices extends BaseElement { }; this.slicesTbl!.loading = true; - Promise.all([result1(), result2(), result3()]).then(res => { + Promise.all([result1(), result2(), result3()]).then(async res => { let processSlicesResult = (res[0] || []).concat(res[1] || []).concat(res[2] || []); if (processSlicesResult !== null && processSlicesResult.length > 0) { + let funcIdArr: Array = []; + let minStartTS = Infinity; + let maxEndTS = -Infinity; + // @ts-ignore + let parentDetail: [{ startTS: number, endTS: number, depth: number, id: number, name: string }] = await getParentDetail(slicesParam.processIds, slicesParam.funTids, slicesParam.leftNs, slicesParam.rightNs); + // @ts-ignore + parentDetail.forEach(item => { + funcIdArr.push(item.id); + if (item.depth === 0) { + if (item.startTS < minStartTS) { + minStartTS = item.startTS; + } + if (item.endTS > maxEndTS) { + maxEndTS = item.endTS; + } + } + }); + + let FuncChildrenList = await getFuncChildren(funcIdArr, slicesParam.processIds, slicesParam.funTids, minStartTS, maxEndTS, false); + let childDurMap: Map> = new Map(); + FuncChildrenList.forEach((it: any) => { + if (!childDurMap.has(it.parentId)) { + childDurMap.set(it.parentId, it.duration); + } else { + let dur = childDurMap.get(it.parentId) + dur += it.duration + childDurMap.set(it.parentId, dur!); + } + }); let sumWall = 0.0; let sumOcc = 0; + let sumSelf = 0.0; let processSlicesResultMap: Map = new Map(); for (let processSliceItem of processSlicesResult) { + //@ts-ignore + processSliceItem.selfTime = childDurMap.has(processSliceItem.id) ? parseFloat(((processSliceItem.wallDuration - childDurMap.get(processSliceItem.id)) / 1000000).toFixed(5)) : parseFloat((processSliceItem.wallDuration / 1000000).toFixed(5)); //@ts-ignore processSliceItem.name = processSliceItem.name === null ? '' : processSliceItem.name; //@ts-ignore @@ -161,6 +193,8 @@ export class TabPaneSlices extends BaseElement { //@ts-ignore sumOcc += processSliceItem.occurrences; //@ts-ignore + sumSelf += processSliceItem.selfTime; + //@ts-ignore processSliceItem.wallDuration = parseFloat((processSliceItem.wallDuration / 1000000.0).toFixed(5)); //@ts-ignore if (processSlicesResultMap.has(processSliceItem.name)) {//@ts-ignore @@ -185,6 +219,7 @@ export class TabPaneSlices extends BaseElement { count.process = ' '; count.wallDuration = parseFloat((sumWall / 1000000.0).toFixed(5)); count.occurrences = sumOcc; + count.selfTime = parseFloat(sumSelf.toFixed(5)); count.tabTitle = 'Summary'; // @ts-ignore count.allName = processSlicesResultsValue.map((item: unknown) => item.name); @@ -204,6 +239,10 @@ export class TabPaneSlices extends BaseElement { }); } async orgnazitionData(data: Object): Promise { + // @ts-ignore + if (data!.tabTitle === 'Summary') { + FuncStruct.funcSelect = true; + } let spApplication = document.querySelector('body > sp-application'); let spSystemTrace = spApplication?.shadowRoot?.querySelector( 'div > div.content > sp-system-trace' @@ -337,6 +376,8 @@ export class TabPaneSlices extends BaseElement { + + `; } diff --git a/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts b/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts index 841a2d4408781f6c704671e498fe590f67806034..e1d9f65f510766993aab693ce857c3113c430e11 100644 --- a/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts +++ b/ide/src/trace/component/trace/timer-shaft/RangeRuler.ts @@ -633,18 +633,15 @@ export class RangeRuler extends Graph { } if (startTime === endTime) { let midNs = (this.range.endNS - this.range.startNS) / 2; - if (startTime > midNs && startTime - midNs < this.range.totalNS - this.range.endNS) { - this.range.startNS = this.range.startNS + startTime - midNs; - this.range.endNS = this.range.endNS + startTime - midNs; - } else if (startTime < midNs && midNs - startTime < this.range.startNS) { - this.range.startNS = this.range.startNS - midNs + startTime; - this.range.endNS = this.range.endNS - midNs + startTime; - } else if (startTime > midNs && startTime - midNs > this.range.totalNS - this.range.endNS) { - this.range.startNS = 2 * startTime - this.range.totalNS; - this.range.endNS = this.range.totalNS; - } else if (startTime < midNs && midNs - startTime > this.range.startNS) { + if (startTime === midNs) { + return; + } + if(startTime * 2 < this.range.totalNS) { this.range.startNS = 0; - this.range.endNS = 2 * startTime; + this.range.endNS = startTime * 2; + } else { + this.range.startNS = (startTime * 2) - this.range.totalNS; + this.range.endNS = this.range.totalNS; } } else { let startX = midX - 150; diff --git a/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts b/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts index ab73e814ae5ac75d0c8302285d27c86f5ea05917..0e5be4219fcbcadd31f83f73af34e3c0a8ef787b 100644 --- a/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts +++ b/ide/src/trace/component/trace/timer-shaft/TabPaneFlag.ts @@ -189,7 +189,6 @@ export class TabPaneFlag extends BaseElement { private textInputKeyUpEventByFlag(index: number, tr: HTMLDivElement): void { tr.querySelector('#text-input')?.addEventListener('keyup', (event: unknown) => { - SpSystemTrace.isKeyUp = true; // @ts-ignore if (this.tableDataSource[index].startTime === this.flagList[index - 1].time && event.code === 'Enter' || event.code === 'NumpadEnter') { // @ts-ignore diff --git a/ide/src/trace/database/SqlLiteWorker.ts b/ide/src/trace/database/SqlLiteWorker.ts index 29506f47a5c49fee11f53e5b041f5eb2fa9abdcc..673cc414fca05e3f41ffd2e1d22f5d43a2ed3173 100644 --- a/ide/src/trace/database/SqlLiteWorker.ts +++ b/ide/src/trace/database/SqlLiteWorker.ts @@ -13,6 +13,10 @@ * limitations under the License. */ +importScripts('sql-wasm.js'); +// @ts-ignore +import {WebSocketManager} from "../../webSocket/WebSocketManager"; + importScripts('sql-wasm.js'); // @ts-ignore import { temp_init_sql_list } from './TempSql'; @@ -20,7 +24,11 @@ import { execProtoForWorker } from './data-trafic/utils/ExecProtoForWorker'; import { TraficEnum } from './data-trafic/utils/QueryEnum'; let conn: unknown = null; - +let enc = new TextEncoder(); +let dec = new TextDecoder(); +const REQ_BUF_SIZE = 4 * 1024 * 1024; +let uploadSoActionId: string = ''; +const failedArray: Array = []; self.onerror = function (error): void { }; self.onmessage = async (e: unknown): Promise => { @@ -97,5 +105,19 @@ self.onmessage = async (e: unknown): Promise => { return []; } }); + } else if (action === 'upload-so') { + onmessageByUploadSoAction(e); } }; + +function onmessageByUploadSoAction(e: unknown): void { + // @ts-ignore + uploadSoActionId = e.data.id; + // @ts-ignore + const result = 'ok'; + self.postMessage({ + id: uploadSoActionId, + action: 'upload-so', + results: { result: result, failedArray: failedArray }, + }); +} \ No newline at end of file diff --git a/ide/src/trace/database/StateBusyTimeWorker.ts b/ide/src/trace/database/StateBusyTimeWorker.ts index 51f62eec37892c9e1f24c0d5911aad0e1561bef5..6dc26e63ba58a68687af837220c3d08e6cc9450d 100644 --- a/ide/src/trace/database/StateBusyTimeWorker.ts +++ b/ide/src/trace/database/StateBusyTimeWorker.ts @@ -20,37 +20,27 @@ function getBusyTime( leftStartNs: number, rightEndNs: number ): void { - if (initFreqResult.length === 0) { + if (initFreqResult.length === 0 || initStateResult.length === 0) { return; } - if (initStateResult.length === 0) { - return; - } - //处理被框选的freq的第一个数据 - //@ts-ignore - let includeData = initFreqResult.findIndex((a) => a.ts >= leftStartNs); - if (includeData !== 0) { - initFreqResult = initFreqResult.slice( - includeData === -1 ? initFreqResult.length - 1 : includeData - 1, - initFreqResult.length - ); - } - //@ts-ignore - let startNS = includeData === 0 ? initFreqResult[0].ts : leftStartNs; - //处理对应的state泳道被框选的第一个数据 - //@ts-ignore - let includeStateData = initStateResult.findIndex((a) => a.ts >= startNS); - if (includeStateData !== 0) { - initStateResult = initStateResult.slice( - includeStateData === -1 ? initStateResult.length - 1 : includeStateData - 1, - initStateResult.length - ); - } - //@ts-ignore - if (initStateResult[0].ts < startNS && includeStateData !== 0 && includeStateData !== -1) { + let handle = (result: Array, startNS: number): Array => { //@ts-ignore - initStateResult[0].ts = startNS; + let firstDataIndex = result.findIndex((a) => a.ts > startNS); + if (firstDataIndex !== 0) { + result = result.slice( + firstDataIndex === -1 ? result.length - 1 : firstDataIndex - 1, + result.length + ); + // @ts-ignore + result[0].ts = startNS; + } + return result } + + // @ts-ignore + let startNS = Math.max(initFreqResult[0].ts, initStateResult[0].ts, leftStartNs); + initFreqResult = handle(initFreqResult, startNS); + initStateResult = handle(initStateResult, startNS); //处理被框选的freq最后一个数据 //@ts-ignore if (initFreqResult[initFreqResult.length - 1].ts !== rightEndNs) { diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts index e610e76e9675518315534e3f3fb19a20cb90021c..46f2e0cfec100c875e696a1a7d6e8e181e083526 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts @@ -264,7 +264,7 @@ class MerageBeanDataSplit { */ //@ts-ignore let parentNode = item.parentNode; - while (parentNode !== undefined && !(parentNode.isStore === 0 && parentNode.searchShow)) { + while (parentNode !== undefined && !(parentNode.isStore === 0 && parentNode.searchShow) && parentNode.addr) { parentNode = parentNode.parentNode; } if (parentNode) { diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts index e3279c73141330496e6022c277b7b1af538a3143..5650e3195b2429f0dec2838a689708b66e84229e 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts @@ -102,6 +102,12 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { case 'perf-action': this.perfAction(data); break; + case 'perf-vaddr-back': + this.rebackVaddrList(data); + break; + case 'perf-vaddr': + this.perfGetVaddr(data); + break; case 'perf-reset': this.perfReset(); break; @@ -201,6 +207,43 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { this.isAnalysis = false; } } + + rebackVaddrList(data: unknown) { + // @ts-ignore + let vaddrCallchainList = convertJSON(data.params.list); + let sampleCallChainList: unknown = []; + for (let i = 0; i < vaddrCallchainList.length; i++) { + let funcVaddrLastItem = {}; + // @ts-ignore + let callChains = [...this.callChainData[vaddrCallchainList[i].callchain_id]]; + const lastCallChain = callChains[callChains.length - 1]; + // @ts-ignore + funcVaddrLastItem.callchain_id = lastCallChain.sampleId; + // @ts-ignore + funcVaddrLastItem.symbolName = this.dataCache.dataDict.get(lastCallChain.name as number); + // @ts-ignore + funcVaddrLastItem.vaddrInFile = lastCallChain.vaddrInFile; + // @ts-ignore + funcVaddrLastItem.offsetToVaddr = lastCallChain.offsetToVaddr; + // @ts-ignore + funcVaddrLastItem.process_id = vaddrCallchainList[i].process_id; + // @ts-ignore + funcVaddrLastItem.thread_id = vaddrCallchainList[i].thread_id; + // @ts-ignore + funcVaddrLastItem.libName = lastCallChain.fileName; + // @ts-ignore + sampleCallChainList.push(funcVaddrLastItem); + } + + self.postMessage({ + //@ts-ignore + id: data.id, + //@ts-ignore + action: data.action, + results: sampleCallChainList, + }); + } + private perfAction(data: unknown): void { //@ts-ignore const params = data.params; @@ -228,6 +271,18 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { } } } + + private perfGetVaddr(data: unknown) { + // @ts-ignore + const params = data.params; + this.backVaddrData(data) + } + + backVaddrData(data: unknown) { + // @ts-ignore + this.handleDataByFuncName(data.params[0].funcName, data.params[0].funcArgs); + } + private perfReset(): void { this.isHideThread = false; this.isHideThreadState = false; @@ -377,6 +432,7 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { `select c.name, c.callchain_id as sampleId, c.vaddr_in_file as vaddrInFile, + c.offset_to_vaddr as offsetToVaddr, c.file_id as fileId, c.depth, c.symbol_id as symbolId @@ -586,10 +642,12 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { //@ts-ignore symbolName = perfCallChains[topIndex].name; } - let perfRootNode = this.currentTreeMapData[symbolName + perfSample.pid]; + // 只展示内核栈合并进程栈 + const usePidAsKey = this.isOnlyKernel ? '' : perfSample.pid; + let perfRootNode = this.currentTreeMapData[symbolName + usePidAsKey]; if (perfRootNode === undefined) { perfRootNode = new PerfCallChainMerageData(); - this.currentTreeMapData[symbolName + perfSample.pid] = perfRootNode; + this.currentTreeMapData[symbolName + usePidAsKey] = perfRootNode; this.currentTreeList.push(perfRootNode); } PerfCallChainMerageData.merageCallChainSample(perfRootNode, perfCallChains[topIndex], perfSample, false); @@ -602,6 +660,11 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { this.allProcess = Object.values(rootMerageMap); } private mergeNodeData(totalEventCount: number, totalSamplesCount: number): MergeMap { + // 只展示内核栈不添加进程这一级的结构 + if (this.isOnlyKernel) { + return this.currentTreeMapData; + } + // 添加进程级结构 let rootMerageMap: MergeMap = {}; // @ts-ignore Object.values(this.currentTreeMapData).forEach((merageData: PerfCallChainMerageData): void => { @@ -975,6 +1038,51 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { this.getCurrentDataFromDb(funcArgs[0]); } } + + private queryVaddrToFile(funcArgs: unknown[]): void { + if (funcArgs[1]) { + let sql = ''; + //@ts-ignore + if (funcArgs[1].processId !== undefined) { + //@ts-ignore + sql += `and thread.process_id = ${funcArgs[1].processId}`; + } + //@ts-ignore + if (funcArgs[1].threadId !== undefined) { + //@ts-ignore + sql += ` and s.thread_id = ${funcArgs[1].threadId}`; + } + //@ts-ignore + this.getVaddrToFile(funcArgs[0], sql); + } else { + //@ts-ignore + this.getVaddrToFile(funcArgs[0]); + } + } + + private getVaddrToFile(selectionParam: SelectionParam, sql?: string): void { + let filterSql = this.setFilterSql(selectionParam, sql); + this.queryData( + this.currentEventId, + 'perf-vaddr-back', + `select s.callchain_id, + s.thread_id, + thread.process_id + from perf_sample s, trace_range t + left join perf_thread thread on s.thread_id = thread.thread_id + where timestamp_trace between ${selectionParam.leftNs} + t.start_ts + and ${selectionParam.rightNs} + t.start_ts + and s.callchain_id != -1 + and s.thread_id != 0 ${filterSql} + group by s.callchain_id`, + { + $startTime: selectionParam.leftNs, + $endTime: selectionParam.rightNs, + $sql: filterSql, + } + ); + } + private handleDataByFuncName(funcName: string, funcArgs: unknown[]): unknown { let result; switch (funcName) { @@ -984,6 +1092,9 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { case 'getCurrentDataFromDb': this.queryDataFromDb(funcArgs); break; + case 'getVaddrToFile': + this.queryVaddrToFile(funcArgs); + break; case 'hideSystemLibrary': this.hideSystemLibrary(); break; @@ -1054,6 +1165,9 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { ) { let analysisSample = new PerfAnalysisSample( threadName, + lastCallChain.depth, + lastCallChain.vaddrInFile, + lastCallChain.offsetToVaddr, processName, lastCallChain.fileId, lastCallChain.fileName, @@ -1243,6 +1357,7 @@ export class PerfCallChain { sampleId: number = 0; callChainId: number = 0; vaddrInFile: number = 0; + offsetToVaddr: number = 0; tid: number = 0; pid: number = 0; name: number | string = 0; @@ -1314,6 +1429,7 @@ export class PerfCallChainMerageData extends ChartStruct { initChildren: PerfCallChainMerageData[] = []; type: number = 0; vaddrInFile: number = 0; + offsetToVaddr: number = 0; isSelected: boolean = false; searchShow: boolean = true; isSearch: boolean = false; @@ -1365,6 +1481,7 @@ export class PerfCallChainMerageData extends ChartStruct { currentNode.tid = sample.tid; currentNode.libName = callChain.fileName; currentNode.vaddrInFile = callChain.vaddrInFile; + currentNode.offsetToVaddr = callChain.offsetToVaddr; currentNode.lib = callChain.fileName; currentNode.addr = `${'0x'}${callChain.vaddrInFile.toString(16)}`; currentNode.canCharge = callChain.canCharge; @@ -1412,6 +1529,9 @@ export class PerfCmdLine { class PerfAnalysisSample extends PerfCountSample { threadName: string; + depth: number; + vaddr_in_file: number; + offset_to_vaddr: number; processName: string; libId: number; libName: string; @@ -1420,6 +1540,9 @@ class PerfAnalysisSample extends PerfCountSample { constructor( threadName: string, + depth: number, + vaddr_in_file: number, + offset_to_vaddr: number, processName: string, libId: number, libName: string, @@ -1428,6 +1551,9 @@ class PerfAnalysisSample extends PerfCountSample { ) { super(); this.threadName = threadName; + this.depth = depth; + this.vaddr_in_file = vaddr_in_file; + this.offset_to_vaddr = offset_to_vaddr; this.processName = processName; this.libId = libId; this.libName = libName; diff --git a/ide/src/trace/database/sql/Func.sql.ts b/ide/src/trace/database/sql/Func.sql.ts index f2a47dc58b15a7674249a751362d3dff5add2008..eeaba5ff92873c3e077bb574c028264ff7609115 100644 --- a/ide/src/trace/database/sql/Func.sql.ts +++ b/ide/src/trace/database/sql/Func.sql.ts @@ -326,6 +326,7 @@ export const getTabSlicesAsyncFunc = ( let sql = ` SELECT c.name AS name, + c.id, sum( c.dur ) AS wallDuration, count( c.name ) AS occurrences FROM @@ -368,6 +369,7 @@ export const getTabDetails = ( SELECT c.name AS name, c.dur AS duration, + c.id, P.pid AS processId, P.name AS process, A.tid AS threadId, @@ -408,6 +410,7 @@ export const getSfDetails = ( P.name AS process, A.tid AS threadId, A.name AS thread, + c.id, c.ts - D.start_ts as startNs FROM (SELECT id, ts, parent_id, dur, name from callstack where cookie NOT NULL) C, @@ -423,6 +426,73 @@ export const getSfDetails = ( `; return query('getSfDetails', sql, {}); }; +export const getParentDetail = ( + asyncPid: Array, + funTids: Array, + leftNS: number, + rightNS: number): + Promise> => + query( + 'getParentTime', + ` SELECT + C.ts - D.start_ts AS startTS, + C.ts - D.start_ts + C.dur AS endTS, + C.depth, + c.id, + c.name + FROM + thread A + JOIN trace_range D + LEFT JOIN process P ON P.id = A.ipid + LEFT JOIN callstack C ON A.id = C.callid + WHERE + C.ts > 0 + AND C.dur >= - 1 + AND NOT ( + ( C.ts - D.start_ts + C.dur < ${leftNS} ) + OR ( C.ts - D.start_ts > ${rightNS} ) + ) + AND C.cookie IS NULL + AND A.tid IN (${funTids!.join(',')}) + AND P.pid IN (${asyncPid.join(',')}) + ` + ); +export const getFuncChildren = ( + funcIds: Array, + asyncPid: Array, + funTids: Array, + leftNS: number, + rightNS: number, + isChild: boolean +): //@ts-ignore + Promise> => { + let durStr = isChild ? 'C.dur AS duration,' : 'SUM(COALESCE(C.dur, 0)) AS duration,'; + let condition = isChild ? '' : 'group by parentName'; + let sql = ` + SELECT + c.parent_id parentId, + ${durStr} + c.id, + c.name, + c1.name parentName + FROM + thread A,trace_range D + LEFT JOIN process P ON P.id = A.ipid + LEFT JOIN callstack C ON A.id = C.callid + LEFT JOIN callstack C1 ON c.parent_id = C1.id + where + C.ts > 0 + and + c.dur >= -1 + and + not ((C.ts - D.start_ts + C.dur < ${leftNS}) or (C.ts - D.start_ts > ${rightNS})) + and A.tid in (${funTids!.join(',')}) + and c.cookie is null + and P.pid in (${asyncPid.join(',')}) + and c.parent_id in (${funcIds.join(',')})${condition} + `; + return query('getTabDetails', sql, {}); +}; export const getGhDetails = ( asyncNames: Array, catName: string, @@ -476,6 +546,7 @@ export const getTabSlicesAsyncCatFunc = ( ` select c.name as name, + c.id, sum(c.dur) as wallDuration, count(c.name) as occurrences from diff --git a/ide/src/trace/database/sql/ProcessThread.sql.ts b/ide/src/trace/database/sql/ProcessThread.sql.ts index 1fa345fe39cd75966f70b0560c221e9492a6bb89..40812eabcd581095c5449614afd4951ccdc4aa81 100644 --- a/ide/src/trace/database/sql/ProcessThread.sql.ts +++ b/ide/src/trace/database/sql/ProcessThread.sql.ts @@ -1215,6 +1215,7 @@ export const getTabSlices = ( ` select c.name as name, + c.id, sum(c.dur) as wallDuration, count(c.name) as occurrences from diff --git a/ide/src/webSocket/Constants.ts b/ide/src/webSocket/Constants.ts index f39f64e1b90bd41063eb3c6ba0ab89d71c9d32bf..c44949c0856bd32f0a7f4e1d3428c097ff950abe 100644 --- a/ide/src/webSocket/Constants.ts +++ b/ide/src/webSocket/Constants.ts @@ -17,8 +17,16 @@ export class Constants { static INTERVAL_TIME = 30000; static LOGIN_PARAM = { type: 0, cmd: 1 }; static LOGIN_CMD = 2;// cmd 2 有效 3无效 + static SESSION_EXCEED = 3; // session满了 static GET_CMD = 1; static UPDATE_CMD = 3; + static GET_VERSION_CMD = 1; + static UPDATE_SUCCESS_CMD = 2; // 升级成功 + static UPDATE_FAIL_CMD = 4; // 升级失败 + static DISASSEMBLY_SAVE_CMD = 1; + static DISASSEMBLY_SAVE_BACK_CMD = 2; + static DISASSEMBLY_QUERY_CMD = 3; + static DISASSEMBLY_QUERY_BACK_CMD = 4; } export class TypeConstants { @@ -28,4 +36,14 @@ export class TypeConstants { static DIAGNOSIS_TYPE = 8; static SENDDB_CMD = 1; static DIAGNOSIS_CMD = 3; + static DISASSEMBLY_TYPE = 12; + static ARKTS_TYPE = 9; + static PROCESS_TYPE = 3; + static USB_TYPE = 10; + static USB_SN_CMD = 1; + static USB_GET_PROCESS = 2; + static USB_GET_CPU_COUNT = 3; + static USB_GET_EVENT = 4; + static USB_GET_APP = 5; + static USB_GET_VERSION = 6; } \ No newline at end of file diff --git a/ide/src/webSocket/WebSocketManager.ts b/ide/src/webSocket/WebSocketManager.ts index cb96890558aee401fc031484e42ecb0a348b4dd7..35129400ba7fb8e72fee34e68c8463adec1167db 100644 --- a/ide/src/webSocket/WebSocketManager.ts +++ b/ide/src/webSocket/WebSocketManager.ts @@ -15,15 +15,32 @@ import { Utils, MessageParam } from './Util'; import { Constants, TypeConstants } from './Constants'; +// 状态枚举 +enum GetStatuses { + UNCONNECTED = 'unconnected', // 服务器未连接 + CONNECTED = 'connected', // 服务器已连接 + LOGINED = 'logined', // 已登录 + LOGINFAILEDBYLACKSESSION = 'loginFailedByLackSession', // session已满 + UPFRADING = 'upgrading', // 正在升级 + UPGRADESUCCESS = 'upgradeSuccess', // 升级成功 + UPGRADEFAILED = 'upgradeFailed', // 升级失败 + READY = 'ready' // 服务与扩展程序准备就绪 +} +const INTERMEDIATE_STATE = 'Intermediate state'; +const FAILED_STATE = 'Failed state'; + + export class WebSocketManager { static instance: WebSocketManager | null | undefined = null; - url: string = `ws://localhost:${Constants.NODE_PORT}`;//8080后期需要修改 + url: string = `ws://localhost:${Constants.NODE_PORT}`; private websocket: WebSocket | null | undefined = null; - private ready: boolean = false; - private distributeMap: Map = new Map(); + private distributeMap: Map = new Map(); private sessionId: number | null | undefined; private session: bigint | null | undefined; private heartbeatInterval: number | null | undefined; + private status: string = GetStatuses.UNCONNECTED; + private cacheInfo: Map = new Map(); + private reconnect: number = -1; constructor() { if (WebSocketManager.instance) { @@ -38,10 +55,11 @@ export class WebSocketManager { this.websocket = new WebSocket(this.url); this.websocket.binaryType = 'arraybuffer'; this.websocket.onopen = (): void => { - // 设置心跳定时器 + this.status = GetStatuses.CONNECTED; + // 设置心跳定时器 this.sendHeartbeat(); - //检查版本 - this.getVersion(); + // 连接后登录 + this.login(); }; //接受webSocket的消息 @@ -59,9 +77,11 @@ export class WebSocketManager { }; this.websocket.onclose = (event): void => { - this.initLoginInfor(); + this.status = GetStatuses.UNCONNECTED; + this.finalStatus(); + //初始化标志位 + this.initLoginInfo(); this.clearHeartbeat(); - this.reconnect(event); }; } @@ -71,39 +91,67 @@ export class WebSocketManager { * 其他业务数据分发 */ onmessage(decode: MessageParam): void { - // 解码event 调decode - if (decode.type === TypeConstants.UPDATE_TYPE) {// 升级 - if (decode.cmd === Constants.GET_CMD) { - // 小于则升级 - let targetVersion = '1.0.1'; - let currentVersion = new TextDecoder().decode(decode.data); - let result = this.compareVersion(currentVersion, targetVersion); - if (result === -1) { - this.updateVersion(); - } else { - // 连接后登录 - this.login(); - } - } - } else if (decode.type === TypeConstants.LOGIN_TYPE) {// 登录 - if (decode.cmd === Constants.LOGIN_CMD) { - this.ready = true; - this.sessionId = decode.session_id; - this.session = decode.session; - } + if (decode.type === TypeConstants.LOGIN_TYPE) { // 先登录 + this.loginMessage(decode); + } else if (decode.type === TypeConstants.UPDATE_TYPE) {// 升级 + this.updateMessage(decode); } else {// type其他 - for (let [key, callback] of this.distributeMap.entries()) { - if (key === decode.type) { - callback(decode.cmd, decode.data); - } - }; + this.businessMessage(decode) + } + } + + // 登录 + loginMessage(decode: MessageParam): void { + if (decode.cmd === Constants.LOGIN_CMD) { + this.status = GetStatuses.LOGINED; + this.sessionId = decode.session_id; + this.session = decode.session; + //检查版本 + this.getVersion(); + } else if (decode.cmd === Constants.SESSION_EXCEED) { // session满了 + this.status = GetStatuses.LOGINFAILEDBYLACKSESSION; + this.finalStatus(); + } + } + + // 升级 + updateMessage(decode: MessageParam): void { + if (decode.cmd === Constants.GET_VERSION_CMD) { + // 小于则升级 + let targetVersion = '1.0.2'; + let currentVersion = new TextDecoder().decode(decode.data); + let result = this.compareVersion(currentVersion, targetVersion); + if (result === -1) { + this.status = GetStatuses.UPFRADING; + this.updateVersion(); + return; + } + this.status = GetStatuses.READY; + this.finalStatus(); + } else if (decode.cmd === Constants.UPDATE_SUCCESS_CMD) { // 升级成功 + this.status = GetStatuses.UPGRADESUCCESS; + this.finalStatus(); + } else if (decode.cmd === Constants.UPDATE_FAIL_CMD) { // 升级失败 + this.status = GetStatuses.UPGRADEFAILED; + this.finalStatus(); + } + } + + // 业务 + businessMessage(decode: MessageParam): void { + if (this.distributeMap.has(decode.type!)){ + const callbackObj = this.distributeMap.get(decode.type!)!; + // 遍历调用所有 eventCallBacks + callbackObj.messageCallbacks.forEach(callback => { + callback(decode.cmd, decode.data); + }); } } // get版本 getVersion(): void { // 获取扩展程序版本 - this.send(TypeConstants.UPDATE_TYPE, Constants.GET_CMD); + this.send(TypeConstants.UPDATE_TYPE, Constants.GET_VERSION_CMD); } //check版本 @@ -140,6 +188,8 @@ export class WebSocketManager { }).then((arrayBuffer) => { this.send(TypeConstants.UPDATE_TYPE, Constants.UPDATE_CMD, new Uint8Array(arrayBuffer)); }).catch((error) => { + this.status = GetStatuses.UPGRADEFAILED; + this.finalStatus(); console.error(error); }); } @@ -157,19 +207,51 @@ export class WebSocketManager { return WebSocketManager.instance } - // WebSocket是否登录成功 - isReady(): boolean { - return this.ready; - } - /** * 消息监听器 * listener是不同模块传来接收数据的函数 * 模块调用 */ - registerMessageListener(type: number, callback: Function): void { + registerMessageListener(type: number, callback: Function, eventCallBack: Function): void { + this.register(type, callback, eventCallBack); + } + + /** + * 消息监听器 + * listener是不同模块传来接收数据的函数 + * 模块调用 + */ + registerCallback(type: number, callback: Function): void { + this.register(type, callback); + } + + private register(type: number, callback: Function, eventCallBack: Function = () => {}): void { + let callbackObj = this.distributeMap.get(type); + if (!callbackObj) { + callbackObj = { + messageCallbacks: [callback], + eventCallBack: eventCallBack + }; + this.distributeMap.set(type, callbackObj); + } else { + if (!callbackObj.messageCallbacks.includes(callback)) { + callbackObj.messageCallbacks.push(callback); + } + callbackObj.eventCallBack = eventCallBack; + } + } + + // 删除回调函数 + unregisterCallback(type: number, callback: Function): void { if (!this.distributeMap.has(type)) { - this.distributeMap.set(type, callback); + return; + } + const callbackObj = this.distributeMap.get(type)!; + callbackObj.messageCallbacks = callbackObj.messageCallbacks.filter((cb) => cb !== callback); + + // 如果回调数组为空,同时 eventCallBack 也为空,则可以删除整个类型 + if (callbackObj.messageCallbacks.length === 0 && !callbackObj.eventCallBack) { + this.distributeMap.delete(type); } } @@ -178,11 +260,16 @@ export class WebSocketManager { * 模块调 */ sendMessage(type: number, cmd?: number, data?: Uint8Array): void { - // 检查WebSocket是否登录成功 - if (!this.ready) {// 改判断条件 ready - return; + // 初始化重连标志位 + this.reconnect = -1; + // 检查状态 + if (this.status !== GetStatuses.READY) { + // 缓存数据 + this.cache(type, cmd, data); + this.checkStatus(type); + } else { + this.send(type, cmd, data); } - this.send(type, cmd, data); } send(type: number, cmd?: number, data?: Uint8Array): void { @@ -198,25 +285,12 @@ export class WebSocketManager { this.websocket!.send(encode!); } - /** - * 传递数据信息至webSocket - * 模块调 - */ - reconnect(event: unknown): void { - //@ts-ignore - if (event.wasClean) {// 正常关闭 - return; - } - // 未连接成功打开定时器 - setTimeout(() => { - this.connectWebSocket(); - }, Constants.INTERVAL_TIME); - } - - // 定时检查心跳 + // 定时检查心跳 sendHeartbeat(): void { this.heartbeatInterval = window.setInterval(() => { - this.sendMessage(TypeConstants.HEARTBEAT_TYPE); + if (this.status === GetStatuses.READY) { + this.send(TypeConstants.HEARTBEAT_TYPE, undefined, undefined); + } }, Constants.INTERVAL_TIME); } @@ -224,8 +298,7 @@ export class WebSocketManager { * 重连时初始化登录信息 * 在异常关闭时调用 */ - initLoginInfor(): void { - this.ready = false; + initLoginInfo(): void { this.sessionId = null; this.session = null; } @@ -237,4 +310,72 @@ export class WebSocketManager { this.heartbeatInterval = null; } } + + // 缓存数据 + cache(type: number, cmd?: number, data?: Uint8Array): void { + if (!this.cacheInfo.has(type)) { + this.cacheInfo.set(type, { type, cmd, data }); + } else { + let obj = this.cacheInfo.get(type); + // @ts-ignore + obj.cmd = cmd; + //@ts-ignore + obj.data = data + } + } + + // 检查状态 中间状态,最终失败状态,最终成功状态 + checkStatus(type: number): void { + // @ts-ignore + let statuses = this.getStatusesPrompt()[this.status]; + const distributeEntry = this.distributeMap.get(type); + + if (distributeEntry && typeof distributeEntry.eventCallBack === 'function') { + if (statuses.type === INTERMEDIATE_STATE) { + distributeEntry.eventCallBack(this.status); + } else if (statuses.type === FAILED_STATE) { + this.reconnect = type; + this.connectWebSocket(); + } + } + } + + // 重连后确认最终状态 + finalStatus(): void { + if (this.reconnect !== -1) { + if (this.status === GetStatuses.READY) { + // @ts-ignore + this.sendMessage(this.reconnect, this.cacheInfo.get(this.reconnect)!.cmd, this.cacheInfo.get(this.reconnect)!.data); + return; + } + this.distributeMap.get(this.reconnect)!.eventCallBack(this.status); + } + this.reconnect = -1; + } + + getStatusesPrompt(): unknown { + return { + unconnected: { + type: FAILED_STATE + },// 重连 + connected: { + type: INTERMEDIATE_STATE + }, // 中间 + logined: { + type: INTERMEDIATE_STATE + }, // 中间 + loginFailedByLackSession: { + type: FAILED_STATE + }, // 重连 + upgrading: { + type: INTERMEDIATE_STATE + }, // 中间 + upgradeSuccess: { + type: FAILED_STATE, + }, // 重连 + upgradeFailed: { + type: FAILED_STATE, + },// 重连 + } + } } diff --git a/ide/webpack.config.js b/ide/webpack.config.js index 05f6d5aa481aa1241e1f471a600c888f4b353f4a..955e330d89568807ed67a4a93f73e445a6c01d81 100644 --- a/ide/webpack.config.js +++ b/ide/webpack.config.js @@ -89,7 +89,7 @@ function buildMultiPlatform() { path.normalize(path.join(outPath, '/', `main.exe`)) : path.normalize(path.join(outPath, '/', `main_${platform}`)); setEnv = ''; - if (os.type() === "Windows_NT") { + if (os.type() === 'Windows_NT') { setEnv += `SET CGO_ENABLED=0&&SET GOOS=${platform}&&SET GOARCH=amd64&&`; } else { setEnv += `CGO_ENABLED=0 GOOS=${platform} GOARCH=amd64`; diff --git a/trace_streamer/build_operator.sh b/trace_streamer/build_operator.sh index 3cdcf6ec74e7600ce813d7f37a5aee270ef89263..f4b86177376bff3442e0411faed1205b4f298027 100755 --- a/trace_streamer/build_operator.sh +++ b/trace_streamer/build_operator.sh @@ -62,6 +62,6 @@ else echo "begin to build ..." prebuilts/"$gn_path"/"$ninja" -C "$out_dir" fi -if [ "$out_dir" == "macx" ];then +if [ "$out_dir" == "out/macx" ];then ./mac_depend.sh fi \ No newline at end of file diff --git a/trace_streamer/src/base/codec_cov.cpp b/trace_streamer/src/base/codec_cov.cpp index 648c6186ac667a69278cff8dc3f158da1abf12fb..7ccaaab7cd3b084061bedf938d6b94028c2af889 100644 --- a/trace_streamer/src/base/codec_cov.cpp +++ b/trace_streamer/src/base/codec_cov.cpp @@ -138,21 +138,26 @@ std::wstring String2WString(const std::string &strInput) std::cout << "strInput is empty" << std::endl; return L""; } + // 获取待转换的数据的长度 int len_in = MultiByteToWideChar(codePage, 0, (LPCSTR)strInput.c_str(), -1, NULL, 0); if (len_in <= 0) { std::cout << "The result of WideCharToMultiByte is Invalid!" << std::endl; return L""; } + // 为输出数据申请空间 std::wstring wstr_out; wstr_out.resize(len_in - 1, L'\0'); + // 数据格式转换 int to_result = MultiByteToWideChar(codePage, 0, (LPCSTR)strInput.c_str(), -1, (LPWSTR)wstr_out.c_str(), len_in); + // 判断转换结果 if (0 == to_result) { std::cout << "Can't transfer String to WString" << std::endl; } + return wstr_out; } #endif diff --git a/trace_streamer/src/base/file.cpp b/trace_streamer/src/base/file.cpp index f879ec211a2dd9a3fe080d708414eb284e9a3e9e..72a2b9a03df3005499b938d11da2478ab2f16d5c 100644 --- a/trace_streamer/src/base/file.cpp +++ b/trace_streamer/src/base/file.cpp @@ -215,7 +215,12 @@ bool LocalZip::Unzip(std::string &traceFile) #ifdef _WIN32 auto fileName = std::filesystem::path(tmpDir_).append(String2WString(filenameInZip)); #else - auto fileName = std::filesystem::path(tmpDir_).append(filenameInZip); + std::string tempFileName = filenameInZip; + if (base::GetCoding(reinterpret_cast(tempFileName.c_str()), tempFileName.length()) != + base::CODING::UTF8) { + tempFileName = "temp_" + std::to_string(i); + } + auto fileName = std::filesystem::path(tmpDir_).append(tempFileName); #endif // 是目录,则创建目录; 是文件,打开 -> 读取 -> 写入解压文件 -> 关闭 auto isDir = fileName.string().back() == '/' || fileName.string().back() == '\\'; diff --git a/trace_streamer/src/base/ts_common.h b/trace_streamer/src/base/ts_common.h index 109dd2ecb454cf87b2c873ba851e8456931e991c..a32daabdc4d271402a45428082ddda8fdf2e7def 100644 --- a/trace_streamer/src/base/ts_common.h +++ b/trace_streamer/src/base/ts_common.h @@ -26,6 +26,7 @@ namespace SysTuning { using ClockId = uint32_t; constexpr size_t G_CHUNK_SIZE = 1024 * 1024; constexpr size_t FLUSH_CHUNK_THRESHOLD = G_CHUNK_SIZE - 10000; +constexpr uint8_t RAW_TRACE_PARSE_MAX = 2; const std::string INVALID_STRING = "INVALID_STRING"; const uint64_t INVALID_ITID = std::numeric_limits::max(); const uint64_t INVALID_IPID = std::numeric_limits::max(); diff --git a/trace_streamer/src/main.cpp b/trace_streamer/src/main.cpp index 78c2ae0e6c65a0ccd7e0f112c40938e1bc7fe71b..2c5367a8c66b3d609a38864328b88e64169bb6e9 100644 --- a/trace_streamer/src/main.cpp +++ b/trace_streamer/src/main.cpp @@ -38,7 +38,6 @@ using namespace SysTuning::TraceStreamer; using namespace SysTuning::base; constexpr int G_MIN_PARAM_NUM = 2; constexpr size_t G_FILE_PERMISSION = 664; -constexpr uint8_t RAW_TRACE_PARSE_MAX = 2; constexpr uint8_t PARSER_THREAD_MAX = 16; constexpr uint8_t PARSER_THREAD_MIN = 1; std::regex traceInvalidStr("\\\\"); diff --git a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp index 0459ccdb48de9f145e74fe707da34569dff8bb05..bc7e3cf0316b0e9b6fe7c355cd5c9bff7710d10c 100644 --- a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp +++ b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp @@ -89,7 +89,9 @@ bool RawTraceParser::InitRawTraceFileHeader(std::deque::iterator &packa bool RawTraceParser::InitEventFormats(const std::string &buffer) { #ifdef IS_WASM - restCommDataCnt_ = INVALID_UINT8; // ensure that the restCommData is parsed only once + if (!isWasmReadFile_) { + restCommDataCnt_ = INVALID_UINT8; // ensure that the restCommData is parsed only once + } #endif std::string line; std::istringstream iss(buffer); @@ -226,10 +228,11 @@ bool RawTraceParser::ParseLastCommData(uint8_t type, const std::string &buffer) break; default: #ifdef IS_WASM - return false; -#else - break; + if (!isWasmReadFile_) { + return false; + } #endif + break; } ++restCommDataCnt_; return true; diff --git a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.h b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.h index 849582b64a595d41cdb77a2f3c4160b9767beed9..e983836494abe4fccdbd6bb83dced15407eddb00 100644 --- a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.h +++ b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.h @@ -44,6 +44,16 @@ public: { return rawTraceSplitCommData_; } +#ifdef IS_WASM + bool IsWasmReadFile() + { + return isWasmReadFile_; + } + void SetWasmReadFile(const bool isWasmReadFile) + { + isWasmReadFile_ = isWasmReadFile; + } +#endif private: bool ParseDataRecursively(std::deque::iterator &packagesCurIter); @@ -64,6 +74,9 @@ private: std::unique_ptr ksymsProcessor_ = nullptr; TraceDataCache *traceDataCache_ = nullptr; bool hasGotHeader_ = false; +#ifdef IS_WASM + bool isWasmReadFile_ = false; +#endif uint8_t fileType_ = 0; uint8_t restCommDataCnt_ = 0; uint32_t curCpuCoreNum_ = 0; diff --git a/trace_streamer/src/rpc/rpc_server.cpp b/trace_streamer/src/rpc/rpc_server.cpp index 396aa27c469337c4f14f411d2a06928757fdd25f..81662a43b925381b6c082a78c789a033edb2a3eb 100644 --- a/trace_streamer/src/rpc/rpc_server.cpp +++ b/trace_streamer/src/rpc/rpc_server.cpp @@ -170,16 +170,23 @@ bool RpcServer::ReadAndParseData(const std::string &filePath) TS_LOGE("can not open %s.", filePath.c_str()); return false; } + uint8_t curParseCnt = 1; while (true) { std::unique_ptr buf = std::make_unique(G_CHUNK_SIZE); inputFile.read(reinterpret_cast(buf.get()), G_CHUNK_SIZE); auto readSize = inputFile.gcount(); - ts_->ParseTraceDataSegment(std::move(buf), readSize, false, inputFile.eof()); - if (inputFile.eof()) { + if (!ts_->ParseTraceDataSegment(std::move(buf), readSize, false, inputFile.eof(), true)) { + return false; + } + // for rawtrace next parse.the first parse is for last comm data; + if (inputFile.eof() && ts_->GetFileType() == TRACE_FILETYPE_RAW_TRACE && curParseCnt < RAW_TRACE_PARSE_MAX) { + ++curParseCnt; + inputFile.clear(); + inputFile.seekg(0, std::ios::beg); + } else if (inputFile.eof()) { break; } } - ts_->WaitForParserEnd(); inputFile.close(); return true; } diff --git a/trace_streamer/src/rpc/wasm_func.cpp b/trace_streamer/src/rpc/wasm_func.cpp index 4a89700dbf547bb2633322f8c0a8a6a673da730c..fda99bb05ec820a76e1a79f54b44a56e492f3519 100644 --- a/trace_streamer/src/rpc/wasm_func.cpp +++ b/trace_streamer/src/rpc/wasm_func.cpp @@ -248,7 +248,9 @@ EMSCRIPTEN_KEEPALIVE int32_t TraceStreamerParseDataEx(int32_t dataLen, bool isFi return g_wasmTraceStreamer.SaveAndParseFfrtData(g_reqBuf, dataLen, &FfrtConvertedResultCallback, isFinish); #endif } else if (g_isZipTrace) { +#if IS_WASM return g_wasmTraceStreamer.SaveAndParseZipTraceData(g_reqBuf, dataLen, &FfrtConvertedResultCallback, isFinish); +#endif } else if (g_wasmTraceStreamer.ParseData(g_reqBuf, dataLen, nullptr, isFinish)) { return 0; } diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp index b6663a6bb0e98721936fcfa56215fddaec6fb279..78f61f496a078b4814f52c163c5bb9398381e3a3 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -289,7 +289,10 @@ void TraceStreamerSelector::InitializeParser() } } -void TraceStreamerSelector::ProcessTraceData(std::unique_ptr data, size_t size, int32_t isFinish) +void TraceStreamerSelector::ProcessTraceData(std::unique_ptr data, + size_t size, + int32_t isFinish, + bool isWasmReadFile) { if (fileType_ == TRACE_FILETYPE_H_TRACE) { pbreaderParser_->ParseTraceDataSegment(std::move(data), size); @@ -303,6 +306,11 @@ void TraceStreamerSelector::ProcessTraceData(std::unique_ptr data, si #endif } else if (fileType_ == TRACE_FILETYPE_RAW_TRACE) { #ifdef ENABLE_RAWTRACE +#ifdef IS_WASM + if (isWasmReadFile && !rawTraceParser_->IsWasmReadFile()) { + rawTraceParser_->SetWasmReadFile(true); + } +#endif rawTraceParser_->ParseTraceDataSegment(std::move(data), size, isFinish); #endif } @@ -313,7 +321,8 @@ void TraceStreamerSelector::ProcessTraceData(std::unique_ptr data, si bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr data, size_t size, bool isSplitFile, - int32_t isFinish) + int32_t isFinish, + bool isWasmReadFile) { if (size == 0) { return true; @@ -344,7 +353,7 @@ bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr dat traceDataCache_->SetSplitFileMinTime(minTs_); traceDataCache_->SetSplitFileMaxTime(maxTs_); traceDataCache_->isSplitFile_ = isSplitFile; - ProcessTraceData(std::move(data), size, isFinish); + ProcessTraceData(std::move(data), size, isFinish, isWasmReadFile); #if !IS_WASM // in the linux,isFinish = 1,clear markinfo diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.h b/trace_streamer/src/trace_streamer/trace_streamer_selector.h index c4d9bdeefecabe007e0fa032bd368e7fe2b5a627..4ca22b7d10bdc8305afa3b0af9e85403e6579a39 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.h +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.h @@ -32,7 +32,11 @@ class TraceStreamerSelector { public: TraceStreamerSelector(); ~TraceStreamerSelector(); - bool ParseTraceDataSegment(std::unique_ptr data, size_t size, bool isSplitFile, int32_t isFinish); + bool ParseTraceDataSegment(std::unique_ptr data, + size_t size, + bool isSplitFile, + int32_t isFinish, + bool isWasmReadFile = false); void EnableMetaTable(bool enabled); void EnableFileSave(bool enabled); static void SetCleanMode(bool cleanMode); @@ -95,7 +99,7 @@ public: return streamFilters_.get(); } void InitializeParser(); - void ProcessTraceData(std::unique_ptr data, size_t size, int32_t isFinish); + void ProcessTraceData(std::unique_ptr data, size_t size, int32_t isFinish, bool isWasmReadFile); // Used to obtain markinfo,skip under Linux void ClearMarkPositionInfo() diff --git a/trace_streamer/test/unittest/ebpf/bio_parser_test.cpp b/trace_streamer/test/unittest/ebpf/bio_parser_test.cpp index e5fd8939d1f206bf059bff4715b07bef96fa51f2..f3b3a39dffeb4699696893bddf52ddf5ac0f7df7 100644 --- a/trace_streamer/test/unittest/ebpf/bio_parser_test.cpp +++ b/trace_streamer/test/unittest/ebpf/bio_parser_test.cpp @@ -26,6 +26,7 @@ using namespace testing::ext; using namespace SysTuning::TraceStreamer; using namespace SysTuning::EbpfStdtype; namespace SysTuning ::TraceStreamer { +namespace BioParserUnitTest { const std::string COMMAND_LINE = "hiebpf --events ptrace --duration 50"; const uint64_t EPBF_ERROR_MAGIC = 0x12345678; const uint32_t EPBF_ERROR_HEAD_SIZE = 0; @@ -232,4 +233,5 @@ HWTEST_F(EbpfBioParserTest, EbpfBioParserCorrectWithMultipleCallback, TestSize.L auto ips1 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[0]; EXPECT_EQ(ips1, ExpectIps1); } +} // namespace BioParserUnitTest } // namespace SysTuning::TraceStreamer diff --git a/trace_streamer/test/unittest/ebpf/paged_memory_parser_test.cpp b/trace_streamer/test/unittest/ebpf/paged_memory_parser_test.cpp index a2dd377b39c7637dee81285963e56152c9cee441..4a52108fde91f653e51f0d26ea4ae8ee5ba212ed 100644 --- a/trace_streamer/test/unittest/ebpf/paged_memory_parser_test.cpp +++ b/trace_streamer/test/unittest/ebpf/paged_memory_parser_test.cpp @@ -26,6 +26,7 @@ using namespace testing::ext; using namespace SysTuning::TraceStreamer; using namespace SysTuning::EbpfStdtype; namespace SysTuning ::TraceStreamer { +namespace PagedMemoryParserUnitTest { const std::string COMMAND_LINE = "hiebpf --events ptrace --duration 50"; const uint64_t START_TIME = 1725645867369; const uint64_t END_TIME = 1725645967369; @@ -200,4 +201,5 @@ HWTEST_F(EbpfPagedMemoryParserTest, EbpfPagedMemoryParserCorrectWithMultipleCall EXPECT_EQ(stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[0], ebpfDataParser->ConvertToHexTextIndex(ips[1])); } +} // namespace PagedMemoryParserUnitTest } // namespace SysTuning::TraceStreamer diff --git a/trace_streamer/test/unittest/filter/animation_filter_test.cpp b/trace_streamer/test/unittest/filter/animation_filter_test.cpp index ed3f3fb719f9314276373d792dc669d33f3fb8d1..ffa002a0dad1327b260c71971eebd3e50f1a2bbb 100644 --- a/trace_streamer/test/unittest/filter/animation_filter_test.cpp +++ b/trace_streamer/test/unittest/filter/animation_filter_test.cpp @@ -93,7 +93,8 @@ HWTEST_F(AnimationFilterTest, InvalidCallStack, TestSize.Level1) "H:RSUniRender::Process:[xxx]", }; // invalid parentId - for (size_t i = 0, depth = 0; i < callStackNames.size(); i++) { + uint8_t depth = 0; + for (size_t i = 0; i < callStackNames.size(); i++) { std::optional parentId = 0; CallStackInternalRow callStackInternalRow = {INVALID_TIME, INVALID_TIME, INVALID_UINT32, INVALID_UINT64, callStackNames[i], ++depth}; @@ -104,7 +105,8 @@ HWTEST_F(AnimationFilterTest, InvalidCallStack, TestSize.Level1) } // the current or the parent callStackNames haven't WindowScene_ uint64_t index = INVALID_UINT64; - for (size_t i = 0, depth = 0; i < callStackNames.size(); i++) { + depth = 0; + for (size_t i = 0; i < callStackNames.size(); i++) { std::optional parentId; if (index != INVALID_UINT64) { parentId = index; @@ -242,7 +244,8 @@ HWTEST_F(AnimationFilterTest, UpdateDynamicFrameInfo, TestSize.Level1) uint64_t index = INVALID_UINT64; uint64_t startTime = 59557002299000; uint64_t dur = ONE_MILLION_NANOSECONDS; - for (size_t i = 0, depth = 0; i < callStackNames.size(); i++) { + uint8_t depth = 0; + for (size_t i = 0; i < callStackNames.size(); i++) { std::optional parentId; if (index != INVALID_UINT64) { parentId = index; diff --git a/trace_streamer/test/unittest/filter/frame_filter_test.cpp b/trace_streamer/test/unittest/filter/frame_filter_test.cpp index eaa35d1f9052f19fb564b1651f2354643b630864..03fa7f2d921263a092c798f4c76366f728c2c01c 100644 --- a/trace_streamer/test/unittest/filter/frame_filter_test.cpp +++ b/trace_streamer/test/unittest/filter/frame_filter_test.cpp @@ -17,23 +17,23 @@ #include #include "frame_filter.h" -#include "trace_data_cache.h" -#include "trace_streamer_filters.h" +#include "process_filter.h" +#include "trace_streamer_selector.h" using namespace testing::ext; using namespace SysTuning::TraceStreamer; namespace SysTuning { namespace TraceStreamer { const uint64_t START_TS = 1; -const uint32_t IPID = 1; -const uint32_t ITID = 1; +const uint32_t PID1 = 156; +const uint32_t TID1 = 248; const uint64_t EXPECTED_START = 5; const uint64_t EXPECTED_END = 10; const uint32_t VSYNC_ID = 1; const uint32_t CALLSTACK_SLICE_ID = 1; const uint64_t RS_START_TS = 5; -const uint32_t RS_IPID = 2; -const uint32_t RS_ITID = 2; +const uint32_t RS_PID = 2; +const uint32_t RS_TID = 2; const uint64_t RS_EXPECTED_START = 6; const uint64_t RS_EXPECTED_END = 11; const uint32_t RS_VSYNC_ID = 2; @@ -43,14 +43,13 @@ class FrameFilterTest : public ::testing::Test { public: void SetUp() { - streamFilters_.frameFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + stream_.InitFilter(); } void TearDown() {} public: - TraceStreamerFilters streamFilters_; - TraceDataCache traceDataCache_; + TraceStreamerSelector stream_ = {}; }; /** @@ -63,17 +62,20 @@ HWTEST_F(FrameFilterTest, AppVsyncNoFrameNum, TestSize.Level1) TS_LOGI("test6-1"); // ut 1 no frameNum // app ---------------VSYNCStart------------------End---uint64_t ts, - streamFilters_.frameFilter_->BeginVsyncEvent(START_TS, IPID, ITID, EXPECTED_START, EXPECTED_END, VSYNC_ID, - CALLSTACK_SLICE_ID); + BytraceLine line = {START_TS, TID1}; + line.tgid = PID1; + auto itid = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(TID1, PID1); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line, EXPECTED_START, EXPECTED_END, VSYNC_ID, + CALLSTACK_SLICE_ID); const uint64_t END_TS = 10; - auto res = streamFilters_.frameFilter_->EndVsyncEvent(END_TS, ITID); + auto res = stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS, itid); EXPECT_FALSE(res); - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->Flags()[0], 2); // actural frame, no frameNum - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->Flags()[1], 2); // expect frame, no frameNum - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->TimeStampData()[0], START_TS); // actural frame - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->TimeStampData()[1], EXPECTED_START); // expect frame - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->Durs()[0], END_TS - START_TS); // actural frame - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->Durs()[1], EXPECTED_END - EXPECTED_START); // expect frame + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->Flags()[0], 2); // actural frame, no frameNum + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->Flags()[1], 2); // expect frame, no frameNum + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->TimeStampData()[0], START_TS); // actural frame + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->TimeStampData()[1], EXPECTED_START); // expect frame + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->Durs()[0], END_TS - START_TS); // actural frame + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->Durs()[1], EXPECTED_END - EXPECTED_START); // expect frame } /** @@ -87,22 +89,25 @@ HWTEST_F(FrameFilterTest, AppVsyncHasFrameNum, TestSize.Level1) // ut 2 has frameNum // app -----VSYNCStart------------------End--- // -----------------frameNum-------------- - streamFilters_.frameFilter_->BeginVsyncEvent(START_TS, IPID, ITID, EXPECTED_START, EXPECTED_END, VSYNC_ID, - CALLSTACK_SLICE_ID); + BytraceLine line = {START_TS, TID1}; + line.tgid = PID1; + auto itid = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(TID1, PID1); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line, EXPECTED_START, EXPECTED_END, VSYNC_ID, + CALLSTACK_SLICE_ID); const uint64_t FRAME_TS = 5; const uint32_t FRAME_NUM = 1; - bool res = streamFilters_.frameFilter_->BeginRSTransactionData(FRAME_TS, ITID, FRAME_NUM); + bool res = stream_.streamFilters_->frameFilter_->BeginRSTransactionData(FRAME_TS, itid, FRAME_NUM); EXPECT_TRUE(res); const uint64_t END_TS = 10; - res = streamFilters_.frameFilter_->EndVsyncEvent(END_TS, ITID); + res = stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS, itid); EXPECT_TRUE(res); - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->Flags()[0], 0); // actural frame, no frameNum - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->Flags()[1], 255); // expect frame, no frameNum - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->TimeStampData()[0], START_TS); // actural frame - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->TimeStampData()[1], EXPECTED_START); // expect frame - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->Durs()[0], END_TS - START_TS); // actural frame - EXPECT_EQ(traceDataCache_.GetFrameSliceData()->Durs()[1], EXPECTED_END - EXPECTED_START); // expect frame - EXPECT_EQ(streamFilters_.frameFilter_->dstRenderSlice_[ITID][FRAME_NUM].get()->startTs_, START_TS); + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->Flags()[0], 0); // actural frame, no frameNum + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->Flags()[1], 255); // expect frame, no frameNum + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->TimeStampData()[0], START_TS); // actural frame + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->TimeStampData()[1], EXPECTED_START); // expect frame + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->Durs()[0], END_TS - START_TS); // actural frame + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->Durs()[1], EXPECTED_END - EXPECTED_START); // expect frame + EXPECT_EQ(stream_.streamFilters_->frameFilter_->dstRenderSlice_[itid][FRAME_NUM].get()->startTs_, START_TS); } /** * @tc.name: RSVsyncHasFrameNum @@ -114,15 +119,18 @@ HWTEST_F(FrameFilterTest, RSVsyncHasNoFrameNum, TestSize.Level1) TS_LOGI("test6-3"); // ut3 RS no frame // RS ---------------VSYNCStart------------------End--- - streamFilters_.frameFilter_->BeginVsyncEvent(START_TS, IPID, ITID, EXPECTED_START, EXPECTED_END, VSYNC_ID, - CALLSTACK_SLICE_ID); + BytraceLine line = {START_TS, TID1}; + line.tgid = PID1; + auto itid = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(TID1, PID1); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line, EXPECTED_START, EXPECTED_END, VSYNC_ID, + CALLSTACK_SLICE_ID); const uint64_t ON_DO_COMPOSITION_TS = 2; - auto res = streamFilters_.frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, ITID); + auto res = stream_.streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, itid); EXPECT_TRUE(res); const uint64_t END_TS = 10; - res = streamFilters_.frameFilter_->EndVsyncEvent(END_TS, ITID); + res = stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS, itid); EXPECT_TRUE(res); - EXPECT_TRUE(streamFilters_.frameFilter_->vsyncRenderSlice_[ITID].begin()->get()->isRsMainThread_ == true); + EXPECT_TRUE(stream_.streamFilters_->frameFilter_->vsyncRenderSlice_[itid].begin()->get()->isRsMainThread_ == true); } /** @@ -136,10 +144,13 @@ HWTEST_F(FrameFilterTest, RSVsyncHasFrameNumNotMatched, TestSize.Level1) // ut4 RS has frame, bu not matched // RS -----VSYNCStart------------------End--- // -----------frameNum------------------- - streamFilters_.frameFilter_->BeginVsyncEvent(START_TS, IPID, ITID, EXPECTED_START, EXPECTED_END, VSYNC_ID, - CALLSTACK_SLICE_ID); + BytraceLine line = {START_TS, TID1}; + line.tgid = PID1; + auto itid = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(TID1, PID1); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line, EXPECTED_START, EXPECTED_END, VSYNC_ID, + CALLSTACK_SLICE_ID); const uint64_t ON_DO_COMPOSITION_TS = 2; - auto res = streamFilters_.frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, ITID); + auto res = stream_.streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, itid); EXPECT_TRUE(res); const uint32_t SOURCE_ITID1 = 2; @@ -147,12 +158,12 @@ HWTEST_F(FrameFilterTest, RSVsyncHasFrameNumNotMatched, TestSize.Level1) const uint64_t UNI_TS = 3; std::vector frames; frames.push_back({SOURCE_ITID1, SOURCE_FRAME_NUM}); - streamFilters_.frameFilter_->BeginProcessCommandUni(UNI_TS, ITID, frames, 0); + stream_.streamFilters_->frameFilter_->BeginProcessCommandUni(UNI_TS, itid, frames, 0); const uint64_t END_TS = 10; - res = streamFilters_.frameFilter_->EndVsyncEvent(END_TS, ITID); + res = stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS, itid); EXPECT_TRUE(res); - EXPECT_TRUE(streamFilters_.frameFilter_->vsyncRenderSlice_[ITID].begin()->get()->isRsMainThread_ == true); - EXPECT_TRUE(traceDataCache_.GetFrameSliceData()->Srcs()[0].empty() == true); + EXPECT_TRUE(stream_.streamFilters_->frameFilter_->vsyncRenderSlice_[itid].begin()->get()->isRsMainThread_ == true); + EXPECT_TRUE(stream_.traceDataCache_->GetFrameSliceData()->Srcs()[0].empty() == true); } /** @@ -166,10 +177,13 @@ HWTEST_F(FrameFilterTest, RSVsyncHasGpu, TestSize.Level1) // ut5 RS has gpu inner // RS -----VSYNCStart------------------End--- // --------------gpuStart----gpuEnd---------- - streamFilters_.frameFilter_->BeginVsyncEvent(START_TS, IPID, ITID, EXPECTED_START, EXPECTED_END, VSYNC_ID, - CALLSTACK_SLICE_ID); + BytraceLine line = {START_TS, TID1}; + line.tgid = PID1; + auto itid = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(TID1, PID1); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line, EXPECTED_START, EXPECTED_END, VSYNC_ID, + CALLSTACK_SLICE_ID); const uint64_t ON_DO_COMPOSITION_TS = 2; - auto res = streamFilters_.frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, ITID); + auto res = stream_.streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, itid); EXPECT_TRUE(res); const uint32_t SOURCE_ITID1 = 2; @@ -177,12 +191,13 @@ HWTEST_F(FrameFilterTest, RSVsyncHasGpu, TestSize.Level1) const uint64_t UNI_TS = 3; std::vector frames; frames.push_back({SOURCE_ITID1, SOURCE_FRAME_NUM}); - streamFilters_.frameFilter_->BeginProcessCommandUni(UNI_TS, ITID, frames, 0); + stream_.streamFilters_->frameFilter_->BeginProcessCommandUni(UNI_TS, itid, frames, 0); const uint64_t END_TS = 10; - res = streamFilters_.frameFilter_->EndVsyncEvent(END_TS, ITID); + res = stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS, itid); EXPECT_TRUE(res); - EXPECT_TRUE((streamFilters_.frameFilter_->vsyncRenderSlice_[ITID].begin()->get()->isRsMainThread_ == true)); - EXPECT_TRUE(traceDataCache_.GetFrameSliceData()->Srcs()[0].empty() == true); + EXPECT_TRUE( + (stream_.streamFilters_->frameFilter_->vsyncRenderSlice_[itid].begin()->get()->isRsMainThread_ == true)); + EXPECT_TRUE(stream_.traceDataCache_->GetFrameSliceData()->Srcs()[0].empty() == true); } /** @@ -196,23 +211,27 @@ HWTEST_F(FrameFilterTest, RSVsyncHasGpuCross, TestSize.Level1) // ut6 RS has gpu later // RS -----VSYNCStart------------------End------------ // ------------------------------gpuStart----gpuEnd--- - streamFilters_.frameFilter_->BeginVsyncEvent(START_TS, IPID, ITID, EXPECTED_START, EXPECTED_END, VSYNC_ID, - CALLSTACK_SLICE_ID); + BytraceLine line = {START_TS, TID1}; + line.tgid = PID1; + auto itid = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(TID1, PID1); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line, EXPECTED_START, EXPECTED_END, VSYNC_ID, + CALLSTACK_SLICE_ID); const uint64_t ON_DO_COMPOSITION_TS = 2; - auto res = streamFilters_.frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, ITID); + auto res = stream_.streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, itid); EXPECT_TRUE(res); const uint64_t GPU_START_TS = 3; - streamFilters_.frameFilter_->StartFrameQueue(GPU_START_TS, ITID); + stream_.streamFilters_->frameFilter_->StartFrameQueue(GPU_START_TS, itid); const uint64_t END_TS = 10; - res = streamFilters_.frameFilter_->EndVsyncEvent(END_TS, ITID); + res = stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS, itid); EXPECT_TRUE(res); const uint64_t GPU_END_TS = 15; - res = streamFilters_.frameFilter_->EndFrameQueue(GPU_END_TS, ITID); + res = stream_.streamFilters_->frameFilter_->EndFrameQueue(GPU_END_TS, itid); EXPECT_TRUE(res); - EXPECT_TRUE((streamFilters_.frameFilter_->vsyncRenderSlice_[ITID].begin()->get()->isRsMainThread_ == true)); - EXPECT_TRUE(traceDataCache_.GetFrameSliceData()->Durs()[0] == GPU_END_TS - START_TS); + EXPECT_TRUE( + (stream_.streamFilters_->frameFilter_->vsyncRenderSlice_[itid].begin()->get()->isRsMainThread_ == true)); + EXPECT_TRUE(stream_.traceDataCache_->GetFrameSliceData()->Durs()[0] == GPU_END_TS - START_TS); } /** @@ -226,15 +245,18 @@ HWTEST_F(FrameFilterTest, RSVsyncHasGpu2Slices, TestSize.Level1) // ut7 RS two slice across // RS -----VSYNCStart------------------End-----VSYNCStart------------------End-------- // --------------gpuStart------------------------------gpuEnd---------gpuStart----gpuEnd------ - streamFilters_.frameFilter_->BeginVsyncEvent(START_TS, IPID, ITID, EXPECTED_START, EXPECTED_END, VSYNC_ID, - CALLSTACK_SLICE_ID); + BytraceLine line1 = {START_TS, TID1}; + line1.tgid = PID1; + auto itid = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(TID1, PID1); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line1, EXPECTED_START, EXPECTED_END, VSYNC_ID, + CALLSTACK_SLICE_ID); const uint64_t ON_DO_COMPOSITION_TS = 2; - auto res = streamFilters_.frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, ITID); + auto res = stream_.streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS, itid); EXPECT_TRUE(res); const uint64_t GPU_START_TS = 3; - streamFilters_.frameFilter_->StartFrameQueue(GPU_START_TS, ITID); + stream_.streamFilters_->frameFilter_->StartFrameQueue(GPU_START_TS, itid); const uint64_t END_TS = 10; - res = streamFilters_.frameFilter_->EndVsyncEvent(END_TS, ITID); + res = stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS, itid); EXPECT_TRUE(res); const uint64_t START_TS2 = 4; @@ -242,29 +264,32 @@ HWTEST_F(FrameFilterTest, RSVsyncHasGpu2Slices, TestSize.Level1) const uint64_t EXPECTED_END2 = 11; const uint32_t VSYNC_ID2 = 2; const uint32_t CALLSTACK_SLICE_ID2 = 2; - - streamFilters_.frameFilter_->BeginVsyncEvent(START_TS2, IPID, ITID, EXPECTED_START2, EXPECTED_END2, VSYNC_ID2, - CALLSTACK_SLICE_ID2); + BytraceLine line2 = {START_TS2, TID1}; + line2.tgid = PID1; + auto itid2 = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(TID1, PID1); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line2, EXPECTED_START2, EXPECTED_END2, VSYNC_ID2, + CALLSTACK_SLICE_ID2); const uint64_t ON_DO_COMPOSITION_TS2 = 5; - res = streamFilters_.frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS2, ITID); + res = stream_.streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS2, itid2); EXPECT_TRUE(res); const uint64_t GPU_END_TS = 15; - res = streamFilters_.frameFilter_->EndFrameQueue(GPU_END_TS, ITID); + res = stream_.streamFilters_->frameFilter_->EndFrameQueue(GPU_END_TS, itid2); const uint64_t GPU_START_TS2 = 16; - streamFilters_.frameFilter_->StartFrameQueue(GPU_START_TS2, ITID); + stream_.streamFilters_->frameFilter_->StartFrameQueue(GPU_START_TS2, itid2); const uint64_t END_TS2 = 18; - res = streamFilters_.frameFilter_->EndVsyncEvent(END_TS2, ITID); + res = stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS2, itid2); const uint64_t GPU_END_TS2 = 20; - res = streamFilters_.frameFilter_->EndFrameQueue(GPU_END_TS2, ITID); + res = stream_.streamFilters_->frameFilter_->EndFrameQueue(GPU_END_TS2, itid2); EXPECT_TRUE(res); - EXPECT_TRUE((streamFilters_.frameFilter_->vsyncRenderSlice_[ITID].begin()->get()->isRsMainThread_ == true)); - EXPECT_TRUE(traceDataCache_.GetFrameSliceData()->Durs()[0] == GPU_END_TS - START_TS); - EXPECT_TRUE(traceDataCache_.GetFrameSliceData()->Durs()[2] == GPU_END_TS2 - START_TS2); - EXPECT_TRUE(streamFilters_.frameFilter_->vsyncRenderSlice_.size() == 1); + EXPECT_TRUE( + (stream_.streamFilters_->frameFilter_->vsyncRenderSlice_[itid].begin()->get()->isRsMainThread_ == true)); + EXPECT_TRUE(stream_.traceDataCache_->GetFrameSliceData()->Durs()[0] == GPU_END_TS - START_TS); + EXPECT_TRUE(stream_.traceDataCache_->GetFrameSliceData()->Durs()[2] == GPU_END_TS2 - START_TS2); + EXPECT_TRUE(stream_.streamFilters_->frameFilter_->vsyncRenderSlice_.size() == 1); } /** @@ -281,48 +306,55 @@ HWTEST_F(FrameFilterTest, SliceFromAppToRS, TestSize.Level1) // -----------------frameNum-------------- // RS -------------------------VSYNCStart------------------End-----VSYNCStart------------------End----------------- // -----------------------------------gpuStart------------------------------gpuEnd---------gpuStart----gpuEnd------ - streamFilters_.frameFilter_->BeginVsyncEvent(START_TS, IPID, ITID, EXPECTED_START, EXPECTED_END, VSYNC_ID, - CALLSTACK_SLICE_ID); + BytraceLine line = {START_TS, TID1}; + line.tgid = PID1; + auto itid = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(TID1, PID1); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line, EXPECTED_START, EXPECTED_END, VSYNC_ID, + CALLSTACK_SLICE_ID); const uint64_t ON_DO_COMPOSITION_TS = 2; const uint32_t FRAME_NUM = 1; - EXPECT_TRUE(streamFilters_.frameFilter_->BeginRSTransactionData(ON_DO_COMPOSITION_TS, ITID, FRAME_NUM)); - streamFilters_.frameFilter_->BeginVsyncEvent(RS_START_TS, RS_IPID, RS_ITID, RS_EXPECTED_START, RS_EXPECTED_END, - RS_VSYNC_ID, RS_CALLSTACK_SLICE_ID); + EXPECT_TRUE(stream_.streamFilters_->frameFilter_->BeginRSTransactionData(ON_DO_COMPOSITION_TS, itid, FRAME_NUM)); + BytraceLine line2 = {RS_START_TS, RS_PID}; + line.tgid = RS_TID; + auto itid2 = stream_.streamFilters_->processFilter_->GetOrCreateThreadWithPid(RS_TID, RS_PID); + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line2, RS_EXPECTED_START, RS_EXPECTED_END, RS_VSYNC_ID, + RS_CALLSTACK_SLICE_ID); const uint64_t ON_DO_COMPOSITION_TS2 = 7; - streamFilters_.frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS2, RS_ITID); + stream_.streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS2, RS_TID); const uint64_t GPU_START_TS2 = 7; - streamFilters_.frameFilter_->StartFrameQueue(GPU_START_TS2, RS_ITID); + stream_.streamFilters_->frameFilter_->StartFrameQueue(GPU_START_TS2, RS_TID); const uint64_t END_TS = 10; - EXPECT_TRUE(streamFilters_.frameFilter_->EndVsyncEvent(END_TS, ITID)); + EXPECT_TRUE(stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS, itid)); const uint64_t RS_END_TS = 10; - streamFilters_.frameFilter_->EndVsyncEvent(RS_END_TS, RS_ITID); + stream_.streamFilters_->frameFilter_->EndVsyncEvent(RS_END_TS, itid2); const uint64_t RS_START_TS2 = 11; const uint64_t RS_EXPECTED_START2 = 11; const uint64_t RS_EXPECTED_END2 = 25; const uint32_t RS_VSYNC_ID2 = 3; const uint32_t RS_CALLSTACK_SLICE_ID2 = 3; - streamFilters_.frameFilter_->BeginVsyncEvent(RS_START_TS2, RS_IPID, RS_ITID, RS_EXPECTED_START2, RS_EXPECTED_END2, - RS_VSYNC_ID2, RS_CALLSTACK_SLICE_ID2); + BytraceLine line3 = {RS_START_TS2, RS_PID, RS_TID}; + stream_.streamFilters_->frameFilter_->BeginVsyncEvent(line3, RS_EXPECTED_START2, RS_EXPECTED_END2, RS_VSYNC_ID2, + RS_CALLSTACK_SLICE_ID2); const uint64_t ON_DO_COMPOSITION_TS3 = 12; - streamFilters_.frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS3, RS_ITID); + stream_.streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(ON_DO_COMPOSITION_TS3, RS_TID); const uint64_t GPU_END_TS = 15; - streamFilters_.frameFilter_->EndFrameQueue(GPU_END_TS, RS_ITID); + stream_.streamFilters_->frameFilter_->EndFrameQueue(GPU_END_TS, RS_TID); const uint64_t GPU_START_TS3 = 16; - streamFilters_.frameFilter_->StartFrameQueue(GPU_START_TS3, RS_ITID); + stream_.streamFilters_->frameFilter_->StartFrameQueue(GPU_START_TS3, RS_TID); const uint64_t END_TS3 = 20; - streamFilters_.frameFilter_->EndVsyncEvent(END_TS3, RS_ITID); + stream_.streamFilters_->frameFilter_->EndVsyncEvent(END_TS3, RS_TID); const uint64_t GPU_END_TS3 = 25; - streamFilters_.frameFilter_->EndFrameQueue(GPU_END_TS3, RS_ITID); + stream_.streamFilters_->frameFilter_->EndFrameQueue(GPU_END_TS3, RS_TID); - EXPECT_TRUE(traceDataCache_.GetFrameSliceData()->Durs()[0] == END_TS - START_TS); - EXPECT_TRUE(traceDataCache_.GetFrameSliceData()->Durs()[2] == GPU_END_TS - RS_START_TS); - EXPECT_TRUE(atoi(traceDataCache_.GetFrameSliceData()->Srcs()[2].c_str()) == - traceDataCache_.GetFrameSliceData()->IdsData()[0]); + EXPECT_TRUE(stream_.traceDataCache_->GetFrameSliceData()->Durs()[0] == END_TS - START_TS); + EXPECT_EQ(stream_.traceDataCache_->GetFrameSliceData()->Durs()[2], GPU_END_TS3 - END_TS3); + EXPECT_TRUE(atoi(stream_.traceDataCache_->GetFrameSliceData()->Srcs()[2].c_str()) == + stream_.traceDataCache_->GetFrameSliceData()->IdsData()[0]); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/test/unittest/filter/measure_filter_test.cpp b/trace_streamer/test/unittest/filter/measure_filter_test.cpp index 7e152797567847ba2602d006353bf4be72632c25..e9c3ccab732905f0d4b34a50c48c74cc2ab872f3 100644 --- a/trace_streamer/test/unittest/filter/measure_filter_test.cpp +++ b/trace_streamer/test/unittest/filter/measure_filter_test.cpp @@ -57,11 +57,12 @@ HWTEST_F(MeasureFilterTest, CpuFilter, TestSize.Level1) { TS_LOGI("test23-3"); auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(CPU_TYPE_0); - uint32_t filterId = stream_.streamFilters_->cpuMeasureFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); + auto &measureFilter = stream_.streamFilters_->measureFilter_; + uint32_t filterId = measureFilter->GetOrCreateFilterId(EnumMeasureFilter::CPU, CPU_ID_0, nameIndex_0); EXPECT_TRUE(filterId == 0); auto nameIndex_1 = stream_.traceDataCache_->GetDataIndex(CPU_TYPE_1); - filterId = stream_.streamFilters_->cpuMeasureFilter_->GetOrCreateFilterId(CPU_ID_1, nameIndex_1); + filterId = measureFilter->GetOrCreateFilterId(EnumMeasureFilter::CPU, CPU_ID_1, nameIndex_1); EXPECT_TRUE(filterId == 1); Filter *filterTable = stream_.traceDataCache_->GetFilterData(); @@ -84,11 +85,12 @@ HWTEST_F(MeasureFilterTest, ClockRateFilter, TestSize.Level1) { TS_LOGI("test23-5"); auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); - uint32_t filterId = stream_.streamFilters_->clockRateFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); + auto &measureFilter = stream_.streamFilters_->measureFilter_; + uint32_t filterId = measureFilter->GetOrCreateFilterId(EnumMeasureFilter::CLOCK_RATE, CPU_ID_0, nameIndex_0); EXPECT_TRUE(filterId == 0); auto nameIndex_1 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_1); - filterId = stream_.streamFilters_->clockRateFilter_->GetOrCreateFilterId(CPU_ID_1, nameIndex_1); + filterId = measureFilter->GetOrCreateFilterId(EnumMeasureFilter::CLOCK_RATE, CPU_ID_1, nameIndex_1); EXPECT_TRUE(filterId == 1); Filter *filterTable = stream_.traceDataCache_->GetFilterData(); @@ -110,12 +112,13 @@ HWTEST_F(MeasureFilterTest, ClockRateFilter, TestSize.Level1) HWTEST_F(MeasureFilterTest, ClockEnableFilter, TestSize.Level1) { TS_LOGI("test23-6"); + auto &measureFilter = stream_.streamFilters_->measureFilter_; auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); - uint32_t filterId = stream_.streamFilters_->clockEnableFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); + uint32_t filterId = measureFilter->GetOrCreateFilterId(EnumMeasureFilter::CLOCK_ENABLE, CPU_ID_0, nameIndex_0); EXPECT_TRUE(filterId == 0); auto nameIndex_1 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_1); - filterId = stream_.streamFilters_->clockEnableFilter_->GetOrCreateFilterId(CPU_ID_1, nameIndex_1); + filterId = measureFilter->GetOrCreateFilterId(EnumMeasureFilter::CLOCK_ENABLE, CPU_ID_1, nameIndex_1); EXPECT_TRUE(filterId == 1); Filter *filterTable = stream_.traceDataCache_->GetFilterData(); @@ -137,12 +140,13 @@ HWTEST_F(MeasureFilterTest, ClockEnableFilter, TestSize.Level1) HWTEST_F(MeasureFilterTest, ClockDisableFilter, TestSize.Level1) { TS_LOGI("test23-7"); + auto &measureFilter = stream_.streamFilters_->measureFilter_; auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); - uint32_t filterId = stream_.streamFilters_->clockDisableFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); + uint32_t filterId = measureFilter->GetOrCreateFilterId(EnumMeasureFilter::CLOCK_DISABLE, CPU_ID_0, nameIndex_0); EXPECT_TRUE(filterId == 0); auto nameIndex_1 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_1); - filterId = stream_.streamFilters_->clockDisableFilter_->GetOrCreateFilterId(CPU_ID_1, nameIndex_1); + filterId = measureFilter->GetOrCreateFilterId(EnumMeasureFilter::CLOCK_DISABLE, CPU_ID_1, nameIndex_1); EXPECT_TRUE(filterId == 1); Filter *filterTable = stream_.traceDataCache_->GetFilterData(); @@ -167,8 +171,8 @@ HWTEST_F(MeasureFilterTest, MeasureFilterTest, TestSize.Level1) uint64_t itid = 1; const std::string_view MEASURE_ITEM_NAME = "mem_rss"; auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); - auto threadMeasureFilter = stream_.streamFilters_->processMeasureFilter_.get(); - threadMeasureFilter->AppendNewMeasureData(itid, nameIndex0, 168758682476000, 1200); + stream_.streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::PROCESS, itid, nameIndex0, + 168758682476000, 1200); EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == 1); } @@ -182,13 +186,14 @@ HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToSingleThread, TestSize.Lev { TS_LOGI("test23-9"); uint64_t itid = 1; - auto threadMeasureFilter = stream_.streamFilters_->processMeasureFilter_.get(); const std::string_view MEASURE_ITEM_NAME = "mem_rss"; auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); - threadMeasureFilter->AppendNewMeasureData(itid, nameIndex0, 168758682476000, 1200); + stream_.streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::PROCESS, itid, nameIndex0, + 168758682476000, 1200); const std::string_view MEASURE_ITEM_NAME2 = "mem_vm"; auto nameIndex1 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME2); - threadMeasureFilter->AppendNewMeasureData(itid, nameIndex1, 168758682477000, 9200); + stream_.streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::PROCESS, itid, nameIndex1, + 168758682477000, 9200); EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == 2); } @@ -203,13 +208,14 @@ HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToMultiThread, TestSize.Leve TS_LOGI("test23-10"); uint64_t itid = 1; uint64_t itid2 = 2; - auto threadMeasureFilter = stream_.streamFilters_->processMeasureFilter_.get(); const std::string_view MEASURE_ITEM_NAME = "mem_rss"; auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); - threadMeasureFilter->AppendNewMeasureData(itid, nameIndex0, 168758682476000, 1200); + stream_.streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::PROCESS, itid, nameIndex0, + 168758682476000, 1200); const std::string_view MEASURE_ITEM_NAME2 = "mem_vm"; auto nameIndex1 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME2); - threadMeasureFilter->AppendNewMeasureData(itid2, nameIndex1, 168758682477000, 9200); + stream_.streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::PROCESS, itid2, nameIndex1, + 168758682477000, 9200); EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == 2); EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().ValuesData()[0] == 1200); EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().ValuesData()[1] == 9200); @@ -225,10 +231,10 @@ HWTEST_F(MeasureFilterTest, MeasureFilterAddPerfclLfMux, TestSize.Level1) TS_LOGI("test23-11"); uint64_t cpuId = 1; int64_t state = 0; - auto threadMeasureFilter = stream_.streamFilters_->clockDisableFilter_.get(); const std::string_view MEASURE_ITEM_NAME = "perfcl_lf_mux"; auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); - threadMeasureFilter->AppendNewMeasureData(cpuId, nameIndex0, 168758682476000, state); + stream_.streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::CLOCK_DISABLE, cpuId, nameIndex0, + 168758682476000, state); EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == state); } @@ -243,10 +249,10 @@ HWTEST_F(MeasureFilterTest, MeasureFilterAddPerfclPll, TestSize.Level1) TS_LOGI("test23-12"); uint64_t cpuId = 1; int64_t state = 1747200000; - auto threadMeasureFilter = stream_.streamFilters_->clockRateFilter_.get(); const std::string_view MEASURE_ITEM_NAME = "perfcl_pll"; auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); - threadMeasureFilter->AppendNewMeasureData(cpuId, nameIndex0, 168758682476000, state); + stream_.streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::CLOCK_RATE, cpuId, nameIndex0, + 168758682476000, state); EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == state); } diff --git a/trace_streamer/test/unittest/pbreader_parser/diskio_parser_test.cpp b/trace_streamer/test/unittest/pbreader_parser/diskio_parser_test.cpp index 5480e2cdea2ec4d404dc633f43784fab32ff2240..f253ed093a9cc40e54363f2fac53f93190a85c92 100644 --- a/trace_streamer/test/unittest/pbreader_parser/diskio_parser_test.cpp +++ b/trace_streamer/test/unittest/pbreader_parser/diskio_parser_test.cpp @@ -30,6 +30,7 @@ using namespace SysTuning::TraceStreamer; namespace SysTuning { namespace TraceStreamer { +namespace DiskioParserUnitTest { const uint64_t TS = 100; const uint64_t RD_01 = 100; const uint64_t WR_01 = 101; @@ -237,5 +238,6 @@ HWTEST_F(PbreaderDiskioParserTest, ParsePbreaderDiskioWithMultipleDiskioData, Te EXPECT_EQ(diskIOData.WrCountDatas()[1], WR_03); EXPECT_EQ(diskIOData.WrCountDatas()[2], WR_04); } +} // namespace DiskioParserUnitTest } // namespace TraceStreamer } // namespace SysTuning \ No newline at end of file diff --git a/trace_streamer/test/unittest/pbreader_parser/hilog_parser_test.cpp b/trace_streamer/test/unittest/pbreader_parser/hilog_parser_test.cpp index 5d80c5861afd461e6c7399282a61eb5c203fe90e..3066d358ab3129113a39909f73f83f8a7fc40d65 100644 --- a/trace_streamer/test/unittest/pbreader_parser/hilog_parser_test.cpp +++ b/trace_streamer/test/unittest/pbreader_parser/hilog_parser_test.cpp @@ -30,6 +30,7 @@ using namespace SysTuning::TraceStreamer; namespace SysTuning { namespace TraceStreamer { +namespace HilogUnitTest { const uint32_t PID = 2716; const uint32_t TID = 1532; const uint64_t LOG_ID = 1; @@ -359,6 +360,6 @@ HWTEST_F(HilogParserTest, ParseTxtHilogInfoWithTimeFormat, TestSize.Level1) EXPECT_TRUE(ta->traceDataCache_->GetConstHilogData().HilogLineSeqs().size() == 5); } - +} // namespace HilogUnitTest } // namespace TraceStreamer } // namespace SysTuning \ No newline at end of file diff --git a/trace_streamer/test/unittest/pbreader_parser/native_memory/native_hook_parser_test.cpp b/trace_streamer/test/unittest/pbreader_parser/native_memory/native_hook_parser_test.cpp index 1b8bf60aaca0668de231a7cb3020914ee15d86bf..374e1863f26aa7d9ee65c74f36aad76b35f57fb0 100644 --- a/trace_streamer/test/unittest/pbreader_parser/native_memory/native_hook_parser_test.cpp +++ b/trace_streamer/test/unittest/pbreader_parser/native_memory/native_hook_parser_test.cpp @@ -32,7 +32,7 @@ using namespace SysTuning::TraceStreamer; namespace SysTuning { namespace TraceStreamer { -bool ParseTraceFile(TraceStreamerSelector &ts_, const std::string &tracePath); +namespace NativeMemoryUnitTest { const uint32_t INDEX_SIZE_02 = 2; const uint32_t INDEX_SIZE_03 = 3; const uint32_t INDEX_SIZE_04 = 4; @@ -1639,5 +1639,6 @@ HWTEST_F(NativeHookParserTest, ParseOfflineSymMixedStack, TestSize.Level1) auto &statAndInfo = stream_.traceDataCache_->GetConstStatAndInfo(); EXPECT_TRUE(1 == statAndInfo.GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED)); } +} // namespace NativeMemoryUnitTest } // namespace TraceStreamer } // namespace SysTuning \ No newline at end of file diff --git a/trace_streamer/test/unittest/pbreader_parser/pbreader_cpu_data_parser_test.cpp b/trace_streamer/test/unittest/pbreader_parser/pbreader_cpu_data_parser_test.cpp index f7e32096fd79b82c3b4fb268eaecc518a722d3f0..66ad48744fa390d684689167422d9c5b6edea5b2 100644 --- a/trace_streamer/test/unittest/pbreader_parser/pbreader_cpu_data_parser_test.cpp +++ b/trace_streamer/test/unittest/pbreader_parser/pbreader_cpu_data_parser_test.cpp @@ -30,6 +30,7 @@ using namespace SysTuning::TraceStreamer; namespace SysTuning { namespace TraceStreamer { +namespace PbReaderCpuDataParserUnitTest { const uint64_t TS = 104; const uint64_t TOTALLOAD_01 = 4; const uint64_t USERLOAD_01 = 44; @@ -230,5 +231,6 @@ HWTEST_F(HtraceCpuDataParserTest, ParseHtraceWithMultipleCpuData, TestSize.Level EXPECT_EQ(cpuUsageInfoData.SystemLoad()[1], SYSTEMLOAD_03); EXPECT_EQ(cpuUsageInfoData.SystemLoad()[2], SYSTEMLOAD_04); } +} // namespace PbReaderCpuDataParserUnitTest } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/test/unittest/pbreader_parser/pbreader_mem_parser_test.cpp b/trace_streamer/test/unittest/pbreader_parser/pbreader_mem_parser_test.cpp index a976d1106402d64dd03d61cfe6712b29c8cee8f4..89fca1f18b16b13f2b703a8e95963a8a4b4138a9 100644 --- a/trace_streamer/test/unittest/pbreader_parser/pbreader_mem_parser_test.cpp +++ b/trace_streamer/test/unittest/pbreader_parser/pbreader_mem_parser_test.cpp @@ -144,7 +144,7 @@ HWTEST_F(HtraceMemParserTest, ParseMemParseTestMeasureDataSize, TestSize.Level1) EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessData(1).pid_ == pid); auto processMeasureData = stream_.traceDataCache_->GetConstProcessMeasureData(); - EXPECT_EQ(processMeasureData.Size(), MEM_PURG_SUM * 1); + EXPECT_EQ(processMeasureData.Size(), MEM_OOM_SCORE_ADJ * 1); EXPECT_EQ(stream_.traceDataCache_->GetConstProcessData().size(), 2); for (auto i = 0; i < MEM_PURG_SUM; i++) { @@ -230,7 +230,7 @@ HWTEST_F(HtraceMemParserTest, ParseMultiEmptyProcessMemoryInfo, TestSize.Level1) auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_MEMORY, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == MEM_PURG_SUM * 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == MEM_OOM_SCORE_ADJ * 2); } /** diff --git a/trace_streamer/test/unittest/pbreader_parser/pbreader_network_parser_test.cpp b/trace_streamer/test/unittest/pbreader_parser/pbreader_network_parser_test.cpp index fb1055967f4bdf10d1075eb2d455359515f69d1a..31f1449734106f7e0cd17e441f9e5e66b153dbb2 100644 --- a/trace_streamer/test/unittest/pbreader_parser/pbreader_network_parser_test.cpp +++ b/trace_streamer/test/unittest/pbreader_parser/pbreader_network_parser_test.cpp @@ -30,6 +30,7 @@ using namespace SysTuning::TraceStreamer; namespace SysTuning { namespace TraceStreamer { +namespace PbReaderNetworkParserTest { const uint64_t TS = 100; const uint64_t DURS_01 = 1999632781; const uint64_t TX_01 = 712921; @@ -223,5 +224,6 @@ HWTEST_F(HtraceNetworkParserTest, ParseHtraceNetworkWithMultipleNetworkData, Tes EXPECT_EQ(netDetailData.PacketOut()[1], PACKETOUT_03); EXPECT_EQ(netDetailData.PacketOut()[2], PACKETOUT_04); } +} // namespace PbReaderNetworkParserTest } // namespace TraceStreamer } // namespace SysTuning \ No newline at end of file diff --git a/trace_streamer/test/unittest/pbreader_parser/pbreader_process_parser_test.cpp b/trace_streamer/test/unittest/pbreader_parser/pbreader_process_parser_test.cpp index 6b31035dff874b211215c925fd84748af867c0cd..128ac280042ce0b49273c5926648f32a5bc3a6fe 100644 --- a/trace_streamer/test/unittest/pbreader_parser/pbreader_process_parser_test.cpp +++ b/trace_streamer/test/unittest/pbreader_parser/pbreader_process_parser_test.cpp @@ -30,6 +30,7 @@ using namespace SysTuning::TraceStreamer; namespace SysTuning { namespace TraceStreamer { +namespace PbreaderProcessParserUnitTest { uint64_t TS = 100; const uint32_t PID_01 = 311; const std::string NAME_01 = "resource_schedu01"; @@ -217,5 +218,6 @@ HWTEST_F(HtraceProcessParserTest, ParseHtraceProcessWithMultipleProcessData, Tes EXPECT_EQ(liveProcessData.UserName()[1], std::to_string(UID_03)); EXPECT_EQ(liveProcessData.UserName()[2], std::to_string(UID_04)); } +} // namespace PbreaderProcessParserUnitTest } // namespace TraceStreamer } // namespace SysTuning \ No newline at end of file diff --git a/trace_streamer/test/unittest/pbreader_parser/smaps_parser_test.cpp b/trace_streamer/test/unittest/pbreader_parser/smaps_parser_test.cpp index 71be72d853008a1dc9d9ac1a08dbd10aba2aa4cf..564b65024c48f9da7de3a9b0b51b31f5fdd7f7f1 100644 --- a/trace_streamer/test/unittest/pbreader_parser/smaps_parser_test.cpp +++ b/trace_streamer/test/unittest/pbreader_parser/smaps_parser_test.cpp @@ -78,7 +78,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "data/resource/out.db"; + const std::string dbPath_ = "out.db"; }; /** * @tc.name: ParseSmapsParse diff --git a/trace_streamer/test/unittest/ptreader_parser/event_parser_test.cpp b/trace_streamer/test/unittest/ptreader_parser/event_parser_test.cpp index 8875eb206300e94c0c12992b74356e385818eee0..442b28ab5cc2d7420fc546822fd3610b24400224 100644 --- a/trace_streamer/test/unittest/ptreader_parser/event_parser_test.cpp +++ b/trace_streamer/test/unittest/ptreader_parser/event_parser_test.cpp @@ -147,8 +147,7 @@ HWTEST_F(EventParserTest, ParseSchedSwitchNoArgs, TestSize.Level1) BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(bytraceLine); eventParser.FilterAllEvents(); - EXPECT_EQ(1, - stream_.traceDataCache_->GetStatAndInfo()->GetValue(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_DATA_INVALID)); + EXPECT_EQ(1, stream_.traceDataCache_->GetStatAndInfo()->GetValue(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_RECEIVED)); } /** @@ -164,8 +163,6 @@ HWTEST_F(EventParserTest, ParseSchedWakeupNoArgs, TestSize.Level1) bytraceLine.pid = 1; bytraceLine.cpu = 0; bytraceLine.task = "ACCS0-2716"; - bytraceLine.pidStr = "12"; - bytraceLine.tGidStr = "12"; bytraceLine.eventName = "sched_wakeup"; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(bytraceLine); @@ -694,7 +691,6 @@ HWTEST_F(EventParserTest, ParseTaskNewtaskByInitParam, TestSize.Level1) { TS_LOGI("test5-27"); BytraceLine bytraceLine; - bytraceLine.tGidStr = "12"; static std::unordered_map args{{"comm", "POSIX"}, {"pid", "8542"}, {"clone_flags", "1"}}; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int32_t result = eventParser.TaskNewtaskEvent(args, bytraceLine); diff --git a/trace_streamer/test/unittest/ptreader_parser/ptreader_parser_test.cpp b/trace_streamer/test/unittest/ptreader_parser/ptreader_parser_test.cpp index 8305d395470a681fd1b7a0ea925008f504e62977..d7c3769551a2067ea3cc7e02c6d72d614a22816b 100644 --- a/trace_streamer/test/unittest/ptreader_parser/ptreader_parser_test.cpp +++ b/trace_streamer/test/unittest/ptreader_parser/ptreader_parser_test.cpp @@ -197,8 +197,8 @@ HWTEST_F(PtreaderParserTest, LineParser_abnormal_pid_err, TestSize.Level1) ptreaderParser.WaitForParserEnd(); EXPECT_TRUE(ptreaderParser.TraceCommentLines() == 0); - EXPECT_TRUE(ptreaderParser.ParsedTraceValidLines() == 0); - EXPECT_TRUE(ptreaderParser.ParsedTraceInvalidLines() == 1); + EXPECT_TRUE(ptreaderParser.ParsedTraceValidLines() == 1); + EXPECT_TRUE(ptreaderParser.ParsedTraceInvalidLines() == 0); } /** diff --git a/trace_streamer/test/unittest/query/sqllite_prepar_cache_data_test.cpp b/trace_streamer/test/unittest/query/sqllite_prepar_cache_data_test.cpp index 9273f0ab23fcadb6523c119a810c8dd3fb6c19b6..f4eb03942c7c1d8390e649c6dd811f7fd186ae4d 100644 --- a/trace_streamer/test/unittest/query/sqllite_prepar_cache_data_test.cpp +++ b/trace_streamer/test/unittest/query/sqllite_prepar_cache_data_test.cpp @@ -32,6 +32,7 @@ using namespace SysTuning; using namespace SysTuning::TraceStreamer; namespace SysTuning { namespace TraceStreamer { +namespace SqlitePreparCacheUnitTest { const int32_t PROCESS_ID = 100; const int32_t CPU = 101; const int32_t PID = 102; @@ -1211,5 +1212,6 @@ HWTEST_F(SqllitePreparCacheDataTest, ParseBatchSphCpuAbilityData, TestSize.Level EXPECT_EQ(batchsphCpuAbilityDataRes.values(0).cpu_ability_data().start_ns(), START_NS); EXPECT_EQ(batchsphCpuAbilityDataRes.values(0).cpu_ability_data().dur(), DUR); } +} // namespace SqlitePreparCacheUnitTest } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/test/unittest/rawtrace/rawtrace_parser_test.cpp b/trace_streamer/test/unittest/rawtrace/rawtrace_parser_test.cpp index 583da95339072f40d46abe2508531e8b14d4cbf4..57d22f76d76fe621968fb8b5ae08dcf47c3bba78 100644 --- a/trace_streamer/test/unittest/rawtrace/rawtrace_parser_test.cpp +++ b/trace_streamer/test/unittest/rawtrace/rawtrace_parser_test.cpp @@ -33,7 +33,6 @@ using namespace SysTuning::base; namespace SysTuning { namespace TraceStreamer { -bool ParseTraceFile(TraceStreamerSelector &ts, const std::string &tracePath); constexpr uint64_t PRINTK_VALID_ADDR = 0xffffffc011bdd3ea; class RawTraceParserTest : public ::testing::Test { diff --git a/trace_streamer/test/unittest/table/table_test.cpp b/trace_streamer/test/unittest/table/table_test.cpp index 130edca9fbd1b2b26e4dfca01f7265495be94686..410a7e5031f198e914115c56b2ca62fb0266f731 100644 --- a/trace_streamer/test/unittest/table/table_test.cpp +++ b/trace_streamer/test/unittest/table/table_test.cpp @@ -484,7 +484,7 @@ HWTEST_F(TableTest, HisysEventMeasureTableTest, TestSize.Level1) int32_t type = 1; double numericValue = 0; DataIndex stringValue = stream_.traceDataCache_->GetDataIndex("stringValue"); - HiSysEventMeasureDataRow hiSysEventMeasureDataRow = {ts, nameId, keyId, type, numericValue, stringValue, serial}; + HiSysEventMeasureDataRow hiSysEventMeasureDataRow = {serial, ts, nameId, keyId, type, numericValue, stringValue}; stream_.traceDataCache_->GetHiSysEventMeasureData()->AppendData(hiSysEventMeasureDataRow); EXPECT_EQ(stream_.traceDataCache_->SearchDatabase(sqlSelect, false), 1); } @@ -554,10 +554,10 @@ HWTEST_F(TableTest, IoLatencySampleTableTest, TestSize.Level1) uint64_t filePathId = stream_.traceDataCache_->GetDataIndex("filePathId"); uint64_t durPer4k = 1; - uint64_t callChainId1 = 2; + uint32_t callChainId1 = 2; uint64_t type1 = 2; - uint64_t ipid1 = 2; - uint64_t itid1 = 2; + uint32_t ipid1 = 2; + uint32_t itid1 = 2; uint64_t startTs1 = 1663869224160; uint64_t endTs1 = 1663869424160; uint64_t latencyDur1 = 200; @@ -577,8 +577,8 @@ HWTEST_F(TableTest, IoLatencySampleTableTest, TestSize.Level1) stream_.traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(timestamp1, fps1); EXPECT_EQ(stream_.traceDataCache_->SearchDatabase(sqlSelect1, false), 2); - GetBioLatencySampleDataRow bioLatencySampleDataRow = {CALLCHAIN_ID, TYPE, IPID, ITID, startTs, endTs, - latencyDur, tier, size, blockNumber, filePathId, durPer4k}; + BioLatencySampleDataRow bioLatencySampleDataRow = {CALLCHAIN_ID, TYPE, IPID, ITID, startTs, endTs, + latencyDur, tier, size, blockNumber, filePathId, durPer4k}; stream_.traceDataCache_->GetBioLatencySampleData()->AppendNewData(bioLatencySampleDataRow); bioLatencySampleDataRow = {callChainId1, type1, ipid1, itid1, startTs1, endTs1, latencyDur1, tier1, size1, blockNumber1, filePathId1, durPer4k1}; @@ -748,7 +748,7 @@ HWTEST_F(TableTest, NativeHookTableTest, TestSize.Level1) int64_t memSize = 1; int64_t curMemSize = 1; - uint64_t callChainId1 = 2; + uint32_t callChainId1 = 2; uint32_t ipid1 = 2; uint32_t itid1 = 2; std::string eventType1 = "eventType1"; @@ -785,7 +785,7 @@ HWTEST_F(TableTest, NativeHookFrameTableTest, TestSize.Level1) std::string sqlSelect2 = "select * from native_hook_frame where callchain_id > 1"; std::string sqlSelect3 = "select * from native_hook_frame where symbol_id >= 1"; std::string sqlSelect4 = "select * from native_hook_frame where file_id < 2"; - uint64_t depth = 1; + uint16_t depth = 1; uint64_t ip = 1; DataIndex symbolName = stream_.traceDataCache_->GetDataIndex("symbolName"); DataIndex filePath = stream_.traceDataCache_->GetDataIndex("filePath"); @@ -793,7 +793,7 @@ HWTEST_F(TableTest, NativeHookFrameTableTest, TestSize.Level1) uint64_t symbolOffset = 1; const std::string vaddr = "addr"; - uint64_t depth1 = 2; + uint16_t depth1 = 2; uint64_t ip1 = 2; DataIndex symbolName1 = stream_.traceDataCache_->GetDataIndex("symbolName1"); DataIndex filePath1 = stream_.traceDataCache_->GetDataIndex("filePath1"); @@ -803,8 +803,9 @@ HWTEST_F(TableTest, NativeHookFrameTableTest, TestSize.Level1) NativeHookFrameVaddrRow nativeHookFrameVaddrRow = {CALLCHAIN_ID, depth, ip, symbolName, filePath, offset, symbolOffset, vaddr}; stream_.traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame(nativeHookFrameVaddrRow); - nativeHookFrameVaddrRow = {CALLCHAIN_ID1, depth1, ip1, symbolName1, filePath1, offset1, symbolOffset1, vaddr1}; - stream_.traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame(nativeHookFrameVaddrRow); + NativeHookFrameVaddrRow nativeHookFrameVaddrRow2 = {CALLCHAIN_ID1, depth1, ip1, symbolName1, + filePath1, offset1, symbolOffset1, vaddr1}; + stream_.traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame(nativeHookFrameVaddrRow2); EXPECT_EQ(stream_.traceDataCache_->SearchDatabase(sqlSelect, false), 2); EXPECT_EQ(stream_.traceDataCache_->SearchDatabase(sqlSelect1, false), 1); EXPECT_EQ(stream_.traceDataCache_->SearchDatabase(sqlSelect2, false), 1); @@ -852,14 +853,14 @@ HWTEST_F(TableTest, PerfCallchainTableTest, TestSize.Level1) std::string sqlSelect2 = "select * from perf_callchain where callchain_id > 1"; std::string sqlSelect3 = "select * from perf_callchain where file_id < 1"; std::string sqlSelect4 = "select * from perf_callchain where symbol_id >= 1"; - uint64_t callChainId = stream_.traceDataCache_->GetDataIndex("callChain"); + uint32_t callChainId = stream_.traceDataCache_->GetDataIndex("callChain"); uint32_t depth = 0; uint64_t ip = 123; uint64_t vaddrInFile = 1; uint64_t fileId = stream_.traceDataCache_->GetDataIndex("file"); uint64_t symbolId = stream_.traceDataCache_->GetDataIndex("symbolId"); - uint64_t callChainId1 = 2; + uint32_t callChainId1 = 2; uint32_t depth1 = 1; uint64_t ip1 = 234; uint64_t vaddrInFile1 = 2; @@ -931,18 +932,18 @@ HWTEST_F(TableTest, PerfSampleTableTest, TestSize.Level1) std::string sqlSelect3 = "select * from perf_sample where thread_id < 1"; std::string sqlSelect4 = "select * from perf_sample where event_type_id >= 1"; std::string sqlSelect5 = "select * from perf_sample where cpu_id <= 1"; - uint64_t sampleId = stream_.traceDataCache_->GetDataIndex("type"); - uint64_t timeStamp = 1663869124160; - uint64_t tid = 1; + uint32_t sampleId = stream_.traceDataCache_->GetDataIndex("type"); + uint64_t timestamp = 1663869124160; + uint32_t tid = 1; uint64_t eventCount = 2; uint64_t eventTypeId = 1; uint64_t timestampTrace = 1; uint64_t cpuId = 1; uint64_t threadState = stream_.traceDataCache_->GetDataIndex("threadState"); - uint64_t sampleId1 = stream_.traceDataCache_->GetDataIndex("type1"); + uint32_t sampleId1 = stream_.traceDataCache_->GetDataIndex("type1"); uint64_t timestamp1 = 1663869124160; - uint64_t tid1 = 2; + uint32_t tid1 = 2; uint64_t eventCount1 = 3; uint64_t eventTypeId1 = 2; uint64_t timestampTrace1 = 2; @@ -1096,16 +1097,16 @@ HWTEST_F(TableTest, SchedSliceTest, TestSize.Level1) uint64_t ts = 1663869124160; uint64_t dur = 200; uint64_t cpu = 1; - uint64_t internalTid = 1; + uint32_t internalTid = 1; uint64_t endState = 1; - uint64_t priority = 1; + int32_t priority = 1; uint64_t ts1 = 1663869224160; uint64_t dur1 = 200; uint64_t cpu1 = 2; - uint64_t internalTid1 = 2; + uint32_t internalTid1 = 2; uint64_t endState1 = 2; - uint64_t priority1 = 2; + int32_t priority1 = 2; SchedSliceRow schedSliceRow = {ts, dur, cpu, internalTid, endState, priority}; SchedSliceRow schedSliceRow1 = {ts1, dur1, cpu1, internalTid1, endState1, priority1}; @@ -1165,8 +1166,7 @@ HWTEST_F(TableTest, StatTableTest, TestSize.Level1) { TS_LOGI("test31-37"); std::string sqlSelect = "select * from stat"; - stream_.traceDataCache_->GetStatAndInfo(); - EXPECT_EQ(stream_.traceDataCache_->SearchDatabase(sqlSelect, false), 460); + EXPECT_EQ(stream_.traceDataCache_->SearchDatabase(sqlSelect, false), TRACE_EVENT_MAX * STAT_EVENT_MAX); } /** * @tc.name: SymbolsTableTest