diff --git a/ide/server/main.go b/ide/server/main.go index 530ff115573a70338e10786ec5502b39091784da..ab310beba173f21d5db7ace7ffa4afbc3882684b 100644 --- a/ide/server/main.go +++ b/ide/server/main.go @@ -53,6 +53,7 @@ const HttpPort = 9000 var exPath string var serveInfo string +var aiInfo string var msgPublishData MsgPublishData var hdcPublicKey string var hdcPrivateKey *rsa.PrivateKey @@ -173,10 +174,11 @@ func main() { mime.TypeByExtension(".js") mime.AddExtensionType(".js", "application/javascript") log.Println(mime.TypeByExtension(".js")) - mux.HandleFunc("/logger", consoleHandler) + mux.HandleFunc("/application/logger", consoleHandler) mux.Handle("/application/upload/", http.StripPrefix("/application/upload/", http.FileServer(http.Dir(filepath.FromSlash(exPath+"/upload"))))) mux.HandleFunc("/application/download-file", downloadHandler) mux.HandleFunc("/application/serverInfo", serverInfo) + mux.HandleFunc("/application/getAiInfo", getAiInfo) mux.HandleFunc("/application/hdcPublicKey", getHdcPublicKey) mux.HandleFunc("/application/encryptHdcMsg", encryptHdcMsg) mux.HandleFunc("/application/signatureHdcMsg", signatureHdcMsg) @@ -257,6 +259,12 @@ func serverInfo(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) } +func getAiInfo(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("ai_info", aiInfo) + w.WriteHeader(200) +} + func getHdcPublicKey(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Content-Type", "text/json") @@ -340,6 +348,7 @@ func getMsgPublish(w http.ResponseWriter, r *http.Request) { type ServerConfig struct { ServeInfo string `json:"ServeInfo"` MsgPublishFile string `json:"MsgPublishFile"` + AiInfo string } type MsgPublishData struct { @@ -371,6 +380,7 @@ func readReqServerConfig() { return } serveInfo = sc.ServeInfo + aiInfo = sc.AiInfo msgPublishData.Mux.Lock() msgPublishData.FilePath = sc.MsgPublishFile msgPublishData.Mux.Unlock() diff --git a/ide/src/base-ui/icon.svg b/ide/src/base-ui/icon.svg index e93c2d8b1e100e23558c6809eea7f93d80128607..21b0b9e52eb9c07239917f8828e79b14fcdb03cf 100644 --- a/ide/src/base-ui/icon.svg +++ b/ide/src/base-ui/icon.svg @@ -553,4 +553,21 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ide/src/base-ui/menu/LitMainMenu.ts b/ide/src/base-ui/menu/LitMainMenu.ts index ab22f2d6fa3628a7414935bfb1929f83c669a38f..433937a1410b0402df291ff1039acec388cddc88 100644 --- a/ide/src/base-ui/menu/LitMainMenu.ts +++ b/ide/src/base-ui/menu/LitMainMenu.ts @@ -299,7 +299,7 @@ export class LitMainMenu extends BaseElement {
- +
diff --git a/ide/src/base-ui/select/LitSelectV.ts b/ide/src/base-ui/select/LitSelectV.ts index 4a67e03a962f2f4a0f39a249ccfbf5a59d04cc87..a9cb856b907680fbd4502d77275c48ef77e1af0f 100644 --- a/ide/src/base-ui/select/LitSelectV.ts +++ b/ide/src/base-ui/select/LitSelectV.ts @@ -20,6 +20,7 @@ import { selectHtmlStr, selectVHtmlStr } from './LitSelectHtml'; @element('lit-select-v') export class LitSelectV extends BaseElement { showItems: Array = []; + ignoreValues: Array = []; itemValue: Array = []; customItem: Array = []; private focused: unknown; @@ -147,6 +148,28 @@ export class LitSelectV extends BaseElement { } } + setIgnoreValues(values: string[]) { + this.ignoreValues = values; + } + + setSelectedOptions(selectArray: Array) { + let allSelected = true; + this.shadowRoot?.querySelectorAll('lit-select-option').forEach((a) => { + if (selectArray.includes(a.textContent!)) { + a.setAttribute('selected', ''); + } else { + allSelected = false; + a.removeAttribute('selected'); + } + }); + this.all = allSelected; + selectArray.forEach((i) => { + this.showItems.push(i); + }); + // @ts-ignore + this.selectVInputEl.value = selectArray.filter(it => !this.ignoreValues.includes(it)); + } + initDataItem(selectVDataItem: Array): void { selectVDataItem.forEach((item) => { let selectVOption = document.createElement('lit-select-option'); @@ -263,7 +286,7 @@ export class LitSelectV extends BaseElement { let number = this.showItems.indexOf(a.textContent!); if (number > -1) { this.showItems!.splice(number, 1); // @ts-ignore - this.selectVInputEl!.value = this.showItems; + this.selectVInputEl!.value = this.showItems.filter(it => !this.ignoreValues.includes(it)); } this.all = false; querySelector.removeAttribute('selected'); @@ -274,7 +297,7 @@ export class LitSelectV extends BaseElement { let value = this.showItems.indexOf(a.textContent!); if (index > -1 && value === -1) { this.showItems.push(a.textContent!); // @ts-ignore - this.selectVInputEl!.value = this.showItems; + this.selectVInputEl!.value = this.showItems.filter(it => !this.ignoreValues.includes(it)); } if (this.showItems.length >= this.itemValue.length) { querySelector.setAttribute('selected', ''); @@ -344,10 +367,11 @@ export class LitSelectV extends BaseElement { }); if (this.customItem.length > 0) { // @ts-ignore - this.selectVInputEl.value = this.customItem.concat(this.showItems); + this.selectVInputEl.value = this.customItem.concat(this.showItems) + .filter(it => !this.ignoreValues.includes(it)); } else { // @ts-ignore - this.selectVInputEl.value = this.showItems; + this.selectVInputEl.value = this.showItems.filter(it => !this.ignoreValues.includes(it)); } }); }); @@ -363,7 +387,7 @@ export class LitSelectV extends BaseElement { this.itemValue.forEach((i) => { this.showItems.push(i); }); // @ts-ignore - this.selectVInputEl.value = this.itemValue; + this.selectVInputEl.value = this.itemValue.filter(it => !this.ignoreValues.includes(it));; } else { this.shadowRoot?.querySelectorAll('lit-select-option').forEach((i) => { i.removeAttribute('selected'); diff --git a/ide/src/base-ui/table/lit-table.ts b/ide/src/base-ui/table/lit-table.ts index d5b410511355bbb095c9481f9d71b447172e4408..339b77a57101fbc613addd31465263505f977bae 100644 --- a/ide/src/base-ui/table/lit-table.ts +++ b/ide/src/base-ui/table/lit-table.ts @@ -1649,7 +1649,7 @@ export class LitTable extends HTMLElement { (child as HTMLElement).title = rowObject.data.time + 'ns'; } else { //@ts-ignore - (child as HTMLElement).title = text; + (child as HTMLElement).title = text.replace(/</g,'<').replace(/>/g,'>'); } } } diff --git a/ide/src/config/config.json b/ide/src/config/config.json new file mode 100644 index 0000000000000000000000000000000000000000..6b4ff707e4ac4994d91ccaefd8be8ced8ed21ca8 --- /dev/null +++ b/ide/src/config/config.json @@ -0,0 +1,136 @@ +{ + "_comment": "这是动效的相关打点", + "Animation": { + "_comment": "动效过程打点线程,render_service为并行化前的打点线程,RSUniRenderThre为并行化后的打点线程", + "animationProcEvents_": [ + "render_service", + "RSUniRenderThre" + ], + "_comment": "动效相关打点,H:LAUNCHER_APP_LAUNCH_FROM_ICON为桌面图标点击启动,H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR为通知栏通知消息点击启动,H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR_IN_LOCKSCREEN为锁屏通知消息点击启动,H:LAUNCHER_APP_LAUNCH_FROM_RECENT为多任务点击应用,H:LAUNCHER_APP_SWIPE_TO_HOME为HOME键返回桌面,H:LAUNCHER_APP_BACK_TO_HOME为Back键返回桌面,H:APP_TRANSITION_TO_OTHER_APP为应用切换到另一个应用,H:APP_TRANSITION_FROM_OTHER_APP为从另一个应用跳回,H:APP_LIST_FLING为应用中列表滑动", + "onAnimationStartEvents_": [ + "H:LAUNCHER_APP_LAUNCH_FROM_ICON", + "H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR", + "H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR_IN_LOCKSCREEN", + "H:LAUNCHER_APP_LAUNCH_FROM_RECENT", + "H:LAUNCHER_APP_SWIPE_TO_HOME", + "H:LAUNCHER_APP_BACK_TO_HOME", + "H:APP_TRANSITION_TO_OTHER_APP", + "H:APP_TRANSITION_FROM_OTHER_APP", + "H:APP_LIST_FLING" + ], + "_comment": "H:GenerateVsyncCount,用于计算设备的平均帧率,累计6次后输出平均帧率", + "frameRateCmd_": [ + "H:GenerateVsyncCount" + ], + "_comment": "H:RSJankStats::RecordAnimationDynamicFrameRate,用于更新动效的帧率,若存在此打点,则以这个打点为准,否则以H:Repaint为准", + "realFrameRateCmd_": [ + "H:RSJankStats::RecordAnimationDynamicFrameRate" + ], + "_comment": "H:Repaint(硬件合成器合成绘制),用于计算动效帧率", + "frameCountCmd_": [ + "H:Repaint" + ], + "_comment": "H:RSUniRender::Process:[WindowScene_和H:RSSurfaceRenderNodeDrawable::OnDraw:[WindowScene_用来获取动效帧数据的打点,其中H:RSUniRender::Process:[WindowScene_为并行化前打点", + "frameBeginCmd_": [ + "H:RSUniRender::Process:[WindowScene_", + "H:RSSurfaceRenderNodeDrawable::OnDraw:[WindowScene_" + ], + "_comment": "H:RSUniRender::Process:[SCBDesktop和H:RSSurfaceRenderNodeDrawable::OnDraw:[SCBDesktop用来获取设备的宽高,其中H:RSUniRender::Process:[SCBDesktop为并行化前打点", + "screenSizeCmd_": [ + "H:RSUniRender::Process:[SCBDesktop", + "H:RSSurfaceRenderNodeDrawable::OnDraw:[SCBDesktop" + ], + "_comment": "H:RSMainThread::DoComposition和H:RenderFrame用来获取动效帧的结束时间,其中H:RSMainThread::DoComposition为并行化前的打点", + "frameEndTimeCmd_": [ + "H:RenderFrame" + ], + "_comment": "H:PostAndWait, parallel type并行化的标志", + "parallelTypeCmd_": [ + "H:PostAndWait, parallel type" + ] + }, + "_comment": "这是启动场景的相关打点", + "AppStartup": { + "_comment": "启动第一阶段,手指点击", + "phase1": { + "pName": "ProcessTouchEvent", + "start": [ + "H:client dispatch touchId:" + ], + "end": [ + "H:OHOS::ErrCode OHOS::AAFwk::AbilityManagerClient::StartUIAbilityBySCB" + ] + }, + "_comment": "启动第二阶段,处理创建进程信息,创建窗口", + "phase2": { + "pName": "StartUIAbilityBySCB", + "start": [ + "H:OHOS::ErrCode OHOS::AAFwk::AbilityManagerClient::StartUIAbilityBySCB" + ], + "end": [ + "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::LoadAbility" + ] + }, + "_comment": "启动第三阶段,拉起应用进程", + "phase3": { + "pName": "LoadAbility", + "start": [ + "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::LoadAbility" + ], + "end": [ + "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::AttachApplication(const pid_t, const sptr &)##" + ] + }, + "_comment": "启动第四阶段,加载应用", + "phase4": { + "pName": "Application Launching", + "start": [ + "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::AttachApplication(const pid_t, const sptr &)##" + ], + "end": [ + "H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility(const std::shared_ptr &)##" + ] + }, + "_comment": "启动第五阶段,加载 UI Ability", + "phase5": { + "pName": "UI Ability Launching", + "start": [ + "H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility(const std::shared_ptr &)##" + ], + "end": [ + "H:void OHOS::AbilityRuntime::FAAbilityThread::HandleAbilityTransaction(const OHOS::AbilityRuntime::Want &, const OHOS::AbilityRuntime::LifeCycleStateInfo &, sptr)##", + "H:void OHOS::AbilityRuntime::UIAbilityThread::HandleAbilityTransaction" + ] + }, + "_comment": "启动第六阶段,应用进入前台", + "phase6": { + "pName": "UI Ability OnForeground", + "start": [ + "H:void OHOS::AbilityRuntime::FAAbilityThread::HandleAbilityTransaction(const OHOS::AbilityRuntime::Want &, const OHOS::AbilityRuntime::LifeCycleStateInfo &, sptr)##", + "H:void OHOS::AbilityRuntime::UIAbilityThread::HandleAbilityTransaction" + ], + "end": [ + "H:ReceiveVsync dataCount" + ] + } + }, + "_comment": "Flag 开关", + "config": { + "TaskPool": 0, + "AnimationAnalysis": 0, + "AppStartup": 0, + "SchedulingAnalysis": 0, + "BinderRunnable": 0, + "FfrtConvert": 0, + "HMKernel": 1, + "VSync": 0, + "Hangs Detection": 0, + "LTPO": 0, + "Start&Finish Trace Category": 0, + "UserPluginsRow": 0, + "CPU by Irq": 0, + "RawTraceCutStartTs": 1, + "AI": 0, + "System Calls": "" + } +} \ No newline at end of file diff --git a/ide/src/doc/md/des_tables.md b/ide/src/doc/md/des_tables.md index ccca67b778d46004816e73d3bc19c14e837cfe90..3e26dacc8f8f8a5f16662868c2236facd8a16ef0 100644 --- a/ide/src/doc/md/des_tables.md +++ b/ide/src/doc/md/des_tables.md @@ -18,7 +18,7 @@ TraceStreamer可以将trace数据源转化为易于理解和使用的数据库 | app_startup | 记录了应用启动相关数据| | args | 记录方法参数集合| | bio_latency_sample | 记录IO操作相关方法调用,及调用栈数据| -| callstack | 记录调用堆栈和异步调用信息,其中depth,stack_id和parent_stack_id仅在非异步调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号| +| callstack | 记录调用堆栈和异步调用信息,其中depth仅在非异步调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,child_callid为子线程唯一号| | clk_event_filter | 记录时钟相关的信息| | clock_event_filter | 此结构用来维护时钟事件,cpu与唯一的ID做关联| | clock_snapshot | 时钟号和时间,时钟名的映射表| @@ -362,8 +362,13 @@ js_heap_sample:记录timeline的时间轴信息 |spanId |TEXT | |parentSpanId |TEXT | |flag |TEXT | +|trace_level |TEXT | +|trace_tag |TEXT | +|custom_category |TEXT | +|custom_args |TEXT | +|child_callid |INT | #### 表描述 -记录调用堆栈和异步调用信息,其中depth,stack_id和parent_stack_id仅在非异步的调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号。 +记录调用堆栈和异步调用信息,其中depth仅在非异步的调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,child_callid为子线程唯一号。 #### 字段详细描述 - id: 唯一标识 - ts: 数据事件上报时间戳 @@ -379,6 +384,11 @@ js_heap_sample:记录timeline的时间轴信息 - spanId:分布式调用关联关系,当前帧的id - parentSpanId: 分布式调用关联关系,当前帧的parent的SpanId,对应当前表的spandId - flag:C表示分布式调用发送方,S表示接受方 +- trace_level:决定trace的等级,log和nolog等级不同,其中log表示详细记录所有相关的调用信息,nolog 表示不记录 +- trace_tag:Tag标签,标识请求的来源或类型 +- custom_category:聚合标签,用于关联同类信息 +- custom_args:自定义参数,用于存储与调用相关的额外信息 +- child_callid:当为异步调用,此时callid为进程唯一号,child_callid为子线程唯一号,反之为无效值 ### clk_event_filter表 #### 表结构 diff --git a/ide/src/doc/quickstart_extensions.html b/ide/src/doc/quickstart_extensions.html index fab0d8479b3a195a9fc52d241d71452e6c80838b..063f237ec35abac5b243b4091a5d570b4e355726 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.1.2,如果本地存在以其他方式安装的非正式版本,请手动关闭扩展服务,并重新按照该指导安装 + 备注:当前扩展服务版本为1.1.4,如果本地存在以其他方式安装的非正式版本,请手动关闭扩展服务,并重新按照该指导安装

@@ -840,8 +840,7 @@ targetElement.scrollIntoView({ behavior: 'smooth' }); } // 假设这是你的文件的 URL - const fileUrl = `https://${window.location.host.split(':')[0]}:${window.location.port - }/application/extend/hi-smart-perf-host-extend.zip`; + const fileUrl = `../extend/hi-smart-perf-host-extend.zip`; const fileName = 'hi-smart-perf-host-extend'; // 创建一个隐藏的 a 元素 const a = document.createElement('a'); diff --git a/ide/src/doc/quickstart_schedulinganalysis.html b/ide/src/doc/quickstart_schedulinganalysis.html index a4104ab2bf9838938a3d185ba1c97cc4c95bef5a..e7738ee12cf7e7dd2b9db1cb7f2983dd5cdab577 100644 --- a/ide/src/doc/quickstart_schedulinganalysis.html +++ b/ide/src/doc/quickstart_schedulinganalysis.html @@ -1016,7 +1016,7 @@ duration:运行总时长。

Top20线程大中小核占用率

- 选择Thread Analysis标签页,各个CPU通过勾选big或者middle或者small来设置CPU的分类。 + 选择Thread Analysis标签页,各个CPU通过勾选big或者middle或者little来设置CPU的分类。
GitHub Logo
@@ -1080,7 +1080,7 @@ middle core:中核占用时长。

  • -small core:小核占用时长。
    +little core:小核占用时长。
     
  • diff --git a/ide/src/figures/Schedulinganalysis/CPUdetailsetting.jpg b/ide/src/figures/Schedulinganalysis/CPUdetailsetting.jpg index 9683b732eee0a99ca2afd50a42bae44befba67cb..b414073a0879f54e8bfc0bbf4822842950c40e9c 100644 Binary files a/ide/src/figures/Schedulinganalysis/CPUdetailsetting.jpg and b/ide/src/figures/Schedulinganalysis/CPUdetailsetting.jpg differ diff --git a/ide/src/figures/Schedulinganalysis/CPUsetting.jpg b/ide/src/figures/Schedulinganalysis/CPUsetting.jpg index b2d43b9b41cfd5023acfd195cbaf829355ba9f7d..f46651947d5996a0fdeeb97870742ef18497ee74 100644 Binary files a/ide/src/figures/Schedulinganalysis/CPUsetting.jpg and b/ide/src/figures/Schedulinganalysis/CPUsetting.jpg differ diff --git a/ide/src/hdc/hdcclient/HdcClient.ts b/ide/src/hdc/hdcclient/HdcClient.ts index 5393d55cbd76d9da46093ea60d4845a828676304..40ca22cdd5f6110bb931bbe0634d1557bde9d2ba 100644 --- a/ide/src/hdc/hdcclient/HdcClient.ts +++ b/ide/src/hdc/hdcclient/HdcClient.ts @@ -78,7 +78,7 @@ export class HdcClient implements DataListener { continue; case AuthType.AUTH_SIGNATURE: const hdcMsgUrl = this.isSigna ? 'signatureHdcMsg' : 'encryptHdcMsg'; - const response = await fetch(`${window.location.origin}/application/${hdcMsgUrl}?message=` + returnBuf); + const response = await fetch(`${window.location.origin}${window.location.pathname}${hdcMsgUrl}?message=` + returnBuf); const dataBody = await response.json(); let signatureHdcMsg = ''; if (dataBody.success) { @@ -95,7 +95,7 @@ export class HdcClient implements DataListener { } else { this.isSigna = false; } - const responsePub = await fetch(`${window.location.origin}/application/hdcPublicKey`); + const responsePub = await fetch(`${window.location.origin}${window.location.pathname}hdcPublicKey`); const data = await responsePub.json(); const publicKey = data.success && (`smartPerf-Host` + String.fromCharCode(12) + data.data.publicKey); await this.handShakeConnect(AuthType.AUTH_PUBLICKEY, publicKey); diff --git a/ide/src/statistics/util/SpStatisticsHttpUtil.ts b/ide/src/statistics/util/SpStatisticsHttpUtil.ts index 0d9357cc0f71684be4f8bd01df4558624bf1b4e7..1f7761cc4059159b419d4790c4549e2c9e018f16 100644 --- a/ide/src/statistics/util/SpStatisticsHttpUtil.ts +++ b/ide/src/statistics/util/SpStatisticsHttpUtil.ts @@ -22,7 +22,6 @@ export class SpStatisticsHttpUtil { static timeDiff: number = 0; static retryCount: number = 0; static retryMaxCount: number = 5; - static pauseRetry: boolean = false; static retryRestTimeOut: boolean = false; static recordPlugin: Array = []; static controllersMap: Map = new Map(); @@ -30,42 +29,16 @@ export class SpStatisticsHttpUtil { static initStatisticsServerConfig(): void { if (SpStatisticsHttpUtil.requestServerInfo === '') { - SpStatisticsHttpUtil.requestServerInfo = SpStatisticsHttpUtil.getRequestServerInfo(); + return; } if (SpStatisticsHttpUtil.serverTime === 0) { SpStatisticsHttpUtil.getServerTime(); } } - static getRequestServerInfo(): string { - try { - let req = new XMLHttpRequest(); - req.onreadystatechange = (): void => { - if (req.readyState === 4 && req.status === 200) { - let requestInfo = req.getResponseHeader('request_info'); - if (requestInfo && requestInfo.length > 0) { - SpStatisticsHttpUtil.requestServerInfo = requestInfo; - } - } - }; - req.open( - 'GET', - `${window.location.protocol}//${window.location.host.split(':')[0]}:${window.location.port - }/application/serverInfo`, - true - ); - req.send(null); - } catch { - warn('Connect Server Failed'); - } - return ''; - } static getServerTime(): void { if (SpStatisticsHttpUtil.requestServerInfo === '') { - SpStatisticsHttpUtil.requestServerInfo = SpStatisticsHttpUtil.getRequestServerInfo(); - } - if (SpStatisticsHttpUtil.pauseRetry) { return; } fetch(`https://${SpStatisticsHttpUtil.requestServerInfo}/serverTime`) @@ -77,26 +50,9 @@ export class SpStatisticsHttpUtil { } }); }) - .catch((e) => { - this.handleRequestException(); - }); + .catch((e) => {}); } - private static handleRequestException(): void { - if (SpStatisticsHttpUtil.retryCount >= SpStatisticsHttpUtil.retryMaxCount) { - SpStatisticsHttpUtil.pauseRetry = true; - if (SpStatisticsHttpUtil.retryRestTimeOut) { - return; - } - SpStatisticsHttpUtil.retryRestTimeOut = true; - setTimeout(() => { - SpStatisticsHttpUtil.retryCount = 0; - SpStatisticsHttpUtil.pauseRetry = false; - SpStatisticsHttpUtil.retryRestTimeOut = false; - }, 600000); - } - ++SpStatisticsHttpUtil.retryCount; - } static addUserVisitAction(requestUrl: string): void { // @ts-ignore @@ -104,9 +60,6 @@ export class SpStatisticsHttpUtil { return; } if (SpStatisticsHttpUtil.requestServerInfo === '') { - SpStatisticsHttpUtil.requestServerInfo = SpStatisticsHttpUtil.getRequestServerInfo(); - } - if (SpStatisticsHttpUtil.pauseRetry) { return; } let visitId = 0; @@ -147,9 +100,6 @@ export class SpStatisticsHttpUtil { return; } if (SpStatisticsHttpUtil.requestServerInfo === '') { - SpStatisticsHttpUtil.requestServerInfo = SpStatisticsHttpUtil.getRequestServerInfo(); - } - if (SpStatisticsHttpUtil.pauseRetry) { return; } requestBody.ts = SpStatisticsHttpUtil.getCorrectRequestTime(); @@ -266,7 +216,8 @@ export class SpStatisticsHttpUtil { method: 'post', signal: controller.signal, headers: { - 'Content-Type': 'application/json' + 'Content-Type': 'application/json', + 'Authorization': 'Bearer app-6mUvoj5WO5hRaMVLBzV0oCVl' }, body: JSON.stringify(requestBody) }).then(async res => { @@ -274,7 +225,7 @@ export class SpStatisticsHttpUtil { if (res.status === 200) { let resp = await res.text(); let resj = await JSON.parse(resp); - response.data = resj.reason && resj.reason === 'ok' ? resj.chatbot_reply : '服务器异常,请稍后再试'; + response.data = resj.event && resj.event === 'message' ? resj.answer : '服务器异常,请稍后再试'; } else { response.data = '服务器请求失败'; diff --git a/ide/src/trace/SpApplication.ts b/ide/src/trace/SpApplication.ts index 0a703a338e20688745448085a85f1bbfd30ac246..062ea60d276c5f74e934e7bc4291ade97fa63db4 100644 --- a/ide/src/trace/SpApplication.ts +++ b/ide/src/trace/SpApplication.ts @@ -67,6 +67,7 @@ import './component/SpKeyboard'; import { parseKeyPathJson } from './component/Utils'; import { Utils } from './component/trace/base/Utils'; import { + addExportDBToParentEvent, applicationHtml, clearTraceFileCache, findFreeSizeAlgorithm, @@ -74,9 +75,10 @@ import { indexedDataToBufferData, isZipFile, isZlibFile, + loadTraceCompleteEvent, postLog, readTraceFileBuffer, - TraceMode, + TraceMode } from './SpApplicationPublicFunc'; import { queryExistFtrace } from './database/sql/SqlLite.sql'; import '../base-ui/chart/scatter/LitChartScatter'; @@ -182,6 +184,7 @@ export class SpApplication extends BaseElement { static traceType: String = ''; private isZipFile: boolean = false; isClear: boolean = false; + isOpenTrace: boolean = false; static spSnapShotView: SpSnapShotView | undefined | null; static get observedAttributes(): Array { @@ -280,8 +283,29 @@ export class SpApplication extends BaseElement { } initPlugin(): void { - SpStatisticsHttpUtil.initStatisticsServerConfig(); - SpStatisticsHttpUtil.addUserVisitAction('visit'); + let url = `${window.location.protocol}//${window.location.host.split(':')[0]}:${window.location.port + }${window.location.pathname}serverInfo`; + fetch(url, { method: 'GET' }).then((res) => { + if (res.headers) { + const headers = res.headers; + SpStatisticsHttpUtil.requestServerInfo = headers.get('request_info')!; + SpStatisticsHttpUtil.initStatisticsServerConfig(); + SpStatisticsHttpUtil.addUserVisitAction('visit'); + } + }) + let aiurl = `${window.location.protocol}//${window.location.host.split(':')[0]}:${window.location.port + }${window.location.pathname}getAiInfo`; + fetch(aiurl, { method: 'GET' }).then((res) => { + if (res.headers) { + const headers = res.headers; + let aiAnalysisShow = this.shadowRoot + ?.querySelector('lit-main-menu')! + .shadowRoot!.querySelector('.ai_analysis') as HTMLDivElement; + if (headers.get('ai_info') !== '') { + aiAnalysisShow.style.display = ''; + } + } + }) LongTraceDBUtils.getInstance().createDBAndTable().then(); } @@ -649,6 +673,7 @@ export class SpApplication extends BaseElement { private openTraceFile(ev: File): void { SpApplication.isTraceLoaded = false; + this.isOpenTrace = true; this.returnOriginalUrl(); this.removeAttribute('custom-color'); this.chartFilter!.setAttribute('hidden', ''); @@ -1114,7 +1139,7 @@ export class SpApplication extends BaseElement { let data = this.markPositionHandler(reader.result as ArrayBuffer); this.spSystemTrace!.loadDatabaseArrayBuffer( data, - '', + '', '', (command: string, _: number) => { this.setProgress(command); }, @@ -1172,7 +1197,8 @@ export class SpApplication extends BaseElement { traceType = 'sqlite'; } Promise.all([threadPool.init(traceType), threadPool2.init(traceType)]).then(() => { - let wasmUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}/application/wasm.json`; + let wasmUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}${window.location.pathname}wasm.json`; + let configUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}${window.location.pathname}config/config.json`; Promise.all([file1.arrayBuffer(), file2.arrayBuffer()]).then((bufArr) => { this.litSearch!.setPercent('ArrayBuffer loaded ', 2); SpApplication.loadingProgress = 0; @@ -1182,7 +1208,7 @@ export class SpApplication extends BaseElement { info('initData start Parse Data'); this.spSystemTrace!.loadDatabaseArrayBuffer( buf1, - wasmUrl, + wasmUrl, configUrl, (command: string, _: number) => this.setProgress(command), true, completeHandler, @@ -1237,14 +1263,15 @@ export class SpApplication extends BaseElement { reader.onloadend = (ev): void => { info('read file onloadend'); this.litSearch!.setPercent('ArrayBuffer loaded ', 2); - let wasmUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}/application/wasm.json`; + let wasmUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}${window.location.pathname}wasm.json`; + let configUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}${window.location.pathname}config/config.json`; SpApplication.loadingProgress = 0; SpApplication.progressStep = 3; let data = this.markPositionHandler(reader.result as ArrayBuffer); info('initData start Parse Data'); this.spSystemTrace!.loadDatabaseArrayBuffer( data, - wasmUrl, + wasmUrl, configUrl, (command: string, _: number) => this.setProgress(command), false, completeHandler @@ -1326,18 +1353,22 @@ export class SpApplication extends BaseElement { SpApplication.isTraceLoaded = true; if (!isDistributed) { this.importConfigDiv!.style.display = Utils.getInstance().getSchedSliceMap().size > 0 ? 'block' : 'none'; - } + } this.showContent(this.spSystemTrace!); this.litSearch!.setPercent('', 101); this.chartFilter!.setAttribute('mode', ''); this.freshMenuDisable(false); + Utils.currentTraceName = fileName; } else { + info('loadDatabaseArrayBuffer failed'); //@ts-ignore this.litSearch!.setPercent(res.msg || 'This File is not supported!', -1); this.resetMenus(); + Utils.currentTraceName = ''; this.freshMenuDisable(false); } + loadTraceCompleteEvent(); this.progressEL!.loading = false; this.headerDiv!.style.pointerEvents = 'auto'; this.spInfoAndStats!.initInfoAndStatsData(); @@ -1757,6 +1788,12 @@ export class SpApplication extends BaseElement { let querySelectors = menuGroup.querySelectorAll('lit-main-menu-item'); querySelectors.forEach((item) => { if (item.getAttribute('title') === 'Convert to .systrace') { + if (fileName.indexOf('.htrace') > 0) { + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + event: 'convert_systrace', + action: 'convert_systrace', + }); + } item!.setAttribute('icon', 'convert-loading'); item!.classList.add('pending'); item!.style.fontKerning = ''; @@ -2056,7 +2093,7 @@ export class SpApplication extends BaseElement { }); this.cutTraceFile!.addEventListener('click', (ev) => { this.validateFileCacheLost(); - if (this.isClear) { + if (this.isClear && !this.isOpenTrace) { let search = document.querySelector('body > sp-application')!.shadowRoot!.querySelector('#lit-search'); let progressEL = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("div > div.search-vessel > lit-progress-bar"); progressEL!.loading = false; @@ -2085,6 +2122,7 @@ export class SpApplication extends BaseElement { // 鼠标拖动改变大小 this.aiPageResize(); + addExportDBToParentEvent(); } private aiPageResize(): void { @@ -2339,6 +2377,7 @@ export class SpApplication extends BaseElement { }); }); this.isClear = true; + this.isOpenTrace = false; this.mainMenu!.menus = this.mainMenu!.menus; } else { this.isClear = false; @@ -2545,7 +2584,7 @@ export class SpApplication extends BaseElement { openUrl(arrayBuf, fileName, showFileName, arrayBuf.byteLength); }); } else { - let api = `${window.location.origin}/application/download-file`; + let api = `${window.location.origin}${window.location.pathname}download-file`; fetch(api, { method: 'POST', headers: { @@ -2567,7 +2606,7 @@ export class SpApplication extends BaseElement { } }) .catch((e) => { - let api = `${window.location.origin}/application/download-file`; + let api = `${window.location.origin}${window.location.pathname}download-file`; fetch(api, { method: 'POST', headers: { diff --git a/ide/src/trace/SpApplicationPublicFunc.ts b/ide/src/trace/SpApplicationPublicFunc.ts index 6c366a72c11745e3017f60c5cc80eed972da158c..e50657e7cda9b51a33585e9f1a2dcffa8244970c 100644 --- a/ide/src/trace/SpApplicationPublicFunc.ts +++ b/ide/src/trace/SpApplicationPublicFunc.ts @@ -13,7 +13,8 @@ * limitations under the License. */ -import { getThreadPoolTraceBufferCacheKey } from './database/SqlLite'; +import { Utils as TraceUtil } from './component/trace/base/Utils'; +import { getThreadPoolTraceBufferCacheKey, threadPool } from './database/SqlLite'; export enum TraceMode { NORMAL, @@ -471,7 +472,7 @@ export function clearTraceFileCache(): void { } export function postLog(filename: string, fileSize: string): void { - fetch(`https://${window.location.host.split(':')[0]}:${window.location.port}/logger`, { + fetch(`https://${window.location.host.split(':')[0]}:${window.location.port}${window.location.pathname}logger`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -590,4 +591,36 @@ export function isZlibFile(uint8Array: Uint8Array): boolean { } } return true; +} + +/** + * 外部交互,向外传输db文件 + */ +export function addExportDBToParentEvent() { + window.addEventListener('message', e => { + if (e.data.name == 'exportDbToParent') { + threadPool.submit('download-db', '', {}, async (reqBufferDB: ArrayBuffer) => { + if (reqBufferDB && reqBufferDB.byteLength > 0) { + window.parent.postMessage({ + name: `${(TraceUtil.currentTraceName || 'trace').split('.')[0]}.db`, + data: reqBufferDB + }, '*'); + } else { + window.parent.postMessage({ + name: `暂无数据`, + data: null + }, '*'); + } + }, 'download-db'); + } + }); +} + +export function loadTraceCompleteEvent() { + if (window?.parent) { + window.parent.postMessage({ + name:'trace_load_complete', + data: null + }, '*'); + } } \ No newline at end of file diff --git a/ide/src/trace/bean/BoxSelection.ts b/ide/src/trace/bean/BoxSelection.ts index c83bb3455d9a05551a5afb0f34a454a821cdad84..81cd3c3ea2c982428e80752fc04a75e5403a2180 100644 --- a/ide/src/trace/bean/BoxSelection.ts +++ b/ide/src/trace/bean/BoxSelection.ts @@ -103,6 +103,8 @@ export class SelectionParam { irqCallIds: Array = []; softIrqCallIds: Array = []; funTids: Array = []; + threadSysCallIds: Array = []; + processSysCallIds: Array = []; funAsync: Array<{ name: string; pid: number, tid: number | undefined }> = []; funCatAsync: Array<{ pid: number; threadName: string }> = []; nativeMemory: Array = []; @@ -164,6 +166,7 @@ export class SelectionParam { hiSysEvents: Array = []; sampleData: Array = []; gpuCounter: Array = []; + isImportSo: boolean = false; // @ts-ignore pushSampleData(it: TraceRow): void { @@ -194,6 +197,16 @@ export class SelectionParam { } } + // @ts-ignore + pushSysCallIds(it: TraceRow): void { + if (it.rowType === TraceRow.ROW_TYPE_THREAD_SYS_CALL) { + const arr = it.rowId?.split('-'); + if (arr && arr.length === 3) { + this.threadSysCallIds.push(parseInt(arr[1])); + } + } + } + // @ts-ignore pushCpuStateFilterIds(it: TraceRow): void { if (it.rowType === TraceRow.ROW_TYPE_CPU_STATE_ALL) { @@ -258,6 +271,14 @@ export class SelectionParam { if (it.rowType === TraceRow.ROW_TYPE_PROCESS || it.rowType === TraceRow.ROW_TYPE_IMPORT) { sp.pushPidToSelection(this, it.rowId!, it.summaryProtoPid); sp.pushPidToSelection(this, it.rowId!); + if (it.getRowSettingCheckStateByKey('SysCall Event')) { + let pid = parseInt(it.rowId!); + if (!isNaN(pid!)) { + if (!this.processSysCallIds.includes(pid!)) { + this.processSysCallIds.push(pid!); + } + } + } if (it.getAttribute('hasStartup') === 'true') { this.startup = true; } @@ -1348,6 +1369,7 @@ export class SelectionParam { this.pushStaticInit(it, sp); this.pushAppStartUp(it, sp); this.pushThread(it, sp); + this.pushSysCallIds(it); this.pushVirtualMemory(it, sp); this.pushFps(it, sp); this.pushCpuAbility(it, sp); @@ -1388,6 +1410,27 @@ export class BoxJumpParam { currentId: string | undefined | null; } +export class SysCallBoxJumpParam { + traceId: string | undefined | null; + leftNs: number = 0; + rightNs: number = 0; + processId: number[] | undefined; + threadId: number[] | undefined; + sysCallId: number | undefined; + isJumpPage: boolean | undefined; +} + +export class PerfSampleBoxJumpParam { + traceId: string | undefined | null; + leftNs: number = 0; + rightNs: number = 0; + isJumpPage: boolean | undefined; + pid: number | undefined; + tid: number | undefined; + count: number = 0; + tsArr: number[] = []; +} + export class SliceBoxJumpParam { traceId: string | undefined | null; leftNs: number = 0; diff --git a/ide/src/trace/bean/FrameChartStruct.ts b/ide/src/trace/bean/FrameChartStruct.ts index de1eeb94f33fb1119a9175451d17092ea664ce23..052b84e2b684c80518c70890d3c6a4218c83a6c1 100644 --- a/ide/src/trace/bean/FrameChartStruct.ts +++ b/ide/src/trace/bean/FrameChartStruct.ts @@ -37,6 +37,7 @@ export class ChartStruct extends BaseStruct { static hoverFuncStruct: ChartStruct | undefined; static selectFuncStruct: ChartStruct | undefined; static lastSelectFuncStruct: ChartStruct | undefined; + static tempSelectStruct: ChartStruct | undefined; isDraw = false; // 是否绘制,太小的不绘制 depth: number = 0; symbol: string = ''; diff --git a/ide/src/trace/bean/FuncStruct.ts b/ide/src/trace/bean/FuncStruct.ts index 214bf1103971b831674fc33cefdb5982e4c9a3ab..3c3a156a85f15b571eb12d1e941d88412f9e2d26 100644 --- a/ide/src/trace/bean/FuncStruct.ts +++ b/ide/src/trace/bean/FuncStruct.ts @@ -46,6 +46,10 @@ export class FuncStruct extends BaseStruct { spanId: string | undefined; parentSpanId: string | undefined; chainFlag: string | undefined; + trace_level: string | undefined; + trace_tag: string | undefined; + custom_args: string | undefined; + category: string | undefined; static draw(funcBeanStructCanvasCtx: CanvasRenderingContext2D, funcBeanStruct: FuncStruct): void { if (funcBeanStruct.frame) { diff --git a/ide/src/trace/bean/PerfProfile.ts b/ide/src/trace/bean/PerfProfile.ts index d35a7eeb2ae24528cfe4f3c5a5f2470c1b8f989a..f7561bff8937bfb10880acc92533a8993e1dae72 100644 --- a/ide/src/trace/bean/PerfProfile.ts +++ b/ide/src/trace/bean/PerfProfile.ts @@ -121,6 +121,9 @@ export class PerfStack { fileId: number = 0; type: number = 0; vaddrInFile: number = 0; + sourceId: number | undefined; + sourceFile: string | undefined; + lineNumber: number | undefined; } export class PerfCmdLine { diff --git a/ide/src/trace/component/SpAiAnalysisPage.ts b/ide/src/trace/component/SpAiAnalysisPage.ts index 3742c4626ec0457c18cde967bee4ef5f5561fad0..ab6c5407d762be745ada0e446788b01bc502ffb6 100644 --- a/ide/src/trace/component/SpAiAnalysisPage.ts +++ b/ide/src/trace/component/SpAiAnalysisPage.ts @@ -169,9 +169,9 @@ export class SpAiAnalysisPage extends BaseElement { // 给右边栏添加点击事件 // @ts-ignore - rightBarGroup.forEach((barItem: unknown, index: number) => { + rightBarGroup.forEach((barItem: unknown, index: number) => { // @ts-ignore - barItem.barEl.addEventListener('click', (ev: Event) => { + barItem.barEl.addEventListener('click', (ev: Event) => { // @ts-ignore if (barItem.isMustLoadedTrace && !SpApplication.isTraceLoaded) { let importTraceTips = '请先导入trace,再使用诊断功能'; @@ -180,26 +180,26 @@ export class SpAiAnalysisPage extends BaseElement { return; } // this.tipsContent!.style.display = this.isNodata && barItem.barFlag === 'detect' ? 'flex' : 'none'; - this.tipsContainer!.style.display = 'none'; + this.tipsContainer!.style.display = 'none'; // @ts-ignore - this.showPageFlag = barItem.barFlag; + this.showPageFlag = barItem.barFlag; // @ts-ignore - barItem.imgEl.src = barItem.activeImg; + barItem.imgEl.src = barItem.activeImg; // @ts-ignore - barItem.barEl.classList.add('active'); + barItem.barEl.classList.add('active'); // @ts-ignore - barItem.showPage.style.display = 'block'; + barItem.showPage.style.display = 'block'; // @ts-ignore if (this.tipContentArr.indexOf(barItem.barFlag) > -1) { this.tipsContainer!.style.display = 'flex'; - } + } // @ts-ignore for (let i = 0; i < rightBarGroup.length; i++) { - if (i !== index) { + if (i !== index) { // @ts-ignore - rightBarGroup[i].barEl.classList.remove('active'); + rightBarGroup[i].barEl.classList.remove('active'); // @ts-ignore - rightBarGroup[i].imgEl.src = rightBarGroup[i].img; + rightBarGroup[i].imgEl.src = rightBarGroup[i].img; // @ts-ignore rightBarGroup[i].showPage.style.display = 'none'; } @@ -396,26 +396,21 @@ export class SpAiAnalysisPage extends BaseElement { this.createChatBox(); this.createAiChatBox('AI智能分析中...'); this.q_a_window!.scrollTop = this.q_a_window!.scrollHeight; - // 没有token - if (this.chatToken === '') { - await this.getToken90Min('aiTakeToken', true); - } - if (this.chatToken !== '') { - this.answer(); - } + this.answer(); } } // ai对话 async answer(): Promise { let requestBody = { - token: this.chatToken, - question: this.question, - collection: 'smart_perf_test', - scope: 'smartperf' + 'inputs': {}, + 'query': this.question, + 'response_mode': 'blocking', + 'conversation_id': '', + 'user': 'abc-123' }; - await SpStatisticsHttpUtil.askAi(requestBody, 'aiAsk').then(res => { + await SpStatisticsHttpUtil.askAi(requestBody, 'difyAsk').then(res => { if (res.status === 200) { SpStatisticsHttpUtil.generalRecord('AI_statistic', 'large_model_q&a', []); } diff --git a/ide/src/trace/component/SpFlag.html.ts b/ide/src/trace/component/SpFlag.html.ts index 273c5cea4fe0a2c30c8f4f9fccbcd34c870e38ce..7c88577bd0e05fdf57e1ccd6c081e9e19264e2f5 100644 --- a/ide/src/trace/component/SpFlag.html.ts +++ b/ide/src/trace/component/SpFlag.html.ts @@ -106,6 +106,9 @@ export const SpFlagHtml = `
    diff --git a/ide/src/trace/component/SpFlags.ts b/ide/src/trace/component/SpFlags.ts index d3bf084543549f1adf13fd55484064a0fa4bf7dc..8d9594c888967e538c8fdbdf21624f22c48aa644 100644 --- a/ide/src/trace/component/SpFlags.ts +++ b/ide/src/trace/component/SpFlags.ts @@ -15,6 +15,9 @@ import { BaseElement, element } from '../../base-ui/BaseElement'; import { SpFlagHtml } from './SpFlag.html'; +import { LitSelectV } from '../../base-ui/select/LitSelectV'; +import { SysCallMap } from './trace/base/SysCallUtils'; + const NUM = '000000'; //vsync二级下拉选框对应的value和content const VSYNC_CONTENT = [ @@ -46,14 +49,75 @@ const CONFIG_STATE: unknown = { export class SpFlags extends BaseElement { private bodyEl: HTMLElement | undefined | null; private xiaoLubanEl: Element | null | undefined; + private systemCallSelect: LitSelectV | undefined | null; + private systemCallInput: HTMLInputElement | undefined | null; + private systemCallEventId: number[] = []; + private systemCallSwitch: HTMLSelectElement | undefined | null; + + + connectedCallback(): void { + this.systemCallSelect?.addEventListener('blur', this.systemCallSelectBlurHandler); + } + + disconnectedCallback(): void { + super.disconnectedCallback(); + this.systemCallSelect?.removeEventListener('blur', this.systemCallSelectBlurHandler); + } initElements(): void { let parentElement = this.parentNode as HTMLElement; parentElement.style.overflow = 'hidden'; this.bodyEl = this.shadowRoot?.querySelector('.body'); this.initConfigList(); + this.systemCallSelect = this.shadowRoot?.querySelector("lit-select-v[title='SystemCall']"); + this.systemCallSwitch = this.shadowRoot?.querySelector("select[title='System Calls']"); + this.systemCallInput = this.systemCallSelect!.shadowRoot?.querySelector('input') as HTMLInputElement; + this.updateSystemCallSelect(); + } + + private updateSystemCallSelect(): void { + const selectedArr = FlagsConfig.getSystemcallEventId('SystemParsing'); + let checkAll = true; + systemCallConfigList[0].selectArray = Array.from(SysCallMap.entries()) + .map(([id, name]) => { + if (!selectedArr.includes(id)) { + checkAll = false; + } + return `${name}`; + }); + this.systemCallSelect?.dataSource(systemCallConfigList[0].selectArray, 'ALL-SystemCall'); + this.systemCallSelect?.setIgnoreValues(['ALL-SystemCall']); + if (this.systemCallSwitch?.title === 'System Calls' && this.systemCallSwitch.selectedOptions[0].value === 'Enabled') { + this.systemCallSelect?.removeAttribute('disabled'); + const arr = checkAll ? ['ALL-SystemCall' ] : []; + FlagsConfig.getSystemcallEventId('SystemParsing').forEach(it => arr.push(SysCallMap.get(it) || '')); + this.systemCallSelect?.setSelectedOptions(arr); + } else { + this.systemCallSelect?.setAttribute('disabled', 'disabled'); + this.systemCallSelect?.setSelectedOptions([]); + } } + private systemCallSelectBlurHandler = () => { + let systemCallSelectOptions = this.systemCallSelect!.shadowRoot?.querySelectorAll('.option'); + this.systemCallEventId = []; + systemCallSelectOptions!.forEach((option) => { + if (option.hasAttribute('selected')) { + const systemCallEventItem = Array.from(SysCallMap.entries()) + .find(([id, name]) => name === option.getAttribute('value')); + if (systemCallEventItem) { + this.handleSystemCallEventId(systemCallEventItem[0]); + } + } + }); + FlagsConfig.updateSystemcallEventId(this.systemCallEventId, 'SystemParsing'); + return this.systemCallEventId; + }; + + private handleSystemCallEventId = (systemCallEventId: number): void => { + this.systemCallEventId.push(systemCallEventId); + }; + initHtml(): string { return SpFlagHtml; } @@ -102,6 +166,16 @@ export class SpFlags extends BaseElement { this.xiaoLubanEl?.removeAttribute('enabled'); } } + if (configSelect.title === 'System Calls') { + if (configSelect.selectedOptions[0].value === 'Enabled') { + this.systemCallSelect?.removeAttribute('disabled'); + } else { + this.systemCallSelect?.setAttribute('disabled', 'disabled'); + this.systemCallEventId = []; + FlagsConfig.updateSystemcallEventId([], 'SystemParsing'); + this.systemCallSelect?.setSelectedOptions([]); + } + } }); let userIdInput: HTMLInputElement | null | undefined = this.shadowRoot?.querySelector('#user_id_input'); if (configSelect.title === 'AI' && configSelect.selectedOptions[0].value === 'Enabled' && userIdInput?.value === '') { @@ -226,10 +300,51 @@ export class SpFlags extends BaseElement { configFooterDiv.appendChild(userIdInputEl); configDiv.appendChild(configFooterDiv); } + if (config.title === 'System Calls') { + let configFooterDiv = document.createElement('div'); + configFooterDiv.className = 'config_footer'; + let systemCallConfigEl = document.createElement('div'); + systemCallConfigEl.className = 'system-call-config'; + systemCallConfigList.forEach((config) => { + let systemCallConfigDiv = document.createElement('div'); + if (config.hidden) { + systemCallConfigDiv.className = 'systemCall-config-div hidden'; + } else { + systemCallConfigDiv.className = 'systemCall-config-div'; + } + switch (config.type) { + case 'select-multiple': + this.configTypeBySelectMultiple(config, systemCallConfigDiv); + break; + default: + break; + } + systemCallConfigEl.appendChild(systemCallConfigDiv); + }) + configFooterDiv.appendChild(systemCallConfigEl); + configDiv.appendChild(configFooterDiv); + } this.bodyEl!.appendChild(configDiv); }); } + private configTypeBySelectMultiple(config: unknown, systemCallConfigDiv: HTMLDivElement): void { + let html = ''; + //@ts-ignore + let placeholder = config.selectArray[0]; + html += ``; + //@ts-ignore + config.selectArray.forEach((value: string) => { + html += `${value}`; + }); + html += ''; + systemCallConfigDiv.innerHTML = systemCallConfigDiv.innerHTML + html; + } + private createPersonOption(list: unknown, key: string, config: unknown): HTMLDivElement { let configFooterDiv = document.createElement('div'); configFooterDiv.className = 'config_footer'; @@ -279,6 +394,7 @@ export type Params = { export class FlagsConfig { static FLAGS_CONFIG_KEY = 'FlagsConfig'; + static SYSTEM_PRASE = 'SystemParsing'; static DEFAULT_CONFIG: Array = [ { title: 'TaskPool', @@ -359,6 +475,12 @@ export class FlagsConfig { switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], describeContent: 'Start AI', addInfo: { userId: '' }, + }, + { + title: 'System Calls', + switchOptions: [{ option: 'Enabled' }, { option: 'Disabled', selected: true }], + describeContent: 'Start System Call Parsing', + addInfo: { userId: '' }, } ]; @@ -417,6 +539,11 @@ export class FlagsConfig { }); // @ts-ignore parseConfig[configItem.title] = selectedOption[0].option === 'Enabled' ? 1 : 0; + // @ts-ignore + if (configItem.title === 'System Calls') { + // @ts-ignore + parseConfig[configItem.title] = selectedOption[0].option === 'Enabled' ? FlagsConfig.getSystemcallEventId('SystemParsing').join(';') : ''; + } }); return JSON.stringify({ config: parseConfig }); } @@ -471,6 +598,20 @@ export class FlagsConfig { flagConfigObj[key] = value; window.localStorage.setItem(FlagsConfig.FLAGS_CONFIG_KEY, JSON.stringify(flagConfigObj)); } + + + static getSystemcallEventId(value: string): number[] { + let list = window.localStorage.getItem(FlagsConfig.SYSTEM_PRASE); + return JSON.parse(list!) || []; + } + + static updateSystemcallEventId(systemCallEventId: number[], value: unknown): void { + let systemCallEventIdArray:number[] = []; + if (systemCallEventId !== null) { + systemCallEventIdArray = systemCallEventId; + } + window.localStorage.setItem(FlagsConfig.SYSTEM_PRASE, JSON.stringify(systemCallEventIdArray)); + } } export interface FlagConfigItem { @@ -484,3 +625,12 @@ export interface OptionItem { option: string; selected?: boolean; } + +const systemCallConfigList = [ + { + title: 'SystemCall', + des: '', + hidden: true, + type: 'select-multiple', + selectArray: [''], + }] diff --git a/ide/src/trace/component/SpHelp.ts b/ide/src/trace/component/SpHelp.ts index 3aca9c13dd8ad4549d6d2e3a15d91f4c00af5c8a..4cd235c63d2895706bfc1b4a1ccc3b1a8661309d 100644 --- a/ide/src/trace/component/SpHelp.ts +++ b/ide/src/trace/component/SpHelp.ts @@ -39,7 +39,7 @@ export class SpHelp extends BaseElement { } this.helpFile!.innerHTML = '`; this.navbarInit(helpDocDetail!.name); @@ -269,13 +269,13 @@ export class SpHelp extends BaseElement { event: event, action: 'help_doc', }); - that.helpFile!.innerHTML = ``; + that.helpFile!.innerHTML = ``; this.navbarInit(docName); this.changeItemURL(index!); } private navbarInit(docName: string): void { - fetch(`/application/doc/${docName}.html`) + fetch(`doc/${docName}.html`) .then(response => response.text()) .then(htmlString => { const parser = new DOMParser(); @@ -303,7 +303,7 @@ export class SpHelp extends BaseElement { navLink.closest('li')!.classList.add('active'); let targetId = navLink.id; e.preventDefault(); - this.helpFile!.innerHTML = ``; + this.helpFile!.innerHTML = ``; }); }); @@ -312,7 +312,7 @@ export class SpHelp extends BaseElement { navLinks.forEach((navLink) => { navLink.closest('li')?.classList.remove('active'); }); - this.helpFile!.innerHTML = ``; + this.helpFile!.innerHTML = ``; }); }) diff --git a/ide/src/trace/component/SpRecordTrace.ts b/ide/src/trace/component/SpRecordTrace.ts index dfb8d1b8f04082732bf5ffdf90519120b60e4870..27649444b8f9cc29020ebf8eda8d1f6bc940e607 100644 --- a/ide/src/trace/component/SpRecordTrace.ts +++ b/ide/src/trace/component/SpRecordTrace.ts @@ -114,10 +114,15 @@ export class SpRecordTrace extends BaseElement { private spWebShell: SpWebHdcShell | undefined; private menuGroup: LitMainMenuGroup | undefined | null; private appContent: HTMLElement | undefined | null; + private optionNum: number = 0; private record = 'Record'; private stop = 'StopRecord'; private nowChildItem: HTMLElement | undefined; private longTraceList: Array = []; + private fileList: Array<{ + fileName: string, + file: File + }> = []; private refreshDeviceTimer: number | undefined; private hintEl: HTMLSpanElement | undefined; private selectedTemplate: Map = new Map(); @@ -134,6 +139,7 @@ export class SpRecordTrace extends BaseElement { public static usbGetEvent: string; public static usbGetApp: string; private static usbGetVersion: string; + public static usbGetHisystem: string; static snapShotList: Array = []; static snapShotDuration: number = 0; static isSnapShotCapture: boolean = false; @@ -532,6 +538,7 @@ export class SpRecordTrace extends BaseElement { let isCheckSnapshot = this.spArkTs!.radioBoxType === 0 ? true : false; // 是否check snapshot let isCheckTimeLine = this.spArkTs!.radioBoxType === 1 ? true : false; // 是否 check timeline + let isLongTrace = SpApplication.isLongTrace; let maxDur = this.recordSetting!.maxDur; // 抓取trace的时长 let snapShotDur = this.recordSetting!.snapShot;//截图 SpRecordTrace.snapShotDuration = snapShotDur; @@ -542,6 +549,7 @@ export class SpRecordTrace extends BaseElement { let enableCpuProfiler = this.spArkTs!.isStartCpuProfiler; let params: unknown = { + isLongTrace: isLongTrace, isRecordArkTs: isRecordArkTs, isRecordHitrace: isRecordHitrace, type: '', @@ -591,7 +599,7 @@ export class SpRecordTrace extends BaseElement { this.progressEL!.loading = false;// @ts-ignore let errorMsg = new TextDecoder().decode(result); this.useExtentTip!.style.display = 'block'; - let urlAsciiArr = [104,116,116,112,115,58,47,47,119,105,107,105,46,104,117,97,119,101,105,46,99,111,109,47,100,111,109,97,105,110,115,47,55,54,57,49,49,47,119,105,107,105,47,49,50,53,52,56,48,47,87,73,75,73,50,48,50,53,48,49,49,54,53,55,53,48,52,53,52]; + let urlAsciiArr = [104, 116, 116, 112, 115, 58, 47, 47, 119, 105, 107, 105, 46, 104, 117, 97, 119, 101, 105, 46, 99, 111, 109, 47, 100, 111, 109, 97, 105, 110, 115, 47, 55, 54, 57, 49, 49, 47, 119, 105, 107, 105, 47, 49, 50, 53, 52, 56, 48, 47, 87, 73, 75, 73, 50, 48, 50, 53, 48, 49, 49, 54, 53, 55, 53, 48, 52, 53, 52]; let exceptGuid = String.fromCodePoint(...urlAsciiArr); this.useExtentTip!.innerHTML = `抓取trace异常:${errorMsg} 可根据[常见异常处理]解决异常`; this.refreshDisableStyle(false, false); @@ -613,12 +621,88 @@ export class SpRecordTrace extends BaseElement { this.litSearch!.setPercent('Tracing htrace down', -1); } else if (cmd === 8) { this.litSearch!.setPercent('Downloading Hitrace file...', -1); + } else if (cmd === 9) {// @ts-ignore + let re = JSON.parse(new TextDecoder('utf-8').decode(result)); + let binaryString = window.atob(re.data); + let len = binaryString.length; + let bytes = new Uint8Array(len); + for (let i = 0; i < len; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + re.data = bytes.buffer; + let fileInfo = { + fileName: re.fileName, + file: new File([re.data], re.fileName) + }; + this.fileList.push(fileInfo); + this.longTraceList.push(fileInfo.fileName); + if (this.fileList.length === re.total) { + this.openLongTraceHandle(); + } } }; WebSocketManager.getInstance()!.registerMessageListener(TypeConstants.ARKTS_TYPE, onmessageCallBack, this.eventCallBack); WebSocketManager.getInstance()!.sendMessage(TypeConstants.ARKTS_TYPE, 1, encoder.encode(JSON.stringify(params))); }; + async openLongTraceHandle() { + this.fileList.sort((a, b) => { + const getNumber = (name: string) => { + const match = name.match(/_(\d+)\.htrace$/); + return match ? parseInt(match[1]) : 0; + }; + return getNumber(a.fileName) - getNumber(b.fileName); + }); + let timStamp = new Date().getTime(); + this.sp!.longTraceHeadMessageList = []; + for (const fileInfo of this.fileList) { + await this.saveLongTrace(fileInfo.file, timStamp); + } + await this.openLongTrace(timStamp); + this.fileList = []; + this.longTraceList = []; + } + + async saveLongTrace(file: File, timStamp: number) { + let traceTypePage = this.getLongTraceTypePage(); + let types = this.sp!.fileTypeList.filter(type => + file.name.toLowerCase().includes(type.toLowerCase()) + ); + let pageNumber = 0; + let fileType = types[0] || 'trace'; + if (types.length === 0) { + let searchNumber = Number( + file.name.substring( + file.name.lastIndexOf('_') + 1, + file.name.lastIndexOf('.') + ) + ) - 1; + pageNumber = traceTypePage.lastIndexOf(searchNumber); + } + this.litSearch!.setPercent(`downloading ${fileType} file`, 101); + await this.saveIndexDBByLongTrace(file, fileType, pageNumber, timStamp); + } + + async openLongTrace(timStamp: number) { + let main = this.parentNode!.parentNode!.querySelector('lit-main-menu') as LitMainMenu; + let children = main.menus as Array; + let child = children[1].children as Array; + let fileHandler = child[0].clickHandler; + if (fileHandler && !SpRecordTrace.cancelRecord) { + this.freshConfigMenuDisable(false); + this.freshMenuDisable(false); + this.buttonDisable(false); + this.recordButtonDisable(false); + fileHandler({ + detail: { + timeStamp: timStamp + } + }, true); + } else { + SpRecordTrace.cancelRecord = false; + } + } + recordTempAddProbe = (ev: CustomEventInit<{ elementId: string }>): void => { if ( FlagsConfig.DEFAULT_CONFIG.find((flagItem) => { @@ -721,6 +805,35 @@ export class SpRecordTrace extends BaseElement { }; }; + usbGetVersion(dev: string) { + let option = document.createElement('option'); + option.className = 'select'; + this.optionNum++; + // @ts-ignore + option.value = dev; + // @ts-ignore + option.textContent = dev.toString(); + this.deviceSelect!.appendChild(option); + if (dev.toString() === SpRecordTrace.serialNumber || SpRecordTrace.serialNumber === '') { + SpRecordTrace.serialNumber = dev; + option.selected = true; + this.recordButton!.hidden = false; + this.disconnectButton!.hidden = false; + this.cancelButton!.hidden = true; + this.devicePrompt!.innerText = ''; + this.hintEl!.textContent = ''; + // @ts-ignore + WebSocketManager.getInstance()!.sendMessage(TypeConstants.USB_TYPE, TypeConstants.USB_GET_VERSION, new TextEncoder().encode(dev)); + setTimeout(() => { + if (SpRecordTrace.usbGetVersion) { + SpRecordTrace.selectVersion = this.getDeviceVersion(SpRecordTrace.usbGetVersion); + this.setDeviceVersionSelect(SpRecordTrace.selectVersion); + this.nativeMemoryHideBySelectVersion(); + } + }, 1000); + } + } + webSocketCallBackasync = (cmd: number, result: Uint8Array): void => { const decoder = new TextDecoder(); const jsonString = decoder.decode(result); @@ -730,20 +843,37 @@ export class SpRecordTrace extends BaseElement { HdcDeviceManager.findDevice().then((usbDevices): void => { SpRecordTrace.serialNumber = usbDevices.serialNumber; this.usbSerialNum = jsonRes.resultMessage; - let optionNum = 0; - if (this.usbSerialNum.length === 1 && this.usbSerialNum[0].includes('Empty')) { + this.optionNum = 0; + if (this.usbSerialNum.length === 1) { + if (this.usbSerialNum[0].includes('Empty')) { + this.usbSerialNum.shift(); + this.recordButton!.hidden = true; + this.disconnectButton!.hidden = true; + this.cancelButton!.hidden = true; + this.devicePrompt!.innerText = 'Device not connected'; + this.deviceSelect!.style!.border = '2px solid red'; + setTimeout(() => { + this.deviceSelect!.style!.border = '1px solid #4D4D4D'; + }, 3000); + this.useExtentTip!.style.display = 'block'; + this.useExtentTip!.innerHTML = '手机连接有问题,请重新插拔一下手机,或者请使用系统管理员权限打开cmd窗口,并执行hdc shell'; + return; + }else{ + this.usbGetVersion(this.usbSerialNum[0]); + } + }else if(this.usbSerialNum.length > 1 && usbDevices.serialNumber === ''){ this.usbSerialNum.shift(); - this.recordButton!.hidden = true; - this.disconnectButton!.hidden = true; - this.cancelButton!.hidden = true; - this.devicePrompt!.innerText = 'Device not connected'; - this.deviceSelect!.style!.border = '2px solid red'; - setTimeout(() => { - this.deviceSelect!.style!.border = '1px solid #4D4D4D'; - }, 3000); - this.useExtentTip!.style.display = 'block'; - this.useExtentTip!.innerHTML = '手机连接有问题,请重新插拔一下手机,或者请使用系统管理员权限打开cmd窗口,并执行hdc shell'; - return; + this.recordButton!.hidden = true; + this.disconnectButton!.hidden = true; + this.cancelButton!.hidden = true; + this.devicePrompt!.innerText = 'Device not connected'; + this.deviceSelect!.style!.border = '2px solid red'; + setTimeout(() => { + this.deviceSelect!.style!.border = '1px solid #4D4D4D'; + }, 3000); + this.useExtentTip!.style.display = 'block'; + this.useExtentTip!.innerHTML = '加密设备仅限连接一台'; + return; } // @ts-ignore while (this.deviceSelect!.firstChild) { @@ -751,33 +881,9 @@ export class SpRecordTrace extends BaseElement { } for (let len = 0; len < this.usbSerialNum.length; len++) { let dev = this.usbSerialNum[len]; - let option = document.createElement('option'); - option.className = 'select'; - optionNum++; - // @ts-ignore - option.value = dev; - // @ts-ignore - option.textContent = dev.toString(); - this.deviceSelect!.appendChild(option); - if (dev.toString() === SpRecordTrace.serialNumber) { - option.selected = true; - this.recordButton!.hidden = false; - this.disconnectButton!.hidden = false; - this.cancelButton!.hidden = true; - this.devicePrompt!.innerText = ''; - this.hintEl!.textContent = ''; - // @ts-ignore - WebSocketManager.getInstance()!.sendMessage(TypeConstants.USB_TYPE, TypeConstants.USB_GET_VERSION, new TextEncoder().encode(dev)); - setTimeout(() => { - if (SpRecordTrace.usbGetVersion) { - SpRecordTrace.selectVersion = this.getDeviceVersion(SpRecordTrace.usbGetVersion); - this.setDeviceVersionSelect(SpRecordTrace.selectVersion); - this.nativeMemoryHideBySelectVersion(); - } - }, 1000); - } + this.usbGetVersion(dev); } - if (!optionNum) { + if (!this.optionNum) { this.deviceSelect!.style!.border = '2px solid red'; setTimeout(() => { this.deviceSelect!.style!.border = '1px solid #4D4D4D'; @@ -801,6 +907,8 @@ export class SpRecordTrace extends BaseElement { SpRecordTrace.usbGetApp = jsonRes.resultMessage; } else if (cmd === TypeConstants.USB_GET_VERSION) { SpRecordTrace.usbGetVersion = jsonRes.resultMessage; + } else if (cmd === TypeConstants.USB_GET_HISYSTEM) { + SpRecordTrace.usbGetHisystem = jsonRes.resultMessage; } }; diff --git a/ide/src/trace/component/SpSystemTrace.event.ts b/ide/src/trace/component/SpSystemTrace.event.ts index 165126d615a35e2c5b1c3906c4cde10c37673cfa..da0632941ac24396ceca06f69b997ea12617e41c 100644 --- a/ide/src/trace/component/SpSystemTrace.event.ts +++ b/ide/src/trace/component/SpSystemTrace.event.ts @@ -63,6 +63,7 @@ import { XpowerGpuFreqStruct, XpowerGpuFreqStructOnClick } from '../database/ui- import { XpowerThreadCountStruct, XpowerThreadCountStructOnClick } from '../database/ui-worker/ProcedureWorkerXpowerThreadCount'; import { XpowerGpuFreqCountStruct, XpowerGpuFreqCountStructOnClick } from '../database/ui-worker/ProcedureWorkerXpowerGpuFreqCount'; import { SnapShotOnClick, SnapShotStruct } from '../database/ui-worker/ProcedureWorkerSnaps'; +import { ThreadSysCallStruct, ThreadSysCallStructOnClick } from '../database/ui-worker/ProcedureWorkerThreadSysCall'; function timeoutJudge(sp: SpSystemTrace): number { let timeoutJudge = window.setTimeout((): void => { @@ -421,6 +422,7 @@ function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRo .then(() => sampleStructOnClick(clickRowType, sp, row as TraceRow, entry as SampleStruct)) .then(() => gpuCounterStructOnClick(clickRowType, sp, entry as GpuCounterStruct)) .then(() => PerfToolsStructOnClick(clickRowType, sp, entry as PerfToolStruct)) + .then(() => ThreadSysCallStructOnClick(clickRowType, sp, entry as ThreadSysCallStruct)) .then(() => SnapShotOnClick(clickRowType, sp, entry as SnapShotStruct)) .then(() => { if (!JankStruct.hoverJankStruct && JankStruct.delJankLineFlag) { @@ -578,7 +580,8 @@ function spSystemTraceDocumentOnMouseMoveMouseUp( sp.hoverStructNull(); } const transformYMatch = sp.canvasPanel?.style.transform.match(/\((\d+)[^\)]+\)/); - const transformY = transformYMatch![1]; + if (transformYMatch && transformYMatch![1]) { + const transformY = transformYMatch![1]; let favoriteHeight = sp.favoriteChartListEL!.getBoundingClientRect().height; // @ts-ignore let memTr = rows.filter((item: unknown) => item.rowType === TraceRow.ROW_TYPE_MEM); @@ -611,6 +614,7 @@ function spSystemTraceDocumentOnMouseMoveMouseUp( tr.findHoverStruct?.(); tr.focusHandler?.(ev); }); + } requestAnimationFrame(() => sp.refreshCanvas(true, 'sp move up')); } diff --git a/ide/src/trace/component/SpSystemTrace.init.ts b/ide/src/trace/component/SpSystemTrace.init.ts index 69a4599be3aa1cc90a0481ce88e109ab91ca6436..3247792004fc600e50ccd17497751c0cc32dbd7e 100644 --- a/ide/src/trace/component/SpSystemTrace.init.ts +++ b/ide/src/trace/component/SpSystemTrace.init.ts @@ -661,6 +661,7 @@ function selectHandlerRefreshCheckBox(sp: SpSystemTrace, rows: Array>): void { + Utils.isRangeSelectRefresh = true; let selection = new SelectionParam(); selection.traceId = Utils.currentSelectTrace; selection.cpuStateRowsId = sp.stateRowsId; @@ -1125,6 +1126,14 @@ function findEntryTypeFunc(sp: SpSystemTrace, findEntry: unknown): void { // @ts-ignore cookie: findEntry.cookie, // @ts-ignore + trace_level: findEntry.trace_level, + // @ts-ignore + trace_tag: findEntry.trace_tag, + // @ts-ignore + custom_args: findEntry.custom_args, + // @ts-ignore + category:findEntry.category, + // @ts-ignore //因异步trace分类出的rowId类型有三种,故新增row_id字段,该字段为异步方法的对应的rowId,支持搜索查询定位到该方法属于那个row,只有缓存的异步trace数据中含该字段 row_id: findEntry.rowId ? findEntry.rowId : null, }, @@ -1181,6 +1190,7 @@ async function spSystemTraceInitBuffer( sp: SpSystemTrace, param: { buf?: ArrayBuffer; Url?: string; buf2?: ArrayBuffer }, wasmConfigUri: string, + configUri: string, progress: Function ): Promise<{ status: boolean; @@ -1194,13 +1204,24 @@ async function spSystemTraceInitBuffer( error('getWasmConfigFailed', e); } let parseConfig = FlagsConfig.getSpTraceStreamParseConfig(); - let { status, msg, sdkConfigMap } = await threadPool.initSqlite(param.buf, parseConfig, configJson, progress); + let systemParseConfigJson = ''; + try { + systemParseConfigJson = await fetch(configUri).then((res) => res.text()); + let systemParseConfig = JSON.parse(systemParseConfigJson); + let parseConfigObj = JSON.parse(parseConfig); + systemParseConfig.config = parseConfigObj.config; + systemParseConfigJson = JSON.stringify(systemParseConfig); + } catch (e) { + systemParseConfigJson = parseConfig; + error('systemParseConfigJsonFailed', e); + } + let { status, msg, sdkConfigMap } = await threadPool.initSqlite(param.buf, systemParseConfigJson, configJson, progress); if (!status) { return { status: false, msg: msg }; } SpSystemTrace.SDK_CONFIG_MAP = sdkConfigMap; if (param.buf2) { - let { status, msg } = await threadPool2.initSqlite(param.buf2, parseConfig, configJson, progress); + let { status, msg } = await threadPool2.initSqlite(param.buf2, systemParseConfigJson, configJson, progress); if (!status) { return { status: false, msg: msg }; } @@ -1214,6 +1235,7 @@ async function spSystemTraceInitUrl( sp: SpSystemTrace, param: { buf?: ArrayBuffer; url?: string }, wasmConfigUri: string, + configUri: string, progress: Function ): Promise<{ status: boolean; @@ -1234,16 +1256,17 @@ export async function spSystemTraceInit( sp: SpSystemTrace, param: { buf?: ArrayBuffer; url?: string; buf2?: ArrayBuffer; fileName1?: string; fileName2?: string }, wasmConfigUri: string, + configUri: string, progress: Function, isDistributed: boolean ): Promise { progress('Load database', 6); sp.rowsPaneEL!.scroll({ top: 0, left: 0 }); - let rsBuf = await spSystemTraceInitBuffer(sp, param, wasmConfigUri, progress); + let rsBuf = await spSystemTraceInitBuffer(sp, param, wasmConfigUri, configUri, progress); if (rsBuf) { return rsBuf; } - let rsUrl = await spSystemTraceInitUrl(sp, param, wasmConfigUri, progress); + let rsUrl = await spSystemTraceInitUrl(sp, param, wasmConfigUri, configUri, progress); if (rsUrl) { return rsUrl; } @@ -1307,7 +1330,7 @@ export async function spSystemTraceInit( SpStatisticsHttpUtil.recordPluginUsage(); // trace文件加载完毕,将动效json文件读取并存入缓存 let funDetailUrl = `https://${window.location.host.split(':')[0]}:${window.location.port - }/application/doc/funDetail.json`; + }${window.location.pathname}doc/funDetail.json`; let xhr = new XMLHttpRequest(); // 创建XMLHttpRequest对象 xhr.open('GET', funDetailUrl); diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index c771f929b9aa4fa9d68a6e5737b19b4ee28a9a09..8f1449ea2d2f38e20f59751d0621a293b7676e37 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -144,6 +144,7 @@ import { XpowerThreadInfoStruct } from '../database/ui-worker/ProcedureWorkerXpo import { XpowerGpuFreqStruct } from '../database/ui-worker/ProcedureWorkerXpowerGpuFreq'; import { LitProgressBar } from '../../base-ui/progress-bar/LitProgressBar'; import { SnapShotStruct } from '../database/ui-worker/ProcedureWorkerSnaps'; +import { ThreadSysCallStruct } from '../database/ui-worker/ProcedureWorkerThreadSysCall'; function dpr(): number { return window.devicePixelRatio || 1; @@ -1370,6 +1371,7 @@ export class SpSystemTrace extends BaseElement { CpuStruct.hoverCpuStruct = undefined; CpuFreqStruct.hoverCpuFreqStruct = undefined; ThreadStruct.hoverThreadStruct = undefined; + ThreadSysCallStruct.hoverStruct = undefined; FuncStruct.hoverFuncStruct = undefined; ProcessMemStruct.hoverProcessMemStruct = undefined; HiPerfCpuStruct.hoverStruct = undefined; @@ -1412,6 +1414,7 @@ export class SpSystemTrace extends BaseElement { CpuFreqStruct.selectCpuFreqStruct = undefined; ThreadStruct.selectThreadStruct = undefined; ThreadStruct.isClickPrio = false; + ThreadSysCallStruct.selectStruct = undefined; FuncStruct.selectFuncStruct = undefined; SpHiPerf.selectCpuStruct = undefined; CpuStateStruct.selectStateStruct = undefined; @@ -2254,7 +2257,7 @@ export class SpSystemTrace extends BaseElement { complete?: ((res: { status: boolean; msg: string }) => void) | undefined ): void { this.observerScrollHeightEnable = false; - this.init({ url: url }, '', progress, false).then((res) => { + this.init({ url: url }, '', '', progress, false).then((res) => { if (complete) { // @ts-ignore complete(res); @@ -2268,6 +2271,7 @@ export class SpSystemTrace extends BaseElement { loadDatabaseArrayBuffer( buf: ArrayBuffer, thirdPartyWasmConfigUrl: string, + configUrl:string, progress: (name: string, percent: number) => void, isDistributed: boolean, complete?: ((res: { status: boolean; msg: string }) => void) | undefined, @@ -2281,7 +2285,7 @@ export class SpSystemTrace extends BaseElement { } else { this.timerShaftEL?.removeAttribute('distributed'); } - this.init({ buf, buf2, fileName1, fileName2 }, thirdPartyWasmConfigUrl, progress, isDistributed).then((res) => { + this.init({ buf, buf2, fileName1, fileName2 }, thirdPartyWasmConfigUrl, configUrl, progress, isDistributed).then((res) => { // @ts-ignore this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it)); if (complete) { @@ -2745,10 +2749,11 @@ export class SpSystemTrace extends BaseElement { init = async ( param: { buf?: ArrayBuffer; url?: string; buf2?: ArrayBuffer; fileName1?: string; fileName2?: string }, wasmConfigUri: string, + configUrl: string, progress: Function, isDistributed: boolean ): Promise => { - return spSystemTraceInit(this, param, wasmConfigUri, progress, isDistributed); + return spSystemTraceInit(this, param, wasmConfigUri, configUrl, progress, isDistributed); }; // @ts-ignore extracted(it: TraceRow) { diff --git a/ide/src/trace/component/chart/FrameChart.ts b/ide/src/trace/component/chart/FrameChart.ts index 8255fec26dfd78bec4a67c691e2cdfe45773fedf..afa92e75cbb014ad80654357f94bcd1e8ce7d9a5 100644 --- a/ide/src/trace/component/chart/FrameChart.ts +++ b/ide/src/trace/component/chart/FrameChart.ts @@ -232,6 +232,7 @@ export class FrameChart extends BaseElement { private clearOtherDisplayInfo(node: ChartStruct): void { for (const children of node.children) { if (children.isChartSelect) { + children.isChartSelect = false; this.clearOtherDisplayInfo(children); continue; } @@ -674,6 +675,20 @@ export class FrameChart extends BaseElement { this.floatHint!.innerHTML = this.hintContent; this.floatHint!.style.display = 'block'; this.floatHint!.style.zIndex = '9999999'; + const countSpan = this.floatHint!.querySelector('.count'); + if (countSpan) { + //@ts-ignore + countSpan.onclick = (e) => { + this.dispatchEvent( + new CustomEvent('td-click', { + detail: ChartStruct.tempSelectStruct, + composed: true, + }) + ); + // @ts-ignore + e.stopPropagation(); + }; + } let tipArea = this.tabPaneFilter?.getBoundingClientRect().top! - this.canvas.getBoundingClientRect().top - @@ -737,9 +752,9 @@ export class FrameChart extends BaseElement { this.setSelectStatusRecursive(ChartStruct.lastSelectFuncStruct!, false); } // 递归设置点选的parent,children为点选状态 + this.calDrawArgs(false); this.setSelectStatusRecursive(ChartStruct.selectFuncStruct!, true); - this.calDrawArgs(false); this.calculateChartData(); } @@ -857,6 +872,7 @@ export class FrameChart extends BaseElement { if (ChartStruct.hoverFuncStruct && ChartStruct.hoverFuncStruct !== ChartStruct.selectFuncStruct) { ChartStruct.lastSelectFuncStruct = ChartStruct.selectFuncStruct; ChartStruct.selectFuncStruct = ChartStruct.hoverFuncStruct; + ChartStruct.tempSelectStruct = undefined; this.isClickMode = ChartStruct.selectFuncStruct !== this.rootNode; this.rect.width = this.canvas!.clientWidth; // 重置缩放 @@ -875,8 +891,13 @@ export class FrameChart extends BaseElement { }) ); } + this.hideTip(); + } else { + // mouse right button + if (ChartStruct.hoverFuncStruct) { + ChartStruct.tempSelectStruct = ChartStruct.hoverFuncStruct; + } } - this.hideTip(); } private hideTip(): void { @@ -919,7 +940,7 @@ export class FrameChart extends BaseElement { const label = ChartMode.Count === this._mode ? 'Count' : 'EventCount'; const count = this.getNodeValue(hoverNode); let sourceHint = ''; - if (hoverNode.sourceFile !== '') { + if (hoverNode.sourceFile) { const lines = Array.from(hoverNode.lineNumber).sort((a, b) => a - b).join(','); sourceHint = `Source: ${hoverNode?.sourceFile} : ${lines}
    `; } @@ -928,7 +949,7 @@ export class FrameChart extends BaseElement { Lib: ${hoverNode?.lib}
    Addr: ${hoverNode?.addr}
    ${sourceHint} - ${label}: ${count}`; + ${label}: ${count}`; break; } if (this._mode !== ChartMode.Byte) { @@ -984,14 +1005,20 @@ export class FrameChart extends BaseElement { const searchResult = this.searchDataByCoord(this.currentData!, this.canvasX, this.canvasY); if (searchResult && (searchResult.isDraw || searchResult.depth === 0)) { ChartStruct.hoverFuncStruct = searchResult; + if (ChartStruct.hoverFuncStruct !== ChartStruct.tempSelectStruct) { + ChartStruct.tempSelectStruct = undefined; + } // 悬浮的node未改变,不需要更新悬浮框文字信息,不绘图 if (searchResult !== lastNode) { this.updateTipContent(); this.calculateChartData(); } - this.showTip(); + if (ChartStruct.tempSelectStruct === undefined) { + this.showTip(); + } } else { this.hideTip(); + ChartStruct.tempSelectStruct = undefined; ChartStruct.hoverFuncStruct = undefined; } } @@ -1022,7 +1049,6 @@ export class FrameChart extends BaseElement { this.canvas = this.shadowRoot!.querySelector('#canvas')!; this.canvasContext = this.canvas.getContext('2d')!; this.floatHint = this.shadowRoot?.querySelector('#float_hint'); - this.canvas!.oncontextmenu = (): boolean => { return false; }; @@ -1041,10 +1067,11 @@ export class FrameChart extends BaseElement { }; this.canvas!.onmouseleave = (): void => { - this.isFocusing = false; - this.hideTip(); + if (!ChartStruct.tempSelectStruct) { + this.isFocusing = false; + this.hideTip(); + } }; - document.addEventListener('keydown', (e) => { if (!this.isFocusing) { return; @@ -1095,6 +1122,10 @@ export class FrameChart extends BaseElement { .bold{ font-weight: bold; } + .count { + text-decoration: underline; + cursor: pointer + } .text{ max-width:350px; word-break: break-all; diff --git a/ide/src/trace/component/chart/SpChartManager.ts b/ide/src/trace/component/chart/SpChartManager.ts index 3590d966776c6043eb1d6e33db65427d744a3206..816d1fe341e17b685141012b1dad6b27dbe013f6 100644 --- a/ide/src/trace/component/chart/SpChartManager.ts +++ b/ide/src/trace/component/chart/SpChartManager.ts @@ -62,7 +62,7 @@ import { SpUserFileChart } from './SpUserPluginChart'; import { SpImportUserPluginsChart } from './SpImportUserPluginsChart'; import { queryDmaFenceIdAndCat } from '../../database/sql/dmaFence.sql'; import { queryAllFuncNames } from '../../database/sql/Func.sql'; -import {SpSnapShotChart} from './spSnapShotChart'; +import { SpSnapShotChart } from './spSnapShotChart'; import { SpRecordTrace } from '../SpRecordTrace'; export class SpChartManager { @@ -197,7 +197,7 @@ export class SpChartManager { await this.initCpu(progress); await this.logChart.init(); await this.spHiSysEvent.init(); - if (SpRecordTrace.snapShotList.length > 0) { + if (SpRecordTrace.snapShotList.length > 0 && SpRecordTrace.isSnapShotCapture) { await this.spSnapShotChart.init(); } let idAndNameArr = await queryDmaFenceIdAndCat(); diff --git a/ide/src/trace/component/chart/SpClockChart.ts b/ide/src/trace/component/chart/SpClockChart.ts index a521cb0a3ce910214737e7c469a2c51f4e706f7a..707ac3b06c57b3ac61f4b8464caa635e182ce49c 100644 --- a/ide/src/trace/component/chart/SpClockChart.ts +++ b/ide/src/trace/component/chart/SpClockChart.ts @@ -47,8 +47,16 @@ export class SpClockChart { } else { this.trace.rowsEL?.appendChild(folder); } - await this.initData(folder, clockList, traceId); + // heca_freq Frequency移动到数组末尾 + const index = clockList.findIndex(item => item.name === 'heca_freq Frequency'); + if (index !== -1) { + const item = clockList.splice(index, 1); + if (item && item.length) { + clockList.push(item[0]); + } + } await this.initDmaFence(folder); + await this.initData(folder, clockList, traceId); } private clockSupplierFrame( diff --git a/ide/src/trace/component/chart/SpHiPerf.ts b/ide/src/trace/component/chart/SpHiPerf.ts index 23192717555e386c4a54930ac087975b115f2164..9ffcc2f5dc9906e36b3aea7b0d82ab51a9018b46 100644 --- a/ide/src/trace/component/chart/SpHiPerf.ts +++ b/ide/src/trace/component/chart/SpHiPerf.ts @@ -480,7 +480,7 @@ export class SpHiPerf { let array = this.group[key] as Array; let process = array.filter((th): boolean => th.pid === th.tid)[0]; let row = TraceRow.skeleton(); - row.rowId = `${process.pid}-Perf-Process`; + row.rowId = `${process ? process.pid : Number(key)}-Perf-Process`; row.index = index; row.rowType = TraceRow.ROW_TYPE_HIPERF_PROCESS; row.rowParentId = 'HiPerf'; @@ -491,14 +491,14 @@ export class SpHiPerf { row.addTemplateTypes('AppStartup'); } row.addTemplateTypes('HiPerf'); - row.name = `${process.processName || 'Process'} [${process.pid}]`; + row.name = `${process ? process.processName : 'Process'} [${process ? process.pid : Number(key)}]`; row.folderPaddingLeft = 6; row.style.height = '40px'; row.favoriteChangeHandler = this.trace.favoriteChangeHandler; row.selectChangeHandler = this.trace.selectChangeHandler; //@ts-ignore row.supplierFrame = (): Promise => { return hiperfProcessDataSender( - process.pid, + process ? process.pid : Number(key), row.drawType, this.maxCpuId + 1, SpHiPerf.stringResult?.fValue || 1, diff --git a/ide/src/trace/component/chart/SpProcessChart.ts b/ide/src/trace/component/chart/SpProcessChart.ts index 019a765c869ebfd02cbc05fa0c0cbbd6e439ac5f..f73df505621311ba3b17aadfa6f63d103615c5c0 100644 --- a/ide/src/trace/component/chart/SpProcessChart.ts +++ b/ide/src/trace/component/chart/SpProcessChart.ts @@ -29,6 +29,7 @@ import { SoRender, SoStruct } from '../../database/ui-worker/ProcedureWorkerSoIn import { FlagsConfig } from '../SpFlags'; import { processDataSender } from '../../database/data-trafic/process/ProcessDataSender'; import { threadDataSender } from '../../database/data-trafic/process/ThreadDataSender'; +import { threadSysCallDataSender } from '../../database/data-trafic/process/ThreadSysCallDataSender'; import { funcDataSender } from '../../database/data-trafic/process/FuncDataSender'; import { processMemDataSender } from '../../database/data-trafic/process/ProcessMemDataSender'; import { processStartupDataSender } from '../../database/data-trafic/process/ProcessStartupDataSender'; @@ -39,10 +40,11 @@ import { processDeliverInputEventDataSender } from '../../database/data-trafic/p import { processTouchEventDispatchDataSender } from '../../database/data-trafic/process/ProcessTouchEventDispatchDataSender'; import { getMaxDepthByTid, queryProcessAsyncFunc, queryProcessAsyncFuncCat } from '../../database/sql/Func.sql'; import { queryMemFilterIdMaxValue, queryMemFilterIdMinValue } from '../../database/sql/Memory.sql'; -import { queryAllSoInitNames, queryAllSrcSlices, queryEventCountMap } from '../../database/sql/SqlLite.sql'; +import { queryAllSoInitNames, queryAllSrcSlices, queryEventCountMap, queryCallstackDetail } from '../../database/sql/SqlLite.sql'; import { queryProcessByTable, queryProcessContentCount, + querySysCallThreadIds, queryProcessMem, queryProcessSoMaxDepth, queryProcessThreadsByTable, @@ -53,13 +55,13 @@ import { } from '../../database/sql/ProcessThread.sql'; import { queryAllJankProcess } from '../../database/sql/Janks.sql'; import { BaseStruct } from '../../bean/BaseStruct'; -import { promises } from 'dns'; import { HangStruct } from '../../database/ui-worker/ProcedureWorkerHang'; import { hangDataSender } from '../../database/data-trafic/HangDataSender'; import { SpHangChart } from './SpHangChart'; import { queryHangData } from '../../database/sql/Hang.sql'; import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { renders } from '../../database/ui-worker/ProcedureWorker'; +import { ThreadSysCallStruct } from '../../database/ui-worker/ProcedureWorkerThreadSysCall'; const FOLD_HEIGHT = 24; export class SpProcessChart { @@ -97,6 +99,7 @@ export class SpProcessChart { private traceId?: string | undefined; private parentRow: TraceRow | undefined; static asyncFuncCache: unknown[] = []; + private callStackDetail: Map = new Map(); static threadStateList: Map = new Map(); static processRowSortMap: Map = new Map(); private sameThreadFolder!: TraceRow; @@ -127,6 +130,7 @@ export class SpProcessChart { this.distributedDataMap.clear(); this.renderRow = null; SpProcessChart.asyncFuncCache = []; + this.callStackDetail.clear(); if (this.parentRow) { this.parentRow.clearMemory(); this.parentRow = undefined; @@ -378,6 +382,7 @@ export class SpProcessChart { //@ts-ignore it.flag = 'Did not end'; } + this.addCallStackDetail(it as FuncStruct) createDepth(0, i); }); if (funcRow && !funcRow.isComplete) { @@ -479,6 +484,12 @@ export class SpProcessChart { }); info('convert tid and maxDepth array to map'); let pidCountArray = await queryProcessContentCount(traceId); + info('fetch syscall event tid'); + let sysCallTidArray = await querySysCallThreadIds(traceId); + Utils.getInstance().sysCallEventTidsMap.clear(); + sysCallTidArray.forEach((it) => { + Utils.getInstance().sysCallEventTidsMap.set(it.tid, it); + }); info('fetch per process pid,switch_count,thread_count,slice_count,mem_count'); pidCountArray.forEach((it) => { //@ts-ignore @@ -518,6 +529,13 @@ export class SpProcessChart { traceId: traceId!, }); }); + let callstackData: Array = await queryCallstackDetail(); + for (let index = 0; index < callstackData.length; index++) { + const indexData = callstackData[index]; + if (indexData && !this.callStackDetail.has(indexData.id!)) { + this.callStackDetail.set(indexData.id!, indexData); + } + } info('The amount of initialized process threads data is : ', this.processThreads!.length); } @@ -602,6 +620,9 @@ export class SpProcessChart { processRow.rowType = TraceRow.ROW_TYPE_PROCESS; processRow.rowParentId = ''; processRow.style.height = '40px'; + if (FlagsConfig.getFlagsConfigEnableStatus('System Calls')) { + this.processRowSettingConfig(processRow); + } processRow.folder = true; if ( //@ts-ignore @@ -634,6 +655,20 @@ export class SpProcessChart { return processRow; } + processRowSettingConfig(row: TraceRow): void { + row.rowSettingCheckBoxList = ['SysCall Event']; + row.addRowSettingCheckBox(false); + row.rowSetting = 'enable'; + row.rowSettingPopoverDirection = 'bottomLeft'; + row.onRowSettingCheckBoxChangeHandler = (value): void => { + row.childrenList.forEach((childRow) => { + if (childRow.rowType === TraceRow.ROW_TYPE_THREAD_SYS_CALL) { + childRow.rowDiscard = !row.getRowSettingCheckStateByKey('SysCall Event'); + } + }) + }; + } + addProcessRowListener(processRow: TraceRow, actualRow: TraceRow | null): void { let offsetYTimeOut: unknown = undefined; processRow.addEventListener('expansion-change', (e: unknown) => { @@ -981,6 +1016,58 @@ export class SpProcessChart { return null; } + addThreadSysCallRow( + data: { + pid: number | null; + processName: string | null; + }, + processRow: TraceRow, + threadRow: TraceRow, + thread: unknown + ): TraceRow | null { + //@ts-ignore + const ids = Utils.getInstance().sysCallEventTidsMap.get(thread.tid); + if (ids) { + const threadSysCallRow = TraceRow.skeleton(); + threadSysCallRow.rowType = TraceRow.ROW_TYPE_THREAD_SYS_CALL; + threadSysCallRow.rowId = `${data.pid}-${ids.itid}-syscall`; + threadSysCallRow.rowParentId = `${data.pid}`; + threadSysCallRow.rowHidden = !processRow.expansion; + threadSysCallRow.style.width = '100%'; + threadSysCallRow.name = `syscall event ${ids.tid}`; + threadSysCallRow.addTemplateTypes('SysCallEvent'); + threadSysCallRow.setAttribute('children', ''); + threadSysCallRow.supplierFrame = async (): Promise => { + let promiseData = threadSysCallDataSender(ids.itid!, ids.tid!, data.pid!, threadSysCallRow); + if (promiseData === null) { + return new Promise>((resolve) => resolve([])); + } else { + return promiseData.then(); + } + }; + threadSysCallRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + threadSysCallRow.selectChangeHandler = this.trace.selectChangeHandler; + threadSysCallRow.findHoverStruct = (): void => { + ThreadSysCallStruct.hoverStruct = threadSysCallRow.getHoverStruct(); + }; + threadSysCallRow.onThreadHandler = rowThreadHandler( + 'threadSysCall', + 'context', + { + type: threadSysCallRow.rowId, + translateY: threadSysCallRow.translateY, + }, + threadSysCallRow, + this.trace + ); + threadSysCallRow.rowDiscard = true; + processRow.addChildTraceRowAfter(threadSysCallRow, threadRow); + return threadSysCallRow; + } + return null; + } + + jankSenderCallback( res: JankStruct[], type: string, @@ -1326,6 +1413,7 @@ export class SpProcessChart { // @ts-ignore this.insertRowToDoc(it, j, thread, pRow, tRow, list, tRowArr, actualRow, expectedRow, hangRow, startupRow, soRow); this.addFuncStackRow(it, thread, j, list, tRowArr, tRow, pRow); + this.addThreadSysCallRow(it, pRow, tRow, thread); // @ts-ignore if ((thread.switchCount || 0) === 0) { tRow.rowDiscard = true; @@ -1475,6 +1563,7 @@ export class SpProcessChart { funs[index].ipid = thread.upid; funs[index].tid = thread.tid; funs[index].pid = thread.pid; + this.addCallStackDetail(funs[index]) funs[index].funName = this.traceId ? Utils.getInstance().getCallStatckMap().get(`${this.traceId}_${funs[index].id}`) : Utils.getInstance().getCallStatckMap().get(funs[index].id!); if (Utils.isBinder(fun)) { } else { @@ -1680,18 +1769,18 @@ export class SpProcessChart { for (let i = 0; i < asyncFuncList.length; i++) { const el = asyncFuncList[i]; // @ts-ignore - if (el.cat !== null) { + if (el.category !== null) { if (flag) {//business first asyncCatArr.push(el); } else {//thread first //@ts-ignore - if (asyncCatMap.has(`${el.cat}:${el.threadName} ${el.tid}`)) { + if (asyncCatMap.has(`${el.category}:${el.threadName} ${el.tid}`)) { //@ts-ignore - let item: Array = asyncCatMap.get(`${el.cat}:${el.threadName} ${el.tid}`); + let item: Array = asyncCatMap.get(`${el.category}:${el.threadName} ${el.tid}`); item.push(el); } else { //@ts-ignore - asyncCatMap.set(`${el.cat}:${el.threadName} ${el.tid}`, [el]); + asyncCatMap.set(`${el.category}:${el.threadName} ${el.tid}`, [el]); } } } else { @@ -1699,7 +1788,7 @@ export class SpProcessChart { asyncRemoveCatArr.push(el); } } - asyncCat = flag ? Utils.groupBy(asyncCatArr, 'cat') : Object.fromEntries(asyncCatMap); + asyncCat = flag ? Utils.groupBy(asyncCatArr, 'category') : Object.fromEntries(asyncCatMap); return { asyncRemoveCatArr, asyncCat }; } //处理cat字段为null的数据,按funname分类,分别按len>1和=1去处理 @@ -1845,6 +1934,16 @@ export class SpProcessChart { processRow.addChildTraceRow(funcRow); } + addCallStackDetail(item: FuncStruct): void { + if (this.callStackDetail.has(item.id!)) { + const data: FuncStruct | undefined = this.callStackDetail.get(item.id!); + item.custom_args = data!.custom_args; + item.trace_level = data!.trace_level; + item.trace_tag = data!.trace_tag; + item.category = data!.category; + } + } + addAsyncCatFunction(it: { pid: number; processName: string | null }, processRow: TraceRow): void { //@ts-ignore let asyncFuncCatList = this.processAsyncFuncCatMap[it.pid] || []; diff --git a/ide/src/trace/component/chart/SpVmTrackerChart.ts b/ide/src/trace/component/chart/SpVmTrackerChart.ts index da031c881a053f4286eb6b2f513025ffa2c71f36..8c0d3f4719a37775d9ef347fc7e3064a152ea25e 100644 --- a/ide/src/trace/component/chart/SpVmTrackerChart.ts +++ b/ide/src/trace/component/chart/SpVmTrackerChart.ts @@ -62,6 +62,12 @@ export class VmTrackerChart { static gpuWindowModule: number | null = null; //ns private smapsRecordTab: TabPaneSmapsRecord | undefined | null; private scratchId = -1; + private isExistsPurgeableTotal: Array = []; + private isExistsPurgeablePin: Array = []; + private isExistsGpuMemory: Array = []; + private isExistsGpuResource: Array = []; + private isExistsGraph: Array = []; + private isExistsGl: Array = []; constructor(trace: SpSystemTrace) { this.trace = trace; } @@ -79,17 +85,30 @@ export class VmTrackerChart { } } const result = await querySmapsExits(); - if (result.length <= 0) { + this.isExistsPurgeableTotal = await queryisExistsPurgeableData(this.memoryConfig.iPid, false); + this.isExistsPurgeablePin = await queryisExistsPurgeableData(this.memoryConfig.iPid, true); + this.isExistsGpuMemory = await queryisExistsGpuMemoryData(this.memoryConfig.iPid); + this.isExistsGpuResource = await queryisExistsGpuResourceData(this.scratchId); + this.isExistsGraph = await queryisExistsGpuData(MemoryConfig.getInstance().iPid, "'mem.graph_pss'"); + this.isExistsGl = await queryisExistsGpuData(MemoryConfig.getInstance().iPid, "'mem.gl_pss'"); + const isExistsShm = await queryisExistsShmData(this.memoryConfig.iPid); + const isExistsDma = await queryisExistsDmaData(this.memoryConfig.iPid); + //@ts-ignore + if (result.length === 0 && isExistsShm[0].data_exists === 0 && isExistsDma[0].data_exists === 0 && this.isExistsPurgeableTotal[0].data_exists === 0 && + //@ts-ignore + this.isExistsPurgeablePin[0].data_exists === 0 && this.isExistsGpuMemory[0].data_exists === 0 && this.isExistsGpuResource[0].data_exists === 0 && + //@ts-ignore + this.isExistsGraph[0].data_exists === 0 && this.isExistsGl[0].data_exists === 0) { return; } await this.initVmTrackerFolder(); - await this.initSMapsFolder(); - const rowNameList: Array = ['Dirty', 'Swapped', 'RSS', 'PSS', 'USS']; - for (const rowName of rowNameList) { - await this.initSmapsRows(rowName); + if (result.length > 0) { + await this.initSMapsFolder(); + const rowNameList: Array = ['Dirty', 'Swapped', 'RSS', 'PSS', 'USS']; + for (const rowName of rowNameList) { + await this.initSmapsRows(rowName); + } } - const isExistsShm = await queryisExistsShmData(this.memoryConfig.iPid); - const isExistsDma = await queryisExistsDmaData(this.memoryConfig.iPid); //@ts-ignore if (isExistsShm[0].data_exists) { await this.initShmRows(); @@ -103,37 +122,33 @@ export class VmTrackerChart { } private async initGpuData(): Promise { - const isExistsGpuMemory = await queryisExistsGpuMemoryData(this.memoryConfig.iPid); - const isExistsGpuResource = await queryisExistsGpuResourceData(this.scratchId); - const isExistsGraph = await queryisExistsGpuData(MemoryConfig.getInstance().iPid, "'mem.graph_pss'"); - const isExistsGl = await queryisExistsGpuData(MemoryConfig.getInstance().iPid, "'mem.gl_pss'"); if ( // @ts-ignore - isExistsGpuMemory[0].data_exists || + this.isExistsGpuMemory[0].data_exists || // @ts-ignore - isExistsGpuResource[0].data_exists || + this.isExistsGpuResource[0].data_exists || // @ts-ignore - isExistsGraph[0].data_exists || + this.isExistsGraph[0].data_exists || // @ts-ignore - isExistsGl[0].data_exists + this.isExistsGl[0].data_exists ) { await this.initGpuFolder(); // @ts-ignore - if (isExistsGpuMemory[0].data_exists) { + if (this.isExistsGpuMemory[0].data_exists) { await this.initGpuMemoryRow(); } // @ts-ignore - if (isExistsGpuResource[0].data_exists) { + if (this.isExistsGpuResource[0].data_exists) { await this.initGpuResourceRow(this.scratchId); } else { this.smapsRecordTab!.GLESHostCache = []; } // @ts-ignore - if (isExistsGraph[0].data_exists) { + if (this.isExistsGraph[0].data_exists) { await this.addGpuGraphRow(); } // @ts-ignore - if (isExistsGl[0].data_exists) { + if (this.isExistsGl[0].data_exists) { await this.addGpuGLRow(); await this.addGpuTotalRow(); await this.addGpuWindowRow(); @@ -338,12 +353,11 @@ export class VmTrackerChart { private initPurgeableVM = async (): Promise => { let time = new Date().getTime(); - const isExistsPurgeableTotal = await queryisExistsPurgeableData(this.memoryConfig.iPid, false); - const isExistsPurgeablePin = await queryisExistsPurgeableData(this.memoryConfig.iPid, true); //@ts-ignore - if (isExistsPurgeableTotal[0].data_exists) { + //@ts-ignore + if (this.isExistsPurgeableTotal[0].data_exists) { await this.initPurgeableTotal(); } //@ts-ignore - if (isExistsPurgeablePin[0].data_exists) { + if (this.isExistsPurgeablePin[0].data_exists) { await this.initPurgeablePin(); } let durTime = new Date().getTime() - time; diff --git a/ide/src/trace/component/schedulingAnalysis/CheckCpuSetting.ts b/ide/src/trace/component/schedulingAnalysis/CheckCpuSetting.ts index 493a97f5bd042b2db394a57bc810aa866fdd289f..e4ecb112697eaa5fc6e476afcb42abf34fd619ad 100644 --- a/ide/src/trace/component/schedulingAnalysis/CheckCpuSetting.ts +++ b/ide/src/trace/component/schedulingAnalysis/CheckCpuSetting.ts @@ -24,14 +24,14 @@ export class CpuSetting { cpu: number = 0; big: boolean = false; middle: boolean = true; - small: boolean = false; + little: boolean = false; } @element('check-cpu-setting') export class CheckCpuSetting extends BaseElement { static mid_cores: number[] = []; static big_cores: number[] = []; - static small_cores: number[] = []; + static little_cores: number[] = []; static init_setting: boolean = false; private table: HTMLDivElement | null | undefined; @@ -68,7 +68,7 @@ export class CheckCpuSetting extends BaseElement { // @ts-ignore middle: CheckCpuSetting.mid_cores.includes(i), // @ts-ignore - small: CheckCpuSetting.small_cores.includes(i), + little: CheckCpuSetting.little_cores.includes(i), }; data.push(obj); this.createTableLine(obj); @@ -79,7 +79,7 @@ export class CheckCpuSetting extends BaseElement { if (!CheckCpuSetting.init_setting) { CheckCpuSetting.mid_cores = []; CheckCpuSetting.big_cores = []; - CheckCpuSetting.small_cores = []; + CheckCpuSetting.little_cores = []; for (let i = 0; i < SpSchedulingAnalysis.cpuCount; i++) { CheckCpuSetting.mid_cores.push(i); } @@ -94,33 +94,33 @@ export class CheckCpuSetting extends BaseElement { bigCheckBox.checked = cpuSetting.big; let midCheckBox: LitCheckBox = new LitCheckBox(); midCheckBox.checked = cpuSetting.middle; - let smallCheckBox: LitCheckBox = new LitCheckBox(); - smallCheckBox.checked = cpuSetting.small; + let littleCheckBox: LitCheckBox = new LitCheckBox(); + littleCheckBox.checked = cpuSetting.little; bigCheckBox.addEventListener('change', (): void => { midCheckBox.checked = false; - smallCheckBox.checked = false; + littleCheckBox.checked = false; cpuSetting.big = true; CheckCpuSetting.big_cores.push(cpuSetting.cpu); CheckCpuSetting.mid_cores = CheckCpuSetting.mid_cores.filter((it): boolean => it !== cpuSetting.cpu); - CheckCpuSetting.small_cores = CheckCpuSetting.small_cores.filter((it): boolean => it !== cpuSetting.cpu); + CheckCpuSetting.little_cores = CheckCpuSetting.little_cores.filter((it): boolean => it !== cpuSetting.cpu); }); midCheckBox.addEventListener('change', (): void => { bigCheckBox.checked = false; - smallCheckBox.checked = false; + littleCheckBox.checked = false; cpuSetting.middle = true; CheckCpuSetting.mid_cores.push(cpuSetting.cpu); CheckCpuSetting.big_cores = CheckCpuSetting.big_cores.filter((it): boolean => it !== cpuSetting.cpu); - CheckCpuSetting.small_cores = CheckCpuSetting.small_cores.filter((it): boolean => it !== cpuSetting.cpu); + CheckCpuSetting.little_cores = CheckCpuSetting.little_cores.filter((it): boolean => it !== cpuSetting.cpu); }); - smallCheckBox.addEventListener('change', (): void => { + littleCheckBox.addEventListener('change', (): void => { midCheckBox.checked = false; bigCheckBox.checked = false; - cpuSetting.small = true; - CheckCpuSetting.small_cores.push(cpuSetting.cpu); + cpuSetting.little = true; + CheckCpuSetting.little_cores.push(cpuSetting.cpu); CheckCpuSetting.mid_cores = CheckCpuSetting.mid_cores.filter((it): boolean => it !== cpuSetting.cpu); CheckCpuSetting.big_cores = CheckCpuSetting.big_cores.filter((it): boolean => it !== cpuSetting.cpu); }); - this.table?.append(...[div, bigCheckBox, midCheckBox, smallCheckBox]); + this.table?.append(...[div, bigCheckBox, midCheckBox, littleCheckBox]); } createHeaderDiv(): void { @@ -139,14 +139,14 @@ export class CheckCpuSetting extends BaseElement { let column4 = document.createElement('div'); column4.className = 'setting_line'; column4.style.fontWeight = 'bold'; - column4.textContent = 'small'; + column4.textContent = 'little'; this.table?.append(...[column1, column2, column3, column4]); } static resetCpuSettings(): void { CheckCpuSetting.init_setting = false; CheckCpuSetting.big_cores = []; - CheckCpuSetting.small_cores = []; + CheckCpuSetting.little_cores = []; CheckCpuSetting.mid_cores = []; } diff --git a/ide/src/trace/component/schedulingAnalysis/Top20ThreadCpuUsage.html.ts b/ide/src/trace/component/schedulingAnalysis/Top20ThreadCpuUsage.html.ts index 34f7f3ac5e99ffbdead928178d326ed35fa2d384..5f543de0ee8422f12733d321c7a8801c43c3305f 100644 --- a/ide/src/trace/component/schedulingAnalysis/Top20ThreadCpuUsage.html.ts +++ b/ide/src/trace/component/schedulingAnalysis/Top20ThreadCpuUsage.html.ts @@ -80,23 +80,23 @@ export const Top20ThreadCpuUsageHtml = `
    big
    mid
    -
    small
    +
    little
    -
    +
    Top20线程小核占用率
    -
    small
    +
    little
    - +
    diff --git a/ide/src/trace/component/schedulingAnalysis/Top20ThreadCpuUsage.ts b/ide/src/trace/component/schedulingAnalysis/Top20ThreadCpuUsage.ts index e1c86a497861390c67cf70ae37bd7aca9a1a9a87..c78526ffb04e61c0af7c43ded4c3b57f59392501 100644 --- a/ide/src/trace/component/schedulingAnalysis/Top20ThreadCpuUsage.ts +++ b/ide/src/trace/component/schedulingAnalysis/Top20ThreadCpuUsage.ts @@ -36,7 +36,7 @@ export class Top20ThreadCpuUsage extends BaseElement { private table: LitTable | null | undefined; private tableBig: LitTable | null | undefined; private tableMid: LitTable | null | undefined; - private tableSmall: LitTable | null | undefined; + private tableLittle: LitTable | null | undefined; private chartTotal: LitChartColumn | null | undefined; private chart2: LitChartColumn | null | undefined; private chart3: LitChartColumn | null | undefined; @@ -49,10 +49,10 @@ export class Top20ThreadCpuUsage extends BaseElement { private data: Array = []; private dataBig: Array = []; private dataMid: Array = []; - private dataSmall: Array = []; + private dataLittle: Array = []; private sort: unknown = { total: { key: '', sort: 0 }, - small: { key: '', sort: 0 }, + little: { key: '', sort: 0 }, mid: { key: '', sort: 0 }, big: { key: '', sort: 0 }, }; @@ -82,9 +82,9 @@ export class Top20ThreadCpuUsage extends BaseElement { `; - private smallColumn = ` - - + private littleColumn = ` + + `; initElements(): void { @@ -93,14 +93,14 @@ export class Top20ThreadCpuUsage extends BaseElement { this.table = this.shadowRoot!.querySelector('#tb-thread-usage'); this.tableBig = this.shadowRoot!.querySelector('#tb-thread-big'); this.tableMid = this.shadowRoot!.querySelector('#tb-thread-mid'); - this.tableSmall = this.shadowRoot!.querySelector('#tb-thread-small'); + this.tableLittle = this.shadowRoot!.querySelector('#tb-thread-little'); this.chartTotal = this.shadowRoot!.querySelector('#chart_total'); this.chart2 = this.shadowRoot!.querySelector('#chart_2'); this.chart3 = this.shadowRoot!.querySelector('#chart_3'); this.chart4 = this.shadowRoot!.querySelector('#chart_4'); this.map = new Map(); this.map.set('total', { chart: this.chartTotal!, table: this.table! }); - this.map.set('small', { chart: this.chart2!, table: this.tableSmall! }); + this.map.set('little', { chart: this.chart2!, table: this.tableLittle! }); this.map.set('mid', { chart: this.chart3!, table: this.tableMid! }); this.map.set('big', { chart: this.chart4!, table: this.tableBig! }); this.setting = this.shadowRoot!.querySelector('#setting'); @@ -110,8 +110,8 @@ export class Top20ThreadCpuUsage extends BaseElement { //@ts-ignore (this.shadowRoot!.querySelector('#total')! as unknown).style.display = 'grid'; //@ts-ignore - (this.shadowRoot!.querySelector('#small')! as unknown).style.display = - CheckCpuSetting.small_cores.length > 0 ? 'grid' : 'none'; + (this.shadowRoot!.querySelector('#little')! as unknown).style.display = + CheckCpuSetting.little_cores.length > 0 ? 'grid' : 'none'; //@ts-ignore (this.shadowRoot!.querySelector('#mid')! as unknown).style.display = CheckCpuSetting.mid_cores.length > 0 ? 'grid' : 'none'; @@ -153,9 +153,9 @@ export class Top20ThreadCpuUsage extends BaseElement { if (key === 'total') { //@ts-ignore this.sortByColumn(evt.detail, tab, this.data); - } else if (key === 'small') { + } else if (key === 'little') { //@ts-ignore - this.sortByColumn(evt.detail, tab, this.dataSmall); + this.sortByColumn(evt.detail, tab, this.dataLittle); } else if (key === 'mid') { //@ts-ignore this.sortByColumn(evt.detail, tab, this.dataMid); @@ -211,8 +211,8 @@ export class Top20ThreadCpuUsage extends BaseElement { key = 'big'; } else if (key === 'midTimeStr') { key = 'mid'; - } else if (key === 'smallTimeStr') { - key = 'small'; + } else if (key === 'littleTimeStr') { + key = 'little'; } else if ( key === 'bigPercent' || key === 'ratio' || @@ -296,7 +296,7 @@ export class Top20ThreadCpuUsage extends BaseElement { //@ts-ignore mid: it.mid, //@ts-ignore - small: it.small, + little: it.little, no: index + 1, visible: 1, //@ts-ignore @@ -304,13 +304,13 @@ export class Top20ThreadCpuUsage extends BaseElement { //@ts-ignore midPercent: it.midPercent, //@ts-ignore - smallPercent: it.smallPercent, + littlePercent: it.littlePercent, //@ts-ignore bigTimeStr: it.bigTimeStr, //@ts-ignore midTimeStr: it.midTimeStr, //@ts-ignore - smallTimeStr: it.smallTimeStr, + littleTimeStr: it.littleTimeStr, hideHandler: (): void => { //@ts-ignore let arr = source.filter((o) => o.visible === 1); @@ -333,8 +333,8 @@ export class Top20ThreadCpuUsage extends BaseElement { private assignmentData(key: string, source: unknown[], obj: { chart: LitChartColumn; table: LitTable }): void { if (key === 'total') { this.data = source; - } else if (key === 'small') { - this.dataSmall = source; + } else if (key === 'little') { + this.dataLittle = source; } else if (key === 'mid') { this.dataMid = source; } else if (key === 'big') { @@ -362,7 +362,7 @@ export class Top20ThreadCpuUsage extends BaseElement { return '#2f72f8'; //@ts-ignore } else if (a.size === 'middle core') { return '#ffab67'; //@ts-ignore - } else if (a.size === 'small core') { + } else if (a.size === 'little core') { return '#a285d2'; } else { return '#0a59f7'; @@ -450,10 +450,10 @@ export class Top20ThreadCpuUsage extends BaseElement { pName: obj.pName, //@ts-ignore tid: obj.tid, //@ts-ignore tName: obj.tName, //@ts-ignore - total: obj.small, - size: 'small core', //@ts-ignore + total: obj.little, + size: 'little core', //@ts-ignore no: obj.no, //@ts-ignore - timeStr: obj.smallTimeStr, + timeStr: obj.littleTimeStr, }); } else { data.push({ @@ -479,7 +479,7 @@ export class Top20ThreadCpuUsage extends BaseElement { { bigCores: CheckCpuSetting.big_cores, midCores: CheckCpuSetting.mid_cores, - smallCores: CheckCpuSetting.small_cores, + littleCores: CheckCpuSetting.little_cores, }, undefined, handler @@ -490,13 +490,13 @@ export class Top20ThreadCpuUsage extends BaseElement { getTableColumns(type: string): string { if (type === 'total') { - return `${this.publicColumns}${this.bigColumn}${this.midColumn}${this.smallColumn}`; + return `${this.publicColumns}${this.bigColumn}${this.midColumn}${this.littleColumn}`; } else if (type === 'big') { return `${this.publicColumns}${this.bigColumn}`; } else if (type === 'mid') { return `${this.publicColumns}${this.midColumn}`; - } else if (type === 'small') { - return `${this.publicColumns}${this.smallColumn}`; + } else if (type === 'little') { + return `${this.publicColumns}${this.littleColumn}`; } else { return ''; } diff --git a/ide/src/trace/component/setting/SpHisysEvent.ts b/ide/src/trace/component/setting/SpHisysEvent.ts index 779567297cb6ed1c237e00214fa2db891cdb30a7..1bddae3872e74399e9051d5f8293f5b5eeef603a 100644 --- a/ide/src/trace/component/setting/SpHisysEvent.ts +++ b/ide/src/trace/component/setting/SpHisysEvent.ts @@ -22,6 +22,8 @@ import { HdcDeviceManager } from '../../../hdc/HdcDeviceManager'; import { LitAllocationSelect } from '../../../base-ui/select/LitAllocationSelect'; import { SpHiSysEventHtml } from './SpHisysEvent.html'; import { LitSelectV } from '../../../base-ui/select/LitSelectV'; +import { WebSocketManager } from '../../../webSocket/WebSocketManager'; +import { TypeConstants } from '../../../webSocket/Constants'; @element('sp-hisys-event') export class SpHisysEvent extends BaseElement { @@ -64,7 +66,7 @@ export class SpHisysEvent extends BaseElement { } get sysEventConfigPath(): string { - return '/system/etc/hiview/hisysevent.def'; + return '//data/system/hiview/unzip_configs/sys_event_def/hisysevent.def'; } initElements(): void { @@ -99,11 +101,11 @@ export class SpHisysEvent extends BaseElement { if (SpRecordTrace.serialNumber === '') { this.domainInputEL!.dataSource([], ''); } else { - HdcDeviceManager.fileRecv(this.sysEventConfigPath, () => { }).then((pullRes) => { - pullRes.arrayBuffer().then((buffer) => { - if (buffer.byteLength > 0) { - let dec = new TextDecoder(); - this.eventConfig = JSON.parse(dec.decode(buffer)); + if (SpRecordTrace.useExtend) { + WebSocketManager.getInstance()!.sendMessage(TypeConstants.USB_TYPE, TypeConstants.USB_GET_HISYSTEM, new TextEncoder().encode(SpRecordTrace.serialNumber)); + setTimeout(() => { + if (SpRecordTrace.usbGetHisystem) { + this.eventConfig = JSON.parse(SpRecordTrace.usbGetHisystem); let domainList = Object.keys(this.eventConfig!); if (domainList.length > 0) { this.domainInputEL!.dataSource(domainList, 'ALL-Domain', true); @@ -111,8 +113,23 @@ export class SpHisysEvent extends BaseElement { this.domainInputEL!.dataSource([], ''); } } + }, 1000); + } else { + HdcDeviceManager.fileRecv(this.sysEventConfigPath, () => { }).then((pullRes) => { + pullRes.arrayBuffer().then((buffer) => { + if (buffer.byteLength > 0) { + let dec = new TextDecoder(); + this.eventConfig = JSON.parse(dec.decode(buffer)); + let domainList = Object.keys(this.eventConfig!); + if (domainList.length > 0) { + this.domainInputEL!.dataSource(domainList, 'ALL-Domain', true); + } else { + this.domainInputEL!.dataSource([], ''); + } + } + }); }); - }); + } } this.domainInputEl!.removeAttribute('readonly'); } else { diff --git a/ide/src/trace/component/setting/SpRecordSetting.ts b/ide/src/trace/component/setting/SpRecordSetting.ts index 6973ae7a26170165b08ec17a9fd393d342554012..6ed9c65f5bd9230af5a32794afaadd706b3fd36c 100644 --- a/ide/src/trace/component/setting/SpRecordSetting.ts +++ b/ide/src/trace/component/setting/SpRecordSetting.ts @@ -244,12 +244,14 @@ export class SpRecordSetting extends BaseElement { rootEl.removeChild(longTraceMaxSlide); } this.outputPath!.value = 'hiprofiler_data.htrace'; + this.snapShotNumber!.style.display = 'grid'; } private longTraceModelRadioHandler(rootEl: HTMLDivElement, longTraceMaxSlide: HTMLDivElement): void { SpApplication.isLongTrace = true; rootEl.appendChild(longTraceMaxSlide); this.outputPath!.value = 'long_trace'; + this.snapShotNumber!.style.display = 'none'; } private maxSizeInputHandler(maxSizeSliders: LitSlider, maxSizeParentElement: Element): void { diff --git a/ide/src/trace/component/setting/SpSdkConfig.ts b/ide/src/trace/component/setting/SpSdkConfig.ts index a8426c1a3e1de4ece2cb47b6fc7050a7daa552d3..868475ee1f8dbd2cad1ddf881de3008fc9bf131f 100644 --- a/ide/src/trace/component/setting/SpSdkConfig.ts +++ b/ide/src/trace/component/setting/SpSdkConfig.ts @@ -149,9 +149,9 @@ export class SpSdkConfig extends BaseElement { private initSdkWasm(): void { try { let spApplication = document.querySelector('sp-application'); - let wasmJsonUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}/application/wasm.json`; + let wasmJsonUrl = `https://${window.location.host.split(':')[0]}:${window.location.port}${window.location.pathname}wasm.json`; if (spApplication!.hasAttribute('vs')) { - wasmJsonUrl = `http://${window.location.host.split(':')[0]}:${window.location.port}/wasm.json`; + wasmJsonUrl = `http://${window.location.host.split(':')[0]}:${window.location.port}${window.location.pathname}/wasm.json`; } fetch(wasmJsonUrl) .then((res): void => { diff --git a/ide/src/trace/component/trace/base/SysCallUtils.ts b/ide/src/trace/component/trace/base/SysCallUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..eda34c18f8cdb6b2efd40e2bb82f6b660d127c15 --- /dev/null +++ b/ide/src/trace/component/trace/base/SysCallUtils.ts @@ -0,0 +1,347 @@ +/* + * 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 SysCallMap = new Map([ + [0, "sys_io_setup"], + [1, "sys_io_destroy"], + [2, "sys_io_submit"], + [3, "sys_io_cancel"], + [4, "sys_io_getevents"], + [5, "sys_setxattr"], + [6, "sys_lsetxattr"], + [7, "sys_fsetxattr"], + [8, "sys_getxattr"], + [9, "sys_lgetxattr"], + [10, "sys_fgetxattr"], + [11, "sys_listxattr"], + [12, "sys_llistxattr"], + [13, "sys_flistxattr"], + [14, "sys_removexattr"], + [15, "sys_lremovexattr"], + [16, "sys_fremovexattr"], + [17, "sys_getcwd"], + [18, "sys_lookup_dcookie"], + [19, "sys_eventfd2"], + [20, "sys_epoll_create1"], + [21, "sys_epoll_ctl"], + [22, "sys_epoll_pwait"], + [23, "sys_dup"], + [24, "sys_dup3"], + [25, "sys_fcntl"], + [26, "sys_inotify_init1"], + [27, "sys_inotify_add_watch"], + [28, "sys_inotify_rm_watch"], + [29, "sys_ioctl"], + [30, "sys_ioprio_set"], + [31, "sys_ioprio_get"], + [32, "sys_flock"], + [33, "sys_mknodat"], + [34, "sys_mkdirat"], + [35, "sys_unlinkat"], + [36, "sys_symlinkat"], + [37, "sys_linkat"], + [38, "sys_renameat"], + [39, "sys_umount2"], + [40, "sys_mount"], + [41, "sys_pivot_root"], + [42, "sys_nfsservctl"], + [43, "sys_statfs"], + [44, "sys_fstatfs"], + [45, "sys_truncate"], + [46, "sys_ftruncate"], + [47, "sys_fallocate"], + [48, "sys_faccessat"], + [49, "sys_chdir"], + [50, "sys_fchdir"], + [51, "sys_chroot"], + [52, "sys_fchmod"], + [53, "sys_fchmodat"], + [54, "sys_fchownat"], + [55, "sys_fchown"], + [56, "sys_openat"], + [57, "sys_close"], + [58, "sys_vhangup"], + [59, "sys_pipe2"], + [60, "sys_quotactl"], + [61, "sys_getdents64"], + [62, "sys_lseek"], + [63, "sys_read"], + [64, "sys_write"], + [65, "sys_readv"], + [66, "sys_writev"], + [67, "sys_pread64"], + [68, "sys_pwrite64"], + [69, "sys_preadv"], + [70, "sys_pwritev"], + [71, "sys_sendfile"], + [72, "sys_pselect6"], + [73, "sys_ppoll"], + [74, "sys_signalfd4"], + [75, "sys_vmsplice"], + [76, "sys_splice"], + [77, "sys_tee"], + [78, "sys_readlinkat"], + [79, "sys_fstatat"], + [80, "sys_fstat"], + [81, "sys_sync"], + [82, "sys_fsync"], + [83, "sys_fdatasync"], + [84, "sys_sync_file_range"], + [85, "sys_timerfd_create"], + [86, "sys_timerfd_settime"], + [87, "sys_timerfd_gettime"], + [88, "sys_utimensat"], + [89, "sys_acct"], + [90, "sys_capget"], + [91, "sys_capset"], + [92, "sys_personality"], + [93, "sys_exit"], + [94, "sys_exit_group"], + [95, "sys_waitid"], + [96, "sys_set_tid_address"], + [97, "sys_unshare"], + [98, "sys_futex"], + [99, "sys_set_robust_list"], + [100, "sys_get_robust_list"], + [101, "sys_nanosleep"], + [102, "sys_getitimer"], + [103, "sys_setitimer"], + [104, "sys_kexec_load"], + [105, "sys_init_module"], + [106, "sys_delete_module"], + [107, "sys_timer_create"], + [108, "sys_timer_gettime"], + [109, "sys_timer_getoverrun"], + [110, "sys_timer_settime"], + [111, "sys_timer_delete"], + [112, "sys_clock_settime"], + [113, "sys_clock_gettime"], + [114, "sys_clock_getres"], + [115, "sys_clock_nanosleep"], + [116, "sys_syslog"], + [117, "sys_ptrace"], + [118, "sys_sched_setparam"], + [119, "sys_sched_setscheduler"], + [120, "sys_sched_getscheduler"], + [121, "sys_sched_getparam"], + [122, "sys_sched_setaffinity"], + [123, "sys_sched_getaffinity"], + [124, "sys_sched_yield"], + [125, "sys_sched_get_priority_max"], + [126, "sys_sched_get_priority_min"], + [127, "sys_sched_rr_get_interval"], + [128, "sys_restart_syscall"], + [129, "sys_kill"], + [130, "sys_tkill"], + [131, "sys_tgkill"], + [132, "sys_sigaltstack"], + [133, "sys_rt_sigsuspend"], + [134, "sys_rt_sigaction"], + [135, "sys_rt_sigprocmask"], + [136, "sys_rt_sigpending"], + [137, "sys_rt_sigtimedwait"], + [138, "sys_rt_sigqueueinfo"], + [139, "sys_rt_sigreturn"], + [140, "sys_setpriority"], + [141, "sys_getpriority"], + [142, "sys_reboot"], + [143, "sys_setregid"], + [144, "sys_setgid"], + [145, "sys_setreuid"], + [146, "sys_setuid"], + [147, "sys_setresuid"], + [148, "sys_getresuid"], + [149, "sys_setresgid"], + [150, "sys_getresgid"], + [151, "sys_setfsuid"], + [152, "sys_setfsgid"], + [153, "sys_times"], + [154, "sys_setpgid"], + [155, "sys_getpgid"], + [156, "sys_getsid"], + [157, "sys_setsid"], + [158, "sys_getgroups"], + [159, "sys_setgroups"], + [160, "sys_uname"], + [161, "sys_sethostname"], + [162, "sys_setdomainname"], + [163, "sys_getrlimit"], + [164, "sys_setrlimit"], + [165, "sys_getrusage"], + [166, "sys_umask"], + [167, "sys_prctl"], + [168, "sys_getcpu"], + [169, "sys_gettimeofday"], + [170, "sys_settimeofday"], + [171, "sys_adjtimex"], + [172, "sys_getpid"], + [173, "sys_getppid"], + [174, "sys_getuid"], + [175, "sys_geteuid"], + [176, "sys_getgid"], + [177, "sys_getegid"], + [178, "sys_gettid"], + [179, "sys_sysinfo"], + [180, "sys_mq_open"], + [181, "sys_mq_unlink"], + [182, "sys_mq_timedsend"], + [183, "sys_mq_timedreceive"], + [184, "sys_mq_notify"], + [185, "sys_mq_getsetattr"], + [186, "sys_msgget"], + [187, "sys_msgctl"], + [188, "sys_msgrcv"], + [189, "sys_msgsnd"], + [190, "sys_semget"], + [191, "sys_semctl"], + [192, "sys_semtimedop"], + [193, "sys_semop"], + [194, "sys_shmget"], + [195, "sys_shmctl"], + [196, "sys_shmat"], + [197, "sys_shmdt"], + [198, "sys_socket"], + [199, "sys_socketpair"], + [200, "sys_bind"], + [201, "sys_listen"], + [202, "sys_accept"], + [203, "sys_connect"], + [204, "sys_getsockname"], + [205, "sys_getpeername"], + [206, "sys_sendto"], + [207, "sys_recvfrom"], + [208, "sys_setsockopt"], + [209, "sys_getsockopt"], + [210, "sys_shutdown"], + [211, "sys_sendmsg"], + [212, "sys_recvmsg"], + [213, "sys_readahead"], + [214, "sys_brk"], + [215, "sys_munmap"], + [216, "sys_mremap"], + [217, "sys_add_key"], + [218, "sys_request_key"], + [219, "sys_keyctl"], + [220, "sys_clone"], + [221, "sys_execve"], + [222, "sys_mmap"], + [223, "sys_fadvise64"], + [224, "sys_swapon"], + [225, "sys_swapoff"], + [226, "sys_mprotect"], + [227, "sys_msync"], + [228, "sys_mlock"], + [229, "sys_munlock"], + [230, "sys_mlockall"], + [231, "sys_munlockall"], + [232, "sys_mincore"], + [233, "sys_madvise"], + [234, "sys_remap_file_pages"], + [235, "sys_mbind"], + [236, "sys_get_mempolicy"], + [237, "sys_set_mempolicy"], + [238, "sys_migrate_pages"], + [239, "sys_move_pages"], + [240, "sys_rt_tgsigqueueinfo"], + [241, "sys_perf_event_open"], + [242, "sys_accept4"], + [243, "sys_recvmmsg"], + [244, "sys_arch_specific_syscall"], + [260, "sys_wait4"], + [261, "sys_prlimit64"], + [262, "sys_fanotify_init"], + [263, "sys_fanotify_mark"], + [264, "sys_name_to_handle_at"], + [265, "sys_open_by_handle_at"], + [266, "sys_clock_adjtime"], + [267, "sys_syncfs"], + [268, "sys_setns"], + [269, "sys_sendmmsg"], + [270, "sys_process_vm_readv"], + [271, "sys_process_vm_writev"], + [272, "sys_kcmp"], + [273, "sys_finit_module"], + [274, "sys_sched_setattr"], + [275, "sys_sched_getattr"], + [276, "sys_renameat2"], + [277, "sys_seccomp"], + [278, "sys_getrandom"], + [279, "sys_memfd_create"], + [280, "sys_bpf"], + [281, "sys_execveat"], + [282, "sys_userfaultfd"], + [283, "sys_membarrier"], + [284, "sys_mlock2"], + [285, "sys_copy_file_range"], + [286, "sys_preadv2"], + [287, "sys_pwritev2"], + [288, "sys_pkey_mprotect"], + [289, "sys_pkey_alloc"], + [290, "sys_pkey_free"], + [291, "sys_statx"], + [292, "sys_io_pgetevents"], + [293, "sys_rseq"], + [294, "sys_kexec_file_load"], + [403, "sys_clock_gettime64"], + [404, "sys_clock_settime64"], + [405, "sys_clock_adjtime64"], + [406, "sys_clock_getres_time64"], + [407, "sys_clock_nanosleep_time64"], + [408, "sys_timer_gettime64"], + [409, "sys_timer_settime64"], + [410, "sys_timerfd_gettime64"], + [411, "sys_timerfd_settime64"], + [412, "sys_utimensat_time64"], + [413, "sys_pselect6_time64"], + [414, "sys_ppoll_time64"], + [416, "sys_io_pgetevents_time64"], + [417, "sys_recvmmsg_time64"], + [418, "sys_mq_timedsend_time64"], + [419, "sys_mq_timedreceive_time64"], + [420, "sys_semtimedop_time64"], + [421, "sys_rt_sigtimedwait_time64"], + [422, "sys_futex_time64"], + [423, "sys_sched_rr_get_interval_time64"], + [424, "sys_pidfd_send_signal"], + [425, "sys_io_uring_setup"], + [426, "sys_io_uring_enter"], + [427, "sys_io_uring_register"], + [428, "sys_open_tree"], + [429, "sys_move_mount"], + [430, "sys_fsopen"], + [431, "sys_fsconfig"], + [432, "sys_fsmount"], + [433, "sys_fspick"], + [434, "sys_pidfd_open"], + [435, "sys_clone3"], + [436, "sys_close_range"], + [437, "sys_openat2"], + [438, "sys_pidfd_getfd"], + [439, "sys_faccessat2"], + [440, "sys_process_madvise"], + [441, "sys_epoll_pwait2"], + [442, "sys_mount_setattr"], + [443, "sys_quotactl_fd"], + [444, "sys_landlock_create_ruleset"], + [445, "sys_landlock_add_rule"], + [446, "sys_landlock_restrict_self"], + [447, "sys_memfd_secret"], + [448, "sys_process_mrelease"], + [449, "sys_futex_waitv"], + [450, "sys_set_mempolicy_home_node"], + [451, "sys_cachestat"], + [452, "sys_fchmodat2"], + [453, "sys_syscalls"] +]); \ No newline at end of file diff --git a/ide/src/trace/component/trace/base/TraceRow.ts b/ide/src/trace/component/trace/base/TraceRow.ts index 7bda9c89dd3648f3c8ef1ef178b154f1c7cd029f..c5873d745de8af9417a49f028c4f8914859cb0e4 100644 --- a/ide/src/trace/component/trace/base/TraceRow.ts +++ b/ide/src/trace/component/trace/base/TraceRow.ts @@ -79,6 +79,7 @@ export class TraceRow extends HTMLElement { static ROW_TYPE_APP_STARTUP = 'app-startup'; static ROW_TYPE_STATIC_INIT = 'static-init'; static ROW_TYPE_THREAD = 'thread'; + static ROW_TYPE_THREAD_SYS_CALL = 'thread-sys-call'; static ROW_TYPE_THREAD_NAME = 'sameThread_process'; static ROW_TYPE_MEM = 'mem'; static ROW_TYPE_VIRTUAL_MEMORY_GROUP = 'virtual-memory-group'; @@ -354,12 +355,21 @@ export class TraceRow extends HTMLElement { } set rowDiscard(value: boolean) { + let height = 0; if (value) { this.setAttribute('row-discard', ''); this.style.display = 'none'; + height = 0; } else { this.removeAttribute('row-discard'); this.style.display = 'block'; + height = this.clientHeight; + } + if (this.collect) { + window.publish(window.SmartEvent.UI.RowHeightChange, { + expand: this.funcExpand, + value: height, + }); } } @@ -656,7 +666,7 @@ export class TraceRow extends HTMLElement { } // @ts-ignore - addChildTraceRowAfter(child: TraceRow, targetRow: TraceRow): void { + addChildTraceRowAfter(child: TraceRow, targetRow: TraceRow, hidden: boolean = false): void { // @ts-ignore TraceRowConfig.allTraceRowList.push(child); child.parentRowEl = this; @@ -665,11 +675,11 @@ export class TraceRow extends HTMLElement { child.setAttribute('scene', ''); if (index !== -1) { this.childrenList.splice(index + 1, 0, child); - child.rowHidden = false; + child.rowHidden = hidden; this.fragment.insertBefore(child, this.fragment.childNodes.item(index + 1)); } else { this.childrenList.push(child); - child.rowHidden = false; + child.rowHidden = hidden; this.fragment.append(child); } } @@ -1022,21 +1032,23 @@ export class TraceRow extends HTMLElement { this.describeEl?.appendChild(this.rowCheckFilePop); } - addRowSettingCheckBox(): void { + addRowSettingCheckBox(appendAll: boolean = true): void { let nameEl = this.shadowRoot && (this.shadowRoot.querySelector('.name') as HTMLLabelElement); nameEl && (nameEl.style.maxWidth = '160px'); let collectEl = (this.shadowRoot && this.shadowRoot.querySelector('.collect') as LitIcon); collectEl && (collectEl.style.marginRight = '20px'); this.rowSettingCheckBoxPop = document.createElement('lit-popover') as LitPopover; let checkboxHtml = ''; - checkboxHtml += `
    + if (appendAll) { + checkboxHtml += `
    `; + } this._rowSettingCheckBoxList && this._rowSettingCheckBoxList.forEach((item) => { checkboxHtml += `
    - +
    `; }); - this._rowSettingCheckedBoxList = new Array(this._rowSettingCheckBoxList?.length).fill(true); + this._rowSettingCheckedBoxList = new Array(this._rowSettingCheckBoxList?.length).fill(appendAll); this.rowSettingCheckBoxPop.innerHTML = `
    ${checkboxHtml}
    @@ -1048,21 +1060,25 @@ export class TraceRow extends HTMLElement { item.onchange = (e: unknown): void => { // @ts-ignore this._rowSettingCheckedBoxList[this._rowSettingCheckBoxList?.indexOf(item.value)] = item.checked; - const allChecked = this._rowSettingCheckedBoxList!.every(item => item); - allCheckBox.checked = allChecked; + if (appendAll) { + const allChecked = this._rowSettingCheckedBoxList!.every(item => item); + allCheckBox.checked = allChecked; + } this.onRowSettingCheckBoxChangeHandler?.(this._rowSettingCheckedBoxList!); }; }); - allCheckBox.onchange = (e: unknown): void => { - checkBoxItems.forEach(item => { - // @ts-ignore - item.checked = allCheckBox.checked; - }); - this._rowSettingCheckedBoxList!.forEach((_, index) => { - this._rowSettingCheckedBoxList![index] = allCheckBox.checked; - }); - this.onRowSettingCheckBoxChangeHandler?.(this._rowSettingCheckedBoxList!); - }; + if (appendAll) { + allCheckBox.onchange = (e: unknown): void => { + checkBoxItems.forEach(item => { + // @ts-ignore + item.checked = allCheckBox.checked; + }); + this._rowSettingCheckedBoxList!.forEach((_, index) => { + this._rowSettingCheckedBoxList![index] = allCheckBox.checked; + }); + this.onRowSettingCheckBoxChangeHandler?.(this._rowSettingCheckedBoxList!); + }; + } this.rowSettingCheckBoxPop.id = 'rowSetting'; this.rowSettingCheckBoxPop.className = 'popover setting'; this.rowSettingCheckBoxPop.setAttribute('placement', 'bottomLeft'); @@ -1122,6 +1138,14 @@ export class TraceRow extends HTMLElement { return []; } + getRowSettingCheckStateByKey(key: string): boolean { + const index = this._rowSettingCheckBoxList?.indexOf(key); + if (index != undefined) { + return this._rowSettingCheckedBoxList?.[index] === true; + } + return false; + } + //@ts-ignore expandFunc(rootRow: TraceRow, sp: SpSystemTrace): void { if (this._enableCollapseChart && !this.funcExpand) { @@ -1388,6 +1412,10 @@ export class TraceRow extends HTMLElement { if (this.tipEL) { this.tipEL.style.display = 'none'; } + if (this.rowSettingCheckBoxPop) { + //@ts-ignore + this.rowSettingCheckBoxPop.visible = false; + } } loadingPin1: number = 0; @@ -1395,7 +1423,7 @@ export class TraceRow extends HTMLElement { static currentActiveRows: Array = []; drawFrame(): void { - if (!this.hasAttribute('row-hidden')) { + if (!this.hasAttribute('row-hidden') && !this.hasAttribute('row-discard')) { if (!this.loadingFrame || window.isLastFrame || !this.isComplete) { if (this.needRefresh || window.isLastFrame) { this.loadingFrame = true; diff --git a/ide/src/trace/component/trace/base/TraceRowConfig.ts b/ide/src/trace/component/trace/base/TraceRowConfig.ts index 904bef122abc92cd741173e055e3b43992b04803..b43e77e9dcabfe8ad94f508fa042bf1750c85fa2 100644 --- a/ide/src/trace/component/trace/base/TraceRowConfig.ts +++ b/ide/src/trace/component/trace/base/TraceRowConfig.ts @@ -441,7 +441,7 @@ export class TraceRowConfig extends BaseElement { private initSwitchClickListener(): void { let jsonUrl = `https://${window.location.host.split(':')[0]}:${window.location.port - }/application/trace/config/custom_temp_config.json`; + }${window.location.pathname}trace/config/custom_temp_config.json`; this.switchButton!.addEventListener('click', () => { // @ts-ignore this.inputElement?.value = ''; diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index c16465188dfee9496b841f1b2ba3ec8adc196a22..5a20b88e859eafb17705310524e1cf0c9a1f420c 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -16,7 +16,13 @@ import { BaseElement, element } from '../../../../base-ui/BaseElement'; import { type LitTabs } from '../../../../base-ui/tabs/lit-tabs'; import { LitTabpane } from '../../../../base-ui/tabs/lit-tabpane'; -import { BoxJumpParam, SelectionParam, SliceBoxJumpParam } from '../../../bean/BoxSelection'; +import { + BoxJumpParam, + SelectionParam, + SysCallBoxJumpParam, + SliceBoxJumpParam, + PerfSampleBoxJumpParam +} from '../../../bean/BoxSelection'; import { type TabPaneCurrentSelection } from '../sheet/TabPaneCurrentSelection'; import { type TabPaneFlag } from '../timer-shaft/TabPaneFlag'; import { type Flag } from '../timer-shaft/Flag'; @@ -28,6 +34,7 @@ import { type CpuStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerC import { CpuFreqStruct } from '../../../database/ui-worker/ProcedureWorkerFreq'; import { CpuFreqLimitsStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; import { type ThreadStruct } from '../../../database/ui-worker/ProcedureWorkerThread'; +import { type ThreadSysCallStruct } from '../../../database/ui-worker/ProcedureWorkerThreadSysCall'; import { type FuncStruct } from '../../../database/ui-worker/ProcedureWorkerFunc'; import { ProcessMemStruct } from '../../../database/ui-worker/ProcedureWorkerMem'; import { CpuStateStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuState'; @@ -110,6 +117,8 @@ import { PerfFunctionAsmParam } from '../../../bean/PerfAnalysis'; import { info, error } from '../../../../log/Log'; import { XpowerThreadCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerThreadCount'; import { XpowerGpuFreqCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerGpuFreqCount'; +import { TabPaneSysCallChild } from '../sheet/process/TabPaneSysCallChild'; +import { TabPanePerfSampleChild } from '../sheet/hiperf/TabPerfSampleChild'; @element('trace-sheet') @@ -119,6 +128,7 @@ export class TraceSheet extends BaseElement { private switchDiv: LitPopover | undefined | null; private processTree: LitTree | undefined | null; private importDiv: HTMLDivElement | undefined | null; + private symbolDiv: HTMLDivElement | undefined | null; private exportBt: LitIcon | undefined | null; private nav: HTMLDivElement | undefined | null; private tabs: HTMLDivElement | undefined | null; @@ -195,6 +205,7 @@ export class TraceSheet extends BaseElement { e.preventDefault(); }); this.importDiv = this.shadowRoot?.querySelector('#import_div'); + this.symbolDiv = this.shadowRoot?.querySelector('#symbol_div'); this.switchDiv = this.shadowRoot?.querySelector('#select-process'); this.processTree = this.shadowRoot?.querySelector('#processTree'); this.optionsDiv = this.shadowRoot?.querySelector('#options'); @@ -301,6 +312,14 @@ export class TraceSheet extends BaseElement { this.getComponentByID('box-slices')?.addEventListener('td-click', (evt: unknown) => { this.tdSliceClickHandler(evt); }); + // @ts-ignore + this.getComponentByID('box-thread-syscall')?.addEventListener('td-click', (evt: unknown) => { + this.tdSysCallClickHandler(evt); + }); + // @ts-ignore + this.getComponentByID('box-perf-profile')?.addEventListener('td-click', (evt: unknown) => { + this.tdPerfSampleClickHandler(evt); + }); } private perfAnalysisListener(evt: MouseEvent): void { @@ -609,19 +628,32 @@ export class TraceSheet extends BaseElement { let importFileBt: HTMLInputElement | undefined | null = this.shadowRoot?.querySelector('#import-file'); importFileBt!.addEventListener('change', (event): void => { - let files = importFileBt?.files; - if (files) { - let fileList: Array = []; - for (let file of files) { - fileList.push(file); + WebSocketManager.instance = null; + WebSocketManager.getInstance(); + let timerOut = window.setTimeout(() => { + window.clearTimeout(timerOut); + let errorTipHtml = document.querySelector('body > sp-application')?.shadowRoot?.querySelector('#sp-system-trace') + ?.shadowRoot?.querySelector('div > trace-sheet')?.shadowRoot?.querySelector('#box-perf-analysis > tabpane-perf-analysis')?.shadowRoot?.querySelector('#SO-err-tips'); + let connected = document.querySelector('body > sp-application') + ?.shadowRoot?.querySelector('#main-menu')?.shadowRoot?.querySelector('div.bottom > div.extend_connect') as HTMLDivElement; + if (connected && connected.style.backgroundColor !== 'green') { + errorTipHtml!.innerHTML = 'Please check if the extension service is enabled and try again!'; + importFileBt!.files = null; + importFileBt!.value = ''; + return; } - if (fileList.length > 0) { - importFileBt!.disabled = true; - this.loadSoComplete = false; - window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Import So File' }); - this.uploadSoOrAN(fileList).then(r => { - // @ts-ignore - document.querySelector('body > sp-application').shadowRoot.querySelector('#sp-system-trace').shadowRoot.querySelector('div > trace-sheet').shadowRoot.querySelector('#box-perf-analysis > tabpane-perf-analysis').shadowRoot.querySelector('#SO-err-tips')?.innerHTML = ''; + let files = importFileBt?.files; + if (files) { + let fileList: Array = []; + for (let file of files) { + fileList.push(file); + } + if (fileList.length > 0) { + importFileBt!.disabled = true; + this.loadSoComplete = false; + window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Import So File' }); + this.uploadSoOrAN(fileList).then(r => { + errorTipHtml!.innerHTML = ''; let soFileList = fileList.filter(item => !item.name.includes('.an')); if (soFileList.length === 0) { window.publish(window.SmartEvent.UI.UploadSOFile, {}); @@ -653,7 +685,57 @@ export class TraceSheet extends BaseElement { } importFileBt!.files = null; importFileBt!.value = ''; + }, 500) }); + this.addClickEventToSoSymbolImport(); + } + + private addClickEventToSoSymbolImport(): void{ + let symbolBt: HTMLInputElement | undefined | null = + this.shadowRoot?.querySelector('#so-symbolization'); + symbolBt!.addEventListener('change', (event): void => { + let files = symbolBt?.files; + if (files) { + let fileList: Array = []; + for (let file of files) { + fileList.push(file); + } + if (fileList.length > 0) { + symbolBt!.disabled = true; + window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Import So File' }); + // @ts-ignore + document.querySelector('body > sp-application').shadowRoot.querySelector('#sp-system-trace').shadowRoot.querySelector('div > trace-sheet').shadowRoot.querySelector('#box-perf-analysis > tabpane-perf-analysis').shadowRoot.querySelector('#SO-err-tips')?.innerHTML = ''; + let soFileList = fileList.filter(item => item.name.includes('.so')); + if (soFileList.length === 0) { + window.publish(window.SmartEvent.UI.UploadSOFile, {}); + symbolBt!.disabled = false; + return; + } + threadPool.submit( + 'upload-so', + '', + soFileList, + (res: unknown) => { + symbolBt!.disabled = false; + setTimeout(() => { + // @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!`); + } + }, 500); + }, + 'upload-so' + ); + } + fileList.length = 0; + } + symbolBt!.files = null; + symbolBt!.value = ''; + }) } private async uploadSoOrAN(fileList: Array): Promise { @@ -728,21 +810,21 @@ export class TraceSheet extends BaseElement { 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 = { + 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), + is_last: writeSize + sliceLen >= file.size }; - - const dataString = JSON.stringify(dataObject); + const jsonStr = `${dataString.length}|${dataString}`; const textEncoder = new TextEncoder(); - const encodedData = textEncoder.encode(dataString); - wsInstance!.sendMessage(TypeConstants.DISASSEMBLY_TYPE, Constants.DISASSEMBLY_SAVE_CMD, encodedData); + const jsonData = textEncoder.encode(jsonStr); + let mergeData: Uint8Array = new Uint8Array(jsonData.length + data.length); + mergeData.set(jsonData); + mergeData.set(data, jsonData.length); + wsInstance!.sendMessage(TypeConstants.DISASSEMBLY_TYPE, Constants.DISASSEMBLY_SAVE_CMD, mergeData); writeSize += sliceLen; // 等待服务器端确认当前分片的 ACK await waitForAck(); @@ -836,9 +918,16 @@ export class TraceSheet extends BaseElement {
    -
    +
    +
    +
    + + @@ -870,6 +959,9 @@ export class TraceSheet extends BaseElement { scrollPrio, callback ); + + displaySysCallData = (data: ThreadSysCallStruct) => + this.displayTab('current-selection').setSysCallData(data); displayMemData = (data: ProcessMemStruct): void => this.displayTab('current-selection').setMemData(data); displayHangData = (data: HangStruct, sp: SpSystemTrace, scrollCallback: Function): Promise => @@ -1252,6 +1344,7 @@ export class TraceSheet extends BaseElement { param.nativeMemoryCurrentIPid = ipid; } } + param.isImportSo = true; this.rangeSelect(param, true); return true; } else { @@ -1274,8 +1367,10 @@ export class TraceSheet extends BaseElement { selection.threadIds.length > 0) ) { this.importDiv!.style.display = 'flex'; + this.symbolDiv!.style.display = 'flex'; } else { this.importDiv!.style.display = 'none'; + this.symbolDiv!.style.display = 'none'; } } isProcessEqual(treeData: Array<{ pid: number; ipid: number }>): boolean { @@ -1382,6 +1477,72 @@ export class TraceSheet extends BaseElement { (pane.children.item(0) as TabPaneBoxChild).data = param; } + tdSysCallClickHandler(e: unknown): 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-thread-syscall-child'); //通过Id找到需要展示的Tab页 + pane.closeable = true; //关闭的ican显示 + pane.hidden = false; + this.litTabs!.activeByKey(pane.key); //显示key值对应的Tab页 + // @ts-ignore + pane.tab = e.detail.name; //设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串 + let param = new SysCallBoxJumpParam(); + param.traceId = this.selection!.traceId; + param.leftNs = this.selection!.leftNs; + param.rightNs = this.selection!.rightNs; + // @ts-ignore + const level = e.detail.level; + if (level === 'Process') { + // @ts-ignore + param.processId = [e.detail.id]; + } else if (level === 'Thread'){ + // @ts-ignore + param.processId = [e.detail.parentId]; + // @ts-ignore + param.threadId = [e.detail.id]; + } else { + // @ts-ignore + param.threadId = [e.detail.parentId]; + // @ts-ignore + param.sysCallId = e.detail.id; + } + param.isJumpPage = true; // @ts-ignore + (pane.children.item(0) as TabPaneSysCallChild).data = param; + } + + tdPerfSampleClickHandler(e: unknown): 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-perf-sample-child'); //通过Id找到需要展示的Tab页 + pane.closeable = true; //关闭的ican显示 + pane.hidden = false; + this.litTabs!.activeByKey(pane.key); //显示key值对应的Tab页 + // @ts-ignore + pane.tab = e.detail.symbol; //设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串 + let param = new PerfSampleBoxJumpParam(); + param.traceId = this.selection!.traceId; + param.leftNs = this.selection!.leftNs; + param.rightNs = this.selection!.rightNs; + //@ts-ignore + param.pid = e.detail.pid; + //@ts-ignore + param.tid = e.detail.tid; + //@ts-ignore + param.count = e.detail.dur || 0; + //@ts-ignore + param.tsArr = e.detail.tsArray || []; + param.isJumpPage = true; + (pane.children.item(0) as TabPanePerfSampleChild).data = param; + } + //Slice Tab点击Occurrences列下的td进行跳转 tdSliceClickHandler(e: unknown): void { // @ts-ignore diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index f5de86153d7f696dfb84db3e8839022138880bc7..44ab3360c2e4b8fbd9154f42c05dac4f16a3dc62 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -30,6 +30,7 @@ import { TabPaneNMStatstics } from '../sheet/native-memory/TabPaneNMStatstics'; import { TabPaneNMemory } from '../sheet/native-memory/TabPaneNMemory'; import { TabPaneNMSampleList } from '../sheet/native-memory/TabPaneNMSampleList'; import { TabpanePerfProfile } from '../sheet/hiperf/TabPerfProfile'; +import { TabPanePerfSampleChild } from '../sheet/hiperf/TabPerfSampleChild'; import { TabPanePerfSample } from '../sheet/hiperf/TabPerfSampleList'; import { TabPaneLiveProcesses } from '../sheet/ability/TabPaneLiveProcesses'; import { TabPaneHistoryProcesses } from '../sheet/ability/TabPaneHistoryProcesses'; @@ -91,6 +92,7 @@ import { TabPaneIOTierStatisticsAnalysis } from '../sheet/file-system/TabPaneIOT import { TabPaneVirtualMemoryStatisticsAnalysis } from '../sheet/file-system/TabPaneVirtualMemoryStatisticsAnalysis'; import { TabPaneCurrent } from '../sheet/TabPaneCurrent'; import { TabPaneStartup } from '../sheet/process/TabPaneStartup'; +import { TabPaneSysCall } from '../sheet/process/TabPaneSysCall'; import { TabPaneStaticInit } from '../sheet/process/TabPaneStaticInit'; import { TabPaneTaskFrames } from '../sheet/task/TabPaneTaskFrames'; import { TabPaneFrameDynamic } from '../sheet/frame/TabPaneFrameDynamic'; @@ -151,6 +153,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 { TabPaneSysCallChild } from '../sheet/process/TabPaneSysCallChild'; import { TabPerfFuncAsm } from '../sheet/hiperf/TabPerfFuncAsm'; export let tabConfig: { @@ -216,6 +219,15 @@ export let tabConfig: { type: TabPaneStartup, require: (param: SelectionParam) => param.processIds.length > 0 && param.startup, }, + 'box-thread-syscall': { + title: 'SysCall Event', + type: TabPaneSysCall, + require: (param: SelectionParam) => param.processSysCallIds.length > 0 || param.threadSysCallIds.length > 0, + }, + 'box-thread-syscall-child': { + title: '', + type: TabPaneSysCallChild, + }, 'box-process-static-init': { title: 'Static Initialization', type: TabPaneStaticInit, @@ -251,6 +263,10 @@ export let tabConfig: { type: TabPanePerfSample, require: (param: SelectionParam) => param.perfSampleIds.length > 0, }, + 'box-perf-sample-child': { + title: '', + type: TabPanePerfSampleChild + }, 'box-perf-async': { title: 'Async Call Profile', type: TabPanePerfAsync, diff --git a/ide/src/trace/component/trace/base/Utils.ts b/ide/src/trace/component/trace/base/Utils.ts index e9e4435a69e2d127719ad203228d72dabd53c7e9..f8ebc2fb51a3d8203d080f5ed085966ecfdeef88 100644 --- a/ide/src/trace/component/trace/base/Utils.ts +++ b/ide/src/trace/component/trace/base/Utils.ts @@ -23,6 +23,8 @@ export class Utils { static currentSelectTrace: string | null | undefined; static currentTraceMode: TraceMode = TraceMode.NORMAL; static distributedTrace: string[] = []; + static isRangeSelectRefresh: boolean = false; + static currentTraceName: string = ''; static DMAFENCECAT_MAP: Map< number, { @@ -54,6 +56,7 @@ export class Utils { totalNS: number = 1; private trace1ThreadMap: Map = new Map(); private trace1ProcessMap: Map = new Map(); + sysCallEventTidsMap: Map = new Map(); private trace1SchedSliceMap: Map< string, { @@ -222,6 +225,7 @@ export class Utils { this.trace2ThreadMap.clear(); this.trace1SchedSliceMap.clear(); this.trace2SchedSliceMap.clear(); + this.sysCallEventTidsMap.clear(); Utils.distributedTrace = []; } diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts index 9e4d54868053ab42e121b1b4bc21d85cd8c1aee4..0cfe639213d9866fdbb67cd37c68251d71ff4cc6 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -51,6 +51,7 @@ import { queryDistributedRelationAllData, queryRWakeUpFrom, queryRunnableTimeByRunning, + querySysCallEventDetail, queryThreadStateArgs, queryThreadWakeUp, queryThreadWakeUpFrom, @@ -70,6 +71,7 @@ import { XpowerAppDetailStruct } from '../../../database/ui-worker/ProcedureWork import { XpowerWifiStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerWifi'; import { XpowerThreadCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerThreadCount'; import { XpowerGpuFreqCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerGpuFreqCount'; +import { ThreadSysCallStruct } from '../../../database/ui-worker/ProcedureWorkerThreadSysCall'; const INPUT_WORD = 'This is the interval from when the task became eligible to run \n(e.g.because of notifying a wait queue it was a suspended on) to\n when it started running.'; @@ -473,6 +475,7 @@ export class TabPaneCurrentSelection extends BaseElement { } list.push(item); }); + this.addTabSliceDetail(data, list) this.currentSelectionTbl!.dataSource = list; // @ts-ignore let startTimeAbsolute = (data.startTs || 0) + (window as unknown).recordStartNS; @@ -494,6 +497,7 @@ export class TabPaneCurrentSelection extends BaseElement { name: 'Thread', value: (this.transferString(threadName ?? '') || 'NULL') + ' [' + dataTid + '] ', }); + this.addTabSliceDetail(data, list) list.push({ name: 'StartTime(Relative)', value: getTimeString(data.startTs || 0), @@ -599,6 +603,7 @@ export class TabPaneCurrentSelection extends BaseElement { argset.forEach((item) => { list.push({ name: item.keyName, value: item.strValue }); }); + this.addTabSliceDetail(data, list) this.addTabPanelContent(list, data, information); this.currentSelectionTbl!.dataSource = list; }); @@ -653,6 +658,7 @@ export class TabPaneCurrentSelection extends BaseElement { } ); } + this.addTabSliceDetail(data, list) this.addTabPanelContent(list, data, information); this.currentSelectionTbl!.dataSource = list; let funcClick = this.currentSelectionTbl?.shadowRoot?.querySelector('#function-jump'); @@ -686,6 +692,21 @@ export class TabPaneCurrentSelection extends BaseElement { }); } + private addTabSliceDetail(data: FuncStruct, list: unknown[]) { + const properties = [ + {key: 'trace_level', name: 'TraceLevel'}, + {key: 'trace_tag', name: 'TraceTag'}, + {key: 'category', name: 'Category'}, + {key: 'custom_args', name: 'CustomArgs'}, + ]; + properties.forEach(prop => { + if (data[prop.key] && list !== undefined) { + list!.push({name: prop.name, value: data[prop.key]}); + } + }); + return list; + } + private handleAsyncBinder( data: FuncStruct, list: unknown[], @@ -748,6 +769,7 @@ export class TabPaneCurrentSelection extends BaseElement { value: (this.transferString(threadName ?? '') || 'NULL') + ' [' + data.tid + '] ', }); } + this.addTabSliceDetail(data, list) this.addTabPanelContent(list, data, information); this.currentSelectionTbl!.dataSource = list; let funcClick = this.currentSelectionTbl?.shadowRoot?.querySelector('#function-jump'); @@ -1197,6 +1219,35 @@ export class TabPaneCurrentSelection extends BaseElement { }); } + async setSysCallData(data: ThreadSysCallStruct) { + this.setTableHeight('350px'); + this.initCanvas(); + let leftTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector('#leftTitle'); + this.setTitleAndButtonStyle(); + if (leftTitle) { + leftTitle.innerText = 'SysCall Event'; + } + let list: unknown[] = []; + list.push({ name: 'Name', value: `${data.name} [${data.id}]` }); + list.push({ + name: 'StartTime(Relative)', + value: getTimeString(data.startTs || 0), + }); + list.push({ + name: 'StartTime(Absolute)', + value: ((data.startTs || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', + }); + list.push({ name: 'Duration', value: getTimeString(data.dur || 0) }); + const eventValue = await querySysCallEventDetail(data.itid!, data.startTs! + Utils.getInstance().getRecordStartNS(), data.dur!); + if (eventValue[0]) { + list.push({ name: 'Process', value: `${eventValue[0].pName} [${data.pid}]` }); + list.push({ name: 'Thread', value: `${eventValue[0].tName} [${data.tid}]` }); + list.push({ name: 'args', value: eventValue[0].args }); + list.push({ name: 'ret', value: eventValue[0].ret }); + } + this.currentSelectionTbl!.dataSource = list; + } + async setThreadData( data: ThreadStruct, scrollCallback: ((d: unknown) => void) | undefined, diff --git a/ide/src/trace/component/trace/sheet/TabPaneFilter.ts b/ide/src/trace/component/trace/sheet/TabPaneFilter.ts index 5fdf7b28d571d9a351f87671510dd0c84ad86814..fbaaf9f1b93f239ebb1efa9e83c4107d0da74051 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneFilter.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneFilter.ts @@ -43,9 +43,9 @@ export interface MiningData { export class CpuStatus { cpu: number = 0; - small: boolean = false; + little: boolean = false; medium: boolean = false; - large: boolean = false; + big: boolean = false; } @element('tab-pane-filter') @@ -482,7 +482,7 @@ export class TabPaneFilter extends BaseElement { } //添加cpu列表 - setCoreConfigList(count: number, small: Array, mid: Array, large: Array): void { + setCoreConfigList(count: number, little: Array, mid: Array, big: Array): void { let divEl = this.shadowRoot!.querySelector('#data-core-popover > div > #tb_core_setting'); divEl!.innerHTML = ''; this.createCoreHeaderDiv(divEl); @@ -490,13 +490,13 @@ export class TabPaneFilter extends BaseElement { let obj = { cpu: i, // @ts-ignore - small: small.includes(i), + little: little.includes(i), // @ts-ignore medium: mid.includes(i), // @ts-ignore - large: large.includes(i), + big: big.includes(i), }; - this.createCheckBoxLine(divEl, obj, small, mid, large); + this.createCheckBoxLine(divEl, obj, little, mid, big); } } @@ -507,89 +507,89 @@ export class TabPaneFilter extends BaseElement { cpuIdLine.style.fontSize = '12px'; cpuIdLine.textContent = 'Cpu'; cpuIdLine.style.textAlign = 'center'; - let smallLine = document.createElement('div'); - smallLine.className = 'core_line'; - smallLine.style.fontWeight = 'bold'; - smallLine.textContent = 'S'; - smallLine.style.fontSize = '12px'; - smallLine.style.textAlign = 'center'; + let littleLine = document.createElement('div'); + littleLine.className = 'core_line'; + littleLine.style.fontWeight = 'bold'; + littleLine.textContent = 'L'; + littleLine.style.fontSize = '12px'; + littleLine.style.textAlign = 'center'; let mediumLine = document.createElement('div'); mediumLine.className = 'core_line'; mediumLine.style.fontWeight = 'bold'; mediumLine.textContent = 'M'; mediumLine.style.fontSize = '12px'; mediumLine.style.textAlign = 'center'; - let largeLine = document.createElement('div'); - largeLine.className = 'core_line'; - largeLine.style.fontWeight = 'bold'; - largeLine.textContent = 'L'; - largeLine.style.fontSize = '12px'; - largeLine.style.textAlign = 'center'; + let bigLine = document.createElement('div'); + bigLine.className = 'core_line'; + bigLine.style.fontWeight = 'bold'; + bigLine.textContent = 'B'; + bigLine.style.fontSize = '12px'; + bigLine.style.textAlign = 'center'; // @ts-ignore - tab?.append(...[cpuIdLine, smallLine, mediumLine, largeLine]); + tab?.append(...[cpuIdLine, littleLine, mediumLine, bigLine]); } //添加对应的cpu checkbox,并添加对应的监听事件 createCheckBoxLine( divEl: unknown, cpuStatus: CpuStatus, - small: Array, + little: Array, mid: Array, - large: Array + big: Array ): void { let div = document.createElement('div'); div.textContent = cpuStatus.cpu + ''; div.style.textAlign = 'center'; div.style.fontWeight = 'normal'; - let smallCheckBox: LitCheckBox = new LitCheckBox(); - smallCheckBox.checked = cpuStatus.small; - smallCheckBox.setAttribute('not-close', ''); - smallCheckBox.style.textAlign = 'center'; - smallCheckBox.style.marginLeft = 'auto'; - smallCheckBox.style.marginRight = 'auto'; + let littleCheckBox: LitCheckBox = new LitCheckBox(); + littleCheckBox.checked = cpuStatus.little; + littleCheckBox.setAttribute('not-close', ''); + littleCheckBox.style.textAlign = 'center'; + littleCheckBox.style.marginLeft = 'auto'; + littleCheckBox.style.marginRight = 'auto'; let midCheckBox: LitCheckBox = new LitCheckBox(); midCheckBox.checked = cpuStatus.medium; midCheckBox.setAttribute('not-close', ''); midCheckBox.style.textAlign = 'center'; midCheckBox.style.marginLeft = 'auto'; midCheckBox.style.marginRight = 'auto'; - let largeCheckBox: LitCheckBox = new LitCheckBox(); - largeCheckBox.checked = cpuStatus.large; - largeCheckBox.setAttribute('not-close', ''); - largeCheckBox.style.marginLeft = 'auto'; - largeCheckBox.style.marginRight = 'auto'; - smallCheckBox.addEventListener('change', (e: unknown) => { + let bigCheckBox: LitCheckBox = new LitCheckBox(); + bigCheckBox.checked = cpuStatus.big; + bigCheckBox.setAttribute('not-close', ''); + bigCheckBox.style.marginLeft = 'auto'; + bigCheckBox.style.marginRight = 'auto'; + littleCheckBox.addEventListener('change', (e: unknown) => { midCheckBox.checked = false; - largeCheckBox.checked = false; + bigCheckBox.checked = false; // @ts-ignore - cpuStatus.small = e.detail.checked; + cpuStatus.little = e.detail.checked; // @ts-ignore - this.canUpdateCheckList(e.detail.checked, small, cpuStatus.cpu); + this.canUpdateCheckList(e.detail.checked, little, cpuStatus.cpu); mid = mid.filter((it) => it !== cpuStatus.cpu); - large = large.filter((it) => it !== cpuStatus.cpu); + big = big.filter((it) => it !== cpuStatus.cpu); }); midCheckBox.addEventListener('change', (e: unknown) => { - largeCheckBox.checked = false; - smallCheckBox.checked = false; + bigCheckBox.checked = false; + littleCheckBox.checked = false; // @ts-ignore cpuStatus.medium = e.detail.checked; // @ts-ignore this.canUpdateCheckList(e.detail.checked, mid, cpuStatus.cpu); - large = large.filter((it) => it !== cpuStatus.cpu); - small = small.filter((it) => it !== cpuStatus.cpu); + big = big.filter((it) => it !== cpuStatus.cpu); + little = little.filter((it) => it !== cpuStatus.cpu); }); - largeCheckBox.addEventListener('change', (e: unknown) => { + bigCheckBox.addEventListener('change', (e: unknown) => { midCheckBox.checked = false; - smallCheckBox.checked = false; + littleCheckBox.checked = false; // @ts-ignore - cpuStatus.large = e.detail.checked; + cpuStatus.big = e.detail.checked; // @ts-ignore - this.canUpdateCheckList(e.detail.checked, large, cpuStatus.cpu); + this.canUpdateCheckList(e.detail.checked, big, cpuStatus.cpu); mid = mid.filter((it) => it !== cpuStatus.cpu); - small = small.filter((it) => it !== cpuStatus.cpu); + little = little.filter((it) => it !== cpuStatus.cpu); }); // @ts-ignore - divEl!.append(...[div, smallCheckBox, midCheckBox, largeCheckBox]); + divEl!.append(...[div, littleCheckBox, midCheckBox, bigCheckBox]); } //判断checkList数组是否需要push数据或删除数据 diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.html.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.html.ts index 02249b1ec86b5d3944b5319a2dcb6c0e05de1126..787aa7d7c5a36c684fa89c4e07f99fd713315485 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.html.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.html.ts @@ -66,8 +66,21 @@ export const TabPanePerfAnalysisHtml = ` width: 100%; height: 20px; } +@keyframes textGrowth { + 0% { + font-size: 16px; + transform: scale(0.9); + } + 100% { + font-size: 18px; + transform: scale(1.0); + } +} #SO-err-tips{ color:red; + animation: textGrowth 2.0s ease-in-out infinite alternate; + will-change: transform, font-size; + transform: translateZ(0); }
    diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts index c04d2ce9193ebb9aa8d80437fac8ecac9538ebf6..57993a75d892168db49a87d982efbe7aaad79e4b 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPanePerfAnalysis.ts @@ -68,13 +68,21 @@ export class TabPanePerfAnalysis extends BaseElement { private isComplete: boolean = true; private currentSelectionParam: SelectionParam | undefined | null; static tabLoadingList: Array = []; + private vaddrList: Array = []; private selectedTabfileName: string = ''; private clickFuncVaddrList: Array = []; private functionListener!: Function | undefined | null; private currentSoName: string = ''; + private currentProcessItem: unknown; + private currentThreadItem: unknown; + private currentLibrayItem: unknown; set data(val: SelectionParam) { + if (val.isImportSo && this.currentLevel > 0) { + this.disableHomeRedirectAfterSoLoad(val); + return; + } if (val === this.currentSelection) { this.pidData.unshift(this.allProcessCount); this.perfTableProcess!.recycleDataSource = this.pidData; @@ -107,6 +115,66 @@ export class TabPanePerfAnalysis extends BaseElement { } } + private disableHomeRedirectAfterSoLoad(val: SelectionParam): void { + this.getDataByWorker(val, (results: unknown) => { + this.isComplete = true; + // @ts-ignore + this.processData = results; + // @ts-ignore + if (this.currentLevel === 3) { + this.reset(this.tableFunction!, true); + this.getHiperfFunction(this.currentLibrayItem); + let title = ''; + if (this.processName.length > 0) { + title += `${this.processName} / `; + } + if (this.threadName.length > 0) { + title += `${this.threadName} / `; + } + if (this.currentSoName.length > 0) { + title += this.currentSoName; + } + this.titleEl!.textContent = title; + this.perfAnalysisPie?.hideTip(); + this.selectedTabfileName = this.currentSoName; + } else if (this.currentLevel === 1) { + if (this.hideThreadCheckBox!.checked) { + this.hideThread(this.currentProcessItem); + } else { + this.reset(this.perfTableThread!, true); + this.getHiperfThread(this.currentProcessItem, val); + } + // @ts-ignore + this.titleEl!.textContent = this.currentProcessItem.tableName; + // @ts-ignore + this.processName = this.currentProcessItem.tableName; + this.perfAnalysisPie?.hideTip(); + } else if (this.currentLevel === 2) { + this.reset(this.perfTableSo!, true); + this.getHiperfSo(this.currentThreadItem, val); + let pName = this.processName; + // @ts-ignore + if (this.processName.length > 0 && this.currentThreadItem.tableName.length > 0) { + pName = `${this.processName} / `; + } + // @ts-ignore + this.titleEl!.textContent = pName + this.currentThreadItem.tableName; + // @ts-ignore + this.threadName = this.currentThreadItem.tableName; + this.perfAnalysisPie?.hideTip(); + } + const args = [ + { + funcName: 'getVaddrToFile', + funcArgs: [val], + }, + ]; + procedurePool.submitWithName('logic0', 'perf-vaddr', args, undefined, (results: Array) => { + this.vaddrList = results; + }); + }); + } + private initPerfTableListener(): void { for (let perfTable of this.tableArray!) { let querySelector = perfTable.shadowRoot?.querySelector('.table'); @@ -407,6 +475,7 @@ export class TabPanePerfAnalysis extends BaseElement { } private perfProcessLevelClickEvent(it: unknown, val: SelectionParam): void { + this.currentProcessItem = it; if (this.hideThreadCheckBox!.checked) { this.hideThread(it); this.showAssignLevel(this.perfTableSo!, this.perfTableProcess!, 1, this.soData); @@ -478,6 +547,7 @@ export class TabPanePerfAnalysis extends BaseElement { } private perfThreadLevelClickEvent(it: unknown, val: SelectionParam): void { + this.currentThreadItem = it; this.reset(this.perfTableSo!, true); this.showAssignLevel(this.perfTableSo!, this.perfTableThread!, 2, this.soData); this.getHiperfSo(it, val); @@ -556,6 +626,7 @@ export class TabPanePerfAnalysis extends BaseElement { } private perfSoLevelClickEvent(it: unknown): void { + this.currentLibrayItem = it; this.reset(this.tableFunction!, true); this.showAssignLevel(this.tableFunction!, this.perfTableSo!, 3, this.functionData); // @ts-ignore @@ -623,7 +694,7 @@ export class TabPanePerfAnalysis extends BaseElement { encodedData = textEncoder.encode(dataString); WebSocketManager.getInstance()?.registerMessageListener(TypeConstants.DISASSEMBLY_TYPE, this.callback, () => { }, true); WebSocketManager.getInstance()?.sendMessage(TypeConstants.DISASSEMBLY_TYPE, Constants.DISASSEMBLY_QUERY_ELF_CMD, encodedData); - if (WebSocketManager.disaStatus !== 'ready') { + if (WebSocketManager.getInstance()!.status !== 'ready') { // @ts-ignore this.perfAnalysisHeadTips?.innerHTML = 'Request timed out.Install the extended service according to the help document.'; return; diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.html.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.html.ts index f7b7de69d872931a13d766549d1f7a0499eb3cc4..83e8a071e94e44b625a02bcb14f76b9cdb2dc770 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.html.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.html.ts @@ -74,9 +74,9 @@ export const TabPerfFuncAsmHtml = ` - - - + + +
    diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.ts index b0db75e263f836ece63d3a647e6279669f574427..cb3ca4164a3cb7bd2b38ebc2df70a4f61b3920d9 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfFuncAsm.ts @@ -13,6 +13,7 @@ * limitations under the License. */ import { TabPerfFuncAsmHtml } from './TabPerfFuncAsm.html'; +import { Utils } from '../../base/Utils'; import { BaseElement, element } from '../../../../../base-ui/BaseElement'; import { LitTable } from '../../../../../base-ui/table/lit-table'; import { @@ -22,6 +23,7 @@ import { } from '../../../../bean/PerfAnalysis'; import { WebSocketManager } from '../../../../../webSocket/WebSocketManager'; import { Constants, TypeConstants } from '../../../../../webSocket/Constants'; +import { SpStatisticsHttpUtil } from '../../../../../statistics/util/SpStatisticsHttpUtil'; @element('tab-perf-func-asm') export class TabPerfFuncAsm extends BaseElement { @@ -140,6 +142,9 @@ export class TabPerfFuncAsm extends BaseElement { } set data(data: PerfFunctionAsmParam) { + if (Utils.isRangeSelectRefresh) { + this.functionName = ''; + } if (this.functionName === data.functionName || data.functionName === undefined) { return; } @@ -151,6 +156,7 @@ export class TabPerfFuncAsm extends BaseElement { this.totalCount = data.totalCount; this.updateTotalCount(); this.showLoading(); + Utils.isRangeSelectRefresh = false; // @ts-ignore const vaddrInFile = data.vaddrList[0].vaddrInFile; // 1. 先转成 BigInt @@ -170,6 +176,10 @@ export class TabPerfFuncAsm extends BaseElement { if (cmd === Constants.DISASSEMBLY_QUERY_BACK_CMD) { const result = JSON.parse(new TextDecoder().decode(e)); if (result.resultCode === 0) { + SpStatisticsHttpUtil.addOrdinaryVisitAction({ + event: 'hiperf_func', + action: 'hiperf_func', + }); if (result.anFileOff) { this.textFileOffElement!.innerHTML = `.text section: ${result.anFileOff}`; this.textFileOffElement!.style.display = 'block'; @@ -256,8 +266,10 @@ export class TabPerfFuncAsm extends BaseElement { 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; + if (this.formattedAsmIntructionArray[instructionPosition]) { + this.formattedAsmIntructionArray[instructionPosition].selfcount = selfCount; + this.formattedAsmIntructionArray[instructionPosition].percent = Math.round((selfCount / this.totalCount) * 10000) / 100; + } }); this.originalShowUpData = this.formattedAsmIntructionArray; } diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.html.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.html.ts index 21c6f8a95f0102640d25427b1a2cb283bb1e3c6e..1abd315dbe6fb1eef2abea32f5ed782fdf25bda9 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.html.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfProfile.html.ts @@ -64,7 +64,7 @@ selector{ + align="flex-start" order tdJump> = []; + private processMap: Map = new Map(); + private sortKey: string = 'timeString'; + private sortType: number = 0; + + set data(sampleChildParam: PerfSampleBoxJumpParam | null | undefined) { + if (sampleChildParam === this.param || !sampleChildParam?.isJumpPage) { + return; + } + this.param = sampleChildParam; + this.perfSampleTbl!.style.visibility = 'visible'; + // @ts-ignore + this.perfSampleTbl?.shadowRoot?.querySelector('.table')?.style?.height = `${ + this.parentElement!.clientHeight - 40 + }px`; + this.perfSampleTbl!.recycleDataSource = []; + // @ts-ignore + this.tblData?.shadowRoot?.querySelector('.table')?.style?.height = `${this.parentElement!.clientHeight - 25}px`; + this.tblData!.recycleDataSource = []; + if (sampleChildParam) { + Promise.all([ + queryPerfProcess(), + queryPerfSampleChildListByTree( + sampleChildParam.leftNs, + sampleChildParam.rightNs, + sampleChildParam.pid, + sampleChildParam.tid, + ), + ]).then((results) => { + let processes = results[0] as Array; + log(`queryPerfProcess size : ${processes.length}`); + let samples = results[1] as Array; + log(`queryPerfSampleChildListByTree size : ${samples.length}`); + this.processMap.clear(); + for (let process of processes) { + this.processMap.set(process.pid, process); + } + + this.initPerfSampleData(samples.filter(it => { + if (sampleChildParam.tsArr && sampleChildParam.tsArr.length > 0) { + return sampleChildParam.tsArr.some(ts => it.time === ts) + } + return true; + })); + }); + } + } + + private initPerfSampleData(samples: PerfSample[]): void { + for (let sample of samples) { + let process = this.processMap.get(sample.pid); + sample.processName = + process === null || process === undefined + ? `Process(${sample.pid})` + : `${process!.processName || 'Process'}(${sample.pid})`; + sample.threadName = + sample.threadName === null || sample.threadName === undefined + ? `Thread(${sample.tid})` + : `${sample.threadName}(${sample.tid})`; + sample.coreName = `CPU ${sample.core}`; + sample.timeString = Utils.getTimeString(sample.time); + sample.backtrace = []; + let call = perfDataQuery.callChainMap.get(sample.sampleId); + if (call === undefined || call === null) { + sample.depth = 0; + sample.backtrace.push('No Effective Call Stack'); + } else { + sample.depth = call.depth; + if (typeof call.name === 'number') { + call.name = SpSystemTrace.DATA_DICT.get(call.name) || ''; + } + sample.backtrace.push(call.name); + sample.backtrace.push(`(${sample.depth} other frames)`); + } + } + this.perfSampleSource = samples; + this.sortPerfSampleTable(this.sortKey, this.sortType); + } + + setRightTableData(sample: PerfSample): void { + queryPerfSampleCallChain(sample.sampleId).then((result) => { + for (let stack of result) { + if (stack.sourceId !== undefined) { + stack.sourceFile = SpSystemTrace.DATA_DICT.get(stack.sourceId) || ''; + } + if (typeof stack.symbol === 'number') { + stack.symbol = SpSystemTrace.DATA_DICT.get(stack.symbol) || ''; + } + if (stack.sourceFile && stack.lineNumber !== undefined) { + stack.symbol = `${stack.symbol}[${stack.sourceFile}(${stack.lineNumber})]`; + } + // @ts-ignore + let files = (perfDataQuery.filesData[stack.fileId] ?? []) as Array; + stack.path = files[stack.symbolId]?.path || ''; + stack.type = stack.path.endsWith('.so.1') || stack.path.endsWith('.dll') || stack.path.endsWith('.so') ? 0 : 1; + } + this.tblData!.dataSource = result; + }); + } + + initElements(): void { + this.perfSampleTbl = this.shadowRoot?.querySelector('#tb-perf-sample'); + this.tblData = this.shadowRoot?.querySelector('#tb-stack-data'); + //监听row的点击事件,在对应起始时间上画标记棋子,并设置调用栈数据 + this.perfSampleTbl!.addEventListener('row-click', (e) => { + // @ts-ignore + let data = e.detail.data as PerfSample; + this.setRightTableData(data); + // @ts-ignore + data.isSelected = true; + this.perfSampleTbl!.clearAllSelection(data); + this.perfSampleTbl!.setCurrentSelection(data); + document.dispatchEvent( + new CustomEvent('triangle-flag', { + detail: { time: [data.time], type: 'triangle' }, + }) + ); + }); + this.perfSampleTbl!.addEventListener('column-click', (evt) => { + // @ts-ignore + this.sortKey = evt.detail.key; + // @ts-ignore + this.sortType = evt.detail.sort; + // @ts-ignore + this.sortPerfSampleTable(evt.detail.key, evt.detail.sort); + }); + } + + connectedCallback(): void { + super.connectedCallback(); + new ResizeObserver(() => { + if (this.parentElement?.clientHeight !== 0) { + // @ts-ignore + this.perfSampleTbl?.shadowRoot.querySelector('.table').style.height = `${ + this.parentElement!.clientHeight - 40 + }px`; + // @ts-ignore + this.tblData?.shadowRoot.querySelector('.table').style.height = `${this.parentElement.clientHeight - 25}px`; + this.perfSampleTbl?.reMeauseHeight(); + this.tblData?.reMeauseHeight(); + } + }).observe(this.parentElement!); + } + + sortPerfSampleTable(key: string, type: number): void { + this.perfSampleSource.sort((perfSampleA, perfSampleB): number => { + if (key === 'timeString') { + if (type === 0) { + return perfSampleA.time - perfSampleB.time; + } else if (type === 1) { + return perfSampleA.time - perfSampleB.time; + } else { + return perfSampleB.time - perfSampleA.time; + } + } else { + if (type === 0) { + return perfSampleA.core - perfSampleB.core; + } else if (type === 1) { + return perfSampleA.core - perfSampleB.core; + } else { + return perfSampleB.core - perfSampleA.core; + } + } + }); + this.perfSampleTbl!.recycleDataSource = this.perfSampleSource; + } + + initHtml(): string { + return ` +
    + +
    + + + + + + + + + + + +
    + + + + + + + +
    +
    `; + } +} diff --git a/ide/src/trace/component/trace/sheet/hiperf/TabPerfSampleList.ts b/ide/src/trace/component/trace/sheet/hiperf/TabPerfSampleList.ts index 5397cd4e3b7b4fe8784f0f21d01e19c84585c8ef..49042adb857b9f3337d1fd50ca2093316d6d7ca4 100644 --- a/ide/src/trace/component/trace/sheet/hiperf/TabPerfSampleList.ts +++ b/ide/src/trace/component/trace/sheet/hiperf/TabPerfSampleList.ts @@ -106,9 +106,16 @@ export class TabPanePerfSample extends BaseElement { setRightTableData(sample: PerfSample): void { queryPerfSampleCallChain(sample.sampleId).then((result) => { for (let stack of result) { + if (stack.sourceId !== undefined) { + stack.sourceFile = SpSystemTrace.DATA_DICT.get(stack.sourceId) || ''; + } if (typeof stack.symbol === 'number') { stack.symbol = SpSystemTrace.DATA_DICT.get(stack.symbol) || ''; - } // @ts-ignore + } + if (stack.sourceFile && stack.lineNumber !== undefined) { + stack.symbol = `${stack.symbol}[${stack.sourceFile}(${stack.lineNumber})]`; + } + //@ts-ignore let files = (perfDataQuery.filesData[stack.fileId] ?? []) as Array; stack.path = files[stack.symbolId]?.path || ''; stack.type = stack.path.endsWith('.so.1') || stack.path.endsWith('.dll') || stack.path.endsWith('.so') ? 0 : 1; diff --git a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts index 212d6bd788ce0d79eaf1e97794542d0aafb752a5..83ea5de7bddf9c295c805b07a17bfba0273a09b2 100644 --- a/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts +++ b/ide/src/trace/component/trace/sheet/native-memory/TabPaneNMStatstics.ts @@ -76,11 +76,6 @@ export class TabPaneNMStatstics extends BaseElement { queryData(nativeStatisticsParam: SelectionParam): void { Promise.all([ queryNativeHookStatistics(nativeStatisticsParam.leftNs, nativeStatisticsParam.rightNs, this.currentSelectIPid), - queryNativeHookStatisticsSubType( - nativeStatisticsParam.leftNs, - nativeStatisticsParam.rightNs, - this.currentSelectIPid - ), queryNativeHookStatisticsMalloc( nativeStatisticsParam.leftNs, nativeStatisticsParam.rightNs, @@ -94,7 +89,7 @@ export class TabPaneNMStatstics extends BaseElement { let index3 = nativeStatisticsParam.nativeMemory.indexOf(this.nativeType[2]); this.setMemoryTypeData(nativeStatisticsParam, values[0], arr); if (index1 !== -1 || index3 !== -1) { - this.setSubTypeTableData(values[1], arr); + this.setSubTypeTableData([values[0][1]], arr); } let type = 0; if (index1 !== -1 || (index2 !== -1 && index3 !== -1)) { @@ -102,7 +97,7 @@ export class TabPaneNMStatstics extends BaseElement { } else { type = index2 !== -1 ? 1 : 2; } - this.setMallocTableData(values[2], arr, type); + this.setMallocTableData(values[1], arr, type); this.nativeStatisticsSource = arr; this.sortByColumn(this.sortColumn, this.sortType); }); diff --git a/ide/src/trace/component/trace/sheet/parallel/TabPaneMtParallel.ts b/ide/src/trace/component/trace/sheet/parallel/TabPaneMtParallel.ts index 0da3c2f3efba7d0a0985ec53248143846b38a620..123880cc106f33653ce3fa4974d94b4d8f062a9b 100644 --- a/ide/src/trace/component/trace/sheet/parallel/TabPaneMtParallel.ts +++ b/ide/src/trace/component/trace/sheet/parallel/TabPaneMtParallel.ts @@ -30,9 +30,9 @@ import { Utils } from '../../base/Utils'; const UNIT: number = 1000000.0; const NUM_DIGITS: number = 3; const CORE_NUM: number = 12; -const SMALL_CPU_NUM: Array = [0, 1, 2, 3]; +const LITTLE_CPU_NUM: Array = [0, 1, 2, 3]; const MID_CPU_NUM12: Array = [4, 5, 6, 7, 8, 9]; -const LARGE_CPU_NUM12: Array = [10, 11]; +const BIG_CPU_NUM12: Array = [10, 11]; const CORE_JSON = { 'group1': [4, 5], 'group2': [6, 7], @@ -41,9 +41,9 @@ const CORE_JSON = { }; export class CpuStatus { cpu: number = 0; - small: boolean = false; + little: boolean = false; medium: boolean = false; - large: boolean = false; + big: boolean = false; } @element('tabpane-mt-parallel') export class TabPaneMtParallel extends BaseElement { @@ -57,8 +57,8 @@ export class TabPaneMtParallel extends BaseElement { private leftStartNs: number = 0; private rightEndNs: number = 0; private midCores: Array = []; - private largeCores: Array = []; - private smallCores: Array = []; + private bigCores: Array = []; + private littleCores: Array = []; private isCreateCpu: boolean = true; private isCreateGroup: boolean = true; private coreTypeMap: Map = new Map(); @@ -94,7 +94,7 @@ export class TabPaneMtParallel extends BaseElement { if (this.isCreateCpu) { this.initDefaultConfig(); this.isCreateCpu = false; - this.bottomFilterEl!.setCoreConfigList(Utils.getInstance().getWinCpuCount(), this.smallCores, this.midCores, this.largeCores); + this.bottomFilterEl!.setCoreConfigList(Utils.getInstance().getWinCpuCount(), this.littleCores, this.midCores, this.bigCores); }; }; this.litSettingPopoverEl!.querySelector('.confirm-button')!.addEventListener('click', (e: unknown) => { @@ -171,7 +171,7 @@ export class TabPaneMtParallel extends BaseElement { updateDataSource(flag: boolean): void { let param = flag ? this.bufferGroupMap.size !== 0 : Utils.getInstance().getWinCpuCount() === CORE_NUM; let value = flag ? this.bufferGroupMap : new Map(Object.entries(CORE_JSON)); - if ((this.midCores.length || this.largeCores.length || this.smallCores.length) && param) { + if ((this.midCores.length || this.bigCores.length || this.littleCores.length) && param) { this.coreTypeMap.clear(); this.dataSourceMap.clear(); this.parallelTable!.loading = true; @@ -186,7 +186,7 @@ export class TabPaneMtParallel extends BaseElement { } } async getMtParallelData(obj: Map) :Promise { - let cpuObj: unknown = { 'L': this.largeCores, 'M': this.midCores, 'S': this.smallCores }; + let cpuObj: unknown = { 'B': this.bigCores, 'M': this.midCores, 'L': this.littleCores }; let processIds: Array = [...new Set(this.selectionParam!.processIds)]; for (const [key, cpuGroup] of obj.entries()) { //判断配的的组是否在同一个核分类中,如果在,返回是那个核分类,反之,返回null @@ -238,7 +238,7 @@ export class TabPaneMtParallel extends BaseElement { } //判断自配的相同物理核是否符合计算MT并行度的要求 - handleSamePhysicsCore(arr: unknown, obj: { 'L': Array; 'M': Array; 'S': Array }): string | null { + handleSamePhysicsCore(arr: unknown, obj: { 'B': Array; 'M': Array; 'S': Array }): string | null { let core = null; // @ts-ignore if (arr.length > 2) { return null } @@ -384,13 +384,13 @@ export class TabPaneMtParallel extends BaseElement { initDefaultConfig(): void { if (this.isCreateCpu) { if (Utils.getInstance().getWinCpuCount() === CORE_NUM) { - this.smallCores = [...SMALL_CPU_NUM]; + this.littleCores = [...LITTLE_CPU_NUM]; this.midCores = [...MID_CPU_NUM12]; - this.largeCores = [...LARGE_CPU_NUM12]; + this.bigCores = [...BIG_CPU_NUM12]; } else { - this.smallCores = []; + this.littleCores = []; this.midCores = []; - this.largeCores = []; + this.bigCores = []; } } } @@ -424,7 +424,7 @@ export class TabPaneMtParallel extends BaseElement { disabled: Utils.getInstance().getWinCpuCount() === CORE_NUM && str !== 'cut' && this.isReset ? !(switchArr.includes(i)) : - !([...this.smallCores, ...this.midCores, ...this.largeCores].includes(i)) + !([...this.littleCores, ...this.midCores, ...this.bigCores].includes(i)) }; this.creatGroupLineDIv(obj); } diff --git a/ide/src/trace/component/trace/sheet/parallel/TabPaneTimeParallel.ts b/ide/src/trace/component/trace/sheet/parallel/TabPaneTimeParallel.ts index 4e0acbdd625193fe7d73682b33df7f43203ea64c..34535d254b4abe62ccaba5234da14c38c1117bbc 100644 --- a/ide/src/trace/component/trace/sheet/parallel/TabPaneTimeParallel.ts +++ b/ide/src/trace/component/trace/sheet/parallel/TabPaneTimeParallel.ts @@ -29,9 +29,9 @@ import { Utils } from '../../base/Utils'; const UNIT: number = 1000000.0; const NUM_DIGITS: number = 3; const CORE_NUM: number = 12; -const SMALL_CPU_NUM: Array = [0, 1, 2, 3]; +const LITTLE_CPU_NUM: Array = [0, 1, 2, 3]; const MID_CPU_NUM12: Array = [4, 5, 6, 7, 8, 9]; -const LARGE_CPU_NUM12: Array = [10, 11]; +const BIG_CPU_NUM12: Array = [10, 11]; @element('tabpane-time-parallel') export class TabPaneTimeParallel extends BaseElement { @@ -44,8 +44,8 @@ export class TabPaneTimeParallel extends BaseElement { private leftStartNs: number = 0; private rightEndNs: number = 0; private midCores: Array = []; - private largeCores: Array = []; - private smallCores: Array = []; + private bigCores: Array = []; + private littleCores: Array = []; private initStatus: boolean = true; set data(threadStatesParam: SelectionParam) { @@ -70,7 +70,7 @@ export class TabPaneTimeParallel extends BaseElement { if (this.initStatus) { this.initDefaultConfig(); this.initStatus = false; - this.bottomFilterEl!.setCoreConfigList(Utils.getInstance().getWinCpuCount(), this.smallCores, this.midCores, this.largeCores); + this.bottomFilterEl!.setCoreConfigList(Utils.getInstance().getWinCpuCount(), this.littleCores, this.midCores, this.bigCores); } }; this.litPopoverEl!.querySelector('.confirm-button')!.addEventListener('click', (e: unknown) => { @@ -85,7 +85,7 @@ export class TabPaneTimeParallel extends BaseElement { // @ts-ignore this.litPopoverEl!.visible = false; //当大中小核未分组时,默认查询所有核 - if (!this.midCores.length && !this.largeCores.length && !this.smallCores.length) { + if (!this.midCores.length && !this.bigCores.length && !this.littleCores.length) { this.assignAllCore(); } else { this.assignGroupCore(); @@ -142,13 +142,13 @@ export class TabPaneTimeParallel extends BaseElement { initDefaultConfig(): void { if (this.initStatus) { if (Utils.getInstance().getWinCpuCount() === CORE_NUM) { - this.smallCores = [...SMALL_CPU_NUM]; + this.littleCores = [...LITTLE_CPU_NUM]; this.midCores = [...MID_CPU_NUM12]; - this.largeCores = [...LARGE_CPU_NUM12]; + this.bigCores = [...BIG_CPU_NUM12]; } else { - this.smallCores = []; + this.littleCores = []; this.midCores = []; - this.largeCores = []; + this.bigCores = []; } } } @@ -166,9 +166,9 @@ export class TabPaneTimeParallel extends BaseElement { let dataSourceMap: Map = new Map(); let processIds: Array = [...new Set(this.selectionParam!.processIds)]; let cpuObj: Object = { - 'L': this.largeCores, + 'B': this.bigCores, 'M': this.midCores, - 'S': this.smallCores + 'L': this.littleCores }; for (const [key, val] of Object.entries(cpuObj)) { if (val.length) { diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSliceChild.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSliceChild.ts index e75097d1ddeacdf678056a825c76d442d759ffe3..c8e6916c30af4d9c7b25856b32e51fefe0aa2e42 100644 --- a/ide/src/trace/component/trace/sheet/process/TabPaneSliceChild.ts +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSliceChild.ts @@ -37,8 +37,10 @@ export class TabPaneSliceChild extends BaseElement { //合并SF异步信息,相同pid和tid的name let sfAsyncFuncMap: Map = new Map(); let filterSfAsyncFuncName = boxChildValue.selection!.funAsync; - if (!boxChildValue.param.isSummary!) { - filterSfAsyncFuncName = filterSfAsyncFuncName.filter((item) => item.name === boxChildValue.param.name![0]); + if (boxChildValue.param.name) { + filterSfAsyncFuncName = filterSfAsyncFuncName.filter((item) => + boxChildValue.param.name?.some((boxItem) => item.name === boxItem) + ); } filterSfAsyncFuncName.forEach((it: { name: string; pid: number, tid: number | undefined }) => { if (sfAsyncFuncMap.has(`${it.pid}-${it.tid}`)) { diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSysCall.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSysCall.ts new file mode 100644 index 0000000000000000000000000000000000000000..45304351a00f0c8b278193f78461856d7c56a0d0 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSysCall.ts @@ -0,0 +1,243 @@ +/* + * 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 { LitTable } from '../../../../../base-ui/table/lit-table'; +import { SelectionParam } from '../../../../bean/BoxSelection'; +import { log } from '../../../../../log/Log'; +import { getProbablyTime } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon'; +import { resizeObserver } from '../SheetUtils'; +import { querySysCallEventWithBoxSelect } from '../../../../database/sql/ProcessThread.sql'; +import { Utils } from '../../base/Utils'; +import { SysCallMap } from '../../base/SysCallUtils'; + +interface SysCallItem { + nameId: number; + name: string; + pName: string; + tName: string; + tid: number; + pid: number; + totalCount: number; + sumDur: number; + durStr?: string; +} + +interface SysCallTreeItem { + name: string; + id: number; + parentId?: number; + totalCount: number; + sumDur: number; + durStr: string; + level: string; + children: SysCallTreeItem[] +} + +@element('tabpane-syscall') +export class TabPaneSysCall extends BaseElement { + private sysCallTbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private sysCallSource: Array = []; + private currentSelectionParam: SelectionParam | undefined; + + set data(sysCallParam: SelectionParam | unknown) { + if (this.currentSelectionParam === sysCallParam) { + return; + } // @ts-ignore + this.currentSelectionParam = sysCallParam; + //@ts-ignore + this.sysCallTbl?.shadowRoot?.querySelector('.table')?.style?.height = `${this.parentElement!.clientHeight - 45}px`; // @ts-ignore + this.range!.textContent = `Selected range: ${((sysCallParam.rightNs - sysCallParam.leftNs) / 1000000.0).toFixed( + 5 + )} ms`; + this.sysCallTbl!.loading = true; + let ipidArr: number[] = []; + Array.from(Utils.getInstance().sysCallEventTidsMap.values()).forEach(it => { + //@ts-ignore + if (sysCallParam?.processSysCallIds?.includes(it.pid)) { + ipidArr.push(it.ipid); + } + }) + //@ts-ignore + querySysCallEventWithBoxSelect(ipidArr, sysCallParam.threadSysCallIds, sysCallParam.leftNs, sysCallParam.rightNs).then( + (retult) => { + this.flatternToTree(retult as SysCallItem[]); + } + ); + } + + private flatternToTree(result: SysCallItem[]): void { + this.sysCallTbl!.loading = false; + if (result !== null && result.length > 0) { + log(`getTabsysCalls result size : ${result.length}`); + let map: Map = new Map(); + result.forEach((item) => { + item.name = SysCallMap.get(item.nameId) || ''; + item.durStr = getProbablyTime(item.sumDur); + this.processSysCallItem(item, map); + }); + let sysCalls: SysCallTreeItem[] = Array.from(map.values()); + this.sysCallSource = sysCalls; + this.sysCallTbl!.recycleDataSource = this.sysCallSource; + } else { + this.sysCallSource = []; + this.sysCallTbl!.recycleDataSource = []; + } + } + + private processSysCallItem(item: SysCallItem, map: Map): void { + const treeItem: SysCallTreeItem = { + id: item.nameId, + name: item.name, + level: 'SysCall', + parentId: item.tid, + totalCount: item.totalCount, + sumDur: item.sumDur, + durStr: item.durStr!, + children:[] + }; + let ps = map.get(item.pid!); + if (ps) { + ps.sumDur += item.sumDur || 0; + ps.durStr = getProbablyTime(ps.sumDur); + ps.totalCount += item.totalCount || 0; + let ts = ps.children?.find(it => it.id === item.tid); + if (ts) { + ts.sumDur += item.sumDur || 0; + ts.durStr = getProbablyTime(ts.sumDur); + ts.totalCount += item.totalCount || 0; + ts.children.push(treeItem); + } else { + ps.children.push({ + id: item.tid, + name: item.tName, + parentId: item.pid, + level: 'Thread', + totalCount: item.totalCount, + sumDur: item.sumDur, + durStr: item.durStr!, + children: [treeItem] + }) + } + } else { + map.set(item.pid!, { + id: item.pid, + level: 'Process', + name: `${item.pName} [${item.pid}]`, + totalCount: item.totalCount, + sumDur: item.sumDur, + durStr: item.durStr!, + children: [{ + id: item.tid, + level: 'Thread', + parentId: item.pid, + name: `${item.tName} [${item.tid}]`, + durStr: item.durStr!, + totalCount: item.totalCount, + sumDur: item.sumDur, + children: [treeItem] + }] + }); + } + } + + initElements(): void { + this.sysCallTbl = this.shadowRoot?.querySelector('#tb-syscall'); + this.range = this.shadowRoot?.querySelector('#syscall-time-range'); + this.sysCallTbl!.addEventListener('column-click', (evt: unknown) => { + // @ts-ignore + this.sortByColumn(evt.detail); + }); + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.sysCallTbl!); + } + + initHtml(): string { + return ` + +
    +
    + +
    +
    + + + + + + + + +
    + `; + } + + sortByColumn(sortDetail: unknown): void { + let compare = (itemA: SysCallTreeItem, itemB: SysCallTreeItem): number => { + // @ts-ignore + if (sortDetail.key === 'durStr') { + // @ts-ignore + if (sortDetail.sort === 0) { + return itemA.sumDur - itemB.sumDur; // @ts-ignore + } else if (sortDetail.sort === 1) { + return itemA.sumDur - itemB.sumDur; + } else { + return itemB.sumDur - itemA.sumDur; + } + } else { + // @ts-ignore + if (sortDetail.sort === 0) { + return itemA.totalCount - itemB.totalCount; // @ts-ignore + } else if (sortDetail.sort === 1) { + return itemA.totalCount - itemB.totalCount; + } else { + return itemB.totalCount - itemA.totalCount; + } + } + }; + this.sysCallSource.forEach((syscall) => { + syscall.children?.sort(compare); + }); + const deepSort = (arr: SysCallTreeItem[]) => { + arr.sort(compare); + arr.forEach(item => { + if (item.children) { + deepSort(item.children); + } + }) + }; + deepSort(this.sysCallSource); + this.sysCallTbl!.recycleDataSource = this.sysCallSource; + } +} diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSysCallChild.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSysCallChild.ts new file mode 100644 index 0000000000000000000000000000000000000000..5b9317457edb19db54ab5b824dba38f8c756d0e0 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSysCallChild.ts @@ -0,0 +1,195 @@ +/* + * 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 { LitTable } from '../../../../../base-ui/table/lit-table'; +import { SysCallBoxJumpParam, SelectionData } from '../../../../bean/BoxSelection'; +import { Utils } from '../../base/Utils'; +import { resizeObserver } from '../SheetUtils'; +import { querySysCallEventWithRange } from '../../../../database/sql/ProcessThread.sql'; +import { SysCallMap } from '../../base/SysCallUtils'; + +interface SysCallChildItem { + pName: string; + tName: string; + pid: number; + tid: number; + nameId: number; + name: string; + startTs: string; + startTime: number; + absoluteTs: number; + dur: number; + args: string; + ret: number +} + +@element('tabpane-syscall-child') +export class TabPaneSysCallChild extends BaseElement { + private boxChildTbl: LitTable | null | undefined; + private boxChildRange: HTMLLabelElement | null | undefined; + private boxChildSource: Array = []; + private boxChildParam: SysCallBoxJumpParam | null | undefined; + + set data(boxChildValue: SysCallBoxJumpParam) { + //切换Tab页 保持childTab数据不变 除非重新点击跳转 + if (boxChildValue === this.boxChildParam || !boxChildValue.isJumpPage) { + return; + } // @ts-ignore + this.boxChildParam = boxChildValue; + //显示框选范围对应的时间 + this.boxChildRange!.textContent = `Selected range: ${parseFloat( + ((boxChildValue.rightNs - boxChildValue.leftNs) / 1000000.0).toFixed(5) + )} ms`; + this.boxChildTbl!.recycleDataSource = []; + this.getDataByDB(boxChildValue); + } + + initElements(): void { + this.boxChildTbl = this.shadowRoot?.querySelector('#tb-syscall-child'); + this.boxChildRange = this.shadowRoot?.querySelector('#time-range'); + this.boxChildTbl!.addEventListener('column-click', (evt): void => { + // @ts-ignore + this.sortByColumn(evt.detail); + }); + //监听row的点击事件,在对应起始时间上画标记棋子 + this.boxChildTbl!.addEventListener('row-click', (evt): void => { + //@ts-ignore + let param = evt.detail.data; + param.isSelected = true; + this.boxChildTbl!.clearAllSelection(param); + this.boxChildTbl!.setCurrentSelection(param); + document.dispatchEvent( + new CustomEvent('triangle-flag', { + detail: { time: [param.startTime], type: 'triangle' }, + }) + ); + }); + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.boxChildTbl!); + } + + getDataByDB(val: SysCallBoxJumpParam): void { + this.boxChildTbl!.loading = true; + let ipidArr: number[] = []; + let itidArr: number[] = []; + Array.from(Utils.getInstance().sysCallEventTidsMap.values()).forEach(it => { + if (val?.processId?.includes(it.pid)) { + ipidArr.push(it.ipid); + } + if (val?.threadId?.includes(it.tid)) { + itidArr.push(it.itid); + } + }); + querySysCallEventWithRange(ipidArr, itidArr, val.leftNs, val.rightNs, val.sysCallId).then(result => { + this.boxChildTbl!.loading = false; + const arr: Array = []; + result.forEach(it => { + arr.push({ + pName: it.pName, + tName: it.tName, + pid: it.pid, + tid: it.tid, + name: SysCallMap.get(it.nameId) || 'unknown event', + nameId: it.nameId, + startTime: it.startTs, + startTs: Utils.getProbablyTime(it.startTs), + // @ts-ignore + absoluteTs: ((window as unknown).recordStartNS + it.startTs) / 1000000000, + dur: it.dur / 1000000, + args: it.args, + ret: it.ret + }); + }); + this.boxChildSource = arr; + if (this.boxChildTbl) { + // @ts-ignore + this.boxChildTbl.recycleDataSource = arr; + } + }); + } + + initHtml(): string { + return ` + + +
    + + + + + + + + + + + + + + + + + + +
    + `; + } + + sortByColumn(detail: unknown): void { + // @ts-ignore + function compare(property, sort, type) { + return function (boxChildLeftData: SelectionData, boxChildRightData: SelectionData): number { + if (type === 'number') { + return sort === 2 + // @ts-ignore + ? parseFloat(boxChildRightData[property]) - parseFloat(boxChildLeftData[property]) + // @ts-ignore + : parseFloat(boxChildLeftData[property]) - parseFloat(boxChildRightData[property]); + } else { + // @ts-ignore + if (boxChildRightData[property] > boxChildLeftData[property]) { + return sort === 2 ? 1 : -1; + } else { + // @ts-ignore + if (boxChildRightData[property] === boxChildLeftData[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + }; + } + + // @ts-ignore + this.boxChildSource.sort(compare(detail.key, detail.sort, 'string')); + this.boxChildTbl!.recycleDataSource = this.boxChildSource; + } +} diff --git a/ide/src/trace/database/TraceWorker.ts b/ide/src/trace/database/TraceWorker.ts index 1923ed8af5c7a7984547128917d8c0033d2416ae..ed200f885dd0ae7b17966a7b5088c47af7aea7ec 100644 --- a/ide/src/trace/database/TraceWorker.ts +++ b/ide/src/trace/database/TraceWorker.ts @@ -313,6 +313,7 @@ function initModuleCallBackAndFun(): void { let tlvResultCallback = (heapPtr: number, size: number, type: number, isEnd: number): void => { //@ts-ignore let out: Uint8Array = wasmModule.HEAPU8.slice(heapPtr, heapPtr + size); + //@ts-ignore protoDataMap.set(type, BatchSphData.decode(out).values); }; //@ts-ignore @@ -332,7 +333,7 @@ function parseThirdWasmByOpenAction(e: MessageEvent): void { if (parseConfig !== '') { let parseConfigArray = enc.encode(parseConfig); //@ts-ignore - let parseConfigAddr = wasmModule._InitializeParseConfig(1024); + let parseConfigAddr = wasmModule._InitializeParseConfig(parseConfigArray.length); //@ts-ignore wasmModule.HEAPU8.set(parseConfigArray, parseConfigAddr); //@ts-ignore diff --git a/ide/src/trace/database/data-trafic/ClockDataReceiver.ts b/ide/src/trace/database/data-trafic/ClockDataReceiver.ts index 003775fb86bb8cf593fb595d2f0ae70472ee6df5..30d84c997aa9f7dfe364cc85d4067aa8ef4ca2d5 100644 --- a/ide/src/trace/database/data-trafic/ClockDataReceiver.ts +++ b/ide/src/trace/database/data-trafic/ClockDataReceiver.ts @@ -63,10 +63,15 @@ export const chartClockDataSql = (args: Args): string => { export const chartClockDataSqlMem = (args: Args): string => { if (args.sqlType === 'clockFrequency') { return ` - with freq as ( select measure.filter_id, measure.ts, measure.type, measure.value from clock_event_filter - left join measure - where clock_event_filter.name = '${args.clockName}' and clock_event_filter.type = 'clock_set_rate' and clock_event_filter.id = measure.filter_id - order by measure.ts) + with freq as ( select + m.filter_id, + m.ts, + m.type, + m.value from clock_event_filter as c + left join measure as m on c.id = m.filter_id + where c.name = '${args.clockName}' + and c.type = 'clock_set_rate' + order by m.ts) select freq.filter_id as filterId,freq.ts - r.start_ts as startNs,freq.type,freq.value from freq,trace_range r order by startNs; `; } else if (args.sqlType === 'clockState') { diff --git a/ide/src/trace/database/data-trafic/process/ThreadSysCallDataReceiver.ts b/ide/src/trace/database/data-trafic/process/ThreadSysCallDataReceiver.ts new file mode 100644 index 0000000000000000000000000000000000000000..8001f4c08111bf0f120ccaffb043d150ea3f9308 --- /dev/null +++ b/ide/src/trace/database/data-trafic/process/ThreadSysCallDataReceiver.ts @@ -0,0 +1,92 @@ +// Copyright (c) 2021 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 { Args } from '../CommonArgs'; +import { threadSysCallList } from '../utils/AllMemoryCache'; +import { filterDataByGroup } from '../utils/DataFilter'; +import { TraficEnum } from '../utils/QueryEnum'; + +export const chartThreadSysCallDataSql = (args: Args):unknown => { + return `SELECT syscall_number as id, itid, ts - ${args.recordStartNS} as startTs, max(dur) as dur, + ((ts - ${args.recordStartNS}) / (${Math.floor((args.endNS - args.startNS) / args.width)})) AS px + from syscall + where itid = ${args.itid} + and startTs + dur >= ${Math.floor(args.startNS)} + and startTs <= ${Math.floor(args.endNS)} + group by px + `; +}; + +export const sysCallMemSql = (args: Args): unknown => { + return `select syscall_number as id, (ts - ${args.recordStartNS}) as startTs, dur from syscall where itid = ${args.itid}` +} + +export function threadSysCallDataReceiver(data: unknown, proc: Function): void { + //@ts-ignore + let itid: number = data.params.itid; + let arr: unknown[] = []; + if (threadSysCallList.has(itid)) { + arr = threadSysCallList.get(itid) || []; + } else { + //@ts-ignore + let sql = sysCallMemSql(data.params); + arr = proc(sql); //@ts-ignore + threadSysCallList.set(itid, arr); + } + let res = filterDataByGroup( + arr, + 'startTs', + 'dur', //@ts-ignore + data.params.startNS, //@ts-ignore + data.params.endNS, //@ts-ignore + data.params.width + ); + arrayBufferHandler(data, res, true, false); +} + +function arrayBufferHandler(data: unknown, res: unknown[], transfer: boolean, isEmpty: boolean): void { + //@ts-ignore + let startTs = new Float64Array(res.length); //@ts-ignore + let dur = new Float64Array(res.length); //@ts-ignore + let id = new Int32Array(res.length); //@ts-ignore + let itid = new Int32Array(res.length); //@ts-ignore + res.forEach((it, i) => { + //@ts-ignore + data.params.trafic === TraficEnum.ProtoBuffer && (it = it.processThreadSysCallData); //@ts-ignore + startTs[i] = it.startTs; //@ts-ignore + dur[i] = it.dur; //@ts-ignore + id[i] = it.id; //@ts-ignore + itid[i] = data.params.itid; //@ts-ignore + }); + (self as unknown as Worker).postMessage( + { + //@ts-ignore + id: data.id, //@ts-ignorew + action: data.action, + results: transfer + ? { + id: id.buffer, + itid: itid.buffer, + startTs: startTs.buffer, + dur: dur.buffer, + } + : {}, + len: res.length, + transfer: transfer, + isEmpty: isEmpty, + }, + transfer + ? [startTs.buffer, dur.buffer, id.buffer, itid.buffer] + : [] + ); +} diff --git a/ide/src/trace/database/data-trafic/process/ThreadSysCallDataSender.ts b/ide/src/trace/database/data-trafic/process/ThreadSysCallDataSender.ts new file mode 100644 index 0000000000000000000000000000000000000000..f874b4f4ca6385924906ca006a5e59dce5bc1ca2 --- /dev/null +++ b/ide/src/trace/database/data-trafic/process/ThreadSysCallDataSender.ts @@ -0,0 +1,82 @@ +// Copyright (c) 2021 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 { CHART_OFFSET_LEFT, MAX_COUNT, QueryEnum, TraficEnum } from '../utils/QueryEnum'; +import { getThreadPool } from '../../SqlLite'; +import { TraceRow } from '../../../component/trace/base/TraceRow'; +import { SysCallMap } from '../../../component/trace/base/SysCallUtils'; +import { Utils } from '../../../component/trace/base/Utils'; +import { ThreadSysCallStruct } from '../../ui-worker/ProcedureWorkerThreadSysCall'; + +export function threadSysCallDataSender( + itid: number, + tid: number, + pid: number, + row: TraceRow, + traceId?: string +): Promise { + let trafic: number = TraficEnum.Memory; + let width = row.clientWidth || row.parentRowEl!.clientWidth - CHART_OFFSET_LEFT; + if (trafic === TraficEnum.SharedArrayBuffer && !row.sharedArrayBuffers) { + row.sharedArrayBuffers = { + startTs: new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * MAX_COUNT), + dur: new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * MAX_COUNT), + id: new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * MAX_COUNT), + itid: new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * MAX_COUNT), + ipid: new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * MAX_COUNT), + }; + } + return new Promise((resolve): void => { + getThreadPool(traceId).submitProto( + QueryEnum.ThreadDataSysCall, + { + itid: itid, + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + recordStartNS: Utils.getInstance().getRecordStartNS(traceId), + recordEndNS: Utils.getInstance().getRecordEndNS(traceId), + width: width, + trafic: trafic, + sharedArrayBuffers: row.sharedArrayBuffers, + }, + (res: unknown, len: number, transfer: boolean, isEmpty: boolean): void => { + if (isEmpty) { + resolve(true); + } else { + resolve(arrayBufferHandler(transfer ? res : row.sharedArrayBuffers, len, tid, pid)); + } + } + ); + }); +} + +function arrayBufferHandler(buffers: unknown, len: number, tid: number, pid: number): ThreadSysCallStruct[] { + let outArr: ThreadSysCallStruct[] = []; //@ts-ignore + let startTs = new Float64Array(buffers.startTs); //@ts-ignore + let dur = new Float64Array(buffers.dur); //@ts-ignore + let id = new Int32Array(buffers.id); //@ts-ignore + let itid = new Int32Array(buffers.itid); //@ts-ignore + for (let i = 0; i < len; i++) { + //@ts-ignore + outArr.push({ + startTs: startTs[i], + dur: dur[i], + id: id[i], + itid: itid[i], + name: SysCallMap.get(id[i]) || 'unknown event', + tid: tid, + pid: pid, + } as ThreadSysCallStruct); + } + return outArr; +} diff --git a/ide/src/trace/database/data-trafic/utils/AllMemoryCache.ts b/ide/src/trace/database/data-trafic/utils/AllMemoryCache.ts index d73f3e6f25769a350b560909750efdc2e77167f6..3abdb0f6ad21e7491b200d9afda7e7d321deb0ad 100644 --- a/ide/src/trace/database/data-trafic/utils/AllMemoryCache.ts +++ b/ide/src/trace/database/data-trafic/utils/AllMemoryCache.ts @@ -47,6 +47,8 @@ export const processList: Map> = new Map(); export const memList: Map> = new Map(); //线程状态 泳道图 memory 模式缓存 export const threadStateList: Map> = new Map(); +//线程系统调用 泳道图 memory数据缓存 +export const threadSysCallList: Map> = new Map(); //进程下卡顿丢帧 泳道图 memory 模式缓存 export const processFrameList: Map> = new Map(); //hiSysEvent 泳道图 memory 模式缓存 @@ -78,6 +80,7 @@ export function clearMemoryCache(data: unknown, proc: Function): void { processList.clear(); memList.clear(); threadStateList.clear(); + threadSysCallList.clear(); processFrameList.clear(); lostFrameList.clear(); hitchTimeList.clear(); diff --git a/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts b/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts index 5531a9f3d4c4a83cb72837956223289356a7ee2c..f551dee718bbe1c46e18b2ab62f364357ad496c8 100644 --- a/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts +++ b/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts @@ -87,6 +87,7 @@ import { hangDataReceiver } from '../HangDataReceiver'; import { xpowerStatisticDataReceiver } from '../xpower/XpowerStatisticDataReceiver'; import { xpowerDataGpuFreqCountReceiver, xpowerDataGpuFreqReceiver } from '../xpower/XpowerGpuFrequencyRecevier'; import { xpowerDataThreadCountReceiver, xpowerDataThreadInfoReceiver } from '../xpower/XpowerThreadReceiver'; +import { threadSysCallDataReceiver } from '../process/ThreadSysCallDataReceiver'; // @ts-ignore const traficHandlers: Map = new Map([]); // @ts-ignore @@ -100,6 +101,7 @@ traficHandlers.set(QueryEnum.CpuStateData, cpuStateReceiver); traficHandlers.set(QueryEnum.CpuFreqLimitData, cpuFreqLimitReceiver); traficHandlers.set(QueryEnum.ProcessData, processDataReceiver); traficHandlers.set(QueryEnum.ThreadData, threadDataReceiver); +traficHandlers.set(QueryEnum.ThreadDataSysCall, threadSysCallDataReceiver); traficHandlers.set(QueryEnum.FuncData, funcDataReceiver); traficHandlers.set(QueryEnum.HiperfCallChart, hiPerfCallChartDataHandler); traficHandlers.set(QueryEnum.HiperfCallStack, hiPerfCallStackCacheHandler); diff --git a/ide/src/trace/database/data-trafic/utils/QueryEnum.ts b/ide/src/trace/database/data-trafic/utils/QueryEnum.ts index f50d855c826233e00e3d61d82a8e716ad4df8ee9..e5cd437539e63894c498d967baff3e1bc2c8f10d 100644 --- a/ide/src/trace/database/data-trafic/utils/QueryEnum.ts +++ b/ide/src/trace/database/data-trafic/utils/QueryEnum.ts @@ -98,8 +98,8 @@ export enum QueryEnum { XpowerGpuFreqData = 308, XpowerStatisticData = 309, XpowerWifiData = 310, - XpowerAppDetailData = 311 - + XpowerAppDetailData = 311, + ThreadDataSysCall = 312, } export const MAX_COUNT = 2000; export enum TraficEnum { diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts index ade2ef7987bd95aca3f9f224df00de9112cca238..814c862e551d3dc4833f55f21ae0575e6452a22f 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts @@ -1449,10 +1449,13 @@ export class ProcedureLogicWorkerPerf extends LogicHandler { combineCallChainForAnalysis(obj?: unknown): PerfAnalysisSample[] { let sampleCallChainList: Array = []; for (let sample of this.samplesData) { + if (!this.callChainData[sample.sampleId]) { + continue; + } let callChains = [...this.callChainData[sample.sampleId]]; const lastCallChain = callChains[callChains.length - 1]; const threadName = this.threadData[sample.tid].threadName || 'Thread'; - const processName = this.threadData[sample.pid].threadName || 'Process'; + const processName = this.threadData[sample.pid] ? this.threadData[sample.pid].threadName : 'Process'; const funcName = this.dataCache.dataDict.get(lastCallChain.name as number); if ( //@ts-ignore diff --git a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerSchedulingAnalysis.ts b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerSchedulingAnalysis.ts index 9533835a02198a69d0f053a5c2ddb74dac181458..5c3af47bb028cfa20c181e82f223bee1d2d12068 100644 --- a/ide/src/trace/database/logic-worker/ProcedureLogicWorkerSchedulingAnalysis.ts +++ b/ide/src/trace/database/logic-worker/ProcedureLogicWorkerSchedulingAnalysis.ts @@ -24,7 +24,7 @@ export class ProcedureLogicWorkerSchedulingAnalysis extends LogicHandler { freq: number = 0; bigCores: Array = []; midCores: Array = []; - smallCores: Array = []; + littleCores: Array = []; cpuFreqMap: Map> = new Map>(); cpuIdle0Map: Map> = new Map>(); threadMap: Map = new Map(); @@ -34,7 +34,7 @@ export class ProcedureLogicWorkerSchedulingAnalysis extends LogicHandler { clearAll(): void { this.bigCores.length = 0; this.midCores.length = 0; - this.smallCores.length = 0; + this.littleCores.length = 0; this.cpuAnalysisMap.clear(); this.threadMap.clear(); this.processMap.clear(); @@ -283,9 +283,9 @@ export class ProcedureLogicWorkerSchedulingAnalysis extends LogicHandler { //@ts-ignore this.midCores = data.params.midCores || []; //@ts-ignore - this.smallCores = data.params.smallCores || []; + this.littleCores = data.params.littleCores || []; //@ts-ignore - this.queryThreadCpuUsage(data.params.bigCores || [], data.params.midCores || [], data.params.smallCores || []); + this.queryThreadCpuUsage(data.params.bigCores || [], data.params.midCores || [], data.params.littleCores || []); } } private schedulingThreadRunTime(data: { id: string; action: string; params: unknown }): void { @@ -526,7 +526,7 @@ where cmf.name = 'cpu_idle' and value != 0 ); } - queryThreadCpuUsage(bigCores: number[], midCores: number[], smallCores: number[]): void { + queryThreadCpuUsage(bigCores: number[], midCores: number[], littleCores: number[]): void { let sql = ` select A.pid,A.tid,A.cpu, sum(A.dur) as total @@ -919,7 +919,7 @@ where cpu not null }) .slice(0, 20); } - private filterThreadCpuUsageArr(arr: unknown, sumBig: number, sumMid: number, sumSmall: number): void { + private filterThreadCpuUsageArr(arr: unknown, sumBig: number, sumMid: number, sumLittle: number): void { //@ts-ignore return arr.reduce((group: unknown, item: { total: number; pid: number; tid: number; cpu: number }) => { const { tid } = item; @@ -934,9 +934,9 @@ where cpu not null cpuType = 'mid'; sumMid += item.total; } - if (this.smallCores.includes(item.cpu)) { - cpuType = 'small'; - sumSmall += item.total; + if (this.littleCores.includes(item.cpu)) { + cpuType = 'little'; + sumLittle += item.total; } if (tidObj) { //@ts-ignore @@ -944,7 +944,7 @@ where cpu not null //@ts-ignore tidObj.mid += cpuType === 'mid' ? item.total : 0; //@ts-ignore - tidObj.small += cpuType === 'small' ? item.total : 0; + tidObj.little += cpuType === 'little' ? item.total : 0; //@ts-ignore tidObj.total += item.total; //@ts-ignore @@ -959,7 +959,7 @@ where cpu not null total: item.total, big: cpuType === 'big' ? item.total : 0, mid: cpuType === 'mid' ? item.total : 0, - small: cpuType === 'small' ? item.total : 0, + little: cpuType === 'little' ? item.total : 0, }; //@ts-ignore group[`${tid}`][`cpu${item.cpu}`] = item.total; @@ -971,8 +971,8 @@ where cpu not null private handlerThreadCpuUsageData(arr: Array): Map { let sumBig = 0; let sumMid = 0; - let sumSmall = 0; - let reduceObj = this.filterThreadCpuUsageArr(arr, sumBig, sumMid, sumSmall); + let sumLittle = 0; + let reduceObj = this.filterThreadCpuUsageArr(arr, sumBig, sumMid, sumLittle); // @ts-ignore let source: unknown[] = Object.values(reduceObj); for (let obj of source) { @@ -981,13 +981,13 @@ where cpu not null // @ts-ignore obj.midPercent = sumMid === 0 ? '0' : ((obj.mid / sumMid) * 100).toFixed(2); // @ts-ignore - obj.smallPercent = sumSmall === 0 ? '0' : ((obj.small / sumSmall) * 100).toFixed(2); + obj.littlePercent = sumLittle === 0 ? '0' : ((obj.little / sumLittle) * 100).toFixed(2); // @ts-ignore obj.bigTimeStr = getProbablyTime(obj.big); // @ts-ignore obj.midTimeStr = getProbablyTime(obj.mid); // @ts-ignore - obj.smallTimeStr = getProbablyTime(obj.small); + obj.littleTimeStr = getProbablyTime(obj.little); } let map: Map> = new Map>(); // @ts-ignore @@ -997,7 +997,7 @@ where cpu not null // @ts-ignore map.set('mid', source.sort((a, b) => b.mid - a.mid).slice(0, 20)); // @ts-ignore - map.set('small', source.sort((a, b) => b.small - a.small).slice(0, 20)); + map.set('little', source.sort((a, b) => b.little - a.little).slice(0, 20)); // @ts-ignore return map; } @@ -1115,13 +1115,13 @@ export class ThreadCpuUsage { total: number = 0; big: number = 0; mid: number = 0; - small: number = 0; + little: number = 0; bigPercent: string = ''; bigTimeStr: string = ''; midPercent: string = ''; midTimeStr: string = ''; - smallPercent: string = ''; - smallTimeStr: string = ''; + littlePercent: string = ''; + littleTimeStr: string = ''; } export class FreqThread { diff --git a/ide/src/trace/database/sql/Func.sql.ts b/ide/src/trace/database/sql/Func.sql.ts index d99a23090d963a890c553b682cb8c42cf6b256e6..f9ca8595cc8e109af7bcc7bcdcd4dee04103112d 100644 --- a/ide/src/trace/database/sql/Func.sql.ts +++ b/ide/src/trace/database/sql/Func.sql.ts @@ -152,14 +152,19 @@ export const queryProcessAsyncFunc = ( P.pid, c.ts-${traceRange.startTs} as startTs, c.dur, - c.cat, + c.custom_category as category, c.id, c.depth, c.argsetid, - c.cookie + c.cookie, + c.trace_level, + c.trace_tag, + c.custom_args, + c.child_callid FROM - (SELECT id, ts, parent_id, dur, depth, argsetid, cookie, cat from callstack where cookie NOT NULL) c - LEFT JOIN thread A ON A.id = c.parent_id + (SELECT id, ts, parent_id, dur, depth, argsetid, cookie, custom_category, child_callid, trace_level, + trace_tag, custom_args from callstack where cookie NOT NULL) c + LEFT JOIN thread A ON A.id = c.child_callid LEFT JOIN process P ON P.id = A.ipid WHERE startTs NOT NULL;`, @@ -179,21 +184,26 @@ export const queryProcessAsyncFuncCat = ( select A.tid, P.pid, - c.cat as threadName, + c.custom_category as threadName, c.name as funName, c.ts-${traceRange.startTs} as startTs, c.dur, c.depth, - c.cookie + c.cookie, + c.trace_level, + c.trace_tag, + c.custom_args, + c.child_callid from - (select callid, name, ts, dur, cat, depth, cookie, parent_id from callstack where cookie not null and cat not null and parent_id is null) C + (select callid, name, ts, dur, custom_category, depth, cookie, parent_id,trace_level,trace_tag, + custom_args,child_callid from callstack where cookie not null and custom_category not null and child_callid is null) c left join - thread A on A.id = C.callid + thread A on A.id = c.callid left join process P on P.id = A.ipid where startTs not null - order by cat; + order by custom_category; `, {} ); @@ -590,6 +600,10 @@ export const querySearchFunc = (search: string): Promise> t.name as threadName, p.pid, c.argsetid, + c.trace_level, + c.trace_tag, + c.custom_args, + c.custom_category as category, 'func' as type from callstack c left join thread t on c.callid = t.id left join process p on t.ipid = p.id left join trace_range r @@ -613,6 +627,10 @@ export const querySearchFunc = (search: string): Promise> t.name as threadName, p.pid, c.argsetid, + c.trace_level, + c.trace_tag, + c.custom_args, + c.custom_category as category, 'func' as type from callstack c left join thread t on c.callid = t.id left join process p on t.ipid = p.id left join trace_range r diff --git a/ide/src/trace/database/sql/Perf.sql.ts b/ide/src/trace/database/sql/Perf.sql.ts index 8bd8b12977675ef358685c3a7836922817f78dd4..1f403d308d6315fea238560370d79aee59c1c4c6 100644 --- a/ide/src/trace/database/sql/Perf.sql.ts +++ b/ide/src/trace/database/sql/Perf.sql.ts @@ -80,6 +80,36 @@ where time >= $leftNs and time <= $rightNs and A.thread_id != 0 }); }; +export const queryPerfSampleChildListByTree = ( + leftNs: number, + rightNs: number, + pid?: number, + tid?: number, +): Promise> => { + let sql = ` +select A.callchain_id as sampleId, + A.thread_id as tid, + C.thread_name as threadName, + A.thread_state as state, + C.process_id as pid, + (timestamp_trace - R.start_ts) as time, + cpu_id as core +from perf_sample A,trace_range R +left join perf_thread C on A.thread_id = C.thread_id +where time >= $leftNs and time <= $rightNs and A.thread_id != 0 + `; + if (pid) { + sql = `${sql} and C.process_id = ${pid}`; + } + if (pid && tid !== undefined) { + sql = `${sql} and A.thread_id = ${tid}`; + } + return query('queryPerfSampleChildListByTree', sql, { + $leftNs: leftNs, + $rightNs: rightNs, + }); +}; + export const queryPerfSampleIdsByTimeRange = ( leftNs: number, rightNs: number, @@ -116,6 +146,8 @@ export const queryPerfSampleCallChain = (sampleId: number): Promise> => + query( + 'querySysCallThreadIds', + `SELECT tid, pid, itid, thread.ipid +FROM + thread left join process on thread.ipid = process.ipid +WHERE + itid IN (SELECT DISTINCT( itid ) FROM syscall ) + `, + {}, + { traceId: traceId} + ); + +export const querySysCallEventDetail = +(itid: number, startTs: number, dur: number, traceId?: string): Promise> => + query( + 'querySysCallEventDetail', + `SELECT tid, thread.name as tName, pid, process.name as pName, args, ret +FROM + (select * from syscall where itid= ${itid} and ts = ${startTs} and dur = ${dur}) A + left join thread on A.itid = thread.itid + left join process on thread.ipid = process.ipid + `, + {}, + { traceId: traceId} + ); + +export const querySysCallEventWithBoxSelect = +(ipidArr: Array, itidArr: Array, leftNs: number, rightNs: number): Promise> => + query( + 'querySysCallEventWithBoxSelect', + `select ifnull(process.name, 'Process') as pName, + ifnull(thread.name, 'Thread') as tName, + process.pid, + thread.tid, + A.nameId, + A.sumDur, + A.totalCount +from ( +select itid, syscall_number as nameId, sum(dur) as sumDur, count(1) as totalCount +from syscall +where + ${itidArr.length > 0 ? 'itid in (' + itidArr.join(',') + ')' : '1 = 1'} + and not ((ts - ${window.recordStartNS} + ifnull(dur,0) < ${leftNs}) or (ts - ${window.recordStartNS} > ${rightNs})) +group by itid, syscall_number +) as A +left join thread on A.itid = thread.itid +left join process on thread.ipid = process.ipid +where + ${ipidArr.length > 0 ? 'thread.ipid in (' + ipidArr.join(',') + ')' : '1 = 1'} + `, + {} + ); + + export const querySysCallEventWithRange = +(ipidArr: Array, itidArr: Array, leftNs: number, rightNs: number, sysCallId?: number): Promise> => + query( + 'querySysCallEventWithRange', + `select ifnull(process.name, 'Process') as pName, + ifnull(thread.name, 'Thread') as tName, + process.pid, + thread.tid, + A.nameId, + A.startTs, + A.dur, + A.args, + A.ret +from ( + select itid, syscall_number as nameId, (ts - ${window.recordStartNS}) as startTs, dur, args, ret + from syscall + where + ${itidArr.length > 0 ? 'itid in (' + itidArr.join(',') + ')' : '1 = 1'} + and ${sysCallId !== undefined ? 'syscall_number = ' + sysCallId : '1 = 1' } + and not ((ts - ${window.recordStartNS} + ifnull(dur,0) < ${leftNs}) or (ts - ${window.recordStartNS} > ${rightNs})) + ) as A + left join thread on A.itid = thread.itid + left join process on thread.ipid = process.ipid +where + ${ipidArr.length > 0 ? 'thread.ipid in (' + ipidArr.join(',') + ')' : '1 = 1'} + `, + {} + ); + export const queryProcessContentCount = (traceId?: string): Promise> => query( `queryProcessContentCount`, diff --git a/ide/src/trace/database/sql/SqlLite.sql.ts b/ide/src/trace/database/sql/SqlLite.sql.ts index 2b547526cca08af488a76c7dbba48ba403ec8f3b..aa6364e1fb9df78adcea3cd45a39abfc855d3c02 100644 --- a/ide/src/trace/database/sql/SqlLite.sql.ts +++ b/ide/src/trace/database/sql/SqlLite.sql.ts @@ -29,6 +29,7 @@ import type { DeviceStruct } from '../../bean/FrameComponentBean'; import { LogStruct } from '../ui-worker/ProcedureWorkerLog'; import { query } from '../SqlLite'; import { Utils } from '../../component/trace/base/Utils'; +import { FuncStruct } from '../ui-worker/ProcedureWorkerFunc'; export const queryEventCountMap = ( traceId?: string @@ -405,7 +406,11 @@ export const queryBinderBySliceId = ( c.depth, c.argsetid, c.name AS funName, - c.cookie + c.cookie, + c.trace_level, + c.trace_tag, + c.custom_category as category, + c.custom_args FROM callstack c, trace_range D @@ -449,8 +454,12 @@ export const queryBinderByArgsId = ( p.pid, c.depth, c.argsetid, - c.name as funName, - c.cookie + c.name as funName, + c.cookie, + c.trace_level, + c.trace_tag, + c.custom_category as category, + c.custom_args from callstack c,trace_range D left join thread t on c.callid = t.id left join process p on p.id = t.ipid @@ -1592,3 +1601,21 @@ export const queryPerfToolsDur = (): Promise> => dur FROM callstack where name = 'H:GRAB'` ); + +export const queryCallstackDetail = (): Promise> => + query( + 'queryCallstackDetail', + `SELECT + id, + trace_level, + trace_tag, + custom_category as category, + custom_args + FROM callstack, trace_range AS TR + where (trace_level is not null or + trace_tag is not null or + custom_args is not null or + custom_category is not null) + and ts - TR.start_ts >= 0 + and TR.end_ts - ts >=0;` + ); diff --git a/ide/src/trace/database/ui-worker/ProcedureWorker.ts b/ide/src/trace/database/ui-worker/ProcedureWorker.ts index cba4720f12009088d68766b9640d1f743e943a39..b4391b7e202dac7e0d417f8a0956bcf49258f976 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorker.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorker.ts @@ -78,6 +78,7 @@ import { XpowerWifiRender } from './ProcedureWorkerXpowerWifi'; import { XpowerGpuFreqCountRender } from './ProcedureWorkerXpowerGpuFreqCount'; import { XpowerGpuFreqRender } from './ProcedureWorkerXpowerGpuFreq'; import { SnapShotRender } from './ProcedureWorkerSnaps'; +import { ThreadSysCallRender } from './ProcedureWorkerThreadSysCall'; let dataList: unknown = {}; let dataList2: unknown = {}; @@ -106,6 +107,7 @@ export let renders = { 'heap-snapshot': new HeapSnapshotRender(), mem: new MemRender(), thread: new ThreadRender(), + threadSysCall: new ThreadSysCallRender(), func: new FuncRender(), native: new NativeMemoryRender(), 'HiPerf-Group': new EmptyRender(), diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerThreadSysCall.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerThreadSysCall.ts new file mode 100644 index 0000000000000000000000000000000000000000..823fe4f2e4606d356dd456f8a52e0520d68ee7a8 --- /dev/null +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerThreadSysCall.ts @@ -0,0 +1,137 @@ +/* + * 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 { + dataFilterHandler, + BaseStruct, + isFrameContainPoint, + Render, + RequestMessage, + drawString, + drawLoadingFrame, +} from './ProcedureWorkerCommon'; +import { TraceRow } from '../../component/trace/base/TraceRow'; +import { ColorUtils } from '../../component/trace/base/ColorUtils'; +import { SpSystemTrace } from '../../component/SpSystemTrace'; + +export class ThreadSysCallRender extends Render { + renderMainThread( + threadReq: { + context: CanvasRenderingContext2D; + useCache: boolean; + type: string; + translateY: number; + }, + row: TraceRow + ): void { + let threadList = row.dataList; + let threadFilter = row.dataListCache; + dataFilterHandler(threadList, threadFilter, { + startKey: 'startTs', + durKey: 'dur', + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 3, + useCache: threadReq.useCache || !(TraceRow.range?.refresh ?? false), + }); + drawLoadingFrame(threadReq.context, threadFilter, row); + threadReq.context.beginPath(); + let find: boolean = false; + for (let re of threadFilter) { + re.translateY = threadReq.translateY; + ThreadSysCallStruct.drawThread(threadReq.context, re); + if (row.isHover && re.frame && isFrameContainPoint(re.frame!, row.hoverX, row.hoverY)) { + ThreadSysCallStruct.hoverStruct = re; + find = true; + } + } + threadReq.context.closePath(); + } + + render(threadReq: RequestMessage, threadList: Array, threadFilter: Array): void {} +} + +export function ThreadSysCallStructOnClick( + clickRowType: string, + sp: SpSystemTrace, + entry?: ThreadSysCallStruct +): Promise { + return new Promise((resolve, reject) => { + if (clickRowType === TraceRow.ROW_TYPE_THREAD_SYS_CALL && (ThreadSysCallStruct.hoverStruct || entry)) { + ThreadSysCallStruct.selectStruct = entry || ThreadSysCallStruct.hoverStruct; + sp.timerShaftEL?.drawTriangle(ThreadSysCallStruct.selectStruct!.startTs || 0, 'inverted'); + sp.traceSheetEL?.displaySysCallData(ThreadSysCallStruct.selectStruct!); + sp.timerShaftEL?.modifyFlagList(undefined); + reject(new Error()); + } else { + resolve(null); + } + }); +} +export class ThreadSysCallStruct extends BaseStruct { + static hoverStruct: ThreadSysCallStruct | undefined; + static selectStruct: ThreadSysCallStruct | undefined; + name: string | undefined; + tid: number | undefined; + id: number | undefined; + pid: number | undefined; + itid: number | undefined; + startTs: number | undefined; + dur: number | undefined; + args: string | undefined; + ret: number | undefined; + + static drawThread(threadContext: CanvasRenderingContext2D, data: ThreadSysCallStruct): void { + if (data.frame) { + threadContext.globalAlpha = 1; + threadContext.fillStyle = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.name || '', 0, ColorUtils.FUNC_COLOR.length)]; + let textColor = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.name || '', 0, ColorUtils.FUNC_COLOR.length)]; + if (ThreadSysCallStruct.hoverStruct && data.name === ThreadSysCallStruct.hoverStruct.name) { + threadContext.globalAlpha = 0.7; + } + threadContext.fillRect(data.frame.x, data.frame.y, data.frame.width, data.frame.height); + threadContext.fillStyle = ColorUtils.funcTextColor(textColor); + threadContext.textBaseline = 'middle'; + threadContext.font = '8px sans-serif'; + data.frame.width > 7 && data.name && drawString(threadContext, data.name, 2, data.frame, data); + if ( + ThreadSysCallStruct.selectStruct && + ThreadSysCallStruct.equals(ThreadSysCallStruct.selectStruct, data) + ) { + threadContext.strokeStyle = '#232c5d'; + threadContext.lineWidth = 2; + threadContext.strokeRect( + data.frame.x, + data.frame.y, + data.frame.width - 2, + data.frame.height + ); + } + } + } + + static equals(d1: ThreadSysCallStruct, d2: ThreadSysCallStruct): boolean { + return ( + d1 && + d2 && + d1.tid === d2.tid && + d1.name === d2.name && + d1.startTs === d2.startTs && + d1.dur === d2.dur + ); + } +} diff --git a/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCPU.ts b/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCPU.ts index 01730f73f533b26b6c0133e2f2e770d4fd82c7b6..9419ba8e56728ea69682687e42a3f2cd209ce3fc 100644 --- a/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCPU.ts +++ b/ide/src/trace/database/ui-worker/cpu/ProcedureWorkerCPU.ts @@ -273,7 +273,6 @@ export class CpuStruct extends BaseStruct { ctx.globalAlpha = 1; ctx.fillStyle = '#e0e0e0'; } - ctx.clearRect(data.frame.x, data.frame.y, width, data.frame.height); ctx.fillRect(data.frame.x, data.frame.y, width, data.frame.height); ctx.globalAlpha = 1; CpuStruct.drawText(ctx, data, width, pid, tid); diff --git a/ide/src/webSocket/Constants.ts b/ide/src/webSocket/Constants.ts index 491dd660e6e34d9fddfeea1005c6f2fb9205f7e3..b4eb937f71b2c0432256c15f1fc4a7751e0895e2 100644 --- a/ide/src/webSocket/Constants.ts +++ b/ide/src/webSocket/Constants.ts @@ -47,4 +47,5 @@ export class TypeConstants { static USB_GET_EVENT = 4; static USB_GET_APP = 5; static USB_GET_VERSION = 6; + static USB_GET_HISYSTEM = 7; } \ No newline at end of file diff --git a/ide/src/webSocket/WebSocketManager.ts b/ide/src/webSocket/WebSocketManager.ts index fc9897fae3221ab00b8515877095d9e6a5ca3690..b92eaa3c231604e3e816b19c40e719132fa10c50 100644 --- a/ide/src/webSocket/WebSocketManager.ts +++ b/ide/src/webSocket/WebSocketManager.ts @@ -38,11 +38,10 @@ export class WebSocketManager { private sessionId: number | null | undefined; private session: bigint | null | undefined; private heartbeatInterval: number | null | undefined; - private status: string = GetStatuses.UNCONNECTED; + public status: string = GetStatuses.UNCONNECTED; private cacheInfo: Map = new Map(); private reconnect: number = -1; private connectStatus: HTMLElement | null | undefined; - static disaStatus: string = GetStatuses.UNCONNECTED; constructor() { if (WebSocketManager.instance) { @@ -58,8 +57,6 @@ export class WebSocketManager { this.connectStatus = document.querySelector("body > sp-application").shadowRoot.querySelector("#main-menu").shadowRoot.querySelector("div.bottom > div.extend_connect"); this.websocket = new WebSocket(this.url); this.websocket.binaryType = 'arraybuffer'; - // @ts-ignore - setInterval(this.checkConnectionStatus(this.websocket), 5000); this.websocket.onopen = (): void => { this.status = GetStatuses.CONNECTED; // 设置心跳定时器 @@ -80,11 +77,12 @@ export class WebSocketManager { this.websocket.onerror = (error): void => { console.error('error:', error); + this.extendTips(false); }; this.websocket.onclose = (event): void => { this.status = GetStatuses.UNCONNECTED; - this.checkConnectionStatus(this.websocket); + this.extendTips(false); this.finalStatus(); //初始化标志位 this.initLoginInfo(); @@ -92,19 +90,6 @@ export class WebSocketManager { }; } - /** - * 实时监听websockets连接状态 - */ - checkConnectionStatus(websocket: WebSocket | null | undefined) { - // @ts-ignore - if (websocket?.readyState === websocket?.OPEN) { - // @ts-ignore - this.connectStatus?.style.backgroundColor = 'green'; - } else { - // @ts-ignore - this.connectStatus?.style.backgroundColor = 'red'; - } - } /** * 接收webSocket返回的buffer数据 @@ -117,9 +102,22 @@ export class WebSocketManager { } else if (decode.type === TypeConstants.UPDATE_TYPE) {// 升级 this.updateMessage(decode); } else {// type其他 + this.businessMessage(decode); + } + } + + // 扩展服务连接状态提示 + extendTips(flag: boolean): void { + if(flag) { // @ts-ignore this.connectStatus?.style.backgroundColor = 'green'; - this.businessMessage(decode); + // @ts-ignore + this.connectStatus?.title = 'The extended service is connected.'; + }else{ + // @ts-ignore + this.connectStatus?.style.backgroundColor = 'red'; + // @ts-ignore + this.connectStatus?.title = 'The extended service is not connected.'; } } @@ -129,8 +127,6 @@ export class WebSocketManager { this.status = GetStatuses.LOGINED; this.sessionId = decode.session_id; this.session = decode.session; - // @ts-ignore - this.connectStatus?.style.backgroundColor = 'green'; //检查版本 this.getVersion(); } else if (decode.cmd === Constants.SESSION_EXCEED) { // session满了 @@ -143,7 +139,7 @@ export class WebSocketManager { updateMessage(decode: MessageParam): void { if (decode.cmd === Constants.GET_VERSION_CMD) { // 小于则升级 - let targetVersion = '1.1.2'; + let targetVersion = '1.1.4'; let currentVersion = new TextDecoder().decode(decode.data); let result = this.compareVersion(currentVersion, targetVersion); if (result === -1) { @@ -152,6 +148,7 @@ export class WebSocketManager { return; } this.status = GetStatuses.READY; + this.extendTips(true); this.finalStatus(); } else if (decode.cmd === Constants.UPDATE_SUCCESS_CMD) { // 升级成功 this.status = GetStatuses.UPGRADESUCCESS; @@ -204,7 +201,7 @@ export class WebSocketManager { updateVersion(): void { // 扩展程序升级 let url = `https://${window.location.host.split(':')[0]}:${window.location.port - }/application/extend/hi-smart-perf-host-extend-update.zip`; + }${window.location.pathname}extend/hi-smart-perf-host-extend-update.zip`; fetch(url).then(response => { if (!response.ok) { throw new Error('No corresponding upgrade compression package found'); @@ -237,7 +234,7 @@ export class WebSocketManager { * listener是不同模块传来接收数据的函数 * 模块调用 */ -registerMessageListener(type: number, callback: Function, eventCallBack: Function, allowMultipleCallback: boolean = false): void { + registerMessageListener(type: number, callback: Function, eventCallBack: Function, allowMultipleCallback: boolean = false): void { let callbackObj = this.distributeMap.get(type); if (!callbackObj) { callbackObj = { @@ -282,7 +279,6 @@ registerMessageListener(type: number, callback: Function, eventCallBack: Functio } else { this.send(type, cmd, data); } - WebSocketManager.disaStatus = this.status; } send(type: number, cmd?: number, data?: Uint8Array): void { @@ -302,9 +298,6 @@ registerMessageListener(type: number, callback: Function, eventCallBack: Functio sendHeartbeat(): void { this.heartbeatInterval = window.setInterval(() => { if (this.status === GetStatuses.READY) { - WebSocketManager.disaStatus = GetStatuses.READY; - // @ts-ignore - this.connectStatus?.style.backgroundColor = 'green'; this.send(TypeConstants.HEARTBEAT_TYPE, undefined, undefined); } }, Constants.INTERVAL_TIME); @@ -360,16 +353,10 @@ registerMessageListener(type: number, callback: Function, eventCallBack: Functio finalStatus(): void { if (this.reconnect !== -1) { if (this.status === GetStatuses.READY) { - WebSocketManager.disaStatus = GetStatuses.READY; - // @ts-ignore - this.connectStatus?.style.backgroundColor = 'green'; // @ts-ignore this.sendMessage(this.reconnect, this.cacheInfo.get(this.reconnect)!.cmd, this.cacheInfo.get(this.reconnect)!.data); return; } - WebSocketManager.disaStatus = GetStatuses.UNCONNECTED; - // @ts-ignore - this.connectStatus?.style.backgroundColor = 'red'; this.distributeMap.get(this.reconnect)!.eventCallBack(this.status); } this.reconnect = -1; diff --git a/ide/webpack.config.js b/ide/webpack.config.js index 598d3265edea0742edad28b764801d58b83f9797..4ff1db13cad343f8f96c164c7a5b3a5988f97b28 100644 --- a/ide/webpack.config.js +++ b/ide/webpack.config.js @@ -147,6 +147,10 @@ const config = { from: './src/doc', to: 'doc', }, + { + from: './src/config', + to: 'config', + }, { from: './src/base-ui/icon.svg', to: 'base-ui/icon.svg', diff --git a/trace_streamer/build/build_base_func.sh b/trace_streamer/build/build_base_func.sh index f635395e1f93ac6354c8fc738a3dce7084192ca8..42292804250d57625c4f7b5aa522eefc7d5d54a2 100644 --- a/trace_streamer/build/build_base_func.sh +++ b/trace_streamer/build/build_base_func.sh @@ -17,6 +17,7 @@ function help() { echo "Usage: $1 [linux/wasm/windows/macx] [debug] [-e ] [-d ]" echo " -e , enable the default plugins." echo " -d , enable the extend plugins." + echo " -m , enable the macro plugins." echo " -l Show the all plugin list." echo " -h Show the help info." exit diff --git a/trace_streamer/build/ts.gni b/trace_streamer/build/ts.gni index d2fdef54b5402418d6a5378aa60da7b84d12ca8b..4e7b0ba7bd137f0b55f5b2321953e97f68a2e59a 100644 --- a/trace_streamer/build/ts.gni +++ b/trace_streamer/build/ts.gni @@ -13,6 +13,7 @@ declare_args() { is_independent_compile = false + hiperf_debug = true enable_hiperf = true enable_ebpf = true enable_native_hook = true diff --git a/trace_streamer/build_operator.sh b/trace_streamer/build_operator.sh index f4b86177376bff3442e0411faed1205b4f298027..656c8ee438d4e8181935bfa0e8b5fc43ffe5095b 100755 --- a/trace_streamer/build_operator.sh +++ b/trace_streamer/build_operator.sh @@ -62,6 +62,14 @@ else echo "begin to build ..." prebuilts/"$gn_path"/"$ninja" -C "$out_dir" fi +if [ "$target" != "wasm" ]; then + if [ -f "config/config.json" ]; then + cp -r "config" "$out_dir" + echo "Successfully found the configuration!" + else + echo "Failed to find the configuration!" + fi +fi if [ "$out_dir" == "out/macx" ];then ./mac_depend.sh fi \ No newline at end of file diff --git a/trace_streamer/config/config.json b/trace_streamer/config/config.json new file mode 100644 index 0000000000000000000000000000000000000000..6b4ff707e4ac4994d91ccaefd8be8ced8ed21ca8 --- /dev/null +++ b/trace_streamer/config/config.json @@ -0,0 +1,136 @@ +{ + "_comment": "这是动效的相关打点", + "Animation": { + "_comment": "动效过程打点线程,render_service为并行化前的打点线程,RSUniRenderThre为并行化后的打点线程", + "animationProcEvents_": [ + "render_service", + "RSUniRenderThre" + ], + "_comment": "动效相关打点,H:LAUNCHER_APP_LAUNCH_FROM_ICON为桌面图标点击启动,H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR为通知栏通知消息点击启动,H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR_IN_LOCKSCREEN为锁屏通知消息点击启动,H:LAUNCHER_APP_LAUNCH_FROM_RECENT为多任务点击应用,H:LAUNCHER_APP_SWIPE_TO_HOME为HOME键返回桌面,H:LAUNCHER_APP_BACK_TO_HOME为Back键返回桌面,H:APP_TRANSITION_TO_OTHER_APP为应用切换到另一个应用,H:APP_TRANSITION_FROM_OTHER_APP为从另一个应用跳回,H:APP_LIST_FLING为应用中列表滑动", + "onAnimationStartEvents_": [ + "H:LAUNCHER_APP_LAUNCH_FROM_ICON", + "H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR", + "H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR_IN_LOCKSCREEN", + "H:LAUNCHER_APP_LAUNCH_FROM_RECENT", + "H:LAUNCHER_APP_SWIPE_TO_HOME", + "H:LAUNCHER_APP_BACK_TO_HOME", + "H:APP_TRANSITION_TO_OTHER_APP", + "H:APP_TRANSITION_FROM_OTHER_APP", + "H:APP_LIST_FLING" + ], + "_comment": "H:GenerateVsyncCount,用于计算设备的平均帧率,累计6次后输出平均帧率", + "frameRateCmd_": [ + "H:GenerateVsyncCount" + ], + "_comment": "H:RSJankStats::RecordAnimationDynamicFrameRate,用于更新动效的帧率,若存在此打点,则以这个打点为准,否则以H:Repaint为准", + "realFrameRateCmd_": [ + "H:RSJankStats::RecordAnimationDynamicFrameRate" + ], + "_comment": "H:Repaint(硬件合成器合成绘制),用于计算动效帧率", + "frameCountCmd_": [ + "H:Repaint" + ], + "_comment": "H:RSUniRender::Process:[WindowScene_和H:RSSurfaceRenderNodeDrawable::OnDraw:[WindowScene_用来获取动效帧数据的打点,其中H:RSUniRender::Process:[WindowScene_为并行化前打点", + "frameBeginCmd_": [ + "H:RSUniRender::Process:[WindowScene_", + "H:RSSurfaceRenderNodeDrawable::OnDraw:[WindowScene_" + ], + "_comment": "H:RSUniRender::Process:[SCBDesktop和H:RSSurfaceRenderNodeDrawable::OnDraw:[SCBDesktop用来获取设备的宽高,其中H:RSUniRender::Process:[SCBDesktop为并行化前打点", + "screenSizeCmd_": [ + "H:RSUniRender::Process:[SCBDesktop", + "H:RSSurfaceRenderNodeDrawable::OnDraw:[SCBDesktop" + ], + "_comment": "H:RSMainThread::DoComposition和H:RenderFrame用来获取动效帧的结束时间,其中H:RSMainThread::DoComposition为并行化前的打点", + "frameEndTimeCmd_": [ + "H:RenderFrame" + ], + "_comment": "H:PostAndWait, parallel type并行化的标志", + "parallelTypeCmd_": [ + "H:PostAndWait, parallel type" + ] + }, + "_comment": "这是启动场景的相关打点", + "AppStartup": { + "_comment": "启动第一阶段,手指点击", + "phase1": { + "pName": "ProcessTouchEvent", + "start": [ + "H:client dispatch touchId:" + ], + "end": [ + "H:OHOS::ErrCode OHOS::AAFwk::AbilityManagerClient::StartUIAbilityBySCB" + ] + }, + "_comment": "启动第二阶段,处理创建进程信息,创建窗口", + "phase2": { + "pName": "StartUIAbilityBySCB", + "start": [ + "H:OHOS::ErrCode OHOS::AAFwk::AbilityManagerClient::StartUIAbilityBySCB" + ], + "end": [ + "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::LoadAbility" + ] + }, + "_comment": "启动第三阶段,拉起应用进程", + "phase3": { + "pName": "LoadAbility", + "start": [ + "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::LoadAbility" + ], + "end": [ + "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::AttachApplication(const pid_t, const sptr &)##" + ] + }, + "_comment": "启动第四阶段,加载应用", + "phase4": { + "pName": "Application Launching", + "start": [ + "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::AttachApplication(const pid_t, const sptr &)##" + ], + "end": [ + "H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility(const std::shared_ptr &)##" + ] + }, + "_comment": "启动第五阶段,加载 UI Ability", + "phase5": { + "pName": "UI Ability Launching", + "start": [ + "H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility(const std::shared_ptr &)##" + ], + "end": [ + "H:void OHOS::AbilityRuntime::FAAbilityThread::HandleAbilityTransaction(const OHOS::AbilityRuntime::Want &, const OHOS::AbilityRuntime::LifeCycleStateInfo &, sptr)##", + "H:void OHOS::AbilityRuntime::UIAbilityThread::HandleAbilityTransaction" + ] + }, + "_comment": "启动第六阶段,应用进入前台", + "phase6": { + "pName": "UI Ability OnForeground", + "start": [ + "H:void OHOS::AbilityRuntime::FAAbilityThread::HandleAbilityTransaction(const OHOS::AbilityRuntime::Want &, const OHOS::AbilityRuntime::LifeCycleStateInfo &, sptr)##", + "H:void OHOS::AbilityRuntime::UIAbilityThread::HandleAbilityTransaction" + ], + "end": [ + "H:ReceiveVsync dataCount" + ] + } + }, + "_comment": "Flag 开关", + "config": { + "TaskPool": 0, + "AnimationAnalysis": 0, + "AppStartup": 0, + "SchedulingAnalysis": 0, + "BinderRunnable": 0, + "FfrtConvert": 0, + "HMKernel": 1, + "VSync": 0, + "Hangs Detection": 0, + "LTPO": 0, + "Start&Finish Trace Category": 0, + "UserPluginsRow": 0, + "CPU by Irq": 0, + "RawTraceCutStartTs": 1, + "AI": 0, + "System Calls": "" + } +} \ No newline at end of file diff --git a/trace_streamer/doc/des_tables.md b/trace_streamer/doc/des_tables.md index fa1e90f3074a8cc056974e4ae524e4249965db93..494ef6ca99007294674ef3f2c69c6c4782c582c9 100755 --- a/trace_streamer/doc/des_tables.md +++ b/trace_streamer/doc/des_tables.md @@ -18,7 +18,7 @@ TraceStreamer可以将trace数据源转化为易于理解和使用的数据库 | app_startup | 记录了应用启动相关数据| | args | 记录方法参数集合| | bio_latency_sample | 记录IO操作相关方法调用,及调用栈数据| -| callstack | 记录调用堆栈和异步调用信息,其中depth,stack_id和parent_stack_id仅在非异步调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号| +| callstack | 记录调用堆栈和异步调用信息,其中depth仅在非异步调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,child_callid为子线程唯一号| | clk_event_filter | 记录时钟相关的信息| | clock_event_filter | 此结构用来维护时钟事件,cpu与唯一的ID做关联| | clock_snapshot | 时钟号和时间,时钟名的映射表| @@ -359,8 +359,13 @@ js_heap_sample:记录timeline的时间轴信息 |spanId |TEXT | |parentSpanId |TEXT | |flag |TEXT | +|trace_level |TEXT | +|trace_tag |TEXT | +|custom_category |TEXT | +|custom_args |TEXT | +|child_callid |INT | #### 表描述 -记录调用堆栈和异步调用信息,其中depth,stack_id和parent_stack_id仅在非异步的调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号。 +记录调用堆栈和异步调用信息,其中depth仅在非异步的调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,child_callid为子线程唯一号。 #### 字段详细描述 - id: 唯一标识 - ts: 数据事件上报时间戳 @@ -376,6 +381,11 @@ js_heap_sample:记录timeline的时间轴信息 - spanId:分布式调用关联关系,当前帧的id - parentSpanId: 分布式调用关联关系,当前帧的parent的SpanId,对应当前表的spandId - flag:C表示分布式调用发送方,S表示接受方 +- trace_level:决定trace的等级,log和nolog等级不同,其中log表示详细记录所有相关的调用信息,nolog 表示不记录 +- trace_tag:Tag标签,标识请求的来源或类型 +- custom_category:聚合标签,用于关联同类信息 +- custom_args:自定义参数,用于存储与调用相关的额外信息 +- child_callid:当为异步调用,此时callid为进程唯一号,child_callid为子线程唯一号,反之为无效值 ### clk_event_filter表 #### 表结构 @@ -1469,19 +1479,21 @@ source_arg_set_id: 同一个source_arg_set_id代表一组数据,一般取得 #### 表结构 | Columns Name | SQL TYPE | |---- |---- | -|syscall_num |INT | -|type |TEXT | -|ipid |INT | +|syscall_number|INT | |ts |INT | +|dur |INT | +|itid |INT | +|args |TEXT | |ret |INT | #### 表描述 记录用户空间函数与内核空间函数相互调用记录。 #### 相关字段描述 -- syscall_num:系统调用的序号 -- type:固定取值:enter或者exit -- ipid:线程所属的进程ID -- ts:时间戳 -- ret:返回值,在type为exit时有效 +- syscall_number:系统调用的序号 +- ts:时间戳 +- dur:持续时间,记录系统调用的执行时间 +- itid: 记录发起调用的线程 +- args: 参数,记录系统调用的参数信息 +- ret:返回值,记录系统调用的返回结果 ### sys_event_filter表 #### 表结构 diff --git a/trace_streamer/gn/BUILD.gn b/trace_streamer/gn/BUILD.gn index 1037621711538bdbcab17813a695866f8b642141..9cd142f5395ef28a6b8a346c67bf6d4c69acfe5e 100644 --- a/trace_streamer/gn/BUILD.gn +++ b/trace_streamer/gn/BUILD.gn @@ -59,6 +59,12 @@ config("default") { "-Wformat", "-Wno-unused-variable", ] + + # for third part hiperf + defines += [ "HIPERF_DEBUG" ] + + # for third part libbpf + defines += [ "__LITTLE_ENDIAN_BITFIELD" ] if (enable_hiperf) { defines += [ "ENABLE_HIPERF" ] } @@ -191,17 +197,17 @@ config("default") { cflags += [ "-D SUPPORTTHREAD" ] } if (is_win) { - cflags += [ "-D is_mingw" ] + cflags += [ "-D is_mingw=true" ] defines += [ "WIN32_LEAN_AND_MEAN" ] libs += [ "wsock32" ] libs += [ "ws2_32" ] cflags += [ "-Wno-attributes" ] } if (is_linux) { - cflags += [ "-D is_linux" ] + cflags += [ "-D is_linux=true" ] } if (is_mac) { - cflags += [ "-D is_mac" ] + cflags += [ "-D is_mac=true" ] } } diff --git a/trace_streamer/pare_third_party.sh b/trace_streamer/pare_third_party.sh index 498c209f454033585fa2b4e2e01b524d1029fc76..8b50614aaf4479ee6a5d2a68b4320c466ba1b754 100755 --- a/trace_streamer/pare_third_party.sh +++ b/trace_streamer/pare_third_party.sh @@ -30,7 +30,7 @@ cd third_party if [ ! -f "sqlite/BUILD.gn" ];then rm -rf sqlite - git clone git@gitee.com:openharmony/third_party_sqlite.git + git clone https://gitee.com/openharmony/third_party_sqlite.git if [ -d "third_party_sqlite" ];then mv third_party_sqlite sqlite cd sqlite @@ -41,7 +41,7 @@ if [ ! -f "sqlite/BUILD.gn" ];then fi if [ ! -f "protobuf/BUILD.gn" ];then rm -rf protobuf - git clone git@gitee.com:openharmony/third_party_protobuf.git + git clone https://gitee.com/openharmony/third_party_protobuf.git if [ -d "third_party_protobuf" ];then mv third_party_protobuf protobuf cd protobuf @@ -52,29 +52,16 @@ if [ ! -f "protobuf/BUILD.gn" ];then fi if [ ! -f "zlib/BUILD.gn" ];then - rm -rf zlib - git clone --depth=1 git@gitee.com:openharmony/third_party_zlib.git - if [ -d "third_party_zlib" ];then - mv third_party_zlib zlib - $cp ../prebuilts/patch_zlib/zlibbuild.gn zlib/BUILD.gn - fi + git clone --depth=1 git@gitee.com:openharmony/third_party_zlib.git zlib fi if [ ! -f "bzip2/BUILD.gn" ];then - rm -rf bzip2 - git clone --depth=1 git@gitee.com:openharmony/third_party_bzip2.git - if [ -d "third_party_bzip2" ];then - mv third_party_bzip2 bzip2 - $cp ../prebuilts/patch_bzip2/bzip2build.gn bzip2/BUILD.gn - cd bzip2 - ./install.sh $(pwd) - cd .. - fi + git clone --depth=1 git@gitee.com:openharmony/third_party_bzip2.git bzip2 fi if [ ! -f "googletest/BUILD.gn" ];then rm -rf googletest - git clone --depth=1 git@gitee.com:openharmony/third_party_googletest.git + git clone --depth=1 https://gitee.com/openharmony/third_party_googletest.git if [ -d "third_party_googletest" ];then mv third_party_googletest googletest $cp ../prebuilts/patch_googletest/googletestbuild.gn ../third_party/googletest/BUILD.gn @@ -84,127 +71,39 @@ fi if [ ! -f "json/BUILD.gn" ];then rm -rf json - git clone --depth=1 git@gitee.com:openharmony/third_party_json.git + git clone --depth=1 https://gitee.com/openharmony/third_party_json.git if [ -d "third_party_json" ];then mv third_party_json json fi fi -if [ ! -f "libunwind/BUILD.gn" ];then - rm -rf libunwind - git clone git@gitee.com:openharmony/third_party_libunwind.git - if [ -d "third_party_libunwind" ];then - mv third_party_libunwind libunwind - cd libunwind - git reset --hard 2c16627236d5e62c8fe78e088d21eca3c362c71c - cd .. - $cp ../prebuilts/patch_libunwind/libunwindbuild.gn libunwind/BUILD.gn - fi +if [ ! -d "libbpf" ];then + git clone --depth=1 git@gitee.com:openharmony/third_party_libbpf.git libbpf fi -if [ ! -f "perf_include/libbpf/linux/perf_event.h" ];then - mkdir -p perf_include/libbpf/linux - rm -rf perf_event.h - curl https://gitee.com/openharmony/third_party_libbpf/raw/20221117/github.com/libbpf/libbpf/refs/tags/v0.7.0/include/uapi/linux/perf_event.h > perf_event.h - mv perf_event.h perf_include/libbpf/linux/perf_event.h - $patch -p0 perf_include/libbpf/linux/perf_event.h ../prebuilts/patch_perf_event/perf_event.h.patch +if [ ! -d "hiviewdfx/faultloggerd" ];then + git clone --depth=1 git@gitee.com:openharmony/hiviewdfx_faultloggerd.git hiviewdfx/faultloggerd/ + cd hiviewdfx/faultloggerd + perl -pi -e 's/\r$//' interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp + $patch -p1 < ../../../prebuilts/patch_hiperf/hiviewdfx_faultloggerd.patch + cd ../../ fi -if [ ! -d "perf_include/hiviewdfx/faultloggerd" ];then - rm -rf hiviewdfx_faultloggerd perf_include/hiviewdfx/faultloggerd - mkdir -p perf_include/hiviewdfx/faultloggerd/interfaces/innerkits - git clone git@gitee.com:openharmony/hiviewdfx_faultloggerd.git - cd hiviewdfx_faultloggerd - git reset --hard 7296f69c0d418cd9353638f3117296e4b494e4e5 - cd .. - mv hiviewdfx_faultloggerd/common/ perf_include/hiviewdfx/faultloggerd - mv hiviewdfx_faultloggerd/interfaces/common/ perf_include/hiviewdfx/faultloggerd/interfaces - mv hiviewdfx_faultloggerd/interfaces/nonlinux/ perf_include/hiviewdfx/faultloggerd/interfaces - mv hiviewdfx_faultloggerd/interfaces/innerkits/unwinder/ perf_include/hiviewdfx/faultloggerd/interfaces/innerkits - find perf_include/hiviewdfx/faultloggerd -type f -name "*.gn" -delete - $cp ../prebuilts/patch_hiperf/hiviewdfx_BUILD.gn ../third_party/perf_include/hiviewdfx/BUILD.gn - rm -rf hiviewdfx_faultloggerd - rm -rf perf_include/hiviewdfx/common/build - rm -rf perf_include/hiviewdfx/common/cutil - rm perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/dfx_regs_x86_64.cpp - $sed -i '/TRAP_BRANCH/s/^/\/\/ /' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/dfx_signal.cpp - $sed -i '/TRAP_HWBKPT/s/^/\/\/ /' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/dfx_signal.cpp - $sed -i '/is_ohos/s/is_ohos/true/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/dfx_mmap.cpp - $sed -i '/is_ohos/s/is_ohos/true/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include/dfx_regs.h - $sed -i '/#include /a #include "debug_logger.h"' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include/unwinder.h - $sed -i '/getpid() == gettid()/s/getpid() == gettid()/false/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/unwinder.cpp - $sed -i '/!realpath(path, realPath)/s/!realpath(path, realPath)/false/g' perf_include/hiviewdfx/faultloggerd/common/dfxutil/dfx_util.cpp - $sed -i '/#include "dfx_util.h"/a #include "utilities.h"' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/dfx_mmap.cpp - $sed -i '/#include /a #include "utilities.h"' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include/dfx_mmap.h - $sed -i '/#if is_ohos && !is_mingw/s/#if is_ohos && !is_mingw/#if is_linux/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include/dfx_elf.h - $sed -i '/#if is_ohos && !is_mingw/s/#if is_ohos && !is_mingw/#if is_linux/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/dfx_elf.cpp - $sed -i '/#if is_ohos/s/#if is_ohos/#if true/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include/dfx_elf.h - $sed -i '/#if is_ohos/s/#if is_ohos/#if true/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/dfx_elf.cpp - $sed -i '/#ifndef is_ohos_lite/s/#ifndef is_ohos_lite/#if false/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/dfx_elf.cpp - $sed -i '/#if is_mingw/s/#if is_mingw/#ifndef is_linux/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/dfx_elf.cpp - $sed -i '/#if !is_mingw/s/#if !is_mingw/#if is_linux/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include/dfx_elf_define.h - $sed -i '/#if is_mingw/s/#if is_mingw/#ifndef is_linux/g' perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include/dfx_elf_parser.h - $sed -i '/#define DFX_NONLINUX_DEFINE_H/a #ifndef is_linux' perf_include/hiviewdfx/faultloggerd/interfaces/nonlinux/dfx_nonlinux_define.h - $sed -i '/#if is_mingw/s/#if is_mingw/#ifndef is_linux/g' perf_include/hiviewdfx/faultloggerd/interfaces/common/byte_order.h - $sed -i '$a #endif' perf_include/hiviewdfx/faultloggerd/interfaces/nonlinux/dfx_nonlinux_define.h - $cp ../prebuilts/patch_hiperf/string_view_util.h ../third_party/perf_include/hiviewdfx/faultloggerd/common/dfxutil/string_view_util.h -fi if [ ! -f "hiperf/BUILD.gn" ];then - rm -rf hiperf developtools_hiperf - git clone git@gitee.com:openharmony/developtools_hiperf.git - cd developtools_hiperf - git reset --hard 9d189f41d76c1ae6e8e12238aef5ef5b8cdbc09f - cd .. - if [ -d "developtools_hiperf" ];then - mv developtools_hiperf hiperf - $cp ../prebuilts/patch_hiperf/BUILD.gn ../third_party/hiperf/BUILD.gn - $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/virtual_thread.h - # $sed -i "s/HIPERF_DEBUG/ALWAYSTRUE/g" hiperf/include/virtual_thread.h - $sed -i "/#include \"report_json_file.h\"/s/^\(.*\)$/\/\/\1/g" hiperf/include/report.h - $sed -i "/#include /s/^\(.*\)$/\/\/\1/g" hiperf/include/debug_logger.h - $sed -i "/#include /s/^\(.*\)$/\/\/\1/g" hiperf/include/utilities.h - $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/virtual_thread.h - $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/callstack.h - # $sed -i '/unwinder.h/s/^/\/\/ /' hiperf/include/callstack.h - $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/symbols_file.h - $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/virtual_runtime.h - $sed -i "/FRIEND_TEST/s/^\(.*\)$/\/\/\1/g" hiperf/include/report.h - $sed -i "s/HIPERF_DEBUG/ALWAYSTRUE/g" hiperf/include/virtual_thread.h - # $sed -i "/using __s8 = char;/a #define unw_word_t uint64_t" hiperf/include/nonlinux/linux/types.h - # $sed -i '/^void Report::PrepareConsole(/,/^}/ s/^.*$/\/\/&/; /^void Report::PrepareConsole(/,/return;/ s/^[[:blank:]]*/ /' hiperf/src/report.cpp - # $sed -i '/namespace HiPerf {/avoid Report::PrepareConsole(){ return;}' hiperf/src/report.cpp - # $sed -i '/HITRACE_METER_NAME/s/^/\/\/ /' hiperf/src/callstack.cpp - # $sed -i '/hitrace_meter.h/s/^/\/\/ /' hiperf/src/callstack.cpp - # $sed -i '/dlfcn.h/s/^/\/\/ /' hiperf/src/callstack.cpp - # $sed -i '/dfx_ark.h/s/^/\/\/ /' hiperf/src/callstack.cpp - # $sed -i '/dfx_regs.h/s/^/\/\/ /' hiperf/src/callstack.cpp - $sed -i '/return DoUnwind2/s/^/\/\/ /' hiperf/src/callstack.cpp - # $sed -i '/#if defined(is_ohos) && is_ohos/s/defined(is_ohos) && is_ohos/true/g' hiperf/src/virtual_runtime.cpp - # $sed -i '/#if defined(is_ohos) && is_ohos/s/defined(is_ohos) && is_ohos/true/g' hiperf/include/virtual_runtime.h - # $sed -i '/symbolsTable, elfFile_, elfPath/s/symbolsTable, elfFile_, elfPath/symbolsTable, elfFile_, filePath_/g' hiperf/src/symbols_file.cpp - $sed -i '/spe_decoder.h/s/^/\/\/ /' hiperf/src/virtual_runtime.cpp - $sed -i '/spe_decoder.h/s/^/\/\/ /' hiperf/src/perf_event_record.cpp - fi + git clone --depth=1 -b adjust_build_for_smartperf_host git@gitee.com:li-yiting880505/developtools_hiperf_1.git hiperf fi if [ ! -f "bounds_checking_function/BUILD.gn" ];then - rm -rf bounds_checking_function git clone --depth=1 git@gitee.com:openharmony/third_party_bounds_checking_function.git bounds_checking_function - $cp ../prebuilts/patch_bounds_checking_function/bounds_checking_functionbuild.gn bounds_checking_function/BUILD.gn fi -if [ ! -d "commonlibrary" ];then - rm -rf commonlibrary - git clone --depth=1 git@gitee.com:openharmony/commonlibrary_c_utils.git - if [ -d "commonlibrary_c_utils" ];then - mv commonlibrary_c_utils commonlibrary - rm -rf commonlibrary_c_utils - fi +if [ ! -d "commonlibrary/c_utils" ];then + git clone --depth=1 git@gitee.com:openharmony/commonlibrary_c_utils.git commonlibrary/c_utils fi if [ ! -f "profiler/device/plugins/ftrace_plugin/include/ftrace_common_type.h" ];then rm -rf profiler - git clone --depth=1 git@gitee.com:openharmony/developtools_profiler.git + git clone --depth=1 https://gitee.com/openharmony/developtools_profiler.git if [ -d "developtools_profiler" ];then mkdir -p profiler/device/plugins/ftrace_plugin/include $cp developtools_profiler/device/plugins/ftrace_plugin/include/ftrace_common_type.h profiler/device/plugins/ftrace_plugin/include @@ -215,7 +114,7 @@ fi if [ ! -d "llvm-project" ];then rm -rf llvm-project - git clone --depth=1 git@gitee.com:openharmony/third_party_llvm-project.git + git clone --depth=1 https://gitee.com/openharmony/third_party_llvm-project.git if [ -d "third_party_llvm-project" ];then mv third_party_llvm-project llvm-project cd llvm-project diff --git a/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_faultloggerd.patch b/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_faultloggerd.patch new file mode 100644 index 0000000000000000000000000000000000000000..8fd8419fc75d40072c95151d2c2325522016f820 --- /dev/null +++ b/trace_streamer/prebuilts/patch_hiperf/hiviewdfx_faultloggerd.patch @@ -0,0 +1,1680 @@ +diff --git a/common/dfxutil/smart_fd.h b/common/dfxutil/smart_fd.h +index fd5e838..858ae73 100644 +--- a/common/dfxutil/smart_fd.h ++++ b/common/dfxutil/smart_fd.h +@@ -28,9 +28,11 @@ public: + SmartFd() = default; + explicit SmartFd(int fd, bool fdsan = true) : fd_(fd), fdsan_(fdsan) + { ++#if is_ohos + if (fd_ >= 0 && fdsan_) { + fdsan_exchange_owner_tag(fd_, 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN)); + } ++#endif + } + + ~SmartFd() +@@ -85,11 +87,14 @@ private: + if (fd_ < 0) { + return; + } ++#if is_ohos + if (fdsan_) { + fdsan_close_with_tag(fd_, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN)); + return; + } ++#else + close(fd_); ++#endif + } + + int fd_{-1}; +diff --git a/common/dfxutil/string_view_util.h b/common/dfxutil/string_view_util.h +index b44a59e..7dbd356 100644 +--- a/common/dfxutil/string_view_util.h ++++ b/common/dfxutil/string_view_util.h +@@ -24,6 +24,24 @@ + + namespace OHOS { + namespace HiviewDFX { ++#ifdef is_mac ++class SpinLock { ++public: ++ void lock() ++ { ++ while (locked_.test_and_set(std::memory_order_acquire)) { ++ ; ++ } ++ } ++ void unlock() ++ { ++ locked_.clear(std::memory_order_release); ++ } ++ ++private: ++ std::atomic_flag locked_ = ATOMIC_FLAG_INIT; ++}; ++#endif + class StringViewHold { + public: + static StringViewHold &Get() +@@ -34,50 +52,77 @@ public: + + const char* Hold(STRING_VIEW view) + { ++#ifndef is_mac + pthread_spin_lock(&spin_lock_); ++#else ++ std::lock_guard lockGurand(spinlock_); ++#endif + if (view.size() == 0) { ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + return ""; + } + + char *p = new (std::nothrow) char[view.size() + 1]; + if (p == nullptr) { ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + return ""; + } + if (memset_s(p, view.size() + 1, '\0', view.size() + 1) != 0) { ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + return ""; + } + std::copy(view.data(), view.data() + view.size(), p); + views_.emplace_back(p); ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + return p; + } + + // only use in UT + void Clean() + { ++#ifndef is_mac + pthread_spin_lock(&spin_lock_); ++#else ++ std::lock_guard lockGurand(spinlock_); ++#endif + for (auto &p : views_) { + delete[] p; + } + views_.clear(); ++#ifndef is_mac + pthread_spin_unlock(&spin_lock_); ++#endif + } ++ + private: ++#ifndef is_mac + StringViewHold() + { + pthread_spin_init(&spin_lock_, PTHREAD_PROCESS_PRIVATE); + } ++#endif + ~StringViewHold() + { + Clean(); ++#ifndef is_mac + pthread_spin_destroy(&spin_lock_); ++#endif + } + + std::vector views_; ++#ifndef is_mac + pthread_spinlock_t spin_lock_; ++#else ++ SpinLock spinlock_; ++#endif + }; + } // namespace HiviewDFX + } // namespace OHOS +diff --git a/interfaces/common/byte_order.h b/interfaces/common/byte_order.h +index 3c40993..a55d9db 100644 +--- a/interfaces/common/byte_order.h ++++ b/interfaces/common/byte_order.h +@@ -16,7 +16,7 @@ + #ifndef BYTE_ORDER_H + #define BYTE_ORDER_H + +-#if is_mingw ++#if is_mingw || is_mac + #define UNWIND_LITTLE_ENDIAN 1234 + #define UNWIND_BIG_ENDIAN 4321 + #define UNWIND_BYTE_ORDER -1 // Unknown +diff --git a/interfaces/innerkits/unwinder/include/dfx_elf_define.h b/interfaces/innerkits/unwinder/include/dfx_elf_define.h +index 6bc9394..a71d76b 100644 +--- a/interfaces/innerkits/unwinder/include/dfx_elf_define.h ++++ b/interfaces/innerkits/unwinder/include/dfx_elf_define.h +@@ -17,7 +17,7 @@ + + #include + #include +-#if !is_mingw ++#if !is_mingw && !is_mac + #include + #include + #endif +diff --git a/interfaces/innerkits/unwinder/include/dfx_elf_parser.h b/interfaces/innerkits/unwinder/include/dfx_elf_parser.h +index b4c8443..86a4bdd 100644 +--- a/interfaces/innerkits/unwinder/include/dfx_elf_parser.h ++++ b/interfaces/innerkits/unwinder/include/dfx_elf_parser.h +@@ -16,7 +16,7 @@ + #define DFX_ELF_PARSER_H + + #include +-#if is_mingw ++#if is_mingw || is_mac + #include "dfx_nonlinux_define.h" + #else + #include +diff --git a/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp b/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp +index 9398e59..79d230e 100644 +--- a/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp ++++ b/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp +@@ -1,749 +1,749 @@ +-/* +- * Copyright (c) 2021-2025 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. +- */ +- +-#include "dfx_elf.h" +- +-#include +-#include +-#include +-#include +-#include +-#if is_mingw +-#include "dfx_nonlinux_define.h" +-#else +-#include +-#include +-#endif +-#include +-#include +-#include +-#include +- +-#include "dfx_define.h" +-#include "dfx_log.h" +-#include "dfx_instr_statistic.h" +-#include "dfx_util.h" +-#include "dfx_maps.h" +-#include "dfx_trace_dlsym.h" +-#include "dwarf_define.h" +-#include "elf_factory.h" +-#include "string_util.h" +-#include "unwinder_config.h" +- +-namespace OHOS { +-namespace HiviewDFX { +-namespace { +-#undef LOG_DOMAIN +-#undef LOG_TAG +-#define LOG_DOMAIN 0xD002D11 +-#define LOG_TAG "DfxElf" +-#if is_ohos && !is_mingw +-enum HdrSection { +- SECTION_TEXT = 0, +- SECTION_ARMEXIDX = 1, +- SECTION_DYNAMIC = 2, +- SECTION_EHFRAMEHDR = 3 +-}; +-#endif +-} +- +-void DfxElf::Init() +-{ +- uti_.namePtr = 0; +- uti_.format = -1; +- hasTableInfo_ = false; +-} +- +-void DfxElf::Clear() +-{ +- if (elfParse_ != nullptr) { +- elfParse_.reset(); +- elfParse_ = nullptr; +- } +- +- if (mmap_ != nullptr) { +- mmap_->Clear(); +- mmap_.reset(); +- mmap_ = nullptr; +- } +-} +- +-bool DfxElf::InitHeaders() +-{ +- if (mmap_ == nullptr) { +- return false; +- } +- +- if (elfParse_ != nullptr) { +- return true; +- } +- +- uint8_t ident[SELFMAG + 1]; +- if (!Read(0, ident, SELFMAG) || !IsValidElf(ident, SELFMAG)) { +- return false; +- } +- +- if (!Read(EI_CLASS, &classType_, sizeof(uint8_t))) { +- return false; +- } +- +- if (classType_ == ELFCLASS32) { +- elfParse_ = std::unique_ptr(new ElfParser32(mmap_)); +- } else if (classType_ == ELFCLASS64) { +- elfParse_ = std::unique_ptr(new ElfParser64(mmap_)); +- } else { +- DFXLOGW("InitHeaders failed, classType: %{public}d", classType_); +- return false; +- } +- if (elfParse_ != nullptr) { +- valid_ = true; +- elfParse_->InitHeaders(); +- } +- return valid_; +-} +- +-bool DfxElf::IsValid() +-{ +- if (valid_ == false) { +- InitHeaders(); +- } +- return valid_; +-} +- +-uint8_t DfxElf::GetClassType() +-{ +- if (IsValid()) { +- return classType_; +- } +- return ELFCLASSNONE; +-} +- +-ArchType DfxElf::GetArchType() +-{ +- if (IsValid()) { +- elfParse_->GetArchType(); +- } +- return ARCH_UNKNOWN; +-} +- +-int64_t DfxElf::GetLoadBias() +-{ +- if (loadBias_ == 0) { +- if (IsValid()) { +- loadBias_ = elfParse_->GetLoadBias(); +- DFXLOGU("Elf loadBias: %{public}" PRIx64 "", (uint64_t)loadBias_); +- } +- } +- return loadBias_; +-} +- +-uint64_t DfxElf::GetLoadBase(uint64_t mapStart, uint64_t mapOffset) +-{ +- if (loadBase_ == static_cast(-1)) { +- if (IsValid()) { +- DFXLOGU("mapStart: %{public}" PRIx64 ", mapOffset: %{public}" PRIx64 "", +- (uint64_t)mapStart, (uint64_t)mapOffset); +- loadBase_ = mapStart - mapOffset - static_cast(GetLoadBias()); +- DFXLOGU("Elf loadBase: %{public}" PRIx64 "", (uint64_t)loadBase_); +- } +- } +- return loadBase_; +-} +- +-void DfxElf::SetLoadBase(uint64_t base) +-{ +- loadBase_ = base; +-} +- +-void DfxElf::SetBaseOffset(uint64_t offset) +-{ +- baseOffset_ = offset; +-} +- +-uint64_t DfxElf::GetBaseOffset() +-{ +- return baseOffset_; +-} +- +-uint64_t DfxElf::GetStartPc() +-{ +- if (startPc_ == static_cast(-1)) { +- if (IsValid()) { +- auto startVaddr = elfParse_->GetStartVaddr(); +- if (loadBase_ != static_cast(-1) && startVaddr != static_cast(-1)) { +- startPc_ = startVaddr + loadBase_; +- DFXLOGU("Elf startPc: %{public}" PRIx64 "", (uint64_t)startPc_); +- } +- } +- } +- return startPc_; +-} +- +-uint64_t DfxElf::GetStartVaddr() +-{ +- if (IsValid()) { +- return elfParse_->GetStartVaddr(); +- } +- return 0; +-} +- +-uint64_t DfxElf::GetEndPc() +-{ +- if (endPc_ == 0) { +- if (IsValid()) { +- auto endVaddr = elfParse_->GetEndVaddr(); +- if (loadBase_ != static_cast(-1) && endVaddr != 0) { +- endPc_ = endVaddr + loadBase_; +- DFXLOGU("Elf endPc: %{public}" PRIx64 "", (uint64_t)endPc_); +- } +- } +- } +- return endPc_; +-} +- +-uint64_t DfxElf::GetEndVaddr() +-{ +- if (IsValid()) { +- return elfParse_->GetEndVaddr(); +- } +- return 0; +-} +- +-uint64_t DfxElf::GetStartOffset() +-{ +- if (IsValid()) { +- return elfParse_->GetStartOffset(); +- } +- return 0; +-} +- +-uint64_t DfxElf::GetRelPc(uint64_t pc, uint64_t mapStart, uint64_t mapOffset) +-{ +- return (pc - GetLoadBase(mapStart, mapOffset)); +-} +- +-uint64_t DfxElf::GetElfSize() +-{ +- if (!IsValid()) { +- return 0; +- } +- return elfParse_->GetElfSize(); +-} +- +-std::string DfxElf::GetElfName() +-{ +- if (!IsValid()) { +- return ""; +- } +- return elfParse_->GetElfName(); +-} +- +-void DfxElf::SetBuildId(const std::string& buildId) +-{ +- buildId_ = buildId; +-} +- +-std::string DfxElf::GetBuildId(uint64_t noteAddr, uint64_t noteSize) +-{ +- return ElfParser::ParseHexBuildId(noteAddr, noteSize); +-} +- +-std::string DfxElf::GetBuildId() +-{ +- if (buildId_.empty()) { +- if (!IsValid()) { +- return ""; +- } +- return elfParse_->GetBuildId(); +- } +- return buildId_; +-} +- +- +-uintptr_t DfxElf::GetGlobalPointer() +-{ +- if (!IsValid()) { +- return 0; +- } +- return elfParse_->GetGlobalPointer(); +-} +- +-bool DfxElf::GetSectionInfo(ShdrInfo& shdr, const std::string secName) +-{ +- if (!IsValid()) { +- return false; +- } +- return elfParse_->GetSectionInfo(shdr, secName); +-} +- +-bool DfxElf::GetSectionData(unsigned char* buf, uint64_t size, std::string secName) +-{ +- if (!IsValid()) { +- return false; +- } +- return elfParse_->GetSectionData(buf, size, secName); +-} +- +-GnuDebugDataHdr DfxElf::GetGnuDebugDataHdr() +-{ +- if (!IsValid()) { +- return {}; +- } +- return elfParse_->GetGnuDebugDataHdr(); +-} +- +-bool DfxElf::IsMiniDebugInfoValid() +-{ +- if (miniDebugInfo_ == nullptr) { +-#if defined(ENABLE_MINIDEBUGINFO) +- MiniDebugInfoFactory miniDebugInfoFactory(elfParse_->GetGnuDebugDataHdr()); +- miniDebugInfo_ = miniDebugInfoFactory.Create(); +-#endif +- } +- return miniDebugInfo_ != nullptr; +-} +- +-const std::set& DfxElf::GetFuncSymbols() +-{ +- if (!IsValid() || !funcSymbols_.empty()) { +- return funcSymbols_; +- } +- if (IsMiniDebugInfoValid()) { +- funcSymbols_ = miniDebugInfo_->elfParse_->GetFuncSymbols(); +- DFXLOGU("Get MiniDebugInfo FuncSymbols, size: %{public}zu", funcSymbols_.size()); +- } +- const auto &symbols = elfParse_->GetFuncSymbols(); +- funcSymbols_.insert(symbols.begin(), symbols.end()); +- DFXLOGU("GetFuncSymbols, size: %{public}zu", funcSymbols_.size()); +- return funcSymbols_; +-} +- +-bool DfxElf::GetFuncInfoLazily(uint64_t addr, ElfSymbol& elfSymbol) +-{ +- DFX_TRACE_SCOPED_DLSYM("GetFuncInfoLazily"); +- if (FindFuncSymbol(addr, funcSymbols_, elfSymbol)) { +- return true; +- } +- bool findSymbol = elfParse_->GetFuncSymbolByAddr(addr, elfSymbol); +- if (!findSymbol && IsMiniDebugInfoValid()) { +- findSymbol = miniDebugInfo_->elfParse_->GetFuncSymbolByAddr(addr, elfSymbol); +- } +- +- if (findSymbol) { +- funcSymbols_.emplace(elfSymbol); +- DFXLOGU("GetFuncInfoLazily, size: %{public}zu", funcSymbols_.size()); +- } +- return findSymbol; +-} +- +-bool DfxElf::GetFuncInfo(uint64_t addr, ElfSymbol& elfSymbol) +-{ +- if (!IsValid()) { +- return false; +- } +- if (UnwinderConfig::GetEnableLoadSymbolLazily()) { +- return GetFuncInfoLazily(addr, elfSymbol); +- } +- +- const auto &symbols = GetFuncSymbols(); +- return FindFuncSymbol(addr, symbols, elfSymbol); +-} +- +-bool DfxElf::FindFuncSymbol(uint64_t addr, const std::set& symbols, ElfSymbol& elfSymbol) +-{ +- DFX_TRACE_SCOPED_DLSYM("FindFuncSymbol"); +- if (symbols.empty()) { +- return false; +- } +- // Find the first position that is not less than value +- ElfSymbol tmpSym; +- tmpSym.value = addr; +- auto next = symbols.upper_bound(tmpSym); +- if (next != symbols.begin()) { +- next--; +- } +- if (next->value <= addr && addr < (next->value + next->size)) { +- elfSymbol = *next; +- return true; +- } +- return false; +-} +- +-const std::unordered_map& DfxElf::GetPtLoads() +-{ +- return elfParse_->GetPtLoads(); +-} +- +-bool DfxElf::FillUnwindTableByExidx(ShdrInfo shdr, uintptr_t loadBase, struct UnwindTableInfo* uti) +-{ +- if (uti == nullptr) { +- return false; +- } +- uti->gp = 0; +- uti->tableData = loadBase + shdr.addr; +- uti->tableLen = shdr.size; +- INSTR_STATISTIC(InstructionEntriesArmExidx, shdr.size, 0); +- uti->format = UNW_INFO_FORMAT_ARM_EXIDX; +- DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, +- (uint64_t)uti->tableData, (int)uti->tableLen); +- return true; +-} +- +-#if is_ohos && !is_mingw +-bool DfxElf::FillUnwindTableByEhhdrLocal(struct DwarfEhFrameHdr* hdr, struct UnwindTableInfo* uti) +-{ +- if (hdr == nullptr) { +- return false; +- } +- if (hdr->version != DW_EH_VERSION) { +- DFXLOGE("[%{public}d]: version(%{public}d) error", __LINE__, hdr->version); +- return false; +- } +- +- uintptr_t ptr = (uintptr_t)(&(hdr->ehFrame)); +- DFXLOGU("[%{public}d]: hdr: %{public}" PRIx64 ", ehFrame: %{public}" PRIx64 "", __LINE__, +- (uint64_t)hdr, (uint64_t)ptr); +- auto memory = std::make_shared(UNWIND_TYPE_LOCAL); +- DFXLOGU("[%{public}d]: gp: %{public}" PRIx64 ", ehFramePtrEnc: %{public}x, fdeCountEnc: %{public}x", __LINE__, +- (uint64_t)uti->gp, hdr->ehFramePtrEnc, hdr->fdeCountEnc); +- memory->SetDataOffset(uti->gp); +- MAYBE_UNUSED uintptr_t ehFrameStart = memory->ReadEncodedValue(ptr, hdr->ehFramePtrEnc); +- uintptr_t fdeCount = memory->ReadEncodedValue(ptr, hdr->fdeCountEnc); +- DFXLOGU("[%{public}d]: ehFrameStart: %{public}" PRIx64 ", fdeCount: %{public}d", __LINE__, +- (uint64_t)ehFrameStart, (int)fdeCount); +- +- if (hdr->tableEnc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { +- DFXLOGU("tableEnc: %{public}x", hdr->tableEnc); +- if (hdr->fdeCountEnc == DW_EH_PE_omit) { +- fdeCount = ~0UL; +- } +- if (hdr->ehFramePtrEnc == DW_EH_PE_omit) { +- DFXLOGE("ehFramePtrEnc(%{public}x) error", hdr->ehFramePtrEnc); +- return false; +- } +- uti->isLinear = true; +- uti->tableLen = fdeCount; +- uti->tableData = ehFrameStart; +- } else { +- uti->isLinear = false; +- uti->tableLen = (fdeCount * sizeof(DwarfTableEntry)) / sizeof(uintptr_t); +- uti->tableData = ptr; +- uti->segbase = (uintptr_t)hdr; +- } +- uti->format = UNW_INFO_FORMAT_REMOTE_TABLE; +- DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, +- (uint64_t)uti->tableData, (int)uti->tableLen); +- return true; +-} +-#endif +- +-bool DfxElf::FillUnwindTableByEhhdr(struct DwarfEhFrameHdr* hdr, uintptr_t shdrBase, struct UnwindTableInfo* uti) +-{ +- if ((hdr == nullptr) || (uti == nullptr)) { +- return false; +- } +- if (hdr->version != DW_EH_VERSION) { +- DFXLOGE("[%{public}d]: version(%{public}d) error", __LINE__, hdr->version); +- return false; +- } +- uintptr_t ptr = (uintptr_t)(&(hdr->ehFrame)); +- DFXLOGU("[%{public}d]: hdr: %{public}" PRIx64 ", ehFrame: %{public}" PRIx64 "", __LINE__, +- (uint64_t)hdr, (uint64_t)ptr); +- +- uti->gp = GetGlobalPointer(); +- DFXLOGU("[%{public}d]: gp: %{public}" PRIx64 ", ehFramePtrEnc: %{public}x, fdeCountEnc: %{public}x", __LINE__, +- (uint64_t)uti->gp, hdr->ehFramePtrEnc, hdr->fdeCountEnc); +- mmap_->SetDataOffset(uti->gp); +- auto ptrOffset = ptr - reinterpret_cast(GetMmapPtr()); +- MAYBE_UNUSED uintptr_t ehFrameStart = mmap_->ReadEncodedValue(ptrOffset, hdr->ehFramePtrEnc); +- uintptr_t fdeCount = mmap_->ReadEncodedValue(ptrOffset, hdr->fdeCountEnc); +- DFXLOGU("[%{public}d]: ehFrameStart: %{public}" PRIx64 ", fdeCount: %{public}d", __LINE__, +- (uint64_t)ehFrameStart, (int)fdeCount); +- ptr = reinterpret_cast(GetMmapPtr()) + ptrOffset; +- +- if (hdr->tableEnc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { +- DFXLOGU("[%{public}d]: tableEnc: %{public}x", __LINE__, hdr->tableEnc); +- if (hdr->fdeCountEnc == DW_EH_PE_omit) { +- fdeCount = ~0UL; +- } +- if (hdr->ehFramePtrEnc == DW_EH_PE_omit) { +- DFXLOGE("[%{public}d]: ehFramePtrEnc(%{public}x) error", __LINE__, hdr->ehFramePtrEnc); +- return false; +- } +- uti->isLinear = true; +- uti->tableLen = fdeCount; +- uti->tableData = shdrBase + ehFrameStart; +- uti->segbase = shdrBase; +- } else { +- uti->isLinear = false; +- uti->tableLen = (fdeCount * sizeof(DwarfTableEntry)) / sizeof(uintptr_t); +- uti->tableData = shdrBase + ptr - (uintptr_t)hdr; +- uti->segbase = shdrBase; +- } +- uti->format = UNW_INFO_FORMAT_REMOTE_TABLE; +- DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, +- (uint64_t)uti->tableData, (int)uti->tableLen); +- return true; +-} +- +-int DfxElf::FindUnwindTableInfo(uintptr_t pc, std::shared_ptr map, struct UnwindTableInfo& uti) +-{ +- if (hasTableInfo_ && pc >= uti_.startPc && pc < uti_.endPc) { +- uti = uti_; +- DFXLOGU("FindUnwindTableInfo had found"); +- return UNW_ERROR_NONE; +- } +- if (map == nullptr) { +- return UNW_ERROR_INVALID_MAP; +- } +- uintptr_t loadBase = GetLoadBase(map->begin, map->offset); +- uti.startPc = GetStartPc(); +- uti.endPc = GetEndPc(); +- if (pc < uti.startPc || pc >= uti.endPc) { +- DFXLOGU("Elf startPc: %{public}" PRIx64 ", endPc: %{public}" PRIx64 "", +- (uint64_t)uti.startPc, (uint64_t)uti.endPc); +- return UNW_ERROR_PC_NOT_IN_UNWIND_INFO; +- } +- +- ShdrInfo shdr; +-#if defined(__arm__) +- if (GetSectionInfo(shdr, ARM_EXIDX)) { +- hasTableInfo_ = FillUnwindTableByExidx(shdr, loadBase, &uti); +- } +-#endif +- +- if (!hasTableInfo_) { +- struct DwarfEhFrameHdr* hdr = nullptr; +- struct DwarfEhFrameHdr synthHdr; +- if (GetSectionInfo(shdr, EH_FRAME_HDR) && GetMmapPtr() != nullptr) { +- INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); +- hdr = (struct DwarfEhFrameHdr *) (shdr.offset + (char *)GetMmapPtr()); +- } else if (GetSectionInfo(shdr, EH_FRAME) && GetMmapPtr() != nullptr) { +- DFXLOGW("[%{public}d]: Elf(%{public}s) no found .eh_frame_hdr section, " \ +- "using synthetic .eh_frame section", __LINE__, map->name.c_str()); +- INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); +- synthHdr.version = DW_EH_VERSION; +- synthHdr.ehFramePtrEnc = DW_EH_PE_absptr | +- ((sizeof(ElfW(Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); // 4 : four bytes +- synthHdr.fdeCountEnc = DW_EH_PE_omit; +- synthHdr.tableEnc = DW_EH_PE_omit; +- synthHdr.ehFrame = (ElfW(Addr))(shdr.offset + (char*)GetMmapPtr()); +- hdr = &synthHdr; +- } +- uintptr_t shdrBase = static_cast(loadBase + shdr.addr); +- hasTableInfo_ = FillUnwindTableByEhhdr(hdr, shdrBase, &uti); +- } +- +- if (hasTableInfo_) { +- uti_ = uti; +- return UNW_ERROR_NONE; +- } +- return UNW_ERROR_NO_UNWIND_INFO; +-} +- +-int DfxElf::FindUnwindTableLocal(uintptr_t pc, struct UnwindTableInfo& uti) +-{ +-#if is_ohos && !is_mingw +- DlCbData cbData; +- (void)memset_s(&cbData, sizeof(cbData), 0, sizeof(cbData)); +- cbData.pc = pc; +- cbData.uti.format = -1; +- int ret = dl_iterate_phdr(DlPhdrCb, &cbData); +- if (ret > 0) { +- if (cbData.uti.format != -1) { +- uti = cbData.uti; +- return UNW_ERROR_NONE; +- } +- } +- return UNW_ERROR_NO_UNWIND_INFO; +-#else +- return UNW_ERROR_UNSUPPORTED_VERSION; +-#endif +-} +- +-#if is_ohos && !is_mingw +-bool DfxElf::FindSection(struct dl_phdr_info* info, const std::string secName, ShdrInfo& shdr) +-{ +- if (info == nullptr) { +- return false; +- } +- const char* file = info->dlpi_name; +- if (strlen(file) == 0) { +- file = PROC_SELF_EXE_PATH; +- } +- RegularElfFactory elfFactory(file); +- auto elf = elfFactory.Create(); +- if (elf == nullptr) { +- return false; +- } +- +- return elf->GetSectionInfo(shdr, secName); +-} +- +-void DfxElf::ParsePhdr(struct dl_phdr_info* info, const ElfW(Phdr)* (&pHdrSections)[4], const uintptr_t pc) +-{ +- const ElfW(Phdr)* phdr = info->dlpi_phdr; +- for (size_t i = 0; i < info->dlpi_phnum && phdr != nullptr; i++, phdr++) { +- switch (phdr->p_type) { +- case PT_LOAD: { +- ElfW(Addr) vaddr = phdr->p_vaddr + info->dlpi_addr; +- if (pc >= vaddr && pc < vaddr + phdr->p_memsz) { +- pHdrSections[SECTION_TEXT] = phdr; +- } +- break; +- } +-#if defined(__arm__) +- case PT_ARM_EXIDX: { +- pHdrSections[SECTION_ARMEXIDX] = phdr; +- break; +- } +-#endif +- case PT_GNU_EH_FRAME: { +- pHdrSections[SECTION_EHFRAMEHDR] = phdr; +- break; +- } +- case PT_DYNAMIC: { +- pHdrSections[SECTION_DYNAMIC] = phdr; +- break; +- } +- default: +- break; +- } +- } +-} +- +-bool DfxElf::ProccessDynamic(const ElfW(Phdr)* pDynamic, ElfW(Addr) loadBase, UnwindTableInfo* uti) +-{ +- ElfW(Dyn)* dyn = reinterpret_cast(pDynamic->p_vaddr + loadBase); +- if (dyn == nullptr) { +- return false; +- } +- for (; dyn->d_tag != DT_NULL; ++dyn) { +- if (dyn->d_tag == DT_PLTGOT) { +- uti->gp = dyn->d_un.d_ptr; +- break; +- } +- } +- return true; +-} +- +-struct DwarfEhFrameHdr* DfxElf::InitHdr(struct DwarfEhFrameHdr& synthHdr, +- struct dl_phdr_info* info, const ElfW(Phdr)* pEhHdr) +-{ +- struct DwarfEhFrameHdr* hdr = nullptr; +- if (pEhHdr) { +- INSTR_STATISTIC(InstructionEntriesEhFrame, pEhHdr->p_memsz, 0); +- hdr = reinterpret_cast(pEhHdr->p_vaddr + info->dlpi_addr); +- } else { +- ShdrInfo shdr; +- if (FindSection(info, EH_FRAME, shdr)) { +- DFXLOGW("[%{public}d]: Elf(%{public}s) no found .eh_frame_hdr section, " \ +- "using synthetic .eh_frame section", __LINE__, info->dlpi_name); +- INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); +- synthHdr.version = DW_EH_VERSION; +- synthHdr.ehFramePtrEnc = DW_EH_PE_absptr | +- ((sizeof(ElfW(Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); // 4 : four bytes +- synthHdr.fdeCountEnc = DW_EH_PE_omit; +- synthHdr.tableEnc = DW_EH_PE_omit; +- synthHdr.ehFrame = (ElfW(Addr))(shdr.addr + info->dlpi_addr); +- hdr = &synthHdr; +- } +- } +- return hdr; +-} +- +-int DfxElf::DlPhdrCb(struct dl_phdr_info* info, size_t size, void* data) +-{ +- struct DlCbData* cbData = reinterpret_cast(data); +- if ((info == nullptr) || (cbData == nullptr)) { +- return -1; +- } +- UnwindTableInfo* uti = &cbData->uti; +- uintptr_t pc = cbData->pc; +- const int numOfPhdrSections = 4; +- const ElfW(Phdr)* pHdrSections[numOfPhdrSections] = {nullptr}; +- ParsePhdr(info, pHdrSections, pc); +- +- if (pHdrSections[SECTION_TEXT] == nullptr) { +- return 0; +- } +- ElfW(Addr) loadBase = info->dlpi_addr; +- uti->startPc = pHdrSections[SECTION_TEXT]->p_vaddr + loadBase; +- uti->endPc = uti->startPc + pHdrSections[SECTION_TEXT]->p_memsz; +- DFXLOGU("Elf name: %{public}s", info->dlpi_name); +- uti->namePtr = reinterpret_cast(info->dlpi_name); +- +-#if defined(__arm__) +- if (pHdrSections[SECTION_ARMEXIDX]) { +- ShdrInfo shdr; +- shdr.addr = pHdrSections[SECTION_ARMEXIDX]->p_vaddr; +- shdr.size = pHdrSections[SECTION_ARMEXIDX]->p_memsz; +- return FillUnwindTableByExidx(shdr, loadBase, uti); +- } +-#endif +- +- if (pHdrSections[SECTION_DYNAMIC]) { +- if (!ProccessDynamic(pHdrSections[SECTION_DYNAMIC], loadBase, uti)) { +- return 0; +- } +- } else { +- uti->gp = 0; +- } +- +- struct DwarfEhFrameHdr synthHdr; +- struct DwarfEhFrameHdr* hdr = InitHdr(synthHdr, info, pHdrSections[SECTION_EHFRAMEHDR]); +- +- return FillUnwindTableByEhhdrLocal(hdr, uti); +-} +-#endif +- +-bool DfxElf::Read(uintptr_t pos, void* buf, size_t size) +-{ +- if ((mmap_ != nullptr) && (mmap_->Read(pos, buf, size) == size)) { +- return true; +- } +- return false; +-} +- +-const uint8_t* DfxElf::GetMmapPtr() +-{ +- if (mmap_ == nullptr) { +- return nullptr; +- } +- return static_cast(mmap_->Get()); +-} +- +-size_t DfxElf::GetMmapSize() +-{ +- if (mmap_ == nullptr) { +- return 0; +- } +- return mmap_->Size(); +-} +- +-bool DfxElf::IsValidElf(const void* ptr, size_t size) +-{ +- if (ptr == nullptr) { +- return false; +- } +- +- if (memcmp(ptr, ELFMAG, size) != 0) { +- DFXLOGD("Invalid elf hdr?"); +- return false; +- } +- return true; +-} +-} // namespace HiviewDFX +-} // namespace OHOS ++/* ++ * Copyright (c) 2021-2025 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. ++ */ ++ ++#include "dfx_elf.h" ++ ++#include ++#include ++#include ++#include ++#include ++#if is_mingw || is_mac ++#include "dfx_nonlinux_define.h" ++#else ++#include ++#include ++#endif ++#include ++#include ++#include ++#include ++ ++#include "dfx_define.h" ++#include "dfx_log.h" ++#include "dfx_instr_statistic.h" ++#include "dfx_util.h" ++#include "dfx_maps.h" ++#include "dfx_trace_dlsym.h" ++#include "dwarf_define.h" ++#include "elf_factory.h" ++#include "string_util.h" ++#include "unwinder_config.h" ++ ++namespace OHOS { ++namespace HiviewDFX { ++namespace { ++#undef LOG_DOMAIN ++#undef LOG_TAG ++#define LOG_DOMAIN 0xD002D11 ++#define LOG_TAG "DfxElf" ++#if is_ohos && !is_mingw ++enum HdrSection { ++ SECTION_TEXT = 0, ++ SECTION_ARMEXIDX = 1, ++ SECTION_DYNAMIC = 2, ++ SECTION_EHFRAMEHDR = 3 ++}; ++#endif ++} ++ ++void DfxElf::Init() ++{ ++ uti_.namePtr = 0; ++ uti_.format = -1; ++ hasTableInfo_ = false; ++} ++ ++void DfxElf::Clear() ++{ ++ if (elfParse_ != nullptr) { ++ elfParse_.reset(); ++ elfParse_ = nullptr; ++ } ++ ++ if (mmap_ != nullptr) { ++ mmap_->Clear(); ++ mmap_.reset(); ++ mmap_ = nullptr; ++ } ++} ++ ++bool DfxElf::InitHeaders() ++{ ++ if (mmap_ == nullptr) { ++ return false; ++ } ++ ++ if (elfParse_ != nullptr) { ++ return true; ++ } ++ ++ uint8_t ident[SELFMAG + 1]; ++ if (!Read(0, ident, SELFMAG) || !IsValidElf(ident, SELFMAG)) { ++ return false; ++ } ++ ++ if (!Read(EI_CLASS, &classType_, sizeof(uint8_t))) { ++ return false; ++ } ++ ++ if (classType_ == ELFCLASS32) { ++ elfParse_ = std::unique_ptr(new ElfParser32(mmap_)); ++ } else if (classType_ == ELFCLASS64) { ++ elfParse_ = std::unique_ptr(new ElfParser64(mmap_)); ++ } else { ++ DFXLOGW("InitHeaders failed, classType: %{public}d", classType_); ++ return false; ++ } ++ if (elfParse_ != nullptr) { ++ valid_ = true; ++ elfParse_->InitHeaders(); ++ } ++ return valid_; ++} ++ ++bool DfxElf::IsValid() ++{ ++ if (valid_ == false) { ++ InitHeaders(); ++ } ++ return valid_; ++} ++ ++uint8_t DfxElf::GetClassType() ++{ ++ if (IsValid()) { ++ return classType_; ++ } ++ return ELFCLASSNONE; ++} ++ ++ArchType DfxElf::GetArchType() ++{ ++ if (IsValid()) { ++ elfParse_->GetArchType(); ++ } ++ return ARCH_UNKNOWN; ++} ++ ++int64_t DfxElf::GetLoadBias() ++{ ++ if (loadBias_ == 0) { ++ if (IsValid()) { ++ loadBias_ = elfParse_->GetLoadBias(); ++ DFXLOGU("Elf loadBias: %{public}" PRIx64 "", (uint64_t)loadBias_); ++ } ++ } ++ return loadBias_; ++} ++ ++uint64_t DfxElf::GetLoadBase(uint64_t mapStart, uint64_t mapOffset) ++{ ++ if (loadBase_ == static_cast(-1)) { ++ if (IsValid()) { ++ DFXLOGU("mapStart: %{public}" PRIx64 ", mapOffset: %{public}" PRIx64 "", ++ (uint64_t)mapStart, (uint64_t)mapOffset); ++ loadBase_ = mapStart - mapOffset - static_cast(GetLoadBias()); ++ DFXLOGU("Elf loadBase: %{public}" PRIx64 "", (uint64_t)loadBase_); ++ } ++ } ++ return loadBase_; ++} ++ ++void DfxElf::SetLoadBase(uint64_t base) ++{ ++ loadBase_ = base; ++} ++ ++void DfxElf::SetBaseOffset(uint64_t offset) ++{ ++ baseOffset_ = offset; ++} ++ ++uint64_t DfxElf::GetBaseOffset() ++{ ++ return baseOffset_; ++} ++ ++uint64_t DfxElf::GetStartPc() ++{ ++ if (startPc_ == static_cast(-1)) { ++ if (IsValid()) { ++ auto startVaddr = elfParse_->GetStartVaddr(); ++ if (loadBase_ != static_cast(-1) && startVaddr != static_cast(-1)) { ++ startPc_ = startVaddr + loadBase_; ++ DFXLOGU("Elf startPc: %{public}" PRIx64 "", (uint64_t)startPc_); ++ } ++ } ++ } ++ return startPc_; ++} ++ ++uint64_t DfxElf::GetStartVaddr() ++{ ++ if (IsValid()) { ++ return elfParse_->GetStartVaddr(); ++ } ++ return 0; ++} ++ ++uint64_t DfxElf::GetEndPc() ++{ ++ if (endPc_ == 0) { ++ if (IsValid()) { ++ auto endVaddr = elfParse_->GetEndVaddr(); ++ if (loadBase_ != static_cast(-1) && endVaddr != 0) { ++ endPc_ = endVaddr + loadBase_; ++ DFXLOGU("Elf endPc: %{public}" PRIx64 "", (uint64_t)endPc_); ++ } ++ } ++ } ++ return endPc_; ++} ++ ++uint64_t DfxElf::GetEndVaddr() ++{ ++ if (IsValid()) { ++ return elfParse_->GetEndVaddr(); ++ } ++ return 0; ++} ++ ++uint64_t DfxElf::GetStartOffset() ++{ ++ if (IsValid()) { ++ return elfParse_->GetStartOffset(); ++ } ++ return 0; ++} ++ ++uint64_t DfxElf::GetRelPc(uint64_t pc, uint64_t mapStart, uint64_t mapOffset) ++{ ++ return (pc - GetLoadBase(mapStart, mapOffset)); ++} ++ ++uint64_t DfxElf::GetElfSize() ++{ ++ if (!IsValid()) { ++ return 0; ++ } ++ return elfParse_->GetElfSize(); ++} ++ ++std::string DfxElf::GetElfName() ++{ ++ if (!IsValid()) { ++ return ""; ++ } ++ return elfParse_->GetElfName(); ++} ++ ++void DfxElf::SetBuildId(const std::string& buildId) ++{ ++ buildId_ = buildId; ++} ++ ++std::string DfxElf::GetBuildId(uint64_t noteAddr, uint64_t noteSize) ++{ ++ return ElfParser::ParseHexBuildId(noteAddr, noteSize); ++} ++ ++std::string DfxElf::GetBuildId() ++{ ++ if (buildId_.empty()) { ++ if (!IsValid()) { ++ return ""; ++ } ++ return elfParse_->GetBuildId(); ++ } ++ return buildId_; ++} ++ ++ ++uintptr_t DfxElf::GetGlobalPointer() ++{ ++ if (!IsValid()) { ++ return 0; ++ } ++ return elfParse_->GetGlobalPointer(); ++} ++ ++bool DfxElf::GetSectionInfo(ShdrInfo& shdr, const std::string secName) ++{ ++ if (!IsValid()) { ++ return false; ++ } ++ return elfParse_->GetSectionInfo(shdr, secName); ++} ++ ++bool DfxElf::GetSectionData(unsigned char* buf, uint64_t size, std::string secName) ++{ ++ if (!IsValid()) { ++ return false; ++ } ++ return elfParse_->GetSectionData(buf, size, secName); ++} ++ ++GnuDebugDataHdr DfxElf::GetGnuDebugDataHdr() ++{ ++ if (!IsValid()) { ++ return {}; ++ } ++ return elfParse_->GetGnuDebugDataHdr(); ++} ++ ++bool DfxElf::IsMiniDebugInfoValid() ++{ ++ if (miniDebugInfo_ == nullptr) { ++#if defined(ENABLE_MINIDEBUGINFO) ++ MiniDebugInfoFactory miniDebugInfoFactory(elfParse_->GetGnuDebugDataHdr()); ++ miniDebugInfo_ = miniDebugInfoFactory.Create(); ++#endif ++ } ++ return miniDebugInfo_ != nullptr; ++} ++ ++const std::set& DfxElf::GetFuncSymbols() ++{ ++ if (!IsValid() || !funcSymbols_.empty()) { ++ return funcSymbols_; ++ } ++ if (IsMiniDebugInfoValid()) { ++ funcSymbols_ = miniDebugInfo_->elfParse_->GetFuncSymbols(); ++ DFXLOGU("Get MiniDebugInfo FuncSymbols, size: %{public}zu", funcSymbols_.size()); ++ } ++ const auto &symbols = elfParse_->GetFuncSymbols(); ++ funcSymbols_.insert(symbols.begin(), symbols.end()); ++ DFXLOGU("GetFuncSymbols, size: %{public}zu", funcSymbols_.size()); ++ return funcSymbols_; ++} ++ ++bool DfxElf::GetFuncInfoLazily(uint64_t addr, ElfSymbol& elfSymbol) ++{ ++ DFX_TRACE_SCOPED_DLSYM("GetFuncInfoLazily"); ++ if (FindFuncSymbol(addr, funcSymbols_, elfSymbol)) { ++ return true; ++ } ++ bool findSymbol = elfParse_->GetFuncSymbolByAddr(addr, elfSymbol); ++ if (!findSymbol && IsMiniDebugInfoValid()) { ++ findSymbol = miniDebugInfo_->elfParse_->GetFuncSymbolByAddr(addr, elfSymbol); ++ } ++ ++ if (findSymbol) { ++ funcSymbols_.emplace(elfSymbol); ++ DFXLOGU("GetFuncInfoLazily, size: %{public}zu", funcSymbols_.size()); ++ } ++ return findSymbol; ++} ++ ++bool DfxElf::GetFuncInfo(uint64_t addr, ElfSymbol& elfSymbol) ++{ ++ if (!IsValid()) { ++ return false; ++ } ++ if (UnwinderConfig::GetEnableLoadSymbolLazily()) { ++ return GetFuncInfoLazily(addr, elfSymbol); ++ } ++ ++ const auto &symbols = GetFuncSymbols(); ++ return FindFuncSymbol(addr, symbols, elfSymbol); ++} ++ ++bool DfxElf::FindFuncSymbol(uint64_t addr, const std::set& symbols, ElfSymbol& elfSymbol) ++{ ++ DFX_TRACE_SCOPED_DLSYM("FindFuncSymbol"); ++ if (symbols.empty()) { ++ return false; ++ } ++ // Find the first position that is not less than value ++ ElfSymbol tmpSym; ++ tmpSym.value = addr; ++ auto next = symbols.upper_bound(tmpSym); ++ if (next != symbols.begin()) { ++ next--; ++ } ++ if (next->value <= addr && addr < (next->value + next->size)) { ++ elfSymbol = *next; ++ return true; ++ } ++ return false; ++} ++ ++const std::unordered_map& DfxElf::GetPtLoads() ++{ ++ return elfParse_->GetPtLoads(); ++} ++ ++bool DfxElf::FillUnwindTableByExidx(ShdrInfo shdr, uintptr_t loadBase, struct UnwindTableInfo* uti) ++{ ++ if (uti == nullptr) { ++ return false; ++ } ++ uti->gp = 0; ++ uti->tableData = loadBase + shdr.addr; ++ uti->tableLen = shdr.size; ++ INSTR_STATISTIC(InstructionEntriesArmExidx, shdr.size, 0); ++ uti->format = UNW_INFO_FORMAT_ARM_EXIDX; ++ DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, ++ (uint64_t)uti->tableData, (int)uti->tableLen); ++ return true; ++} ++ ++#if is_ohos && !is_mingw ++bool DfxElf::FillUnwindTableByEhhdrLocal(struct DwarfEhFrameHdr* hdr, struct UnwindTableInfo* uti) ++{ ++ if (hdr == nullptr) { ++ return false; ++ } ++ if (hdr->version != DW_EH_VERSION) { ++ DFXLOGE("[%{public}d]: version(%{public}d) error", __LINE__, hdr->version); ++ return false; ++ } ++ ++ uintptr_t ptr = (uintptr_t)(&(hdr->ehFrame)); ++ DFXLOGU("[%{public}d]: hdr: %{public}" PRIx64 ", ehFrame: %{public}" PRIx64 "", __LINE__, ++ (uint64_t)hdr, (uint64_t)ptr); ++ auto memory = std::make_shared(UNWIND_TYPE_LOCAL); ++ DFXLOGU("[%{public}d]: gp: %{public}" PRIx64 ", ehFramePtrEnc: %{public}x, fdeCountEnc: %{public}x", __LINE__, ++ (uint64_t)uti->gp, hdr->ehFramePtrEnc, hdr->fdeCountEnc); ++ memory->SetDataOffset(uti->gp); ++ MAYBE_UNUSED uintptr_t ehFrameStart = memory->ReadEncodedValue(ptr, hdr->ehFramePtrEnc); ++ uintptr_t fdeCount = memory->ReadEncodedValue(ptr, hdr->fdeCountEnc); ++ DFXLOGU("[%{public}d]: ehFrameStart: %{public}" PRIx64 ", fdeCount: %{public}d", __LINE__, ++ (uint64_t)ehFrameStart, (int)fdeCount); ++ ++ if (hdr->tableEnc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { ++ DFXLOGU("tableEnc: %{public}x", hdr->tableEnc); ++ if (hdr->fdeCountEnc == DW_EH_PE_omit) { ++ fdeCount = ~0UL; ++ } ++ if (hdr->ehFramePtrEnc == DW_EH_PE_omit) { ++ DFXLOGE("ehFramePtrEnc(%{public}x) error", hdr->ehFramePtrEnc); ++ return false; ++ } ++ uti->isLinear = true; ++ uti->tableLen = fdeCount; ++ uti->tableData = ehFrameStart; ++ } else { ++ uti->isLinear = false; ++ uti->tableLen = (fdeCount * sizeof(DwarfTableEntry)) / sizeof(uintptr_t); ++ uti->tableData = ptr; ++ uti->segbase = (uintptr_t)hdr; ++ } ++ uti->format = UNW_INFO_FORMAT_REMOTE_TABLE; ++ DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, ++ (uint64_t)uti->tableData, (int)uti->tableLen); ++ return true; ++} ++#endif ++ ++bool DfxElf::FillUnwindTableByEhhdr(struct DwarfEhFrameHdr* hdr, uintptr_t shdrBase, struct UnwindTableInfo* uti) ++{ ++ if ((hdr == nullptr) || (uti == nullptr)) { ++ return false; ++ } ++ if (hdr->version != DW_EH_VERSION) { ++ DFXLOGE("[%{public}d]: version(%{public}d) error", __LINE__, hdr->version); ++ return false; ++ } ++ uintptr_t ptr = (uintptr_t)(&(hdr->ehFrame)); ++ DFXLOGU("[%{public}d]: hdr: %{public}" PRIx64 ", ehFrame: %{public}" PRIx64 "", __LINE__, ++ (uint64_t)hdr, (uint64_t)ptr); ++ ++ uti->gp = GetGlobalPointer(); ++ DFXLOGU("[%{public}d]: gp: %{public}" PRIx64 ", ehFramePtrEnc: %{public}x, fdeCountEnc: %{public}x", __LINE__, ++ (uint64_t)uti->gp, hdr->ehFramePtrEnc, hdr->fdeCountEnc); ++ mmap_->SetDataOffset(uti->gp); ++ auto ptrOffset = ptr - reinterpret_cast(GetMmapPtr()); ++ MAYBE_UNUSED uintptr_t ehFrameStart = mmap_->ReadEncodedValue(ptrOffset, hdr->ehFramePtrEnc); ++ uintptr_t fdeCount = mmap_->ReadEncodedValue(ptrOffset, hdr->fdeCountEnc); ++ DFXLOGU("[%{public}d]: ehFrameStart: %{public}" PRIx64 ", fdeCount: %{public}d", __LINE__, ++ (uint64_t)ehFrameStart, (int)fdeCount); ++ ptr = reinterpret_cast(GetMmapPtr()) + ptrOffset; ++ ++ if (hdr->tableEnc != (DW_EH_PE_datarel | DW_EH_PE_sdata4)) { ++ DFXLOGU("[%{public}d]: tableEnc: %{public}x", __LINE__, hdr->tableEnc); ++ if (hdr->fdeCountEnc == DW_EH_PE_omit) { ++ fdeCount = ~0UL; ++ } ++ if (hdr->ehFramePtrEnc == DW_EH_PE_omit) { ++ DFXLOGE("[%{public}d]: ehFramePtrEnc(%{public}x) error", __LINE__, hdr->ehFramePtrEnc); ++ return false; ++ } ++ uti->isLinear = true; ++ uti->tableLen = fdeCount; ++ uti->tableData = shdrBase + ehFrameStart; ++ uti->segbase = shdrBase; ++ } else { ++ uti->isLinear = false; ++ uti->tableLen = (fdeCount * sizeof(DwarfTableEntry)) / sizeof(uintptr_t); ++ uti->tableData = shdrBase + ptr - (uintptr_t)hdr; ++ uti->segbase = shdrBase; ++ } ++ uti->format = UNW_INFO_FORMAT_REMOTE_TABLE; ++ DFXLOGU("[%{public}d]: tableData: %{public}" PRIx64 ", tableLen: %{public}d", __LINE__, ++ (uint64_t)uti->tableData, (int)uti->tableLen); ++ return true; ++} ++ ++int DfxElf::FindUnwindTableInfo(uintptr_t pc, std::shared_ptr map, struct UnwindTableInfo& uti) ++{ ++ if (hasTableInfo_ && pc >= uti_.startPc && pc < uti_.endPc) { ++ uti = uti_; ++ DFXLOGU("FindUnwindTableInfo had found"); ++ return UNW_ERROR_NONE; ++ } ++ if (map == nullptr) { ++ return UNW_ERROR_INVALID_MAP; ++ } ++ uintptr_t loadBase = GetLoadBase(map->begin, map->offset); ++ uti.startPc = GetStartPc(); ++ uti.endPc = GetEndPc(); ++ if (pc < uti.startPc || pc >= uti.endPc) { ++ DFXLOGU("Elf startPc: %{public}" PRIx64 ", endPc: %{public}" PRIx64 "", ++ (uint64_t)uti.startPc, (uint64_t)uti.endPc); ++ return UNW_ERROR_PC_NOT_IN_UNWIND_INFO; ++ } ++ ++ ShdrInfo shdr; ++#if defined(__arm__) ++ if (GetSectionInfo(shdr, ARM_EXIDX)) { ++ hasTableInfo_ = FillUnwindTableByExidx(shdr, loadBase, &uti); ++ } ++#endif ++ ++ if (!hasTableInfo_) { ++ struct DwarfEhFrameHdr* hdr = nullptr; ++ struct DwarfEhFrameHdr synthHdr; ++ if (GetSectionInfo(shdr, EH_FRAME_HDR) && GetMmapPtr() != nullptr) { ++ INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); ++ hdr = (struct DwarfEhFrameHdr *) (shdr.offset + (char *)GetMmapPtr()); ++ } else if (GetSectionInfo(shdr, EH_FRAME) && GetMmapPtr() != nullptr) { ++ DFXLOGW("[%{public}d]: Elf(%{public}s) no found .eh_frame_hdr section, " \ ++ "using synthetic .eh_frame section", __LINE__, map->name.c_str()); ++ INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); ++ synthHdr.version = DW_EH_VERSION; ++ synthHdr.ehFramePtrEnc = DW_EH_PE_absptr | ++ ((sizeof(ElfW(Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); // 4 : four bytes ++ synthHdr.fdeCountEnc = DW_EH_PE_omit; ++ synthHdr.tableEnc = DW_EH_PE_omit; ++ synthHdr.ehFrame = (ElfW(Addr))(shdr.offset + (char*)GetMmapPtr()); ++ hdr = &synthHdr; ++ } ++ uintptr_t shdrBase = static_cast(loadBase + shdr.addr); ++ hasTableInfo_ = FillUnwindTableByEhhdr(hdr, shdrBase, &uti); ++ } ++ ++ if (hasTableInfo_) { ++ uti_ = uti; ++ return UNW_ERROR_NONE; ++ } ++ return UNW_ERROR_NO_UNWIND_INFO; ++} ++ ++int DfxElf::FindUnwindTableLocal(uintptr_t pc, struct UnwindTableInfo& uti) ++{ ++#if is_ohos && !is_mingw ++ DlCbData cbData; ++ (void)memset_s(&cbData, sizeof(cbData), 0, sizeof(cbData)); ++ cbData.pc = pc; ++ cbData.uti.format = -1; ++ int ret = dl_iterate_phdr(DlPhdrCb, &cbData); ++ if (ret > 0) { ++ if (cbData.uti.format != -1) { ++ uti = cbData.uti; ++ return UNW_ERROR_NONE; ++ } ++ } ++ return UNW_ERROR_NO_UNWIND_INFO; ++#else ++ return UNW_ERROR_UNSUPPORTED_VERSION; ++#endif ++} ++ ++#if is_ohos && !is_mingw ++bool DfxElf::FindSection(struct dl_phdr_info* info, const std::string secName, ShdrInfo& shdr) ++{ ++ if (info == nullptr) { ++ return false; ++ } ++ const char* file = info->dlpi_name; ++ if (strlen(file) == 0) { ++ file = PROC_SELF_EXE_PATH; ++ } ++ RegularElfFactory elfFactory(file); ++ auto elf = elfFactory.Create(); ++ if (elf == nullptr) { ++ return false; ++ } ++ ++ return elf->GetSectionInfo(shdr, secName); ++} ++ ++void DfxElf::ParsePhdr(struct dl_phdr_info* info, const ElfW(Phdr)* (&pHdrSections)[4], const uintptr_t pc) ++{ ++ const ElfW(Phdr)* phdr = info->dlpi_phdr; ++ for (size_t i = 0; i < info->dlpi_phnum && phdr != nullptr; i++, phdr++) { ++ switch (phdr->p_type) { ++ case PT_LOAD: { ++ ElfW(Addr) vaddr = phdr->p_vaddr + info->dlpi_addr; ++ if (pc >= vaddr && pc < vaddr + phdr->p_memsz) { ++ pHdrSections[SECTION_TEXT] = phdr; ++ } ++ break; ++ } ++#if defined(__arm__) ++ case PT_ARM_EXIDX: { ++ pHdrSections[SECTION_ARMEXIDX] = phdr; ++ break; ++ } ++#endif ++ case PT_GNU_EH_FRAME: { ++ pHdrSections[SECTION_EHFRAMEHDR] = phdr; ++ break; ++ } ++ case PT_DYNAMIC: { ++ pHdrSections[SECTION_DYNAMIC] = phdr; ++ break; ++ } ++ default: ++ break; ++ } ++ } ++} ++ ++bool DfxElf::ProccessDynamic(const ElfW(Phdr)* pDynamic, ElfW(Addr) loadBase, UnwindTableInfo* uti) ++{ ++ ElfW(Dyn)* dyn = reinterpret_cast(pDynamic->p_vaddr + loadBase); ++ if (dyn == nullptr) { ++ return false; ++ } ++ for (; dyn->d_tag != DT_NULL; ++dyn) { ++ if (dyn->d_tag == DT_PLTGOT) { ++ uti->gp = dyn->d_un.d_ptr; ++ break; ++ } ++ } ++ return true; ++} ++ ++struct DwarfEhFrameHdr* DfxElf::InitHdr(struct DwarfEhFrameHdr& synthHdr, ++ struct dl_phdr_info* info, const ElfW(Phdr)* pEhHdr) ++{ ++ struct DwarfEhFrameHdr* hdr = nullptr; ++ if (pEhHdr) { ++ INSTR_STATISTIC(InstructionEntriesEhFrame, pEhHdr->p_memsz, 0); ++ hdr = reinterpret_cast(pEhHdr->p_vaddr + info->dlpi_addr); ++ } else { ++ ShdrInfo shdr; ++ if (FindSection(info, EH_FRAME, shdr)) { ++ DFXLOGW("[%{public}d]: Elf(%{public}s) no found .eh_frame_hdr section, " \ ++ "using synthetic .eh_frame section", __LINE__, info->dlpi_name); ++ INSTR_STATISTIC(InstructionEntriesEhFrame, shdr.size, 0); ++ synthHdr.version = DW_EH_VERSION; ++ synthHdr.ehFramePtrEnc = DW_EH_PE_absptr | ++ ((sizeof(ElfW(Addr)) == 4) ? DW_EH_PE_udata4 : DW_EH_PE_udata8); // 4 : four bytes ++ synthHdr.fdeCountEnc = DW_EH_PE_omit; ++ synthHdr.tableEnc = DW_EH_PE_omit; ++ synthHdr.ehFrame = (ElfW(Addr))(shdr.addr + info->dlpi_addr); ++ hdr = &synthHdr; ++ } ++ } ++ return hdr; ++} ++ ++int DfxElf::DlPhdrCb(struct dl_phdr_info* info, size_t size, void* data) ++{ ++ struct DlCbData* cbData = reinterpret_cast(data); ++ if ((info == nullptr) || (cbData == nullptr)) { ++ return -1; ++ } ++ UnwindTableInfo* uti = &cbData->uti; ++ uintptr_t pc = cbData->pc; ++ const int numOfPhdrSections = 4; ++ const ElfW(Phdr)* pHdrSections[numOfPhdrSections] = {nullptr}; ++ ParsePhdr(info, pHdrSections, pc); ++ ++ if (pHdrSections[SECTION_TEXT] == nullptr) { ++ return 0; ++ } ++ ElfW(Addr) loadBase = info->dlpi_addr; ++ uti->startPc = pHdrSections[SECTION_TEXT]->p_vaddr + loadBase; ++ uti->endPc = uti->startPc + pHdrSections[SECTION_TEXT]->p_memsz; ++ DFXLOGU("Elf name: %{public}s", info->dlpi_name); ++ uti->namePtr = reinterpret_cast(info->dlpi_name); ++ ++#if defined(__arm__) ++ if (pHdrSections[SECTION_ARMEXIDX]) { ++ ShdrInfo shdr; ++ shdr.addr = pHdrSections[SECTION_ARMEXIDX]->p_vaddr; ++ shdr.size = pHdrSections[SECTION_ARMEXIDX]->p_memsz; ++ return FillUnwindTableByExidx(shdr, loadBase, uti); ++ } ++#endif ++ ++ if (pHdrSections[SECTION_DYNAMIC]) { ++ if (!ProccessDynamic(pHdrSections[SECTION_DYNAMIC], loadBase, uti)) { ++ return 0; ++ } ++ } else { ++ uti->gp = 0; ++ } ++ ++ struct DwarfEhFrameHdr synthHdr; ++ struct DwarfEhFrameHdr* hdr = InitHdr(synthHdr, info, pHdrSections[SECTION_EHFRAMEHDR]); ++ ++ return FillUnwindTableByEhhdrLocal(hdr, uti); ++} ++#endif ++ ++bool DfxElf::Read(uintptr_t pos, void* buf, size_t size) ++{ ++ if ((mmap_ != nullptr) && (mmap_->Read(pos, buf, size) == size)) { ++ return true; ++ } ++ return false; ++} ++ ++const uint8_t* DfxElf::GetMmapPtr() ++{ ++ if (mmap_ == nullptr) { ++ return nullptr; ++ } ++ return static_cast(mmap_->Get()); ++} ++ ++size_t DfxElf::GetMmapSize() ++{ ++ if (mmap_ == nullptr) { ++ return 0; ++ } ++ return mmap_->Size(); ++} ++ ++bool DfxElf::IsValidElf(const void* ptr, size_t size) ++{ ++ if (ptr == nullptr) { ++ return false; ++ } ++ ++ if (memcmp(ptr, ELFMAG, size) != 0) { ++ DFXLOGD("Invalid elf hdr?"); ++ return false; ++ } ++ return true; ++} ++} // namespace HiviewDFX ++} // namespace OHOS diff --git a/trace_streamer/prebuilts/patch_llvm/llvm.patch b/trace_streamer/prebuilts/patch_llvm/llvm.patch index 3dbb0d441f5a87bffac40a9e18bf611f4f84a05a..fcde97762192e38963c5e229d4cdb2b75c744b69 100644 --- a/trace_streamer/prebuilts/patch_llvm/llvm.patch +++ b/trace_streamer/prebuilts/patch_llvm/llvm.patch @@ -144,7 +144,7 @@ index 56d5b2ce7dc3..827184b7a5e0 100644 + deps = [ + "//llvm/include/llvm/Config:config", + "//llvm/lib/Demangle", -+ "//third_party/zlib:libz", ++ "//src/parser/hiperf_parser:libz", + ] + } else { + deps = [ diff --git a/trace_streamer/src/BUILD.gn b/trace_streamer/src/BUILD.gn index 2a07f38406bf9a459077d5876d0d57a254c9bb21..c40825e3d27abb4ca95d9c10cd075398c946dae0 100644 --- a/trace_streamer/src/BUILD.gn +++ b/trace_streamer/src/BUILD.gn @@ -106,11 +106,10 @@ ohos_source_set("trace_streamer_source") { "filter:filter", "metrics:metrics_parser", "parser:parser", + "parser/hiperf_parser:libsec_static", "proto_reader:proto_reader", "table:table", "trace_data:trace_data", - "//third_party/bounds_checking_function:libsec_static", - "//third_party/perf_include/hiviewdfx:libfaultloggerd", ] public_configs = [ ":trace_streamer_cfg" ] public_deps = [] diff --git a/trace_streamer/src/base/BUILD.gn b/trace_streamer/src/base/BUILD.gn index f577bc201291bca06b9e72037d875ff4d7bdd6c9..2996b3d614fd6ea9ecad3d31ae4b9422cedf1eec 100644 --- a/trace_streamer/src/base/BUILD.gn +++ b/trace_streamer/src/base/BUILD.gn @@ -17,7 +17,7 @@ ohos_source_set("base") { subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" part_name = "${OHOS_PROFILER_PART_NAME}" public_deps = [ - "${THIRD_PARTY}/zlib:libz", + "../parser/hiperf_parser:libz", "sqlite_ext:sqliteext", ] include_dirs = [ diff --git a/trace_streamer/src/base/string_help.cpp b/trace_streamer/src/base/string_help.cpp index f18316d33e958b1df1f235b6fbaa8ae681501925..8fd7dbdd3dfcd38f18ee2e37fce3ff028259bd27 100644 --- a/trace_streamer/src/base/string_help.cpp +++ b/trace_streamer/src/base/string_help.cpp @@ -44,19 +44,21 @@ bool EndWith(const std::string &str, const std::string &res) return str.compare(str.size() - res.size(), res.size(), res) == 0; } -std::vector SplitStringToVec(const std::string &str, const std::string &pat) +std::vector SplitStringToVec(const std::string &str, const std::string &pat, uint32_t expectedCount) { std::vector result; size_t curPos = 0; size_t strSize = str.size(); size_t patSize = pat.size(); + uint32_t endFlag = 0; while (curPos < strSize) { auto patPos = str.find(pat, curPos); - if (patPos == std::string::npos) { + if (patPos == std::string::npos || endFlag == expectedCount) { break; } result.emplace_back(str.substr(curPos, patPos - curPos)); curPos = patPos + patSize; + endFlag++; } if (curPos < strSize) { result.emplace_back(str.substr(curPos)); diff --git a/trace_streamer/src/base/string_help.h b/trace_streamer/src/base/string_help.h index c104641078c1baae30e38c2e020c1d2f0a43a81d..df4bb6a7e3edda5428cfb691cdf62f5b47ba08c6 100644 --- a/trace_streamer/src/base/string_help.h +++ b/trace_streamer/src/base/string_help.h @@ -23,7 +23,9 @@ namespace SysTuning { namespace base { char *GetDemangleSymbolIndex(const char *mangled); -std::vector SplitStringToVec(const std::string &str, const std::string &pat); +std::vector SplitStringToVec(const std::string &str, + const std::string &pat, + uint32_t expectedCount = UINT32_MAX); bool StartWith(const std::string &str, const std::string &res); bool EndWith(const std::string &str, const std::string &res); std::string FormatString(const char *p); diff --git a/trace_streamer/src/filter/BUILD.gn b/trace_streamer/src/filter/BUILD.gn index cbe1e74f18f99d352780a73bed960d413b1eb5fe..cb8a9f50a47cd92360477fff57943cb2c2b8a178 100644 --- a/trace_streamer/src/filter/BUILD.gn +++ b/trace_streamer/src/filter/BUILD.gn @@ -46,12 +46,13 @@ config("filter_cfg") { "${THIRD_PARTY}/sqlite/include", "${PERF_DIR}/hiperf/include", "${PERF_DIR}/hiperf/include/nonlinux/linux", - "${THIRD_PARTY}/perf_include/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include", - "${THIRD_PARTY}/perf_include/hiviewdfx/faultloggerd/interfaces/nonlinux", - "${THIRD_PARTY}/perf_include/hiviewdfx/faultloggerd/interfaces/common", - "${THIRD_PARTY}/perf_include/hiviewdfx/faultloggerd/common/dfxutil", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/nonlinux", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/common", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/common/dfxutil", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/common/dfxlog", "${PERF_DIR}/hiperf/include/nonlinux", - "${THIRD_PARTY}/perf_include/libbpf", + "${THIRD_PARTY}/libbpf/include/uapi", "${THIRD_PARTY}/bounds_checking_function/include", "${THIRD_PARTY}/json/single_include/nlohmann", "../proto_reader/include", @@ -82,6 +83,7 @@ ohos_source_set("filter") { "args_filter.cpp", "binder_filter.cpp", "clock_filter_ex.cpp", + "config_filter.cpp", "cpu_filter.cpp", "filter_base.cpp", "filter_filter.cpp", @@ -91,6 +93,7 @@ ohos_source_set("filter") { "process_filter.cpp", "slice_filter.cpp", "stat_filter.cpp", + "syscall_filter.cpp", "system_event_measure_filter.cpp", "task_pool_filter.cpp", ] diff --git a/trace_streamer/src/filter/animation_filter.cpp b/trace_streamer/src/filter/animation_filter.cpp index 4dbe7d94e0d9fb80501c1a049f5d20c65481d8ec..478cf77d80cc62599ea52febd5f7ab06c7092067 100644 --- a/trace_streamer/src/filter/animation_filter.cpp +++ b/trace_streamer/src/filter/animation_filter.cpp @@ -34,18 +34,15 @@ AnimationFilter::AnimationFilter(TraceDataCache *dataCache, const TraceStreamerF if (dynamicFrame_ == nullptr || callStackSlice_ == nullptr) { TS_LOGE("dynamicFrame_ or callStackSlice_ is nullptr."); } - onAnimationStartEvents_ = { - traceDataCache_->GetDataIndex("H:LAUNCHER_APP_LAUNCH_FROM_ICON"), - traceDataCache_->GetDataIndex("H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR"), - traceDataCache_->GetDataIndex("H:LAUNCHER_APP_LAUNCH_FROM_NOTIFICATIONBAR_IN_LOCKSCREEN"), - traceDataCache_->GetDataIndex("H:LAUNCHER_APP_LAUNCH_FROM_RECENT"), - traceDataCache_->GetDataIndex("H:LAUNCHER_APP_SWIPE_TO_HOME"), - traceDataCache_->GetDataIndex("H:LAUNCHER_APP_BACK_TO_HOME"), - traceDataCache_->GetDataIndex("H:APP_TRANSITION_TO_OTHER_APP"), - traceDataCache_->GetDataIndex("H:APP_TRANSITION_FROM_OTHER_APP"), - traceDataCache_->GetDataIndex("H:APP_LIST_FLING")}; } AnimationFilter::~AnimationFilter() {} +void AnimationFilter::InitAnimationStartEvents() +{ + auto res = streamFilters_->configFilter_->GetAnimationConfig().GetOnAnimationStartEvents(); + for (auto &eventName : res) { + onAnimationStartEvents_.insert(traceDataCache_->GetDataIndex(eventName)); + } +} bool AnimationFilter::UpdateDeviceFps(const BytraceLine &line) { generateVsyncCnt_++; @@ -87,24 +84,24 @@ bool AnimationFilter::UpdateDeviceScreenSize(const TracePoint &point) bool AnimationFilter::UpdateDeviceInfoEvent(const TracePoint &point, const BytraceLine &line) { if (traceDataCache_->GetConstDeviceInfo().PhysicalFrameRate() == INVALID_UINT32 && - StartWith(point.name_, frameRateCmd_)) { + streamFilters_->configFilter_->GetAnimationConfig().CheckIfFrameRateCmd(point.name_)) { return UpdateDeviceFps(line); } else if (traceDataCache_->GetConstDeviceInfo().PhysicalWidth() == INVALID_UINT32 && - (StartWith(point.name_, newScreenSizeCmd_) || StartWith(point.name_, screenSizeCmd_))) { + streamFilters_->configFilter_->GetAnimationConfig().CheckIfScreenSizeCmd(point.name_)) { return UpdateDeviceScreenSize(point); } return false; } bool AnimationFilter::BeginDynamicFrameEvent(const TracePoint &point, size_t callStackRow) { - if (StartWith(point.name_, paralleCmd_)) { + if (streamFilters_->configFilter_->GetAnimationConfig().CheckIfParallelCmd(point.name_)) { isNewAnimation_ = true; return true; } - if (StartWith(point.name_, frameCountCmd_)) { + if (streamFilters_->configFilter_->GetAnimationConfig().CheckIfFrameCountCmd(point.name_)) { frameCountRows_.insert(callStackRow); return true; - } else if (StartWith(point.name_, realFrameRateCmd_)) { + } else if (streamFilters_->configFilter_->GetAnimationConfig().CheckIfRealFrameRateCmd(point.name_)) { // eg: `frame rate is 88.61: APP_LIST_FLING, com.taobao.taobao, pages/Index` auto infos = SplitStringToVec(point.funcArgs_, ": "); auto curRealFrameRateFlagInadex = traceDataCache_->GetDataIndex("H:" + infos.back()); @@ -116,7 +113,7 @@ bool AnimationFilter::BeginDynamicFrameEvent(const TracePoint &point, size_t cal traceDataCache_->GetAnimation()->UpdateFrameInfo(animationRow, traceDataCache_->GetDataIndex(curFrameNum + curRealFrameRate)); return true; - } else if (StartWith(point.name_, newFrameBeginCmd_) || StartWith(point.name_, frameBeginCmd_)) { + } else if (streamFilters_->configFilter_->GetAnimationConfig().CheckIfFrameBeginCmd(point.name_)) { // get the parent frame of data const std::optional &parentId = callStackSlice_->ParentIdData()[callStackRow]; uint8_t depth = callStackSlice_->Depths()[callStackRow]; @@ -178,8 +175,9 @@ bool AnimationFilter::UpdateDynamicEndTime(const uint64_t curFrameRow, uint64_t curStackRow = callStackSlice_->ParentIdData()[curStackRow].value(); // use frameEndTimeCmd_'s endTime as dynamicFrame endTime auto nameIndex = callStackSlice_->NamesData()[curStackRow]; - if (isNewAnimation_ && StartWith(traceDataCache_->GetDataFromDict(nameIndex), renderFrameCmd_) || - StartWith(traceDataCache_->GetDataFromDict(nameIndex), frameEndTimeCmd_)) { + if ((!isNewAnimation_ && StartWith(traceDataCache_->GetDataFromDict(nameIndex), frameEndTimeCmd_)) || + streamFilters_->configFilter_->GetAnimationConfig().CheckIfFrameEndTimeCmd( + traceDataCache_->GetDataFromDict(nameIndex))) { auto endTime = callStackSlice_->TimeStampData()[curStackRow] + callStackSlice_->DursData()[curStackRow]; dynamicFrame_->UpdateEndTime(curFrameRow, endTime); return true; diff --git a/trace_streamer/src/filter/animation_filter.h b/trace_streamer/src/filter/animation_filter.h index 3201e06ca675504c4005cc51e3c3b6d51539a60f..177ebbddc5669afbb91d00174f858f523eeace29 100644 --- a/trace_streamer/src/filter/animation_filter.h +++ b/trace_streamer/src/filter/animation_filter.h @@ -25,6 +25,7 @@ #include "string_help.h" #include "string_to_numerical.h" #include "trace_streamer_filters.h" +#include "config_filter.h" namespace SysTuning { namespace TraceStreamer { @@ -40,6 +41,7 @@ public: bool FinishAnimationEvent(const BytraceLine &line, size_t callStackRow); void UpdateDynamicFrameInfo(); void UpdateFrameInfo(); + void InitAnimationStartEvents(); void Clear(); private: @@ -49,18 +51,7 @@ private: const std::regex framePixPattern_ = std::regex(R"(\[(.*?)\]\s*\(\s*-?(\d+),\s*-?(\d+),\s*(\d+),\s*(\d+)\)\s*Alpha:\s+-*(\d+\.\d+))"); // for calculate the frame rate - const std::string frameRateCmd_ = "H:GenerateVsyncCount"; - // if the realFrameRate present, no calculation is required - const std::string realFrameRateCmd_ = "H:RSJankStats::RecordAnimationDynamicFrameRate"; // 动效过程帧率 - const std::string frameCountCmd_ = "H:Repaint"; - const std::string frameBeginCmd_ = "H:RSUniRender::Process:[WindowScene_"; - const std::string newFrameBeginCmd_ = "H:RSSurfaceRenderNodeDrawable::OnDraw:[WindowScene_"; // 动效帧数据 - const std::string frameBeginPrefix_ = "H:RSUniRender::Process:["; - const std::string screenSizeCmd_ = "H:RSUniRender::Process:[SCBDesktop"; - const std::string newScreenSizeCmd_ = "H:RSSurfaceRenderNodeDrawable::OnDraw:[SCBDesktop"; // 设备分辨率 const std::string frameEndTimeCmd_ = "H:RSMainThread::DoComposition"; - const std::string paralleCmd_ = "H:PostAndWait, parallel type"; // 并行化标志 - const std::string renderFrameCmd_ = "H:RenderFrame"; // 并行化后动效帧结束时间相关trace点 std::unordered_set onAnimationStartEvents_ = {}; // for update dynamicFrameInfo at the end, first is callStackRow, second is dynamicFramRow std::deque callstackWithDynamicFrameRows_ = {}; diff --git a/trace_streamer/src/filter/app_start_filter.cpp b/trace_streamer/src/filter/app_start_filter.cpp index bc9c9244f3f99a4322ec4fba1b45909b924755fc..88f0593e6b9e055ea1708b82aa36e52c2ae18719 100644 --- a/trace_streamer/src/filter/app_start_filter.cpp +++ b/trace_streamer/src/filter/app_start_filter.cpp @@ -175,20 +175,20 @@ void APPStartupFilter::ParserAppStartup() auto &nameString = traceDataCache_->GetDataFromDict(sliceData.NamesData()[i]); auto callId = sliceData.CallIds()[i]; auto startTime = sliceData.TimeStampData()[i]; - if (StartWith(nameString, procTouchCmd_)) { + if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase1(nameString)) { procTouchItems_.emplace_back( std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64)); - } else if (StartWith(nameString, startUIAbilityBySCBCmd_)) { + } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase2(nameString)) { startUIAbilityBySCBItems_.emplace_back( std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64)); - } else if (StartWith(nameString, loadAbilityCmd_)) { + } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase3(nameString)) { loadAbilityItems_.emplace_back( std::make_unique(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64)); - } else if (StartWith(nameString, appLaunchCmd_)) { + } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase4(nameString)) { UpdateAPPStartupData(i, nameString, APPLICATION_LAUNCHING); - } else if (StartWith(nameString, uiLaunchCmd_)) { + } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase5(nameString)) { ProcAbilityLaunchData(nameString, i); - } else if (StartWith(nameString, uiOnForegroundFirstCmd_) || StartWith(nameString, uiOnForegroundSecCmd_)) { + } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase6(nameString)) { ProcForegroundData(i); } } diff --git a/trace_streamer/src/filter/app_start_filter.h b/trace_streamer/src/filter/app_start_filter.h index e91befefa12344553078412b7313a1a9d379711a..800658d181e709ca9382a972ec51ebf556b13eba 100644 --- a/trace_streamer/src/filter/app_start_filter.h +++ b/trace_streamer/src/filter/app_start_filter.h @@ -23,6 +23,7 @@ #include "trace_data_cache.h" #include "trace_streamer_filters.h" #include "ts_common.h" +#include "config_filter.h" namespace SysTuning { namespace TraceStreamer { @@ -81,19 +82,6 @@ private: std::deque> loadAbilityItems_; appMap mAPPStartupData_; std::map mAPPStartupDataWithPid_; - const std::string procTouchCmd_ = "H:client dispatch touchId:"; - const std::string startUIAbilityBySCBCmd_ = - "H:OHOS::ErrCode OHOS::AAFwk::AbilityManagerClient::StartUIAbilityBySCB"; - const std::string loadAbilityCmd_ = "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::LoadAbility"; - const std::string appLaunchCmd_ = - "H:virtual void OHOS::AppExecFwk::AppMgrServiceInner::AttachApplication(const pid_t, const " - "sptr &)##"; - const std::string uiLaunchCmd_ = - "H:void OHOS::AppExecFwk::MainThread::HandleLaunchAbility(const std::shared_ptr &)##"; - const std::string uiOnForegroundFirstCmd_ = - "H:void OHOS::AbilityRuntime::FAAbilityThread::HandleAbilityTransaction(const OHOS::AbilityRuntime::Want &, " - "const OHOS::AbilityRuntime::LifeCycleStateInfo &, sptr)##"; - const std::string uiOnForegroundSecCmd_ = "H:void OHOS::AbilityRuntime::UIAbilityThread::HandleAbilityTransaction"; const std::string dlopenCmd_ = "dlopen:"; }; } // namespace TraceStreamer diff --git a/trace_streamer/src/filter/config_filter.cpp b/trace_streamer/src/filter/config_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad7035db9e5c999a02f53c4e23a2ea2b76d91ab6 --- /dev/null +++ b/trace_streamer/src/filter/config_filter.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. + * 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. + */ + +#include "config_filter.h" +namespace SysTuning { +namespace TraceStreamer { +bool CheckIfStartWithKeywords(const std::string &eventName, const std::vector &keywords) +{ + for (auto &keyword : keywords) { + if (StartWith(eventName, keyword)) { + return true; + } + } + return false; +} +bool CheckIfEndWithKeywords(const std::string &eventName, const std::vector &keywords) +{ + for (auto &keyword : keywords) { + if (EndWith(eventName, keyword)) { + return true; + } + } + return false; +} +ConfigFilter::ConfigFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter) + : FilterBase(dataCache, filter) +{ +} + +ConfigFilter::~ConfigFilter() {} +bool ConfigFilter::SetConfig(const std::string &configFile) +{ + json configResult = json::parse(configFile, nullptr, false); + if (configResult.is_discarded()) { + TS_LOGE("Failed to parse config file."); + return false; + } + InitConfig(configResult); + return true; +} +void ConfigFilter::InitConfig(const json &config) +{ + if (config.contains("Animation") && !config["Animation"].empty()) { + animationConfig_ = AnimationConfig(config["Animation"]); + } else { + animationConfig_ = AnimationConfig(); + } + if (config.contains("AppStartup") && !config["AppStartup"].empty()) { + appStartupConfig_ = AppStartupConfig(config["AppStartup"]); + } else { + appStartupConfig_ = AppStartupConfig(); + } + if (config.contains("config") && !config["config"].empty()) { + switchConfig_ = SwitchConfig(config["config"]); + } else { + switchConfig_ = SwitchConfig(); + } + streamFilters_->animationFilter_->InitAnimationStartEvents(); +} +const AnimationConfig &ConfigFilter::GetAnimationConfig() const +{ + return animationConfig_; +} + +const AppStartupConfig &ConfigFilter::GetAppStartupConfig() const +{ + return appStartupConfig_; +} +const SwitchConfig &ConfigFilter::GetSwitchConfig() const +{ + return switchConfig_; +} + +bool AnimationConfig::CheckIfAnimationEvents(const std::string &eventName) const +{ + return CheckIfEndWithKeywords(eventName, animationProcEvents_); +} + +bool AnimationConfig::CheckIfFrameRateCmd(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, frameRateCmd_); +} +bool AnimationConfig::CheckIfRealFrameRateCmd(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, realFrameRateCmd_); +} +bool AnimationConfig::CheckIfFrameCountCmd(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, frameCountCmd_); +} +bool AnimationConfig::CheckIfFrameBeginCmd(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, frameBeginCmd_); +} +bool AnimationConfig::CheckIfScreenSizeCmd(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, screenSizeCmd_); +} +bool AnimationConfig::CheckIfFrameEndTimeCmd(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, frameEndTimeCmd_); +} +bool AnimationConfig::CheckIfParallelCmd(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, parallelCmd_); +} +bool AppStartupConfig::CheckIfPhase1(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, phase1_.start); +} +bool AppStartupConfig::CheckIfPhase2(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, phase2_.start); +} +bool AppStartupConfig::CheckIfPhase3(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, phase3_.start); +} +bool AppStartupConfig::CheckIfPhase4(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, phase4_.start); +} +bool AppStartupConfig::CheckIfPhase5(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, phase5_.start); +} +bool AppStartupConfig::CheckIfPhase6(const std::string &eventName) const +{ + return CheckIfStartWithKeywords(eventName, phase6_.start); +} + +std::vector AnimationConfig::GetOnAnimationStartEvents() const +{ + return onAnimationStartEvents_; +} +SwitchConfig::SwitchConfig(const json &config) +{ + appConfigEnabled_ = config.value("AppStartup", 0) == 1; + animationConfigEnabled_ = config.value("AnimationAnalysis", 0) == 1; + taskPoolConfigEnabled_ = config.value("TaskPool", 0) == 1; + binderRunnableConfigEnabled_ = config.value("BinderRunnable", 0) == 1; + HMKernelTraceEnabled_ = config.value("HMKernel", 0) == 1; + rawTraceCutStartTsEnabled_ = config.value("RawTraceCutStartTs", 0) == 1; + ffrtConvertEnabled_ = config.value("FfrtConvert", 0) == 1; + std::string syscalls = config.value("System Calls", ""); + UpdateSyscallsTsSet(syscalls); + TS_LOGI( + "appConfigEnabled_=%d, animationConfigEnabled_=%d, taskPoolConfigEnabled_=%d, binderRunnableConfigEnabled_=%d, " + "HMKernelTraceEnabled_=%d, rawTraceCutStartTsEnabled_=%d, ffrtConvertEnabled_=%d, syscalls=%s", + appConfigEnabled_, animationConfigEnabled_, taskPoolConfigEnabled_, binderRunnableConfigEnabled_, + HMKernelTraceEnabled_, rawTraceCutStartTsEnabled_, ffrtConvertEnabled_, syscalls.c_str()); +} +bool SwitchConfig::AppConfigEnabled() const +{ + return appConfigEnabled_; +} +bool SwitchConfig::AnimationConfigEnabled() const +{ + return animationConfigEnabled_; +} +bool SwitchConfig::TaskPoolConfigEnabled() const +{ + return taskPoolConfigEnabled_; +} +bool SwitchConfig::BinderRunnableConfigEnabled() const +{ + return binderRunnableConfigEnabled_; +} +bool SwitchConfig::HMKernelTraceEnabled() const +{ + return HMKernelTraceEnabled_; +} +bool SwitchConfig::RawTraceCutStartTsEnabled() const +{ + return rawTraceCutStartTsEnabled_; +} +bool SwitchConfig::FfrtConfigEnabled() const +{ + return ffrtConvertEnabled_; +} +const std::set &SwitchConfig::SyscallsTsSet() const +{ + return syscallNrSet_; +} +void SwitchConfig::UpdateSyscallsTsSet(const std::string &syscalls) +{ + std::stringstream ss(syscalls); + std::string token; + + syscallNrSet_.clear(); + while (std::getline(ss, token, ';')) { + syscallNrSet_.insert(std::stoi(token)); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/filter/config_filter.h b/trace_streamer/src/filter/config_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..4e405f5e584738c92684baef5131fbe73fc2cdaa --- /dev/null +++ b/trace_streamer/src/filter/config_filter.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved. + * 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. + */ + +#ifndef CONFIG_FILTER_H +#define CONFIG_FILTER_H +#include +#include +#include +#include +#include +#include +#include "string_help.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" +#include "animation_filter.h" +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::base; +using json = nlohmann::json; +bool CheckIfStartWithKeywords(const std::string &eventName, const std::vector &keywords); +bool CheckIfEndWithKeywords(const std::string &eventName, const std::vector &keywords); +class AnimationConfig { +public: + AnimationConfig() = default; + AnimationConfig(const json &config) + { + animationProcEvents_ = config.value("animationProcEvents_", std::vector{}); + onAnimationStartEvents_ = config.value("onAnimationStartEvents_", std::vector{}); + frameRateCmd_ = config.value("frameRateCmd_", std::vector{}); + realFrameRateCmd_ = config.value("realFrameRateCmd_", std::vector{}); + frameCountCmd_ = config.value("frameCountCmd_", std::vector{}); + frameBeginCmd_ = config.value("frameBeginCmd_", std::vector{}); + screenSizeCmd_ = config.value("screenSizeCmd_", std::vector{}); + frameEndTimeCmd_ = config.value("frameEndTimeCmd_", std::vector{}); + parallelCmd_ = config.value("parallelCmd_", std::vector{}); + } + ~AnimationConfig() = default; + std::vector GetOnAnimationStartEvents() const; + bool CheckIfAnimationEvents(const std::string &eventName) const; + bool CheckIfFrameRateCmd(const std::string &eventName) const; + bool CheckIfRealFrameRateCmd(const std::string &eventName) const; + bool CheckIfFrameCountCmd(const std::string &eventName) const; + bool CheckIfFrameBeginCmd(const std::string &eventName) const; + bool CheckIfScreenSizeCmd(const std::string &eventName) const; + bool CheckIfFrameEndTimeCmd(const std::string &eventName) const; + bool CheckIfParallelCmd(const std::string &eventName) const; + +private: + std::vector animationProcEvents_; + std::vector onAnimationStartEvents_; + std::vector frameRateCmd_; + std::vector realFrameRateCmd_; + std::vector frameCountCmd_; + std::vector frameBeginCmd_; + std::vector screenSizeCmd_; + std::vector frameEndTimeCmd_; + std::vector parallelCmd_; +}; +struct StartUpPhase { + std::string pName; + std::vector start; + std::vector end; +}; +class AppStartupConfig { +public: + AppStartupConfig() = default; + AppStartupConfig(const json &config) + { + phase1_ = GetPhaseValue(config, "phase1"); + phase2_ = GetPhaseValue(config, "phase2"); + phase3_ = GetPhaseValue(config, "phase3"); + phase4_ = GetPhaseValue(config, "phase4"); + phase5_ = GetPhaseValue(config, "phase5"); + phase6_ = GetPhaseValue(config, "phase6"); + } + ~AppStartupConfig() = default; + bool CheckIfPhase1(const std::string &eventName) const; + bool CheckIfPhase2(const std::string &eventName) const; + bool CheckIfPhase3(const std::string &eventName) const; + bool CheckIfPhase4(const std::string &eventName) const; + bool CheckIfPhase5(const std::string &eventName) const; + bool CheckIfPhase6(const std::string &eventName) const; + +private: + StartUpPhase GetPhaseValue(const json &phaseConfig, const std::string &phaseName) + { + auto phaseContent = phaseConfig.value(phaseName, json::object()); + return {phaseContent.value("pName", ""), phaseContent.value("start", std::vector{}), + phaseContent.value("end", std::vector{})}; + } + StartUpPhase phase1_; + StartUpPhase phase2_; + StartUpPhase phase3_; + StartUpPhase phase4_; + StartUpPhase phase5_; + StartUpPhase phase6_; +}; + +class SwitchConfig { +public: + SwitchConfig() = default; + SwitchConfig(const json &config); + ~SwitchConfig() = default; + bool AppConfigEnabled() const; + bool AnimationConfigEnabled() const; + bool TaskPoolConfigEnabled() const; + bool BinderRunnableConfigEnabled() const; + bool HMKernelTraceEnabled() const; + bool RawTraceCutStartTsEnabled() const; + bool FfrtConfigEnabled() const; + const std::set &SyscallsTsSet() const; + +private: + void UpdateSyscallsTsSet(const std::string &syscalls); + +private: + bool appConfigEnabled_ = false; + bool animationConfigEnabled_ = false; + bool taskPoolConfigEnabled_ = false; + bool binderRunnableConfigEnabled_ = false; + bool HMKernelTraceEnabled_ = false; + bool rawTraceCutStartTsEnabled_ = false; + bool ffrtConvertEnabled_ = false; + std::set syscallNrSet_; +}; +class ConfigFilter : private FilterBase { +public: + ConfigFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter); + ConfigFilter(const ConfigFilter &) = delete; + ConfigFilter &operator=(const ConfigFilter &) = delete; + ~ConfigFilter() override; + bool SetConfig(const std::string &configFile); + const AnimationConfig &GetAnimationConfig() const; + const AppStartupConfig &GetAppStartupConfig() const; + const SwitchConfig &GetSwitchConfig() const; + +private: + AnimationConfig animationConfig_; + AppStartupConfig appStartupConfig_; + SwitchConfig switchConfig_; + void InitConfig(const json &config); +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // CONFIG_FILTER_H diff --git a/trace_streamer/src/filter/cpu_filter.cpp b/trace_streamer/src/filter/cpu_filter.cpp index a280fcb8064b17e969db4adbd36d5e2eb02cc2e2..93dcad601e90a004875629d2b0c47248353383a9 100644 --- a/trace_streamer/src/filter/cpu_filter.cpp +++ b/trace_streamer/src/filter/cpu_filter.cpp @@ -69,7 +69,7 @@ void CpuFilter::ProcPrevPidSwitchEvent(uint64_t ts, auto lastState = traceDataCache_->GetConstThreadStateData().StatesData()[lastRow]; auto lastStartTs = traceDataCache_->GetConstThreadStateData().TimeStampData()[lastRow]; if ((cpu != lastCpu) && (lastState == TASK_RUNNING)) { - if (traceDataCache_->HMKernelTraceEnabled() || (ts == lastStartTs)) { + if (streamFilters_->configFilter_->GetSwitchConfig().HMKernelTraceEnabled() || (ts == lastStartTs)) { isChangeCpu = true; } } @@ -128,7 +128,8 @@ void CpuFilter::InsertSwitchEvent(uint64_t ts, if (prevPid) { ProcPrevPidSwitchEvent(ts, cpu, prevPid, prevState, btInfo); } - if (traceDataCache_->BinderRunnableTraceEnabled() && iTidToTransaction_.find(prevPid) != iTidToTransaction_.end()) { + if (streamFilters_->configFilter_->GetSwitchConfig().BinderRunnableConfigEnabled() && + iTidToTransaction_.find(prevPid) != iTidToTransaction_.end()) { uint64_t transactionId = iTidToTransaction_.at(prevPid); auto iter = transactionIdToInfo_.find(transactionId); if (prevState != TASK_NEW || iter == transactionIdToInfo_.end() || iter->second.iTidFrom != prevPid || diff --git a/trace_streamer/src/filter/cpu_filter.h b/trace_streamer/src/filter/cpu_filter.h index 2e9c25bd76ad1c63c7c39d7b0362612f5e93630a..3fd0b0917c4c20b6622da9b07f1a96ebc3e249e5 100644 --- a/trace_streamer/src/filter/cpu_filter.h +++ b/trace_streamer/src/filter/cpu_filter.h @@ -27,6 +27,7 @@ #include "trace_data_cache.h" #include "trace_streamer_filters.h" #include "ts_common.h" +#include "config_filter.h" namespace SysTuning { namespace TraceStreamer { diff --git a/trace_streamer/src/filter/hook_filter/BUILD.gn b/trace_streamer/src/filter/hook_filter/BUILD.gn index 8af3276601b07041de589fb294e96291f5eb2010..12edd4c68564e013f0e7eb50c776dc7ccdcd8e5f 100644 --- a/trace_streamer/src/filter/hook_filter/BUILD.gn +++ b/trace_streamer/src/filter/hook_filter/BUILD.gn @@ -17,7 +17,7 @@ import("../../../build/ts.gni") config("native_hook_filter_cfg") { include_dirs = [ ".", - "${COMMON_LIBRARY}/base/include", + "${COMMON_LIBRARY}/c_utils/base/include", ] } diff --git a/trace_streamer/src/filter/hook_filter/native_hook_filter.cpp b/trace_streamer/src/filter/hook_filter/native_hook_filter.cpp index 8426e70e8ecfcddf68da62415cac450c801a6f8d..c666fcf7c1c756249dd17244b0a07d8ce4b894ea 100644 --- a/trace_streamer/src/filter/hook_filter/native_hook_filter.cpp +++ b/trace_streamer/src/filter/hook_filter/native_hook_filter.cpp @@ -32,6 +32,7 @@ NativeHookFilter::NativeHookFilter(TraceDataCache *dataCache, const TraceStreame invalidLibPathIndexs_.insert(traceDataCache_->dataDict_.GetStringIndex("/system/lib64/libc++.so")); invalidLibPathIndexs_.insert(traceDataCache_->dataDict_.GetStringIndex("/system/lib/ld-musl-aarch64.so.1")); invalidLibPathIndexs_.insert(traceDataCache_->dataDict_.GetStringIndex("/system/lib/ld-musl-arm.so.1")); + invalidLibPathIndexs_.insert(traceDataCache_->dataDict_.GetStringIndex("/system/lib64/libdfmalloc.z.so")); hookPluginData_->set_name("nativehook"); commHookData_.datas = std::make_unique(); addrToAllocEventRow_ = traceDataCache_->GetNativeHookData()->GetAddrToAllocEventRow(); diff --git a/trace_streamer/src/filter/perf_filter/perf_data_filter.cpp b/trace_streamer/src/filter/perf_filter/perf_data_filter.cpp index 3709e4eddb7c19fac0a8f1ef4496c3b1e02b4ed9..5d343157ce017a2befad146e66d7cd9d896a7ad8 100644 --- a/trace_streamer/src/filter/perf_filter/perf_data_filter.cpp +++ b/trace_streamer/src/filter/perf_filter/perf_data_filter.cpp @@ -36,6 +36,14 @@ size_t PerfDataFilter::AppendPerfFiles(uint64_t fileId, uint32_t serial, DataInd return size; } +void PerfDataFilter::AppendInvalidVaddrIpToFuncName(uint64_t ip, DataIndex nameIndex) +{ + auto iter = invalidVaddrIpToFuncName_.find(ip); + if (iter == invalidVaddrIpToFuncName_.end()) { + invalidVaddrIpToFuncName_.emplace(ip, nameIndex); + } +} + void PerfDataFilter::BeforeReload() { traceDataCache_->GetPerfCallChainData()->Clear(); @@ -43,6 +51,7 @@ void PerfDataFilter::BeforeReload() fileIdToRowInFileTable_.Clear(); fileIds_.clear(); fileIdToRow_.clear(); + invalidVaddrIpToFuncName_.clear(); } void PerfDataFilter::Finish() { @@ -62,13 +71,12 @@ void PerfDataFilter::Finish() continue; } if (vaddrs[i] == 0 || symbolsIds[i] == -1) { - auto pathIndex = filePath[fileIdToRow_.at(fileIds[i])]; - auto fullPath = traceDataCache_->GetDataFromDict(pathIndex); - auto iPos = fullPath.find_last_of('/'); - fullPath = fullPath.substr(iPos + 1, -1); - auto nameIndex = traceDataCache_->GetDataIndex(fullPath + "@0x" + - base::number(ips[i] & flag, base::INTEGER_RADIX_TYPE_HEX)); - traceDataCache_->GetPerfCallChainData()->SetName(i, nameIndex); + auto iter = invalidVaddrIpToFuncName_.find(ips[i]); + if (iter != invalidVaddrIpToFuncName_.end()) { + traceDataCache_->GetPerfCallChainData()->SetName(i, iter->second); + } else { + TS_LOGE("invalidVaddrIpToFuncName_ can't find ip:%p", ips[i]); + } continue; } // if there has the file Id to which the function belongs,and the symboleid is not -1 and vaddrinfile is not -1. @@ -86,6 +94,7 @@ void PerfDataFilter::Finish() fileIdToRowInFileTable_.Clear(); fileIds_.clear(); fileIdToRow_.clear(); + invalidVaddrIpToFuncName_.clear(); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/filter/perf_filter/perf_data_filter.h b/trace_streamer/src/filter/perf_filter/perf_data_filter.h index 5698da906e3042cf63ea5da3239014dd8d531072..e12221c9ecbdfd4df857a2c6a2d248e82ca8ee7e 100644 --- a/trace_streamer/src/filter/perf_filter/perf_data_filter.h +++ b/trace_streamer/src/filter/perf_filter/perf_data_filter.h @@ -34,6 +34,7 @@ public: public: size_t AppendPerfFiles(uint64_t fileId, uint32_t serial, DataIndex symbols, DataIndex filePath); + void AppendInvalidVaddrIpToFuncName(uint64_t ip, DataIndex nameIndex); void Finish(); void BeforeReload(); @@ -41,6 +42,7 @@ private: DoubleMap fileIdToRowInFileTable_; std::set fileIds_; std::map fileIdToRow_{}; + std::map invalidVaddrIpToFuncName_{}; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/filter/process_filter.cpp b/trace_streamer/src/filter/process_filter.cpp index e05a60f8a9217129a6691cc452bd155b17bbcf05..199b470594f9c9c6c54a9d1eb149a51919258ec6 100644 --- a/trace_streamer/src/filter/process_filter.cpp +++ b/trace_streamer/src/filter/process_filter.cpp @@ -244,6 +244,25 @@ std::tuple ProcessFilter::CreateProcessMaybe( return std::make_tuple(internalPid, process); } +void ProcessFilter::UpdateProcessNameByNameToTid(std::unordered_map &tidToName) +{ + auto processList = traceDataCache_->GetConstProcessData(); + auto size = processList.size(); + for (auto row = 0; row < size; row++) { + if (!processList[row].cmdLine_.empty()) { + continue; + } + auto process = traceDataCache_->GetProcessData(row); + if (!process) { + continue; + } + auto it = tidToName.find(process->pid_); + if (it != tidToName.end()) { + auto res = UpdateOrCreateProcessWithName(process->pid_, it->second.c_str()); + TS_LOGI("Update process name %s to tid %d", it->second.c_str(), process->pid_); + } + } +} void ProcessFilter::Clear() { tidMappingSet_.clear(); diff --git a/trace_streamer/src/filter/process_filter.h b/trace_streamer/src/filter/process_filter.h index 1ef82fe96d44032d2e6b29633dd5cc2a6e9b483f..9585135041c42300c2c02b27943ed9eb15f66740 100644 --- a/trace_streamer/src/filter/process_filter.h +++ b/trace_streamer/src/filter/process_filter.h @@ -44,6 +44,7 @@ public: void AddCpuStateCount(uint32_t itid); void AddProcessSliceNum(uint32_t ipid); void Clear(); + void UpdateProcessNameByNameToTid(std::unordered_map &tidToName); private: std::tuple CreateProcessMaybe(uint32_t pid, uint64_t startT); diff --git a/trace_streamer/src/filter/slice_filter.cpp b/trace_streamer/src/filter/slice_filter.cpp index 00ad01d3a72cc112cc4763d0cf040f7dabc7619e..63394dce9c743ab2b4ea60ef1bcb8c6712a64da2 100644 --- a/trace_streamer/src/filter/slice_filter.cpp +++ b/trace_streamer/src/filter/slice_filter.cpp @@ -327,7 +327,8 @@ size_t SliceFilter::StartSlice(uint64_t timeStamp, uint32_t parentId = depth == 0 ? INVALID_UINT32 : slices->IdsData()[stack.back().index]; CallStackInternalRow callStackInternalRow = {sliceData.timeStamp, static_cast(sliceData.duration), sliceData.internalTid, sliceData.cat, - sliceData.name, 0}; + sliceData.name, 0, + INVALID_UINT32}; size_t index = slices->AppendInternalSlice(callStackInternalRow, parentId); if (depth >= std::numeric_limits::max()) { return SIZE_MAX; @@ -464,8 +465,9 @@ uint64_t SliceFilter::StartAsyncSlice(uint64_t timeStamp, // the IDE need a depth to paint call slice in different position of the canvas, the depth of async call // do not mean the parent-to-child relationship, it is different from no-async call uint8_t depth = 0; - CallStackInternalRow callStackInternalRow = {timeStamp, static_cast(-1), internalTid, cat, nameIndex, - depth}; + uint32_t childCallid = parentId; + CallStackInternalRow callStackInternalRow = { + timeStamp, static_cast(-1), internalTid, cat, nameIndex, depth, childCallid}; size_t index = slices->AppendInternalAsyncSlice(callStackInternalRow, cookie, parentId); asyncEventFilterMap_.insert(std::make_pair(asyncEventSize_, AsyncEvent{timeStamp, index})); return index; diff --git a/trace_streamer/src/filter/syscall_filter.cpp b/trace_streamer/src/filter/syscall_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f0f4907b9cceb726b9d710d1f9245b31fbfd295 --- /dev/null +++ b/trace_streamer/src/filter/syscall_filter.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * 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. + */ + +#include "syscall_filter.h" + +#include "config_filter.h" +#include "process_filter.h" + +namespace SysTuning { +namespace TraceStreamer { +SyscallFilter::SyscallFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter) + : FilterBase(dataCache, filter) +{ +} +SyscallFilter::~SyscallFilter() {} + +void SyscallFilter::UpdataSyscallEnterExitMap(const SyscallInfoRow &syscallInfoRow) +{ + TS_LOGD("SysEnterEvent: SysEnter ID %u", syscallInfoRow.number); + const auto &syscallNrSet = streamFilters_->configFilter_->GetSwitchConfig().SyscallsTsSet(); + if (syscallNrSet.find(syscallInfoRow.number) == syscallNrSet.end()) { + return; + } + syscallEnterExitMap_[syscallInfoRow.itid] = syscallInfoRow; +} + +void SyscallFilter::AppendSysCallInfo(uint32_t pid, uint32_t syscallNr, uint64_t ts, int64_t ret) +{ + TS_LOGD("SysExitEvent: SysEnter ID %u", syscallNr); + auto syscallEnterExitItor = syscallEnterExitMap_.find(pid); + if (syscallEnterExitItor != syscallEnterExitMap_.end()) { + auto &syscallInfoRow = syscallEnterExitItor->second; + if (syscallInfoRow.number == syscallNr && syscallInfoRow.ts <= ts) { + syscallInfoRow.dur = ts - syscallInfoRow.ts; + syscallInfoRow.ret = ret; + syscallInfoRow.itid = streamFilters_->processFilter_->UpdateOrCreateThread(ts, pid); + traceDataCache_->GetSysCallData()->AppendSysCallData(syscallInfoRow); + } + syscallEnterExitMap_.erase(pid); + } else { + TS_LOGW("SysExitEvent: No matching sysExit event found for syscallID = %u.", syscallNr); + } +} + +void SyscallFilter::Clear() +{ + syscallEnterExitMap_.clear(); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/filter/syscall_filter.h b/trace_streamer/src/filter/syscall_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..9771bfc50c768fd115708888d586b057a02c2b7b --- /dev/null +++ b/trace_streamer/src/filter/syscall_filter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * 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. + */ + +#ifndef SYSCALL_FILTER_H +#define SYSCALL_FILTER_H + +#include +#include + +#include "clock_filter_ex.h" +#include "common_types.h" +#include "filter_base.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::base; +class SyscallFilter : private FilterBase { +public: + SyscallFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter); + ~SyscallFilter() override; + void UpdataSyscallEnterExitMap(const SyscallInfoRow &syscallInfoRow); + void AppendSysCallInfo(uint32_t pid, uint32_t syscallNr, uint64_t ts, int64_t ret); + void Clear(); + +private: + std::map syscallEnterExitMap_; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // SYSCALL_FILTER_H diff --git a/trace_streamer/src/parser/common_types.h b/trace_streamer/src/parser/common_types.h index 16a3e3bddec1a2dfee05e9834a744d94e681a797..76d48f7765848e796de45af54c3b0757ead7cca8 100644 --- a/trace_streamer/src/parser/common_types.h +++ b/trace_streamer/src/parser/common_types.h @@ -90,7 +90,11 @@ public: args_(point.args_), funcPrefixId_(point.funcPrefixId_), funcPrefix_(point.funcPrefix_), - funcArgs_(point.funcArgs_) + funcArgs_(point.funcArgs_), + traceLevel_(point.traceLevel_), + traceTagId_(point.traceTagId_), + customCategoryId_(point.customCategoryId_), + customArgsId_(point.customArgsId_) { } void operator=(const TracePoint &point) @@ -108,6 +112,10 @@ public: funcPrefixId_ = point.funcPrefixId_; funcPrefix_ = point.funcPrefix_; funcArgs_ = point.funcArgs_; + traceLevel_ = point.traceLevel_; + traceTagId_ = point.traceTagId_; + customCategoryId_ = point.customCategoryId_; + customArgsId_ = point.customArgsId_; } char phase_ = '\0'; uint32_t tgid_ = 0; @@ -123,6 +131,10 @@ public: uint32_t funcPrefixId_ = 0; std::string funcPrefix_ = ""; std::string funcArgs_ = ""; + std::string traceLevel_ = ""; + DataIndex traceTagId_ = INVALID_UINT64; + DataIndex customCategoryId_ = INVALID_UINT64; + DataIndex customArgsId_ = INVALID_UINT64; }; enum class SplitDataDataType { SPLIT_FILE_DATA = 0, SPLIT_FILE_JSON }; diff --git a/trace_streamer/src/parser/ebpf_parser/BUILD.gn b/trace_streamer/src/parser/ebpf_parser/BUILD.gn index 31f6667c07b0558f25bd9454833a3f33fa180c23..9446f8527b0a1597ca87add62bc2c83a73efddbb 100644 --- a/trace_streamer/src/parser/ebpf_parser/BUILD.gn +++ b/trace_streamer/src/parser/ebpf_parser/BUILD.gn @@ -77,7 +77,7 @@ ohos_static_library("ebpf_parser") { public_configs = [ ":ebpf_parser_cfg" ] public_deps = [ "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/memory_data:memory_data_reader", - "${PERF_DIR}/hiperf:hiperf_src", + "../hiperf_parser:ts_hiperf_src", ] deps = [ "${THIRD_PARTY}/protobuf:protobuf_lite_static", diff --git a/trace_streamer/src/parser/hiperf_parser/BUILD.gn b/trace_streamer/src/parser/hiperf_parser/BUILD.gn index 81a43fd649ea8837370bd0818f7fd9dac1db9011..0dd179d138a5b1a5b86e5af400afb394b76f2a0a 100644 --- a/trace_streamer/src/parser/hiperf_parser/BUILD.gn +++ b/trace_streamer/src/parser/hiperf_parser/BUILD.gn @@ -14,6 +14,242 @@ import("//build/ohos.gni") import("../../../build/ts.gni") +# THIRD_PARTY for bzip2 +config("bzip2_config") { + include_dirs = [ "${THIRD_PARTY}/bzip2" ] +} + +ohos_source_set("bzip2_src") { + sources = [ + "${THIRD_PARTY}/bzip2/blocksort.c", + "${THIRD_PARTY}/bzip2/bzlib.c", + "${THIRD_PARTY}/bzip2/compress.c", + "${THIRD_PARTY}/bzip2/crctable.c", + "${THIRD_PARTY}/bzip2/decompress.c", + "${THIRD_PARTY}/bzip2/huffman.c", + "${THIRD_PARTY}/bzip2/randtable.c", + ] + configs += [ ":bzip2_config" ] + + part_name = "bzip2" + subsystem_name = "thirdparty" +} + +ohos_source_set("libbz2") { + deps = [ ":bzip2_src" ] + public_configs = [ ":bzip2_config" ] + + part_name = "bzip2" + subsystem_name = "thirdparty" +} + +# THIRD_PARTY for zlib +config("zlib_config") { + cflags = [ + "-Wno-incompatible-pointer-types", + "-Werror", + "-Wno-strict-prototypes", + "-Wimplicit-function-declaration", + "-D HAVE_BZIP2", + ] +} + +config("zlib_public_config") { + include_dirs = [ "${THIRD_PARTY}/zlib" ] +} + +sources_zlib_with_ts_common = [ + "${THIRD_PARTY}/zlib/adler32.c", + "${THIRD_PARTY}/zlib/compress.c", + "${THIRD_PARTY}/zlib/contrib/minizip/ioapi.c", + "${THIRD_PARTY}/zlib/contrib/minizip/unzip.c", + "${THIRD_PARTY}/zlib/contrib/minizip/zip.c", + "${THIRD_PARTY}/zlib/crc32.c", + "${THIRD_PARTY}/zlib/deflate.c", + "${THIRD_PARTY}/zlib/gzclose.c", + "${THIRD_PARTY}/zlib/gzlib.c", + "${THIRD_PARTY}/zlib/gzread.c", + "${THIRD_PARTY}/zlib/gzwrite.c", + "${THIRD_PARTY}/zlib/infback.c", + "${THIRD_PARTY}/zlib/inffast.c", + "${THIRD_PARTY}/zlib/inflate.c", + "${THIRD_PARTY}/zlib/inftrees.c", + "${THIRD_PARTY}/zlib/trees.c", + "${THIRD_PARTY}/zlib/uncompr.c", + "${THIRD_PARTY}/zlib/zutil.c", +] +ohos_source_set("libz") { + sources = sources_zlib_with_ts_common + configs += [ ":zlib_config" ] + public_configs = [ ":zlib_public_config" ] + public_deps = [ ":libbz2" ] + part_name = "zlib" + subsystem_name = "thirdparty" +} + +# THIRD_PARTY for bounds_checking_function +sources_libsec_with_ts_common = [ + "${THIRD_PARTY}/bounds_checking_function/src/fscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/fwscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/gets_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/memcpy_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/memmove_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/memset_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/scanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/securecutil.c", + "${THIRD_PARTY}/bounds_checking_function/src/secureinput_a.c", + "${THIRD_PARTY}/bounds_checking_function/src/secureinput_w.c", + "${THIRD_PARTY}/bounds_checking_function/src/secureprintoutput_a.c", + "${THIRD_PARTY}/bounds_checking_function/src/secureprintoutput_w.c", + "${THIRD_PARTY}/bounds_checking_function/src/snprintf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/sprintf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/sscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/strcat_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/strcpy_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/strncat_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/strncpy_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/strtok_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/swprintf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/swscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/vfscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/vfwscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/vscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/vsnprintf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/vsprintf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/vsscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/vswprintf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/vswscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/vwscanf_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/wcscat_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/wcscpy_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/wcsncat_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/wcsncpy_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/wcstok_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/wmemcpy_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/wmemmove_s.c", + "${THIRD_PARTY}/bounds_checking_function/src/wscanf_s.c", +] + +ohos_source_set("libsec_static") { + sources = sources_libsec_with_ts_common + include_dirs = [ "${THIRD_PARTY}/bounds_checking_function/include" ] + cflags = [ + "-D_INC_STRING_S", + "-D_INC_WCHAR_S", + "-D_SECIMP=//", + "-D_STDIO_S_DEFINED", + "-D_INC_STDIO_S", + "-D_INC_STDLIB_S", + "-D_INC_MEMORY_S", + ] +} + +# THIRD_PARTY for hiviewdfx faultloggerd +config("faultloggerd_config") { + cflags = [ + "-D ALWAYSTRUE", + "-D DFX_NO_PRINT_LOG", + "-D is_host", + ] +} +config("faultloggerd_public_config") { + include_dirs = [ + "${THIRD_PARTY}/hiviewdfx/faultloggerd/common/dfxlog", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/common/dfxutil", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/common/trace/include", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/common", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/nonlinux", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/include", + "${THIRD_PARTY}/bounds_checking_function/include", + "${COMMON_LIBRARY}/c_utils/base/include", + ] +} +sources_faultloggerd_with_ts_common = [ + "${THIRD_PARTY}/hiviewdfx/faultloggerd/common/dfxutil/dfx_util.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/common/trace/dfx_trace_dlsym.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/ark/dfx_hap.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/elf/dfx_elf.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/elf/dfx_elf_parser.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/elf/dfx_symbols.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/elf/dfx_mmap.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/elf/elf_factory.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/elf/elf_factory_selector.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/maps/dfx_map.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/maps/dfx_maps.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/memory/dfx_memory.cpp", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/innerkits/unwinder/src/utils/unwinder_config.cpp", +] +ohos_source_set("libfaultloggerd") { + sources = sources_faultloggerd_with_ts_common + configs += [ ":faultloggerd_config" ] + public_configs = [ ":faultloggerd_public_config" ] + public_deps = [ ":libsec_static" ] + part_name = "faultloggerd" + subsystem_name = "thirdparty" +} + +# THIRD_PARTY for hiperf +sources_platform_with_ts_common = [ + "${PERF_DIR}/hiperf/src/dwarf_encoding.cpp", + "${PERF_DIR}/hiperf/src/option.cpp", + "${PERF_DIR}/hiperf/src/perf_event_record.cpp", + "${PERF_DIR}/hiperf/src/perf_file_format.cpp", + "${PERF_DIR}/hiperf/src/perf_file_reader.cpp", + "${PERF_DIR}/hiperf/src/register.cpp", + "${PERF_DIR}/hiperf/src/report.cpp", + "${PERF_DIR}/hiperf/src/subcommand.cpp", + "${PERF_DIR}/hiperf/src/symbols_file.cpp", + "${PERF_DIR}/hiperf/src/unique_stack_table.cpp", + "${PERF_DIR}/hiperf/src/utilities.cpp", + "${PERF_DIR}/hiperf/src/virtual_runtime.cpp", + "${PERF_DIR}/hiperf/src/virtual_thread.cpp", +] + +if (hiperf_debug) { + sources_platform_with_ts_common += + [ "${PERF_DIR}/hiperf/src/debug_logger.cpp" ] +} + +config("ts_hiperf_config") { + cflags = [ + "-D ALWAYSTRUE", + "-D CONFIG_NO_HILOG", + ] + cflags_cc = [ + "-std=c++17", + "-fvisibility=hidden", + "-Wno-unused-variable", + ] +} +config("ts_hiperf_public_config") { + include_dirs = [ + "${PERF_DIR}/hiperf/include", + "${PERF_DIR}/hiperf/include/nonlinux", + "${PERF_DIR}/hiperf/include/nonlinux/linux", + ] + include_dirs += [ + "${THIRD_PARTY}/bounds_checking_function/include", + "${COMMON_LIBRARY}/c_utils/base/include", + "${THIRD_PARTY}/libbpf/include/uapi", + ] + if (is_mingw) { + cflags = [ "-includeMingW64Fix.h" ] + } +} +ohos_source_set("ts_hiperf_src") { + subsystem_name = "thirdparty" + part_name = "hiperf" + configs -= [ trace_cfg_path ] + configs += [ ":ts_hiperf_config" ] + public_configs = [ ":ts_hiperf_public_config" ] + public_deps = [ + ":libfaultloggerd", + ":libz", + ] + sources = sources_platform_with_ts_common +} + +# for hiperf parser config("hiperf_parser_cfg") { if (!is_independent_compile) { configs = [ "${TS_DIR}/gn:ts_config" ] @@ -46,7 +282,7 @@ config("hiperf_parser_cfg") { "${THIRD_PARTY}/bounds_checking_function/include", "${THIRD_PARTY}/sqlite/include", "${THIRD_PARTY}/protobuf/src", - "${COMMON_LIBRARY}/base/include", + "${COMMON_LIBRARY}/c_utils/base/include", "${THIRD_PARTY}/googletest/googletest/include", ] include_dirs += [ @@ -62,13 +298,10 @@ config("hiperf_parser_cfg") { ] include_dirs += [ "${THIRD_PARTY}/googletest/googletest/include", - "${THIRD_PARTY}/perf_include/libbpf", - "${THIRD_PARTY}/perf_include/include", - "${THIRD_PARTY}/perf_include", - "${THIRD_PARTY}/perf_include/linux", + "${THIRD_PARTY}/libbpf/include/uapi", "../hiperf_parser", "../hiperf_parser/include", - "${COMMON_LIBRARY}/base/include", + "${COMMON_LIBRARY}/c_utils/base/include", "${THIRD_PARTY}/sqlite", ] if (enable_addr2line) { @@ -82,28 +315,29 @@ config("hiperf_parser_cfg") { } } -ohos_static_library("hiperf_parser") { - subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" - part_name = "${OHOS_PROFILER_PART_NAME}" - sources = [ "perf_data_parser.cpp" ] - public_configs = [ - ":hiperf_parser_cfg", - "../../filter/perf_filter:hiperf_filter_cfg", - ] - public_deps = [ - "${PERF_DIR}/hiperf:hiperf_src", - "${THIRD_PARTY}/protobuf:protobuf_lite_static", - "${THIRD_PARTY}/protobuf:protobuf_static", - "//third_party/perf_include/hiviewdfx:libfaultloggerd", - ] - if (enable_addr2line) { - public_deps += [ - "${LLVM_ROOT}/lib/DebugInfo/DWARF", - "${LLVM_ROOT}/lib/DebugInfo/PDB", - "${LLVM_ROOT}/lib/DebugInfo/Symbolize", - "${LLVM_ROOT}/lib/Demangle", - "${LLVM_ROOT}/lib/Object", - "${LLVM_ROOT}/lib/Support", +if (enable_hiperf) { + ohos_static_library("hiperf_parser") { + subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" + part_name = "${OHOS_PROFILER_PART_NAME}" + sources = [ "perf_data_parser.cpp" ] + public_configs = [ + ":hiperf_parser_cfg", + "../../filter/perf_filter:hiperf_filter_cfg", + ] + public_deps = [ + ":ts_hiperf_src", + "${THIRD_PARTY}/protobuf:protobuf_lite_static", + "${THIRD_PARTY}/protobuf:protobuf_static", ] + if (enable_addr2line) { + public_deps += [ + "${LLVM_ROOT}/lib/DebugInfo/DWARF", + "${LLVM_ROOT}/lib/DebugInfo/PDB", + "${LLVM_ROOT}/lib/DebugInfo/Symbolize", + "${LLVM_ROOT}/lib/Demangle", + "${LLVM_ROOT}/lib/Object", + "${LLVM_ROOT}/lib/Support", + ] + } } } diff --git a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp index 8bfd5bd6e6ce0b2b8d200d1e935731afded6daf1..265feaa76e85483d6b3a9d83a642c4231e6aac9e 100644 --- a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp +++ b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp @@ -683,17 +683,17 @@ void PerfDataParser::UpdateClockType() TS_LOGI("useClockId_ = %u, clockId_ = %u", useClockId_, clockId_); } } -bool PerfDataParser::RecordCallBack(std::unique_ptr record) +bool PerfDataParser::RecordCallBack(PerfEventRecord &record) { // tell process tree what happend for rebuild symbols - report_->virtualRuntime_.UpdateFromRecord(*record); + report_->virtualRuntime_.UpdateFromRecord(record); - if (record->GetType() == PERF_RECORD_SAMPLE) { - std::unique_ptr sample(static_cast(record.release())); + if (record.GetType() == PERF_RECORD_SAMPLE) { + auto *sample = static_cast(&record); uint32_t callChainId = UpdateCallChainUnCompressed(sample); UpdatePerfSampleData(callChainId, sample); - } else if (record->GetType() == PERF_RECORD_COMM) { - auto recordComm = static_cast(record.get()); + } else if (record.GetType() == PERF_RECORD_COMM) { + auto recordComm = static_cast(&record); auto range = tidToPid_.equal_range(recordComm->data_.tid); for (auto it = range.first; it != range.second; it++) { if (it->second == recordComm->data_.pid) { @@ -708,7 +708,7 @@ bool PerfDataParser::RecordCallBack(std::unique_ptr record) return true; } -uint32_t PerfDataParser::UpdateCallChainUnCompressed(const std::unique_ptr &sample) +uint32_t PerfDataParser::UpdateCallChainUnCompressed(const PerfRecordSample *sample) { std::string stackStr = ""; for (auto &callFrame : sample->callFrames_) { @@ -732,12 +732,17 @@ uint32_t PerfDataParser::UpdateCallChainUnCompressed(const std::unique_ptrpc, frame->funcOffset, frame->mapOffset, fileId, frame->index}; + if (frame->funcOffset == 0 || frame->index == -1) { + auto iPos = frame->funcName.find_last_of('/'); + auto nameIndex = traceDataCache_->dataDict_.GetStringIndex(frame->funcName.substr(iPos + 1, -1)); + streamFilters_->perfDataFilter_->AppendInvalidVaddrIpToFuncName(frame->pc, nameIndex); + } traceDataCache_->GetPerfCallChainData()->AppendNewPerfCallChain(perfCallChainRow); } return callChainId; } -void PerfDataParser::UpdatePerfSampleData(uint32_t callChainId, std::unique_ptr &sample) +void PerfDataParser::UpdatePerfSampleData(uint32_t callChainId, const PerfRecordSample *sample) { auto perfSampleData = traceDataCache_->GetPerfSampleData(); uint64_t newTimeStamp = 0; diff --git a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.h b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.h index 1c885c6e6bac0e75866c4f6a114429cf52a06ba3..b47ebf1860f903c69270933f25a733d2e525b4d5 100644 --- a/trace_streamer/src/parser/hiperf_parser/perf_data_parser.h +++ b/trace_streamer/src/parser/hiperf_parser/perf_data_parser.h @@ -103,12 +103,12 @@ private: void UpdateReportWorkloadInfo() const; void UpdateSymbolAndFilesData(); void UpdateClockType(); - bool RecordCallBack(std::unique_ptr record); - void UpdatePerfSampleData(uint32_t callChainId, std::unique_ptr &sample); + bool RecordCallBack(PerfEventRecord &record); + void UpdatePerfSampleData(uint32_t callChainId, const PerfRecordSample *sample); std::tuple GetFileIdWithLikelyFilePath(const std::string &inputFilePath); bool ReloadPerfFile(const std::unique_ptr &symbolsFile, uint64_t &fileId, DataIndex &filePathIndex); void ReloadPerfCallChain(const std::unique_ptr &symbolsFile, uint64_t fileId, DataIndex filePathIndex); - uint32_t UpdateCallChainUnCompressed(const std::unique_ptr &sample); + uint32_t UpdateCallChainUnCompressed(const PerfRecordSample *sample); SplitPerfState DataLengthProcessing(const std::deque &dequeBuffer, perf_event_header &dataHeader, uint64_t size, diff --git a/trace_streamer/src/parser/pbreader_parser/BUILD.gn b/trace_streamer/src/parser/pbreader_parser/BUILD.gn index 26bbe946d0f871e9da73f6a633f7b87b01484b3d..789ffc410f3938f71e412a9699a736a4f68fb62e 100644 --- a/trace_streamer/src/parser/pbreader_parser/BUILD.gn +++ b/trace_streamer/src/parser/pbreader_parser/BUILD.gn @@ -130,7 +130,6 @@ ohos_source_set("pbreader_parser_src") { "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:ts_all_type_cpp_standard", "${THIRD_PARTY}/protobuf:protobuf_lite_static", "${THIRD_PARTY}/protobuf:protobuf_static", - "${THIRD_PARTY}/zlib:libz", - "//third_party/perf_include/hiviewdfx:libfaultloggerd", + "../hiperf_parser:libz", ] } diff --git a/trace_streamer/src/parser/pbreader_parser/cpu_data_parser/pbreader_cpu_data_parser.cpp b/trace_streamer/src/parser/pbreader_parser/cpu_data_parser/pbreader_cpu_data_parser.cpp index a941cc3627ab8f9ac25383d6a409ced04207a9d4..0e16e3041562e69b16b86545f374b6fcf8de702b 100644 --- a/trace_streamer/src/parser/pbreader_parser/cpu_data_parser/pbreader_cpu_data_parser.cpp +++ b/trace_streamer/src/parser/pbreader_parser/cpu_data_parser/pbreader_cpu_data_parser.cpp @@ -31,21 +31,19 @@ PbreaderCpuDataParser::~PbreaderCpuDataParser() void PbreaderCpuDataParser::Parse(ProtoReader::BytesView tracePacket, uint64_t ts) { ProtoReader::CpuData_Reader cpuData(tracePacket.data_, tracePacket.size_); - if (!cpuData.has_cpu_usage_info() && !cpuData.has_thread_info()) { + if (!cpuData.has_cpu_usage_info()) { return; } - if (cpuData.has_cpu_usage_info()) { - auto userLoad = cpuData.user_load(); - auto sysLoad = cpuData.sys_load(); - auto process_num = cpuData.process_num(); - ts = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); - UpdatePluginTimeRange(TS_CLOCK_REALTIME, ts, ts); - auto cpuUsage = std::make_unique(); - streamFilters_->statFilter_->IncreaseStat(TRACE_CPU_USAGE, STAT_EVENT_RECEIVED); - cpuUsage->SetCpuUsage(ts); - cpuUsage->SetExtInfo(cpuData.total_load(), userLoad, sysLoad, process_num); - cpuData_.push_back(std::move(cpuUsage)); - } + auto userLoad = cpuData.user_load(); + auto sysLoad = cpuData.sys_load(); + auto process_num = cpuData.process_num(); + ts = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); + UpdatePluginTimeRange(TS_CLOCK_REALTIME, ts, ts); + auto cpuUsage = std::make_unique(); + streamFilters_->statFilter_->IncreaseStat(TRACE_CPU_USAGE, STAT_EVENT_RECEIVED); + cpuUsage->SetCpuUsage(ts); + cpuUsage->SetExtInfo(cpuData.total_load(), userLoad, sysLoad, process_num); + cpuData_.push_back(std::move(cpuUsage)); } void PbreaderCpuDataParser::Finish() { diff --git a/trace_streamer/src/parser/pbreader_parser/htrace_parser/htrace_event_parser.cpp b/trace_streamer/src/parser/pbreader_parser/htrace_parser/htrace_event_parser.cpp index 108f4c450e277aae7f800e3e1162c203407cb2d4..d68371a788f9522cb856ba7a9f4d50accee4633d 100644 --- a/trace_streamer/src/parser/pbreader_parser/htrace_parser/htrace_event_parser.cpp +++ b/trace_streamer/src/parser/pbreader_parser/htrace_parser/htrace_event_parser.cpp @@ -39,6 +39,7 @@ #include "signal.pbreader.h" #include "slice_filter.h" #include "stat_filter.h" +#include "syscall_filter.h" #include "system_event_measure_filter.h" #include "task.pbreader.h" #include "thread_state_flag.h" @@ -497,7 +498,8 @@ bool HtraceEventParser::BinderTractionEvent(const EventInfo &event) const destTid, transactionId, isReply, flags, msg.code()); streamFilters_->binderFilter_->SendTraction(event.timeStamp, event.pid, transactionId, destNode, destTgid, destTid, isReply, flags, msg.code()); - if (traceDataCache_->BinderRunnableTraceEnabled() && !streamFilters_->binderFilter_->IsAsync(flags)) { + if (streamFilters_->configFilter_->GetSwitchConfig().BinderRunnableConfigEnabled() && + !streamFilters_->binderFilter_->IsAsync(flags)) { streamFilters_->cpuFilter_->InsertRunnableBinderEvent( transactionId, streamFilters_->processFilter_->GetInternalTid(event.pid)); } @@ -509,7 +511,7 @@ bool HtraceEventParser::BinderTractionReceivedEvent(const EventInfo &event) cons ProtoReader::BinderTransactionReceivedFormat_Reader msg(event.detail); int32_t transactionId = msg.debug_id(); streamFilters_->binderFilter_->ReceiveTraction(event.timeStamp, event.pid, transactionId); - if (traceDataCache_->BinderRunnableTraceEnabled()) { + if (streamFilters_->configFilter_->GetSwitchConfig().BinderRunnableConfigEnabled()) { streamFilters_->cpuFilter_->InsertRunnableBinderRecvEvent( transactionId, streamFilters_->processFilter_->GetInternalTid(event.pid)); } @@ -992,18 +994,41 @@ bool HtraceEventParser::DmaFenceSignaledEvent(const EventInfo &event) const } bool HtraceEventParser::SysEnterEvent(const EventInfo &event) const { - streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); + if (streamFilters_->configFilter_->GetSwitchConfig().SyscallsTsSet().empty()) { + return true; + } ProtoReader::SysEnterFormat_Reader msg(event.detail); - auto ipid = streamFilters_->processFilter_->UpdateOrCreateThread(event.timeStamp, event.tgid); - traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), sysEnterName_, ipid, event.timeStamp, 0); + SyscallInfoRow syscallInfoRow; + syscallInfoRow.ts = event.timeStamp; + syscallInfoRow.itid = event.pid; + syscallInfoRow.number = msg.id(); + // if (msg.has_args()) { + // bool parseErrorInfo = false; + // auto eventItor = msg.args(&parseErrorInfo); + // std::ostringstream oss; + // oss << "("; + // while (eventItor) { + // oss << std::hex << std::nouppercase << *eventItor; + // eventItor++; + // if (eventItor) { + // oss << ", "; + // } + // } + // oss << ")"; + // syscallInfoRow.args = traceDataCache_->GetDataIndex(oss.str()); + // } + streamFilters_->syscallFilter_->UpdataSyscallEnterExitMap(syscallInfoRow); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); return true; } bool HtraceEventParser::SysExitEvent(const EventInfo &event) const { - streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_EXIT, STAT_EVENT_RECEIVED); + if (streamFilters_->configFilter_->GetSwitchConfig().SyscallsTsSet().empty()) { + return true; + } ProtoReader::SysExitFormat_Reader msg(event.detail); - auto ipid = streamFilters_->processFilter_->UpdateOrCreateThread(event.timeStamp, event.tgid); - traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), sysExitName_, ipid, event.timeStamp, msg.ret()); + streamFilters_->syscallFilter_->AppendSysCallInfo(event.pid, msg.id(), event.timeStamp, msg.ret()); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_EXIT, STAT_EVENT_RECEIVED); return true; } @@ -1067,7 +1092,7 @@ void HtraceEventParser::FilterAllEvents() streamFilters_->cpuFilter_->Finish(); traceDataCache_->dataDict_.Finish(); traceDataCache_->UpdataZeroThreadInfo(); - if (traceDataCache_->AppStartTraceEnabled()) { + if (streamFilters_->configFilter_->GetSwitchConfig().AppConfigEnabled()) { streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); } traceDataCache_->GetThreadStateData()->SortAllRowByTs(); diff --git a/trace_streamer/src/parser/pbreader_parser/native_hook_parser/BUILD.gn b/trace_streamer/src/parser/pbreader_parser/native_hook_parser/BUILD.gn index 0e512554ee67919c4aa2db6b03d895b69b2f611a..cd10c6bffef6035b7e84fba2c8b5497f08f063a2 100644 --- a/trace_streamer/src/parser/pbreader_parser/native_hook_parser/BUILD.gn +++ b/trace_streamer/src/parser/pbreader_parser/native_hook_parser/BUILD.gn @@ -29,7 +29,7 @@ ohos_static_library("native_hook_parser") { "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/services:ts_all_type_cpp", "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/ftrace_data/${device_kernel_version}:ftrace_data_reader", "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/native_hook:native_hook_data_reader", - "${PERF_DIR}/hiperf:hiperf_src", + "../../hiperf_parser:ts_hiperf_src", ] public_configs = [ ":native_hook_parser_cfg", diff --git a/trace_streamer/src/parser/print_event_parser.cpp b/trace_streamer/src/parser/print_event_parser.cpp index a72718144f336ee6150658f5fdc31b1a9dd9df3a..e24ca87eec76e550cbcad0b2375b5341aba2f442 100644 --- a/trace_streamer/src/parser/print_event_parser.cpp +++ b/trace_streamer/src/parser/print_event_parser.cpp @@ -24,6 +24,9 @@ namespace SysTuning { namespace TraceStreamer { const uint8_t POINT_LENGTH = 1; const uint8_t MAX_POINT_LENGTH = 2; +const uint8_t CATEGORY_INDEX = 2; +const uint8_t PARSER_SYNC_SUM = 2; +const uint8_t PARSER_ASYNC_SUM = 3; PrintEventParser::PrintEventParser(TraceDataCache *dataCache, const TraceStreamerFilters *filter) : EventParserBase(dataCache, filter) { @@ -105,14 +108,18 @@ void PrintEventParser::ParseBeginEvent(const std::string &comm, // add distributed data traceDataCache_->GetInternalSlicesData()->SetDistributeInfo(index, point.chainId_, point.spanId_, point.parentSpanId_, point.flag_); + + // add traceMeta data + traceDataCache_->GetInternalSlicesData()->SetTraceMetadata(index, point.traceLevel_, point.traceTagId_, + point.customArgsId_); if (HandleFrameSliceBeginEvent(point.funcPrefixId_, index, point.funcArgs_, line)) { return; } bool isDiscontinued = false; - if (traceDataCache_->TaskPoolTraceEnabled()) { + if (streamFilters_->configFilter_->GetSwitchConfig().TaskPoolConfigEnabled()) { isDiscontinued = streamFilters_->taskPoolFilter_->TaskPoolEvent(point.name_, index); } - if (traceDataCache_->AnimationTraceEnabled() && !isDiscontinued) { + if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled() && !isDiscontinued) { (void)HandleAnimationBeginEvent(point, index, line); } } else { @@ -123,7 +130,7 @@ void PrintEventParser::ParseEndEvent(uint64_t ts, uint32_t pid, const TracePoint { uint32_t index = streamFilters_->sliceFilter_->EndSlice(ts, pid, point.tgid_); HandleFrameSliceEndEvent(ts, point.tgid_, pid, index); - if (traceDataCache_->AnimationTraceEnabled()) { + if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled()) { streamFilters_->animationFilter_->EndDynamicFrameEvent(ts, index); } } @@ -136,11 +143,18 @@ void PrintEventParser::ParseStartEvent(const std::string &comm, auto cookie = static_cast(point.value_); auto index = streamFilters_->sliceFilter_->StartAsyncSlice(ts, pid, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_)); - if (point.name_ == onFrameQueeuStartEvent_ && index != INVALID_UINT64) { + if (index == INVALID_UINT64) { + return; + } + // add traceMeta data + traceDataCache_->GetInternalSlicesData()->SetTraceMetadata(index, point.traceLevel_, point.traceTagId_, + point.customArgsId_, point.customCategoryId_); + + if (point.name_ == onFrameQueeuStartEvent_) { OnFrameQueueStart(ts, index, point.tgid_); - } else if (traceDataCache_->AnimationTraceEnabled() && index != INVALID_UINT64 && - (base::EndWith(comm, onAnimationProcEvent_) || - base::EndWith(comm, newOnAnimationProcEvent_))) { // the comm is taskName + } else if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled() && index != INVALID_UINT64 && + streamFilters_->configFilter_->GetAnimationConfig().CheckIfAnimationEvents( + comm)) { // the comm is taskName streamFilters_->animationFilter_->StartAnimationEvent(line, point, index); } } @@ -150,7 +164,7 @@ void PrintEventParser::ParseFinishEvent(uint64_t ts, uint32_t pid, const TracePo auto index = streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_)); HandleFrameQueueEndEvent(ts, point.tgid_, point.tgid_, index); - if (traceDataCache_->AnimationTraceEnabled()) { + if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled()) { streamFilters_->animationFilter_->FinishAnimationEvent(line, index); } } @@ -247,6 +261,39 @@ std::string_view PrintEventParser::GetPointNameForBegin(std::string_view pointSt return name; } +void PrintEventParser::ParseSplitTraceMetaData(const std::string &dataStr, TracePoint &outPoint, bool isAsynEvent) const +{ + std::string metaDataStr = base::Strip(dataStr); + uint32_t expectedCount = isAsynEvent ? PARSER_ASYNC_SUM : PARSER_SYNC_SUM; + std::vector traceMetaDatas = base::SplitStringToVec(metaDataStr, "|", expectedCount); + if (traceMetaDatas.size() <= 1) { + TS_LOGD("traceMetaDatas size: %zu, dataStr: %s", traceMetaDatas.size(), dataStr.c_str()); + return; + } + if (!isAsynEvent) { + outPoint.name_ = std::move(traceMetaDatas[0]); + } + + std::string &marker = traceMetaDatas[1]; + if (!marker.empty()) { + outPoint.traceLevel_ = marker.substr(0, 1); + if (marker.size() > 1) { + std::string traceTag = marker.substr(1); + outPoint.traceTagId_ = traceDataCache_->GetDataIndex(traceTag); + } + } + + if (isAsynEvent && traceMetaDatas.size() > CATEGORY_INDEX) { + std::string customCategory = traceMetaDatas[CATEGORY_INDEX]; + outPoint.customCategoryId_ = traceDataCache_->GetDataIndex(customCategory); + } + + if (traceMetaDatas.size() > expectedCount) { + std::string customArgs = traceMetaDatas[expectedCount]; + outPoint.customArgsId_ = traceDataCache_->GetDataIndex(customArgs); + } +} + ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const { outPoint.name_ = GetPointNameForBegin(pointStr, tGidlength); @@ -274,6 +321,9 @@ ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint &ou } else { outPoint.funcPrefixId_ = traceDataCache_->GetDataIndex(outPoint.name_); } + + // traceMetaDatasSrt: H:name|%X%TAG|customArgs + ParseSplitTraceMetaData(outPoint.name_, outPoint, false); } return PARSE_SUCCESS; } @@ -375,21 +425,10 @@ bool PrintEventParser::OnRwTransaction(size_t callStackRow, std::string &args, c { // H:MarshRSTransactionData cmdCount:20 transactionFlag:[3799,8] isUni:1 std::smatch match; - if (std::regex_search(args, match, transFlagPattern_)) { - std::string mainTheadId = match.str(1); - std::string flag2 = match.str(2); - // use to update dstRenderSlice_ - auto mainThreadId = - streamFilters_->processFilter_->GetInternalTid(base::StrToInt(mainTheadId).value()); - // use to update vsyncRenderSlice_ - auto currentThreadId = streamFilters_->processFilter_->GetInternalTid(line.pid); - return streamFilters_->frameFilter_->BeginRSTransactionData( - currentThreadId, base::StrToInt(flag2).value(), mainThreadId); - } if (std::regex_search(args, match, newTransFlagPattern_)) { std::string mainTheadId = match.str(1); - std::string currentThread = match.str(2); - std::string flag2 = match.str(3); + std::string flag2 = match.str(2); + std::string currentThread = match.str(3); std::string timeFlag = match.str(4); auto mainThreadId = streamFilters_->processFilter_->GetInternalTid(base::StrToInt(mainTheadId).value()); @@ -399,6 +438,17 @@ bool PrintEventParser::OnRwTransaction(size_t callStackRow, std::string &args, c return streamFilters_->frameFilter_->BeginRSTransactionData( currentThreadId, base::StrToInt(flag2).value(), mainThreadId, timeId); } + if (std::regex_search(args, match, transFlagPattern_)) { + std::string mainTheadId = match.str(1); + std::string flag2 = match.str(2); + // use to update dstRenderSlice_ + auto mainThreadId = + streamFilters_->processFilter_->GetInternalTid(base::StrToInt(mainTheadId).value()); + // use to update vsyncRenderSlice_ + auto currentThreadId = streamFilters_->processFilter_->GetInternalTid(line.pid); + return streamFilters_->frameFilter_->BeginRSTransactionData( + currentThreadId, base::StrToInt(flag2).value(), mainThreadId); + } return true; } bool PrintEventParser::OnMainThreadProcessCmd(size_t callStackRow, std::string &args, const BytraceLine &line) @@ -535,7 +585,11 @@ ParseResult PrintEventParser::HandlerCSF(std::string_view pointStr, TracePoint & outPoint.categoryGroup_ = std::string_view(pointStr.data() + valuePipe + 1, groupLen); } - + // traceMetaDatasSrt: taskId|%X%TAG|customCategory|customArgs + std::string metaDataStr(pointStr.data() + valueIndex); + if (outPoint.phase_ == 'S') { + ParseSplitTraceMetaData(metaDataStr, outPoint, true); + } return PARSE_SUCCESS; } diff --git a/trace_streamer/src/parser/print_event_parser.h b/trace_streamer/src/parser/print_event_parser.h index 2a6aab55245417f43c232c920e1a3b7f519c20f5..fba9fddf59a7afc7032ab2664da78ec3b5320a20 100644 --- a/trace_streamer/src/parser/print_event_parser.h +++ b/trace_streamer/src/parser/print_event_parser.h @@ -53,6 +53,7 @@ public: void Finish(); void SetTraceType(TraceFileType traceType); void SetTraceClockId(BuiltinClocks clock); + void ParseSplitTraceMetaData(const std::string &dataStr, TracePoint &outPoint, bool isAsynEvent) const; private: using FrameFuncCall = std::function; @@ -100,7 +101,7 @@ private: const std::regex uiVsyncTaskPattern_ = std::regex("\\[(\\w+):(\\d+)\\]"); const std::regex transFlagPattern_ = std::regex(R"(transactionFlag:\[(\d+),(\d+)\])"); const std::regex newTransFlagPattern_ = - std::regex(R"(transactionFlag:\[(\d+),\s*(\d+),\s*(\d+)\],\s*timestamp:(\d+))"); + std::regex(R"(transactionFlag:\[(\d+),(\d+)\],\s*tid:(\d+),\s*timestamp:(\d+))"); const std::regex mainProcessCmdPattern_ = std::regex("\\[(\\d+),(\\d+)\\]"); const std::regex distributeMatcher_ = std::regex(R"(H:\[([a-z0-9]+),([a-z0-9]+),([a-z0-9]+)\]#([CS]?)##(.*))"); std::vector frameCallIds_ = {}; diff --git a/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.cpp b/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.cpp index e22021ff85893060a59b71d2cb1f70ad26a5612f..2722273a7374e326371319911ee25faa29d92a39 100644 --- a/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.cpp +++ b/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.cpp @@ -24,6 +24,7 @@ #include "process_filter.h" #include "slice_filter.h" #include "stat_filter.h" +#include "syscall_filter.h" #include "string_to_numerical.h" #include "thread_state_flag.h" #include "ts_common.h" @@ -71,6 +72,10 @@ BytraceEventParser::BytraceEventParser(TraceDataCache *dataCache, const TraceStr bind(&BytraceEventParser::IpiEntryEvent, this, std::placeholders::_1, std::placeholders::_2)}, {config_.eventNameMap_.at(TRACE_EVENT_IPI_EXIT), bind(&BytraceEventParser::IpiExitEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SYS_ENTRY), + bind(&BytraceEventParser::SysEnterEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SYS_EXIT), + bind(&BytraceEventParser::SysExitEvent, this, std::placeholders::_1, std::placeholders::_2)}, }; InterruptEventInitialization(); ClockEventInitialization(); @@ -188,6 +193,82 @@ void BytraceEventParser::StackEventsInitialization() bind(&BytraceEventParser::WorkqueueExecuteEndEvent, this, std::placeholders::_1, std::placeholders::_2)); } +bool BytraceEventParser::SysEnterEvent(const ArgsMap &args, const BytraceLine &line) +{ + if (streamFilters_->configFilter_->GetSwitchConfig().SyscallsTsSet().empty()) { + return true; + } + Unused(args); + std::string sysEnterStr = base::Strip(line.argsStr); + if (sysEnterStr.empty()) { + TS_LOGD("SysEnterEvent: Empty args string for sysEnterStr, skipping."); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_DATA_INVALID); + return true; + } + + auto firstSpacePos = sysEnterStr.find(" "); + if (firstSpacePos == std::string::npos) { + TS_LOGD("SysEnterEvent: No space found in sysEnterStr: '%s', skipping.", sysEnterStr.c_str()); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_DATA_INVALID); + return true; + } + + // eg:NR 240 (f73bfb0c, 80, 2, f73bfab8, 5f5d907, 0) + DataIndex argsDataIndex = INVALID_UINT64; + auto secondSpacePos = sysEnterStr.find(" ", firstSpacePos + 1); + if (secondSpacePos != std::string::npos) { + std::string argsStr = sysEnterStr.substr(secondSpacePos + 1); + argsDataIndex = traceDataCache_->GetDataIndex(argsStr); + } else { + secondSpacePos = sysEnterStr.length(); + } + + uint32_t syscallNumber = std::atoi(sysEnterStr.substr(firstSpacePos, secondSpacePos).c_str()); + SyscallInfoRow syscallInfoRow; + syscallInfoRow.ts = line.ts; + syscallInfoRow.itid = line.pid; + syscallInfoRow.args = argsDataIndex; + syscallInfoRow.number = syscallNumber; + streamFilters_->syscallFilter_->UpdataSyscallEnterExitMap(syscallInfoRow); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); + return true; +} + +bool BytraceEventParser::SysExitEvent(const ArgsMap &args, const BytraceLine &line) +{ + if (streamFilters_->configFilter_->GetSwitchConfig().SyscallsTsSet().empty()) { + return true; + } + Unused(args); + std::string sysExitStr = base::Strip(line.argsStr); + if (sysExitStr.empty()) { + TS_LOGD("SysExitEvent: Empty args string for sysExitStr, skipping."); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_EXIT, STAT_EVENT_DATA_INVALID); + return true; + } + + auto firstSpacePos = sysExitStr.find(" "); + if (firstSpacePos == std::string::npos) { + TS_LOGD("SysExitEvent: No space found in sysExitStr: '%s', skipping.", sysExitStr.c_str()); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_EXIT, STAT_EVENT_DATA_INVALID); + return true; + } + + // eg:NR 85 = -22 + int64_t ret = INVALID_INT64; + auto secondSpacePos = sysExitStr.find("= "); + if (secondSpacePos != std::string::npos) { + ret = std::atoi(sysExitStr.substr(secondSpacePos + 2).c_str()); + } else { + secondSpacePos = sysExitStr.length(); + } + + uint32_t sysExitId = std::atoi(sysExitStr.substr(firstSpacePos, secondSpacePos).c_str()); + streamFilters_->syscallFilter_->AppendSysCallInfo(line.pid, sysExitId, line.ts, ret); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); + return true; +} + bool BytraceEventParser::SchedSwitchEvent(const ArgsMap &args, const BytraceLine &line) const { if (args.empty() || args.size() < MIN_SCHED_SWITCH_ARGS_COUNT) { @@ -707,8 +788,8 @@ bool BytraceEventParser::BinderTransaction(const ArgsMap &args, const BytraceLin streamFilters_->binderFilter_->SendTraction(line.ts, line.pid, transactionId.value(), destNode.value(), destProc.value(), destThread.value(), isReply.value(), flags.value(), codeStr.value()); - if (traceDataCache_->BinderRunnableTraceEnabled() && transactionId.has_value() && flags.has_value() && - !streamFilters_->binderFilter_->IsAsync(flags.value())) { + if (streamFilters_->configFilter_->GetSwitchConfig().BinderRunnableConfigEnabled() && transactionId.has_value() && + flags.has_value() && !streamFilters_->binderFilter_->IsAsync(flags.value())) { streamFilters_->cpuFilter_->InsertRunnableBinderEvent(transactionId.value(), streamFilters_->processFilter_->GetInternalTid(line.pid)); } @@ -724,7 +805,7 @@ bool BytraceEventParser::BinderTransactionReceived(const ArgsMap &args, const By streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, STAT_EVENT_RECEIVED); auto transactionId = base::StrToInt(args.at("transaction")); streamFilters_->binderFilter_->ReceiveTraction(line.ts, line.pid, transactionId.value()); - if (traceDataCache_->BinderRunnableTraceEnabled() && transactionId.has_value()) { + if (streamFilters_->configFilter_->GetSwitchConfig().BinderRunnableConfigEnabled() && transactionId.has_value()) { streamFilters_->cpuFilter_->InsertRunnableBinderRecvEvent( transactionId.value(), streamFilters_->processFilter_->GetInternalTid(line.pid)); } @@ -821,7 +902,7 @@ void BytraceEventParser::FilterAllEvents() streamFilters_->cpuFilter_->Finish(); traceDataCache_->dataDict_.Finish(); traceDataCache_->UpdataZeroThreadInfo(); - if (traceDataCache_->AppStartTraceEnabled()) { + if (streamFilters_->configFilter_->GetSwitchConfig().AppConfigEnabled()) { streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); } traceDataCache_->GetThreadStateData()->SortAllRowByTs(); diff --git a/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.h b/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.h index cfef3a2d794388862f9e203fb7ef6e83b51da1f1..95ac451d09c86e55d7edec637120a4412117f655 100644 --- a/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.h +++ b/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.h @@ -78,6 +78,8 @@ private: bool BinderTransaction(const ArgsMap &args, const BytraceLine &line) const; bool BinderTransactionReceived(const ArgsMap &args, const BytraceLine &line) const; bool BinderTransactionAllocBufEvent(const ArgsMap &args, const BytraceLine &line) const; + bool SysEnterEvent(const ArgsMap &args, const BytraceLine &line); + bool SysExitEvent(const ArgsMap &args, const BytraceLine &line); void GetDataSegArgs(const BytraceLine &bufLine, ArgsMap &args) const; void InterruptEventInitialization(); void ClockEventInitialization(); @@ -95,7 +97,7 @@ private: static const uint32_t MIN_CPU_IDLE_ARGS_COUNT = 2; static const uint32_t MIN_CPU_FREQUENCY_ARGS_COUNT = 2; static const uint32_t MIN_PROCESS_EXIT_ARGS_COUNT = 2; - static const uint32_t MIN_CLOCK_SET_RATE_ARGS_COUNT = 2; + static const uint32_t MIN_CLOCK_SET_RATE_ARGS_COUNT = 3; static const uint32_t MIN_CLOCK_ENABLE_ARGS_COUNT = 3; static const uint32_t MIN_CLOCK_DISABLE_ARGS_COUNT = 3; static const uint32_t MIN_IRQ_HANDLER_ENTRY_ARGS_COUNT = 2; diff --git a/trace_streamer/src/parser/rawtrace_parser/BUILD.gn b/trace_streamer/src/parser/rawtrace_parser/BUILD.gn index 4786ec41546440831c587bd89bbfca70fd8d5bbf..646ed3af7963949e6af76b9a0bd60093a0d36aa5 100755 --- a/trace_streamer/src/parser/rawtrace_parser/BUILD.gn +++ b/trace_streamer/src/parser/rawtrace_parser/BUILD.gn @@ -29,7 +29,7 @@ config("rawtrace_parser_comm") { "${THIRD_PARTY}/bounds_checking_function/include", "${THIRD_PARTY}/json/single_include/nlohmann", "${PERF_DIR}/profiler/device/plugins/ftrace_plugin/include", - "${COMMON_LIBRARY}/base/include", + "${COMMON_LIBRARY}/c_utils/base/include", ] include_dirs += [ "${SRC}/trace_data/trace_stdtype", diff --git a/trace_streamer/src/parser/rawtrace_parser/cpu_detail_parser.cpp b/trace_streamer/src/parser/rawtrace_parser/cpu_detail_parser.cpp index 801a81f8bc344785c6827f39b00c3abc904c5c9e..108f1db6f324d1ba7af6ee8b5f7406fdbf0ba0f0 100644 --- a/trace_streamer/src/parser/rawtrace_parser/cpu_detail_parser.cpp +++ b/trace_streamer/src/parser/rawtrace_parser/cpu_detail_parser.cpp @@ -244,7 +244,7 @@ void CpuDetailParser::FinishCpuDetailParser() streamFilters_->cpuFilter_->Finish(); traceDataCache_->dataDict_.Finish(); traceDataCache_->UpdataZeroThreadInfo(); - if (traceDataCache_->AppStartTraceEnabled()) { + if (streamFilters_->configFilter_->GetSwitchConfig().AppConfigEnabled()) { streamFilters_->appStartupFilter_->FilterAllAPPStartupData(); } Clear(); diff --git a/trace_streamer/src/parser/rawtrace_parser/ftrace_event_processor.cpp b/trace_streamer/src/parser/rawtrace_parser/ftrace_event_processor.cpp index d6ffa3c2b200c430b8c66203abab7d7380c6a8b7..1c8e1678041f84be1cfa71b962e165f630c1dd37 100644 --- a/trace_streamer/src/parser/rawtrace_parser/ftrace_event_processor.cpp +++ b/trace_streamer/src/parser/rawtrace_parser/ftrace_event_processor.cpp @@ -299,11 +299,12 @@ bool FtraceEventProcessor::SchedWakeup(FtraceEvent &ftraceEvent, uint8_t data[], schedWakeupMsg->set_pid(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); if (format.fields[index].size == NEW_SCHED_PRIO_SIZE) { schedWakeupMsg->set_prio(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + schedWakeupMsg->set_target_cpu(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); } else { schedWakeupMsg->set_prio(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + schedWakeupMsg->set_success(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + schedWakeupMsg->set_target_cpu(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); } - schedWakeupMsg->set_success(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); - schedWakeupMsg->set_target_cpu(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); return true; } bool FtraceEventProcessor::SchedWaking(FtraceEvent &ftraceEvent, uint8_t data[], size_t size, const EventFormat &format) @@ -312,9 +313,14 @@ bool FtraceEventProcessor::SchedWaking(FtraceEvent &ftraceEvent, uint8_t data[], auto schedWakingMsg = ftraceEvent.mutable_sched_waking_format(); schedWakingMsg->set_comm(FtraceFieldProcessor::HandleStrField(format.fields, index++, data, size)); schedWakingMsg->set_pid(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); - schedWakingMsg->set_prio(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); - schedWakingMsg->set_success(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); - schedWakingMsg->set_target_cpu(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + if (format.fields[index].size == NEW_SCHED_PRIO_SIZE) { + schedWakingMsg->set_prio(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + schedWakingMsg->set_target_cpu(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + } else { + schedWakingMsg->set_prio(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + schedWakingMsg->set_success(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + schedWakingMsg->set_target_cpu(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + } return true; } bool FtraceEventProcessor::SchedWakeupNew(FtraceEvent &ftraceEvent, @@ -326,9 +332,14 @@ bool FtraceEventProcessor::SchedWakeupNew(FtraceEvent &ftraceEvent, auto wakeupNewMsg = ftraceEvent.mutable_sched_wakeup_new_format(); wakeupNewMsg->set_comm(FtraceFieldProcessor::HandleStrField(format.fields, index++, data, size)); wakeupNewMsg->set_pid(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); - wakeupNewMsg->set_prio(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); - wakeupNewMsg->set_success(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); - wakeupNewMsg->set_target_cpu(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + if (format.fields[index].size == NEW_SCHED_PRIO_SIZE) { + wakeupNewMsg->set_prio(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + wakeupNewMsg->set_target_cpu(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + } else { + wakeupNewMsg->set_prio(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + wakeupNewMsg->set_success(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + wakeupNewMsg->set_target_cpu(FtraceFieldProcessor::HandleIntField(format.fields, index++, data, size)); + } return true; } bool FtraceEventProcessor::SchedProcessExit(FtraceEvent &ftraceEvent, diff --git a/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.cpp b/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.cpp index 8e70920a24d2692b2742f6410a26f44ee670584f..d77ee53fbb1c168b3ea3a440ce93ce8567ae4165 100644 --- a/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.cpp +++ b/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.cpp @@ -175,7 +175,10 @@ static std::string GetName(const std::map &nameMap, int type) static std::string GetFieldTypeName(EventFieldType type) { static std::map toNames = { -#define VALUE_NAME(x) {x, #x} +#define VALUE_NAME(x) \ + { \ + x, #x \ + } VALUE_NAME(FIELD_TYPE_INVALID), VALUE_NAME(FIELD_TYPE_BOOL), VALUE_NAME(FIELD_TYPE_INT8), VALUE_NAME(FIELD_TYPE_UINT8), VALUE_NAME(FIELD_TYPE_INT16), VALUE_NAME(FIELD_TYPE_UINT16), VALUE_NAME(FIELD_TYPE_INT32), VALUE_NAME(FIELD_TYPE_UINT32), VALUE_NAME(FIELD_TYPE_INT64), @@ -192,7 +195,10 @@ static std::string GetFieldTypeName(EventFieldType type) static std::string GetProtoTypeName(ProtoFieldType type) { static std::map toNames = { -#define VALUE_NAME(x) {x, #x} +#define VALUE_NAME(x) \ + { \ + x, #x \ + } VALUE_NAME(PROTO_TYPE_UNKNOWN), VALUE_NAME(PROTO_TYPE_DOUBLE), VALUE_NAME(PROTO_TYPE_FLOAT), VALUE_NAME(PROTO_TYPE_INT64), VALUE_NAME(PROTO_TYPE_UINT64), VALUE_NAME(PROTO_TYPE_INT32), VALUE_NAME(PROTO_TYPE_FIXED64), VALUE_NAME(PROTO_TYPE_FIXED32), VALUE_NAME(PROTO_TYPE_BOOL), @@ -763,5 +769,9 @@ bool FtraceProcessor::HandleFtraceEvent(FtraceEvent &ftraceEvent, FtraceEventProcessor::GetInstance().HandleEvent(ftraceEvent, data, dataSize, format); return true; } +std::unordered_map &FtraceProcessor::GetTidToName() +{ + return taskNameDict_; +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.h b/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.h index f5d059994130d390878024071a60f09de6afe37f..d8e8a025b0c6e07fbcd87f7e4cce5f63f73be681 100644 --- a/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.h +++ b/trace_streamer/src/parser/rawtrace_parser/ftrace_processor.h @@ -86,6 +86,7 @@ public: bool HandleFtraceEvent(FtraceEvent &ftraceEvent, uint8_t data[], size_t dataSize, const EventFormat &format); bool HandleFtraceCommonFields(FtraceEvent &ftraceEvent, uint8_t data[], size_t dataSize, const EventFormat &format); + std::unordered_map &GetTidToName(); private: std::regex fixedCharArrayRegex_; diff --git a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp index bc7e3cf0316b0e9b6fe7c355cd5c9bff7710d10c..12e28f5481bd4880b908cad727802609e9beb142 100644 --- a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp +++ b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.cpp @@ -41,12 +41,14 @@ void RawTraceParser::WaitForParserEnd() restCommDataCnt_ = 0; hasGotHeader_ = false; curCpuCoreNum_ = 0; + auto tidToName = ftraceProcessor_->GetTidToName(); + streamFilters_->processFilter_->UpdateProcessNameByNameToTid(tidToName); ClearRawTraceData(); TS_LOGI("Parser raw trace end!"); } void RawTraceParser::UpdateTraceMinRange() { - if (!traceDataCache_->RawTraceCutStartTsEnabled()) { + if (!streamFilters_->configFilter_->GetSwitchConfig().RawTraceCutStartTsEnabled()) { return; } auto schedSlice = traceDataCache_->GetConstSchedSliceData(); diff --git a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.h b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.h index e983836494abe4fccdbd6bb83dced15407eddb00..e96619567d71217f1b55081220103fa29605de79 100644 --- a/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.h +++ b/trace_streamer/src/parser/rawtrace_parser/rawtrace_parser.h @@ -21,6 +21,7 @@ #include "ftrace_processor.h" #include "kernel_symbols_processor.h" #include "trace_data_cache.h" +#include "config_filter.h" namespace SysTuning { namespace TraceStreamer { diff --git a/trace_streamer/src/rpc/ffrt_converter.cpp b/trace_streamer/src/rpc/ffrt_converter.cpp index 72b5f3e0593c45a1b464c36d01ecf5a82b122133..2c0b328b55f151a83f4f445b4a4cccfd994a1d7b 100644 --- a/trace_streamer/src/rpc/ffrt_converter.cpp +++ b/trace_streamer/src/rpc/ffrt_converter.cpp @@ -44,7 +44,7 @@ static bool WriteOutputFile(std::ofstream &outfile, std::vector &co std::vector file_buffer(BUFFER_SIZE); outfile.rdbuf()->pubsetbuf(file_buffer.data(), file_buffer.size()); - for (const auto& line : context_) { + for (const auto &line : context_) { outfile.write(line.c_str(), line.size()); outfile.put('\n'); } @@ -87,7 +87,7 @@ bool FfrtConverter::RecoverTraceAndGenerateNewFile(ConStr &ffrtFileName, std::of return WriteOutputFile(outFile, context_); } -static uint32_t ExtractProcessId(ConStr& log) +static uint32_t ExtractProcessId(ConStr &log) { size_t leftParen = log.find('('); size_t rightParen = log.find(')', leftParen); @@ -120,7 +120,7 @@ static uint32_t ExtractProcessId(ConStr& log) return processId; } -static int ExtractThreadId(ConStr& log) +static int ExtractThreadId(ConStr &log) { static const std::regex pattern(R"( \(\s*\d+\)\s+\[\d)"); std::smatch match; @@ -131,16 +131,14 @@ static int ExtractThreadId(ConStr& log) return INT_MAX; } -static std::string TrimRight(ConStr& str) +static std::string TrimRight(ConStr &str) { - auto end = std::find_if_not(str.rbegin(), str.rend(), [](unsigned char ch) { - return std::isspace(ch); - }).base(); + auto end = std::find_if_not(str.rbegin(), str.rend(), [](unsigned char ch) { return std::isspace(ch); }).base(); return std::string(str.begin(), end); } -static void ExtraceFfrtThreadInfoFromSchedSwitch(ConStr &log, std::string &tName, int& tid) +static void ExtraceFfrtThreadInfoFromSchedSwitch(ConStr &log, std::string &tName, int &tid) { static std::string prevComm = "prev_comm"; static std::string prevPid = "prev_pid="; @@ -183,10 +181,10 @@ static std::string ExtractCpuId(ConStr &log) return ""; } -static std::string ExtractTaskLable(ConStr& log) +static std::string ExtractTaskLable(ConStr &log) { size_t pos = log.find("|H:FFRT"); - if (pos != std::string::npos) { // ohos + if (pos != std::string::npos) { // ohos size_t startPos = pos + std::string("|H:FFRT").length(); size_t endPos = log.find("|", startPos); if (endPos != std::string::npos) { @@ -199,7 +197,7 @@ static std::string ExtractTaskLable(ConStr& log) return log.substr(startPos + 1, endPos - startPos - 1); } } - return ""; // Return empty string if no label found + return ""; // Return empty string if no label found } static void FindPrevAndNextPidForSchedSwitch(ConStr &log, int &prevPid, int &nextPid) @@ -218,7 +216,7 @@ static void FindPrevAndNextPidForSchedSwitch(ConStr &log, int &prevPid, int &nex void FfrtConverter::SetOSPlatformKey(const FfrtTidMap &ffrtTidMap) { - for (const auto& tinfo : ffrtTidMap) { + for (const auto &tinfo : ffrtTidMap) { if (tinfo.second.first.find("ffrtwk") != std::string::npos) { osPlatformKet_ = "nohos"; return; @@ -283,7 +281,7 @@ static void FindProcessNamePositions(ConStr &log, std::vector &indexs) } } -static void SplitLogs(std::vector &indexs, std::vector &newLogs, ConStr& log) +static void SplitLogs(std::vector &indexs, std::vector &newLogs, ConStr &log) { for (int i = 0; i < indexs.size(); i++) { int begin = indexs[i]; @@ -296,7 +294,7 @@ static void SplitLogs(std::vector &indexs, std::vector &new } } -static void GenFfrtPids(FfrtPids& ffrtPids, Info &info, FfrtTidMap &ffrtTidMap, WakeLogs &traceMap) +static void GenFfrtPids(FfrtPids &ffrtPids, Info &info, FfrtTidMap &ffrtTidMap, WakeLogs &traceMap) { for (const auto tid : info.second) { if (ffrtTidMap.find(tid) != ffrtTidMap.end()) { @@ -355,7 +353,7 @@ bool IsOldVersionTrace(ConStr &log) return true; } -void FfrtConverter::ClassifyLogsForFfrtWorker(FfrtPids& ffrtPids, FfrtWakeLogs& ffrtWakeLogs) +void FfrtConverter::ClassifyLogsForFfrtWorker(FfrtPids &ffrtPids, FfrtWakeLogs &ffrtWakeLogs) { PidMap pidMap; FfrtTidMap ffrtTidMap; @@ -384,10 +382,10 @@ void FfrtConverter::ClassifyLogsForFfrtWorker(FfrtPids& ffrtPids, FfrtWakeLogs& std::unordered_map> localPidMap; std::unordered_map>> locFfrtTidMap; std::unordered_map> locTraceMap; - std::vector& updates = threadUpdates[threadId]; + std::vector &updates = threadUpdates[threadId]; for (size_t lineno = start; lineno < end && lineno < context_.size(); ++lineno) { - const std::string& log = context_[lineno]; + const std::string &log = context_[lineno]; indexs.clear(); FindProcessNamePositions(log, indexs); @@ -415,13 +413,13 @@ void FfrtConverter::ClassifyLogsForFfrtWorker(FfrtPids& ffrtPids, FfrtWakeLogs& } { std::lock_guard lock(pidMutex); - for (const auto& [pid, tid_set] : localPidMap) { + for (const auto &[pid, tid_set] : localPidMap) { pidMap[pid].insert(tid_set.begin(), tid_set.end()); } } { std::lock_guard lock(tidMutex); - for (const auto& [tid, info] : locFfrtTidMap) { + for (const auto &[tid, info] : locFfrtTidMap) { if (ffrtTidMap.find(tid) == ffrtTidMap.end()) { ffrtTidMap[tid] = info; } @@ -429,8 +427,8 @@ void FfrtConverter::ClassifyLogsForFfrtWorker(FfrtPids& ffrtPids, FfrtWakeLogs& } { std::lock_guard lock(traceMutex); - for (const auto& [tid, traces] : locTraceMap) { - auto& target = traceMap[tid]; + for (const auto &[tid, traces] : locTraceMap) { + auto &target = traceMap[tid]; target.insert(target.end(), traces.begin(), traces.end()); } } @@ -441,35 +439,32 @@ void FfrtConverter::ClassifyLogsForFfrtWorker(FfrtPids& ffrtPids, FfrtWakeLogs& size_t end = std::min((i + 1) * chunkSize, context_.size()); threads.emplace_back(worker, i, start, end); } - for (auto& thread : threads) { + for (auto &thread : threads) { thread.join(); } std::vector allUpdates; - for (const auto& threadUpdate : threadUpdates) { + for (const auto &threadUpdate : threadUpdates) { allUpdates.insert(allUpdates.end(), threadUpdate.begin(), threadUpdate.end()); } std::sort(allUpdates.begin(), allUpdates.end(), - [](const ContextUpdate& a, const ContextUpdate& b) { - return a.position > b.position; - }); - for (const auto& update : allUpdates) { + [](const ContextUpdate &a, const ContextUpdate &b) { return a.position > b.position; }); + for (const auto &update : allUpdates) { context_.erase(context_.begin() + update.position); - context_.insert(context_.begin() + update.position, - update.new_logs.begin(), update.new_logs.end()); + context_.insert(context_.begin() + update.position, update.new_logs.begin(), update.new_logs.end()); } #else uint64_t lineno = 0; bool shouldCheck = true; std::vector indexs; indexs.reserve(ten); - auto classifyLogs = [this, &traceMap, &pidMap, &ffrtTidMap, &ffrtWakeLogs](ConVecStr& newLogs, size_t startLineNo) { + auto classifyLogs = [this, &traceMap, &pidMap, &ffrtTidMap, &ffrtWakeLogs](ConVecStr &newLogs, size_t startLineNo) { for (size_t i = 0; i < newLogs.size(); ++i) { auto logInfo = LogInfo{context_[startLineNo + i], static_cast(startLineNo + i), 0, 0}; FindFfrtProcClassifyLogs(logInfo, traceMap, pidMap, ffrtTidMap, ffrtWakeLogs); } }; while (lineno < context_.size()) { - ConStr& log = context_[lineno]; + ConStr &log = context_[lineno]; indexs.clear(); FindProcessNamePositions(log, indexs); if (shouldCheck && IsOldVersionTrace(log)) { @@ -491,7 +486,7 @@ void FfrtConverter::ClassifyLogsForFfrtWorker(FfrtPids& ffrtPids, FfrtWakeLogs& } #endif SetOSPlatformKey(ffrtTidMap); - for (auto& info : pidMap) { + for (auto &info : pidMap) { GenFfrtPids(ffrtPids, info, ffrtTidMap, traceMap); } } @@ -515,9 +510,7 @@ static size_t FindPatternStart(ConStr &log) ++bracketEnd; } - if (bracketEnd < log.length() && - log[bracketEnd] == '[' && - bracketEnd + 1 < log.length() && + if (bracketEnd < log.length() && log[bracketEnd] == '[' && bracketEnd + 1 < log.length() && isdigit(log[bracketEnd + 1])) { return pos; } @@ -625,8 +618,11 @@ void FfrtConverter::SetTracingMarkerKey(LogInfo logInfo) } } -void FfrtConverter::FindFfrtProcClassifyLogs(LogInfo logInfo, WakeLogs &traceMap, PidMap &pidMap, - FfrtTidMap &ffrtTidMap, FfrtWakeLogs &ffrtWakeLogs) +void FfrtConverter::FindFfrtProcClassifyLogs(LogInfo logInfo, + WakeLogs &traceMap, + PidMap &pidMap, + FfrtTidMap &ffrtTidMap, + FfrtWakeLogs &ffrtWakeLogs) { bool isPrevCommFfrt = logInfo.log.find("prev_comm=ffrt") != std::string::npos; bool isPrevCommFfrtOs = logInfo.log.find("prev_comm=OS_FFRT") != std::string::npos; @@ -748,9 +744,8 @@ static std::string MakeWakeupFakeLog(ConStr &log, const FakeLogArgs &fakeLogArgs { std::string mockTid = GenMockTid(fakeLogArgs.pid, fakeLogArgs.taskRunning); std::stringstream fakeLogStrm; - fakeLogStrm << log.substr(0, log.find(tracingMarkerKey)) << "sched_wakeup: comm=" << - fakeLogArgs.taskLabel << " pid=" << mockTid << " prio=" << - fakeLogArgs.prio << " target_cpu=" << fakeLogArgs.cpuId; + fakeLogStrm << log.substr(0, log.find(tracingMarkerKey)) << "sched_wakeup: comm=" << fakeLogArgs.taskLabel + << " pid=" << mockTid << " prio=" << fakeLogArgs.prio << " target_cpu=" << fakeLogArgs.cpuId; return fakeLogStrm.str(); } @@ -764,19 +759,15 @@ static std::string ReplaceSchedSwitchLog(ConStr &fakeLog, LogInfo logInfo, int g size_t index = fakeLog.find("("); result = " " + label + "-" + mockTid + " " + fakeLog.substr(index); } - result = result.substr(0, result.find("prev_comm=")) + - "prev_comm=" + label + - " " + result.substr(result.find("prev_pid=")); - result = result.substr(0, result.find("prev_pid=")) + - "prev_pid=" + mockTid + - " " + result.substr(result.find("prev_prio=")); + result = result.substr(0, result.find("prev_comm=")) + "prev_comm=" + label + " " + + result.substr(result.find("prev_pid=")); + result = result.substr(0, result.find("prev_pid=")) + "prev_pid=" + mockTid + " " + + result.substr(result.find("prev_prio=")); } else if (logInfo.log.find("next_pid=" + std::to_string(logInfo.tid)) != std::string::npos) { - result = result.substr(0, result.find("next_comm=")) + - "next_comm=" + label + - " " + result.substr(result.find("next_pid=")); - result = result.substr(0, result.find("next_pid=")) + - "next_pid=" + mockTid + - " " + result.substr(result.find("next_prio=")); + result = result.substr(0, result.find("next_comm=")) + "next_comm=" + label + " " + + result.substr(result.find("next_pid=")); + result = result.substr(0, result.find("next_pid=")) + "next_pid=" + mockTid + " " + + result.substr(result.find("next_prio=")); } return result; } @@ -807,11 +798,10 @@ static std::string ReplaceSchedBlockLog(ConStr &fakeLog, int pid, int gid) if (pos != std::string::npos) { pos = fakeLog.find("iowait=", pos); if (pos != std::string::npos) { - result = fakeLog.substr(0, fakeLog.find("pid=")) + "pid=" + - mockTid + " " + fakeLog.substr(pos); + result = fakeLog.substr(0, fakeLog.find("pid=")) + "pid=" + mockTid + " " + fakeLog.substr(pos); } else { - result = fakeLog.substr(0, fakeLog.find("pid=")) + "pid=" + - mockTid + " " + fakeLog.substr(fakeLog.find("io_wait=")); + result = fakeLog.substr(0, fakeLog.find("pid=")) + "pid=" + mockTid + " " + + fakeLog.substr(fakeLog.find("io_wait=")); } } return result; @@ -889,7 +879,7 @@ static void HandleQueTaskInfoOut(ConStr &log, int lineno, int pid, QueueTaskInfo if (fPos == std::string::npos) { return; } - size_t hPos = log.find("|H:F ", fPos); + size_t hPos = log.find("|H:F", fPos); if (hPos == std::string::npos) { return; } @@ -935,7 +925,7 @@ void FfrtConverter::FindQueueTaskInfo(FfrtPids &ffrtPids, QueueTaskInfo &queueTa { for (auto &pidItem : ffrtPids) { int pid = pidItem.first; - queueTaskInfo[pid] = {}; // Initialize map for this pid + queueTaskInfo[pid] = {}; // Initialize map for this pid for (auto &tidItem : pidItem.second) { std::vector &linenos = tidItem.second.second; @@ -988,12 +978,12 @@ void FfrtConverter::ExceTaskGroups(std::vector &group, WakeLogs &wakeLo if (wakeLogs.find(group[i].gid) != wakeLogs.end()) { int gid = group[i].gid; wakeLogs[firstGid].insert(wakeLogs[firstGid].end(), wakeLogs[gid].begin(), wakeLogs[gid].end()); - for (auto& lineno : group[i].begin) { + for (auto &lineno : group[i].begin) { size_t rightIndex = context_[lineno].find_last_of("|"); if (context_[lineno][rightIndex + 1] == 'I') { - context_[lineno] - = context_[lineno].substr(0, context_[lineno].substr(0, rightIndex).find_last_of("|") + 1) - + std::to_string(firstGid) + context_[lineno].substr(rightIndex) + "\n"; + context_[lineno] = + context_[lineno].substr(0, context_[lineno].substr(0, rightIndex).find_last_of("|") + 1) + + std::to_string(firstGid) + context_[lineno].substr(rightIndex) + "\n"; } else { context_[lineno] = context_[lineno].substr(0, rightIndex + 1) + std::to_string(firstGid) + "\n"; } @@ -1004,7 +994,7 @@ void FfrtConverter::ExceTaskGroups(std::vector &group, WakeLogs &wakeLo void FfrtConverter::HandleTaskGroups(std::vector> &taskGroups, WakeLogs &wakeLogs) { - for (auto& group : taskGroups) { + for (auto &group : taskGroups) { if (group.size() > 1) { int firstGid = group[0].gid; if (wakeLogs.find(firstGid) == wakeLogs.end()) { @@ -1016,15 +1006,15 @@ void FfrtConverter::HandleTaskGroups(std::vector> &taskGrou } } -void FfrtConverter::HandleFfrtQueueTasks(FfrtQueueTasks &ffrtQueueTasks, FfrtWakeLogs& ffrtWakeLogs) +void FfrtConverter::HandleFfrtQueueTasks(FfrtQueueTasks &ffrtQueueTasks, FfrtWakeLogs &ffrtWakeLogs) { for (auto &pidItem : ffrtQueueTasks) { WakeLogs tmp = {}; - WakeLogs &wakeLogs = (ffrtWakeLogs.find(pidItem.first) != ffrtWakeLogs.end()) ? - ffrtWakeLogs[pidItem.first] : tmp; + WakeLogs &wakeLogs = + (ffrtWakeLogs.find(pidItem.first) != ffrtWakeLogs.end()) ? ffrtWakeLogs[pidItem.first] : tmp; for (auto &qidItem : pidItem.second) { - auto cmp = [](tidInfo& value1, tidInfo& value2) {return value1.begin[0] < value2.begin[0];}; + auto cmp = [](tidInfo &value1, tidInfo &value2) { return value1.begin[0] < value2.begin[0]; }; std::sort(qidItem.second.begin(), qidItem.second.end(), cmp); std::vector> taskGroups; @@ -1045,8 +1035,8 @@ void FfrtConverter::HandleMarks(ConStr &log, int lineno, int pid) if (lostMarkPos != std::string::npos || faultMarkPos != std::string::npos) { if (tracingMarkerPos != std::string::npos) { - context_[lineno] = log.substr(0, tracingMarkerPos + tracingMarkerKey_.size()) - + "E|" + std::to_string(pid) + "\n"; + context_[lineno] = + log.substr(0, tracingMarkerPos + tracingMarkerKey_.size()) + "E|" + std::to_string(pid) + "\n"; } } } @@ -1132,8 +1122,10 @@ bool IsFfrtTaskBlockOrFinish(ConStr &log) return true; } -bool FfrtConverter::HandleFfrtTaskExecute(FakeLogArgs &fakLogArg, WakeLogs &wakeLogs, - TaskLabels &taskLabels, std::string &label) +bool FfrtConverter::HandleFfrtTaskExecute(FakeLogArgs &fakLogArg, + WakeLogs &wakeLogs, + TaskLabels &taskLabels, + std::string &label) { static const int spaceNum = 7; if (fakLogArg.log.find("|H:FFRT") != std::string::npos) { @@ -1141,13 +1133,14 @@ bool FfrtConverter::HandleFfrtTaskExecute(FakeLogArgs &fakLogArg, WakeLogs &wake if (fakLogArg.taskRunning != -1) { missLog = MakeCoyieldFakeLog(fakLogArg); std::stringstream ss; - ss << " " << fakLogArg.tname << "-" << fakLogArg.tid << " (" << - std::setw(spaceNum) << std::right << fakLogArg.pid << ") [" << - fakLogArg.cpuId << "] .... " << fakLogArg.timestamp << - ": " << tracingMarkerKey_ << "E|" << fakLogArg.pid << "\n"; + ss << " " << fakLogArg.tname << "-" << fakLogArg.tid << " (" << std::setw(spaceNum) << std::right + << fakLogArg.pid << ") [" << fakLogArg.cpuId << "] .... " << fakLogArg.timestamp << ": " + << tracingMarkerKey_ << "E|" << fakLogArg.pid << "\n"; missLog += ss.str(); } - if (label.find("ex_task") != std::string::npos) { return true; } + if (label.find("ex_task") != std::string::npos) { + return true; + } int gid = -1; size_t pos = fakLogArg.log.find_last_of('|'); if (pos != std::string::npos) { @@ -1191,8 +1184,11 @@ bool FfrtConverter::HandleFfrtTaskExecute(FakeLogArgs &fakLogArg, WakeLogs &wake return false; } -bool FfrtConverter::HandlePreLineno(FakeLogArgs &fakArg, WakeLogs &wakeLogs, - TaskLabels &taskLabels, ConStr traceBeginMark, ConStr traceEndMark) +bool FfrtConverter::HandlePreLineno(FakeLogArgs &fakArg, + WakeLogs &wakeLogs, + TaskLabels &taskLabels, + ConStr traceBeginMark, + ConStr traceEndMark) { std::string label = ExtractTaskLable(fakArg.log); if (HandleFfrtTaskExecute(fakArg, wakeLogs, taskLabels, label)) { @@ -1229,14 +1225,15 @@ bool FfrtConverter::HandlePreLineno(FakeLogArgs &fakArg, WakeLogs &wakeLogs, return false; } -void FfrtConverter::ExceTaskLabelOhos(TaskLabels &taskLabels, FfrtWakeLogs &ffrtWakeLogs, - std::pair pidItem, std::string traceBeginMark, +void FfrtConverter::ExceTaskLabelOhos(TaskLabels &taskLabels, + FfrtWakeLogs &ffrtWakeLogs, + std::pair pidItem, + std::string traceBeginMark, std::string traceEndMark) { taskLabels[pidItem.first] = {}; WakeLogs tmp = {}; - WakeLogs &wakeLogs = (ffrtWakeLogs.find(pidItem.first) != ffrtWakeLogs.end()) - ? ffrtWakeLogs[pidItem.first] : tmp; + WakeLogs &wakeLogs = (ffrtWakeLogs.find(pidItem.first) != ffrtWakeLogs.end()) ? ffrtWakeLogs[pidItem.first] : tmp; for (auto &tidItem : pidItem.second) { std::string tname = tidItem.second.first; @@ -1253,15 +1250,16 @@ void FfrtConverter::ExceTaskLabelOhos(TaskLabels &taskLabels, FfrtWakeLogs &ffrt std::string cpuId = ExtractCpuId(log); std::string timestamp = ExtractTimeStr(log); - FakeLogArgs fakArg{pidItem.first, tidItem.first, taskRunning, prio, lineno, - switchInFakeLog, switchOutFakeLog, log, tname, - taskLabels[pidItem.first][taskRunning], cpuId, timestamp}; + FakeLogArgs fakArg{ + pidItem.first, tidItem.first, taskRunning, prio, lineno, + switchInFakeLog, switchOutFakeLog, log, tname, taskLabels[pidItem.first][taskRunning], + cpuId, timestamp}; HandlePreLineno(fakArg, wakeLogs, taskLabels, traceBeginMark, traceEndMark); } } } -void FfrtConverter::GenTaskLabelsOhos(FfrtPids &ffrtPids, FfrtWakeLogs& ffrtWakeLogs, TaskLabels &taskLabels) +void FfrtConverter::GenTaskLabelsOhos(FfrtPids &ffrtPids, FfrtWakeLogs &ffrtWakeLogs, TaskLabels &taskLabels) { static std::string traceBeginMark = tracingMarkerKey_ + "B"; static std::string traceEndMark = tracingMarkerKey_ + "E"; @@ -1270,7 +1268,7 @@ void FfrtConverter::GenTaskLabelsOhos(FfrtPids &ffrtPids, FfrtWakeLogs& ffrtWake } } -void FfrtConverter::ConvertFrrtThreadToFfrtTaskOhos(FfrtPids &ffrtPids, FfrtWakeLogs& ffrtWakeLogs) +void FfrtConverter::ConvertFrrtThreadToFfrtTaskOhos(FfrtPids &ffrtPids, FfrtWakeLogs &ffrtWakeLogs) { QueueTaskInfo queueTaskInfo; FindQueueTaskInfo(ffrtPids, queueTaskInfo); @@ -1284,8 +1282,11 @@ void FfrtConverter::ConvertFrrtThreadToFfrtTaskOhos(FfrtPids &ffrtPids, FfrtWake GenTaskLabelsOhos(ffrtPids, ffrtWakeLogs, taskLabels); } -bool FfrtConverter::HandleHFfrtTaskExecute(FakeLogArgs &fakeArgs, WakeLogs &wakeLogs, TaskLabels &taskLabels, - std::string label, std::unordered_map &schedWakeFlag) +bool FfrtConverter::HandleHFfrtTaskExecute(FakeLogArgs &fakeArgs, + WakeLogs &wakeLogs, + TaskLabels &taskLabels, + std::string label, + std::unordered_map &schedWakeFlag) { static const int spaceNum = 7; if (fakeArgs.log.find("|FFRT") == std::string::npos) { @@ -1295,36 +1296,59 @@ bool FfrtConverter::HandleHFfrtTaskExecute(FakeLogArgs &fakeArgs, WakeLogs &wake if (fakeArgs.taskRunning != -1) { missLog = MakeCoyieldFakeLog(fakeArgs); std::stringstream ss; - ss << " " << fakeArgs.tname << "-" << fakeArgs.tid << " (" << - std::setw(spaceNum) << std::right << fakeArgs.pid << ") [" << - fakeArgs.cpuId << "] .... " << fakeArgs.timestamp << ": " << - tracingMarkerKey_ << "E|" << fakeArgs.pid << "\n"; + ss << " " << fakeArgs.tname << "-" << fakeArgs.tid << " (" << std::setw(spaceNum) << std::right + << fakeArgs.pid << ") [" << fakeArgs.cpuId << "] .... " << fakeArgs.timestamp << ": " << tracingMarkerKey_ + << "E|" << fakeArgs.pid << "\n"; missLog += ss.str(); } - if (label.find("executor_task") != std::string::npos) { return true; } + if (label.find("executor_task") != std::string::npos) { + return true; + } int gid = -1; size_t pos = fakeArgs.log.find_last_of('|'); if (pos != std::string::npos) { - if (pos + 1 >= fakeArgs.log.size()) { return true; } + if (pos + 1 >= fakeArgs.log.size()) { + return true; + } std::string gidStr = fakeArgs.log.substr(pos + 1); auto [ptr, ec] = std::from_chars(gidStr.data(), gidStr.data() + gidStr.size(), gid); - if (ec != std::errc{}) { return true; } + if (ec != std::errc{}) { + return true; + } } if (taskLabels[fakeArgs.pid].find(gid) == taskLabels[fakeArgs.pid].end()) { taskLabels[fakeArgs.pid][gid] = label; } fakeArgs.taskRunning = gid; - FakeLogArgs fakArg2{fakeArgs.pid, fakeArgs.tid, fakeArgs.taskRunning, fakeArgs.prio, fakeArgs.lineno, - fakeArgs.switchInFakeLog, fakeArgs.switchOutFakeLog, fakeArgs.log, fakeArgs.tname, - taskLabels[fakeArgs.pid][fakeArgs.taskRunning], fakeArgs.cpuId, fakeArgs.timestamp}; + FakeLogArgs fakArg2{fakeArgs.pid, + fakeArgs.tid, + fakeArgs.taskRunning, + fakeArgs.prio, + fakeArgs.lineno, + fakeArgs.switchInFakeLog, + fakeArgs.switchOutFakeLog, + fakeArgs.log, + fakeArgs.tname, + taskLabels[fakeArgs.pid][fakeArgs.taskRunning], + fakeArgs.cpuId, + fakeArgs.timestamp}; std::string fakeLog = MakeCostartFakeLog(fakArg2); context_[fakeArgs.lineno] = fakeLog; if (!missLog.empty()) { context_[fakeArgs.lineno] = missLog + context_[fakeArgs.lineno]; } - FakeLogArgs fakArg3{fakeArgs.pid, fakeArgs.tid, fakeArgs.taskRunning, fakeArgs.prio, fakeArgs.lineno, - fakeArgs.switchInFakeLog, fakeArgs.switchOutFakeLog, fakeArgs.log, fakeArgs.tname, - taskLabels[fakeArgs.pid][fakeArgs.taskRunning], fakeArgs.cpuId, fakeArgs.timestamp}; + FakeLogArgs fakArg3{fakeArgs.pid, + fakeArgs.tid, + fakeArgs.taskRunning, + fakeArgs.prio, + fakeArgs.lineno, + fakeArgs.switchInFakeLog, + fakeArgs.switchOutFakeLog, + fakeArgs.log, + fakeArgs.tname, + taskLabels[fakeArgs.pid][fakeArgs.taskRunning], + fakeArgs.cpuId, + fakeArgs.timestamp}; if (wakeLogs.find(fakeArgs.taskRunning) != wakeLogs.end()) { int prevIndex = FindGreaterThan(wakeLogs[fakeArgs.taskRunning], fakeArgs.lineno); if (prevIndex > 0) { @@ -1342,9 +1366,13 @@ static bool IsFfrtTaskBlockOrFinishNohos(ConStr &log) { static const std::string fStr = " F|"; size_t fPos = log.find(fStr); - if (fPos == std::string::npos) { return false; } + if (fPos == std::string::npos) { + return false; + } size_t firstNumberEndPos = log.find('|', fPos + fStr.size()); - if (firstNumberEndPos == std::string::npos) { return false; } + if (firstNumberEndPos == std::string::npos) { + return false; + } std::string firstNumber = log.substr(fPos + 3, firstNumberEndPos - (fPos + fStr.size())); bool isValidNumber = true; for (char c : firstNumber) { @@ -1353,7 +1381,9 @@ static bool IsFfrtTaskBlockOrFinishNohos(ConStr &log) break; } } - if (!isValidNumber) { return false; } + if (!isValidNumber) { + return false; + } size_t typePos = firstNumberEndPos + 1; if (typePos < log.length() && (log[typePos] == 'B' || log[typePos] == 'F')) { size_t thirdPipePos = log.find('|', typePos + 1); @@ -1367,8 +1397,10 @@ static bool IsFfrtTaskBlockOrFinishNohos(ConStr &log) return false; } -bool FfrtConverter::HandlePreLinenoNohos(FakeLogArgs &fakArg, WakeLogs &wakeLogs, - TaskLabels &taskLabels, std::unordered_map &schedWakeFlag) +bool FfrtConverter::HandlePreLinenoNohos(FakeLogArgs &fakArg, + WakeLogs &wakeLogs, + TaskLabels &taskLabels, + std::unordered_map &schedWakeFlag) { std::string label = ExtractTaskLable(fakArg.log); if (HandleHFfrtTaskExecute(fakArg, wakeLogs, taskLabels, label, schedWakeFlag)) { @@ -1388,24 +1420,25 @@ bool FfrtConverter::HandlePreLinenoNohos(FakeLogArgs &fakArg, WakeLogs &wakeLogs } return false; } -void FfrtConverter::ExceTaskLabelNohos(TaskLabels &taskLabels, FfrtWakeLogs &ffrtWakeLogs, - std::pair pidItem, std::unordered_map &schedWakeFlag) +void FfrtConverter::ExceTaskLabelNohos(TaskLabels &taskLabels, + FfrtWakeLogs &ffrtWakeLogs, + std::pair pidItem, + std::unordered_map &schedWakeFlag) { bool oneF = false; bool twoF = false; taskLabels[pidItem.first] = {}; WakeLogs tmp = {}; - WakeLogs &wakeLogs = (ffrtWakeLogs.find(pidItem.first) != ffrtWakeLogs.end()) - ? ffrtWakeLogs[pidItem.first] : tmp; + WakeLogs &wakeLogs = (ffrtWakeLogs.find(pidItem.first) != ffrtWakeLogs.end()) ? ffrtWakeLogs[pidItem.first] : tmp; - for (auto& tidItem : pidItem.second) { + for (auto &tidItem : pidItem.second) { std::string tname = tidItem.second.first; std::vector linenos = tidItem.second.second; int prio = 120; int taskRunning = -1; for (auto lineno : linenos) { - std::string& log = context_[lineno]; + std::string &log = context_[lineno]; HandleMarks(log, lineno, pidItem.first); HandleSchedSwitch(log, tidItem.first, prio); @@ -1414,9 +1447,9 @@ void FfrtConverter::ExceTaskLabelNohos(TaskLabels &taskLabels, FfrtWakeLogs &ffr std::string timestamp = ExtractTimeStr(log); std::string label = ExtractTaskLable(log); - FakeLogArgs fakArg{pidItem.first, tidItem.first, taskRunning, prio, lineno, - oneF, twoF, log, tname, - taskLabels[pidItem.first][taskRunning], cpuId, timestamp}; + FakeLogArgs fakArg{pidItem.first, tidItem.first, taskRunning, prio, lineno, + oneF, twoF, log, tname, taskLabels[pidItem.first][taskRunning], + cpuId, timestamp}; HandlePreLinenoNohos(fakArg, wakeLogs, taskLabels, schedWakeFlag); } } diff --git a/trace_streamer/src/rpc/ffrt_converter.h b/trace_streamer/src/rpc/ffrt_converter.h index 94fb6b6c36771bc780bbe06cd628723f6a8c085f..f117a5f291682961c445d1cacf85a487800e2cf0 100644 --- a/trace_streamer/src/rpc/ffrt_converter.h +++ b/trace_streamer/src/rpc/ffrt_converter.h @@ -24,7 +24,7 @@ namespace SysTuning { namespace TraceStreamer { - using ConStr = const std::string; +using ConStr = const std::string; struct tidInfo { std::vector begin; @@ -78,13 +78,15 @@ public: bool RecoverTraceAndGenerateNewFile(ConStr &ffrtFileName, std::ofstream &outFile); private: - void SetOSPlatformKey(const std::unordered_map>> &ffrt_tid_map); - void FindFfrtProcClassifyLogs(LogInfo logInfo, WakeLogs &traceMap, PidMap &pidMap, - FfrtTidMap &ffrtTidMap, FfrtWakeLogs &ffrtWakeLogs); + void FindFfrtProcClassifyLogs(LogInfo logInfo, + WakeLogs &traceMap, + PidMap &pidMap, + FfrtTidMap &ffrtTidMap, + FfrtWakeLogs &ffrtWakeLogs); void ClassifyLogsForFfrtWorker(FfrtPids &ffrt_pids, FfrtWakeLogs &ffrt_wake_logs); - void ConvertFrrtThreadToFfrtTaskOhos(FfrtPids &ffrtPids, FfrtWakeLogs& ffrtWakeLogs); + void ConvertFrrtThreadToFfrtTaskOhos(FfrtPids &ffrtPids, FfrtWakeLogs &ffrtWakeLogs); void ConvertFrrtThreadToFfrtTaskNohos(FfrtPids &ffrtPids, FfrtWakeLogs &ffrtWakeLogs); // trace content @@ -95,19 +97,21 @@ private: void FindQueueTaskInfo(FfrtPids &ffrtPids, QueueTaskInfo &queueTaskInfo); - void HandleFfrtQueueTasks(FfrtQueueTasks &ffrtQueueTasks, FfrtWakeLogs& ffrtWakeLogs); + void HandleFfrtQueueTasks(FfrtQueueTasks &ffrtQueueTasks, FfrtWakeLogs &ffrtWakeLogs); void HandleMarks(ConStr &log, int lineno, int pid); bool HandleFfrtTaskCo(ConStr &log, int lineno, bool &switchInFakeLog, bool &switchOutFakeLog); - bool HandleFfrtTaskExecute(FakeLogArgs &fakLogArg, WakeLogs &wakeLogs, - TaskLabels &taskLabels, std::string &label); + bool HandleFfrtTaskExecute(FakeLogArgs &fakLogArg, WakeLogs &wakeLogs, TaskLabels &taskLabels, std::string &label); - void GenTaskLabelsOhos(FfrtPids &ffrtPids, FfrtWakeLogs& ffrtWakeLogs, TaskLabels &taskLabels); + void GenTaskLabelsOhos(FfrtPids &ffrtPids, FfrtWakeLogs &ffrtWakeLogs, TaskLabels &taskLabels); - bool HandlePreLineno(FakeLogArgs &fakArg, WakeLogs &wakeLogs, - TaskLabels &taskLabels, ConStr traceBeginMark, ConStr traceEndMark); + bool HandlePreLineno(FakeLogArgs &fakArg, + WakeLogs &wakeLogs, + TaskLabels &taskLabels, + ConStr traceBeginMark, + ConStr traceEndMark); void SetTracingMarkerKey(LogInfo logInfo); @@ -117,17 +121,27 @@ private: void HandleTaskGroups(std::vector> &taskGroups, WakeLogs &wakeLogs); - void ExceTaskLabelOhos(TaskLabels &taskLabels, FfrtWakeLogs &ffrtWakeLogs, std::pair pidItem, - std::string traceBeginMark, std::string traceEndMark); - - bool HandleHFfrtTaskExecute(FakeLogArgs &fakeArgs, WakeLogs &wakeLogs, TaskLabels &taskLabels, - std::string label, std::unordered_map &schedWakeFlag); - - bool HandlePreLinenoNohos(FakeLogArgs &fakArg, WakeLogs &wakeLogs, - TaskLabels &taskLabels, std::unordered_map &schedWakeFlag); - - void ExceTaskLabelNohos(TaskLabels &taskLabels, FfrtWakeLogs &ffrtWakeLogs, - std::pair pidItem, std::unordered_map &schedWakeFlag); + void ExceTaskLabelOhos(TaskLabels &taskLabels, + FfrtWakeLogs &ffrtWakeLogs, + std::pair pidItem, + std::string traceBeginMark, + std::string traceEndMark); + + bool HandleHFfrtTaskExecute(FakeLogArgs &fakeArgs, + WakeLogs &wakeLogs, + TaskLabels &taskLabels, + std::string label, + std::unordered_map &schedWakeFlag); + + bool HandlePreLinenoNohos(FakeLogArgs &fakArg, + WakeLogs &wakeLogs, + TaskLabels &taskLabels, + std::unordered_map &schedWakeFlag); + + void ExceTaskLabelNohos(TaskLabels &taskLabels, + FfrtWakeLogs &ffrtWakeLogs, + std::pair pidItem, + std::unordered_map &schedWakeFlag); }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/rpc/rpc_server.cpp b/trace_streamer/src/rpc/rpc_server.cpp index 4e8195bf3e00955b772c8d9dff2b17a80d3be7f9..7adcc8a44bf6962bec01d86c2d9b4f86df6dd667 100644 --- a/trace_streamer/src/rpc/rpc_server.cpp +++ b/trace_streamer/src/rpc/rpc_server.cpp @@ -837,15 +837,9 @@ bool RpcServer::SplitFile(std::string timeSnaps) bool RpcServer::ParserConfig(std::string parserConfigJson) { - json jMessage = json::parse(parserConfigJson); - jsonns::ParserConfig parserConfig = jMessage.at("config"); - ts_->UpdateAppStartTraceStatus(parserConfig.appConfigValue); - ts_->UpdateAnimationTraceStatus(parserConfig.aniConfigValue); - ts_->UpdateTaskPoolTraceStatus(parserConfig.taskConfigValue); - ts_->UpdateBinderRunnableTraceStatus(parserConfig.binderConfigValue); - ts_->UpdateHMKernelTraceStatus(parserConfig.HMKernelConfigValue); - ts_->UpdateRawTraceCutStartTsStatus(parserConfig.rawTraceCutStartTsValue); - ffrtConvertEnabled_ = parserConfig.ffrtConvertConfigValue; + TS_LOGI("parserConfigJson=%s", parserConfigJson.c_str()); + ts_->SetConfigFile(parserConfigJson); + ffrtConvertEnabled_ = ts_->GetFfrtConfig(); startParseTime_ = (std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch())) .count(); diff --git a/trace_streamer/src/table/ftrace/callstack_table.cpp b/trace_streamer/src/table/ftrace/callstack_table.cpp index 48a1bda1f33c5763ee9b01fa60a6e0f84a9f4db1..ff2d133ec4656dd3db987e2781704fbcb2d11c94 100644 --- a/trace_streamer/src/table/ftrace/callstack_table.cpp +++ b/trace_streamer/src/table/ftrace/callstack_table.cpp @@ -34,7 +34,12 @@ enum class Index : int32_t { CHAIN_IDS, SPAN_IDS, PARENT_SPAN_IDS, - FLAGS + FLAGS, + TRACE_LEVEL, + TRACE_TAG, + CUSTOM_CATEGORY, + CUSTOM_ARGS, + CHILD_CALLID }; CallStackTable::CallStackTable(const TraceDataCache *dataCache) : TableBase(dataCache) { @@ -55,6 +60,11 @@ CallStackTable::CallStackTable(const TraceDataCache *dataCache) : TableBase(data tableColumn_.push_back(TableBase::ColumnInfo("spanId", "TEXT")); tableColumn_.push_back(TableBase::ColumnInfo("parentSpanId", "TEXT")); tableColumn_.push_back(TableBase::ColumnInfo("flag", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("trace_level", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("trace_tag", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("custom_category", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("custom_args", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("child_callid", "INTEGER")); tablePriKey_.push_back("callid"); tablePriKey_.push_back("ts"); tablePriKey_.push_back("depth"); @@ -215,6 +225,26 @@ void CallStackTable::Cursor::HandleTypeColumns(int32_t col) const SetTypeColumnTextNotEmpty(slicesObj_.Flags()[CurrentRow()].empty(), slicesObj_.Flags()[CurrentRow()].c_str()); break; + case Index::TRACE_LEVEL: + SetTypeColumnTextNotEmpty(slicesObj_.TraceLevelsData()[CurrentRow()].empty(), + slicesObj_.TraceLevelsData()[CurrentRow()].c_str()); + break; + case Index::TRACE_TAG: + SetTypeColumnText(slicesObj_.TraceTagsData()[CurrentRow()], INVALID_UINT64); + break; + case Index::CUSTOM_CATEGORY: + SetTypeColumnText(slicesObj_.CustomCategorysData()[CurrentRow()], INVALID_UINT64); + break; + case Index::CUSTOM_ARGS: + SetTypeColumnText(slicesObj_.CustomArgsData()[CurrentRow()], INVALID_UINT64); + break; + case Index::CHILD_CALLID: { + if (slicesObj_.ChildCallidData()[CurrentRow()].has_value()) { + sqlite3_result_int64(context_, + static_cast(slicesObj_.ChildCallidData()[CurrentRow()].value())); + } + break; + } default: TS_LOGF("Unregistered column : %d", col); break; diff --git a/trace_streamer/src/table/ftrace/system_call_table.cpp b/trace_streamer/src/table/ftrace/system_call_table.cpp index 6ec56d27c8b8632c93194c138c1c88199b948279..76dbea5ef9a709e96ea87f74d9e7d99b4c5bddbd 100644 --- a/trace_streamer/src/table/ftrace/system_call_table.cpp +++ b/trace_streamer/src/table/ftrace/system_call_table.cpp @@ -17,15 +17,16 @@ namespace SysTuning { namespace TraceStreamer { -enum class Index : int32_t { SYSCALL_NUM = 0, TYPE, IPID, TS, RET }; +enum class Index : int32_t { SYSCALL_NUMBER, TS, DUR, ITID, ARGS, RET }; SystemCallTable::SystemCallTable(const TraceDataCache *dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("syscall_num", "INTEGER")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); - tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("syscall_number", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("args", "TEXT")); tableColumn_.push_back(TableBase::ColumnInfo("ret", "INTEGER")); - tablePriKey_.push_back("syscall_num"); + tablePriKey_.push_back("ts"); } SystemCallTable::~SystemCallTable() {} @@ -46,19 +47,21 @@ SystemCallTable::Cursor::~Cursor() {} int32_t SystemCallTable::Cursor::Column(int32_t column) const { switch (static_cast(column)) { - case Index::SYSCALL_NUM: - sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().SysCallsData()[CurrentRow()]); - break; - case Index::TYPE: - sqlite3_result_text(context_, dataCache_->GetDataFromDict(sysCallObj_.TypesData()[CurrentRow()]).c_str(), - STR_DEFAULT_LEN, nullptr); - break; - case Index::IPID: - sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().IpidsData()[CurrentRow()]); + case Index::SYSCALL_NUMBER: + sqlite3_result_int(context_, dataCache_->GetConstSysCallData().SysCallNumbersData()[CurrentRow()]); break; case Index::TS: sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().TimeStampData()[CurrentRow()]); break; + case Index::DUR: + sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().DursData()[CurrentRow()]); + break; + case Index::ITID: + sqlite3_result_int(context_, dataCache_->GetConstSysCallData().ItidsData()[CurrentRow()]); + break; + case Index::ARGS: + SetTypeColumnText(dataCache_->GetConstSysCallData().ArgsData()[CurrentRow()], INVALID_UINT64); + break; case Index::RET: sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().RetsData()[CurrentRow()]); break; diff --git a/trace_streamer/src/trace_data/BUILD.gn b/trace_streamer/src/trace_data/BUILD.gn index ad0ff73649a5f1322397d818573706680d3653fc..d2b2664d765dccfd5e6baa68fc28efe61a325bdf 100644 --- a/trace_streamer/src/trace_data/BUILD.gn +++ b/trace_streamer/src/trace_data/BUILD.gn @@ -81,7 +81,7 @@ ohos_source_set("trace_data") { "${THIRD_PARTY}/protobuf/src", "${THIRD_PARTY}/bounds_checking_function/include", "${THIRD_PARTY}/json/single_include/nlohmann", - "${THIRD_PARTY}/perf_include/hiviewdfx/faultloggerd/interfaces/nonlinux", + "${THIRD_PARTY}/hiviewdfx/faultloggerd/interfaces/nonlinux", "${SRC}/trace_data/trace_stdtype", "${SRC}/trace_data/trace_stdtype/ftrace", "${SRC}/trace_data/trace_stdtype/ftrace/template", diff --git a/trace_streamer/src/trace_data/trace_stdtype/ftrace/callstack_stdtype.cpp b/trace_streamer/src/trace_data/trace_stdtype/ftrace/callstack_stdtype.cpp index b13386b5a37b963ba4dd9e13be4e494031c7c72d..3bbbe4b82a05dd06655f5ddfaac219c912b353f2 100644 --- a/trace_streamer/src/trace_data/trace_stdtype/ftrace/callstack_stdtype.cpp +++ b/trace_streamer/src/trace_data/trace_stdtype/ftrace/callstack_stdtype.cpp @@ -21,8 +21,10 @@ size_t CallStack::AppendInternalAsyncSlice(const CallStackInternalRow &callStack const std::optional &parentId) { AppendCommonInfo(callStackInternalRow.startT, callStackInternalRow.durationNs, callStackInternalRow.internalTid); - AppendCallStack(callStackInternalRow.cat, callStackInternalRow.name, callStackInternalRow.depth, parentId); + AppendCallStack(callStackInternalRow.cat, callStackInternalRow.name, callStackInternalRow.depth, + callStackInternalRow.childCallid, parentId); AppendDistributeInfo(); + AppendTraceMetadata(); cookies_.emplace_back(cookid); ids_.emplace_back(id_++); return Size() - 1; @@ -31,10 +33,12 @@ size_t CallStack::AppendInternalSlice(const CallStackInternalRow &callStackInter const std::optional &parentId) { AppendCommonInfo(callStackInternalRow.startT, callStackInternalRow.durationNs, callStackInternalRow.internalTid); - AppendCallStack(callStackInternalRow.cat, callStackInternalRow.name, callStackInternalRow.depth, parentId); + AppendCallStack(callStackInternalRow.cat, callStackInternalRow.name, callStackInternalRow.depth, + callStackInternalRow.childCallid, parentId); ids_.emplace_back(id_++); cookies_.emplace_back(INVALID_INT64); AppendDistributeInfo(); + AppendTraceMetadata(); return Size() - 1; } @@ -45,12 +49,17 @@ void CallStack::AppendCommonInfo(uint64_t startT, uint64_t durationNs, InternalT callIds_.emplace_back(internalTid); colorIndexs_.emplace_back(0); } -void CallStack::AppendCallStack(DataIndex cat, DataIndex name, uint8_t depth, std::optional parentId) +void CallStack::AppendCallStack(DataIndex cat, + DataIndex name, + uint8_t depth, + std::optional childCallid, + std::optional parentId) { parentIds_.emplace_back(parentId); cats_.emplace_back(cat); names_.emplace_back(name); depths_.emplace_back(depth); + childCallid_.emplace_back(childCallid); } void CallStack::SetDistributeInfo(size_t index, const std::string &chainId, @@ -64,6 +73,17 @@ void CallStack::SetDistributeInfo(size_t index, flags_[index] = flag; argSet_[index] = INVALID_UINT32; } +void CallStack::SetTraceMetadata(size_t index, + const std::string &traceLevel, + const DataIndex &tag, + const DataIndex &customArg, + const DataIndex &customCategory) +{ + traceLevels_[index] = traceLevel; + traceTags_[index] = tag; + customArgs_[index] = customArg; + customCategorys_[index] = customCategory; +} void CallStack::AppendDistributeInfo() { chainIds_.emplace_back(""); @@ -72,6 +92,13 @@ void CallStack::AppendDistributeInfo() flags_.emplace_back(""); argSet_.emplace_back(INVALID_UINT32); } +void CallStack::AppendTraceMetadata() +{ + traceLevels_.emplace_back(""); + traceTags_.emplace_back(INVALID_UINT64); + customArgs_.emplace_back(INVALID_UINT64); + customCategorys_.emplace_back(INVALID_UINT64); +} void CallStack::SetDuration(size_t index, uint64_t timeStamp) { durs_[index] = timeStamp - timeStamps_[index]; @@ -161,5 +188,25 @@ const std::deque &CallStack::ArgSetIdsData() const { return argSet_; } +const std::deque &CallStack::TraceLevelsData() const +{ + return traceLevels_; +} +const std::deque &CallStack::TraceTagsData() const +{ + return traceTags_; +} +const std::deque &CallStack::CustomCategorysData() const +{ + return customCategorys_; +} +const std::deque &CallStack::CustomArgsData() const +{ + return customArgs_; +} +const std::deque> &CallStack::ChildCallidData() const +{ + return childCallid_; +} } // namespace TraceStdtype } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_stdtype/ftrace/callstack_stdtype.h b/trace_streamer/src/trace_data/trace_stdtype/ftrace/callstack_stdtype.h index 033d25db69434ed63d6e59f31b1214569fbe219e..07b5322b212a9b57bb7e1430e76b79e01317e68f 100644 --- a/trace_streamer/src/trace_data/trace_stdtype/ftrace/callstack_stdtype.h +++ b/trace_streamer/src/trace_data/trace_stdtype/ftrace/callstack_stdtype.h @@ -29,6 +29,7 @@ struct CallStackInternalRow { DataIndex cat = INVALID_UINT64; DataIndex name = INVALID_UINT64; uint8_t depth = INVALID_UINT8; + uint32_t childCallid = INVALID_UINT32; }; class CallStack : public CacheBase, public CpuCacheBase, public BatchCacheBase { public: @@ -43,7 +44,13 @@ public: const std::string &parentSpanId, const std::string &flag); void AppendDistributeInfo(); + void AppendTraceMetadata(); void SetDuration(size_t index, uint64_t timeStamp); + void SetTraceMetadata(size_t index, + const std::string &traceLevel, + const DataIndex &tag, + const DataIndex &customArg, + const DataIndex &customCategory = INVALID_UINT64); void SetDurationWithFlag(size_t index, uint64_t timeStamp); void SetFlag(size_t index, uint8_t flag); void SetDurationEx(size_t index, uint32_t dur); @@ -67,11 +74,17 @@ public: parentSpanIds_.clear(); flags_.clear(); argSet_.clear(); + traceLevels_.clear(); + traceTags_.clear(); + customCategorys_.clear(); + customArgs_.clear(); + childCallid_.clear(); } void ClearExportedData() override { EraseElements(timeStamps_, ids_, durs_, cats_, cookies_, colorIndexs_, callIds_, names_, depths_, chainIds_, - spanIds_, parentSpanIds_, flags_, argSet_); + spanIds_, parentSpanIds_, flags_, argSet_, traceLevels_, traceTags_, customCategorys_, + customArgs_, childCallid_); } const std::deque> &ParentIdData() const; const std::deque &CatsData() const; @@ -85,10 +98,19 @@ public: const std::deque &ParentSpanIds() const; const std::deque &Flags() const; const std::deque &ArgSetIdsData() const; + const std::deque &TraceLevelsData() const; + const std::deque &TraceTagsData() const; + const std::deque &CustomCategorysData() const; + const std::deque &CustomArgsData() const; + const std::deque> &ChildCallidData() const; private: void AppendCommonInfo(uint64_t startT, uint64_t durationNs, InternalTid internalTid); - void AppendCallStack(DataIndex cat, DataIndex name, uint8_t depth, std::optional parentId); + void AppendCallStack(DataIndex cat, + DataIndex name, + uint8_t depth, + std::optional childCallid, + std::optional parentId); private: std::deque> parentIds_; @@ -103,6 +125,11 @@ private: std::deque parentSpanIds_ = {}; std::deque flags_ = {}; std::deque argSet_ = {}; + std::deque traceLevels_ = {}; + std::deque traceTags_ = {}; + std::deque customCategorys_ = {}; + std::deque customArgs_ = {}; + std::deque> childCallid_; }; } // namespace TraceStdtype } // namespace SysTuning diff --git a/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.cpp b/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.cpp index 4b66c99534f084c686d47777147c2fb6b0aa08c1..70a402b6713e2275d1bfcbed80d19e61bb3d26ff 100644 --- a/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.cpp +++ b/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.cpp @@ -13,16 +13,16 @@ * limitations under the License. */ #include "syscall_stdtype.h" - namespace SysTuning { namespace TraceStdtype { -size_t SysCall::AppendSysCallData(int64_t sysCallNum, DataIndex type, uint32_t ipid, uint64_t timeStamp, int64_t ret) +size_t SysCall::AppendSysCallData(const SyscallInfoRow &syscallInfoRow) { - sysCallNums_.emplace_back(sysCallNum); - types_.emplace_back(type); - ipids_.emplace_back(ipid); - timeStamps_.emplace_back(timeStamp); - rets_.emplace_back(ret); + sysCallNumbers_.emplace_back(syscallInfoRow.number); + timeStamps_.emplace_back(syscallInfoRow.ts); + durs_.emplace_back(syscallInfoRow.dur); + itids_.emplace_back(syscallInfoRow.itid); + args_.emplace_back(syscallInfoRow.args); + rets_.emplace_back(syscallInfoRow.ret); return Size() - 1; } } // namespace TraceStdtype diff --git a/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.h b/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.h index 0fa2844fb02faee8511d6be7fc9d85d9aa35cea3..5e85ad5260450de336788a67cb059a80d4260630 100644 --- a/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.h +++ b/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.h @@ -19,43 +19,57 @@ namespace SysTuning { namespace TraceStdtype { +struct SyscallInfoRow { + uint64_t ts = INVALID_UINT64; + uint64_t dur = INVALID_UINT64; + InternalTid itid = INVALID_UINT32; + uint32_t number = INVALID_UINT32; + DataIndex args = INVALID_UINT64; + int64_t ret = INVALID_INT64; +}; class SysCall : public CacheBase, public BatchCacheBase { public: - size_t AppendSysCallData(int64_t sysCallNum, DataIndex type, uint32_t ipid, uint64_t timeStamp, int64_t ret); - const std::deque &SysCallsData() const + size_t AppendSysCallData(const SyscallInfoRow &syscallNrInfoRow); + const std::deque &SysCallNumbersData() const + { + return sysCallNumbers_; + } + const std::deque &DursData() const { - return sysCallNums_; + return durs_; } - const std::deque &TypesData() const + const std::deque &ItidsData() const { - return types_; + return itids_; } - const std::deque &IpidsData() const + const std::deque &ArgsData() const { - return ipids_; + return args_; } - const std::deque &RetsData() const + const std::deque &RetsData() const { return rets_; } void Clear() override { CacheBase::Clear(); - sysCallNums_.clear(); - types_.clear(); - ipids_.clear(); + sysCallNumbers_.clear(); + durs_.clear(); + itids_.clear(); + args_.clear(); rets_.clear(); } void ClearExportedData() override { - EraseElements(timeStamps_, sysCallNums_, types_, ipids_, rets_); + EraseElements(sysCallNumbers_, timeStamps_, durs_, itids_, args_, rets_); } private: - std::deque sysCallNums_ = {}; - std::deque types_ = {}; - std::deque ipids_ = {}; - std::deque rets_ = {}; + std::deque durs_ = {}; + std::deque sysCallNumbers_ = {}; + std::deque itids_ = {}; + std::deque args_ = {}; + std::deque rets_ = {}; }; } // namespace TraceStdtype } // namespace SysTuning diff --git a/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp b/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp index 31707d3238af296a27dee11b4c89d806412fce68..734bc852a09455dbb4114e56be1d295ed8bfddc3 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp @@ -31,8 +31,10 @@ #include "process_filter.h" #include "slice_filter.h" #include "stat_filter.h" +#include "syscall_filter.h" #include "system_event_measure_filter.h" #include "task_pool_filter.h" +#include "config_filter.h" namespace SysTuning { namespace TraceStreamer { @@ -45,6 +47,7 @@ void TraceStreamerFilters::FilterClear() cpuFilter_->Clear(); irqFilter_->Clear(); frameFilter_->Clear(); + syscallFilter_->Clear(); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_streamer/trace_streamer_filters.h b/trace_streamer/src/trace_streamer/trace_streamer_filters.h index 4e223e904e3d8c6bfded1cb37b62bfe4d702fdf3..d4667c280c7950cd07cbf575f00d0e2fe5119583 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_filters.h +++ b/trace_streamer/src/trace_streamer/trace_streamer_filters.h @@ -30,7 +30,9 @@ class StatFilter; class BinderFilter; class ArgsFilter; class IrqFilter; +class SyscallFilter; class SystemEventMeasureFilter; +class ConfigFilter; #ifdef ENABLE_HISYSEVENT class HiSysEventMeasureFilter; #endif @@ -56,9 +58,11 @@ public: std::unique_ptr binderFilter_; std::unique_ptr argsFilter_; std::unique_ptr irqFilter_; + std::unique_ptr syscallFilter_; std::unique_ptr sysEventMemMeasureFilter_; std::unique_ptr sysEventVMemMeasureFilter_; std::unique_ptr sysEventSourceFilter_; + std::unique_ptr configFilter_; #ifdef ENABLE_HISYSEVENT std::unique_ptr hiSysEventMeasureFilter_; #endif diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp index 2d07bb03431c6cd88833434cad316eb7d843b277..393f6957d1bbfe24bf86cb9e0b07446bf45d0b12 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -21,6 +21,7 @@ #include #include #include "animation_filter.h" +#include "syscall_filter.h" #include "app_start_filter.h" #include "args_filter.h" #include "binder_filter.h" @@ -29,6 +30,7 @@ #include "file.h" #include "filter_filter.h" #include "frame_filter.h" +#include "config_filter.h" #ifdef ENABLE_HISYSEVENT #include "hi_sysevent_measure_filter.h" #endif @@ -144,6 +146,7 @@ void TraceStreamerSelector::InitFilter() { streamFilters_ = std::make_unique(); traceDataCache_ = std::make_unique(); + streamFilters_->configFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->animationFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->cpuFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->sliceFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); @@ -157,6 +160,7 @@ void TraceStreamerSelector::InitFilter() streamFilters_->argsFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->irqFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->frameFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->syscallFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->sysEventMemMeasureFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_SYS_MEMORY_FILTER); streamFilters_->sysEventVMemMeasureFilter_ = std::make_unique( @@ -172,6 +176,9 @@ void TraceStreamerSelector::InitFilter() std::make_unique(traceDataCache_.get(), streamFilters_.get()); #endif streamFilters_->taskPoolFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); +#if !IS_WASM + GetConfigFile(); +#endif } void TraceStreamerSelector::WaitForParserEnd() @@ -195,7 +202,7 @@ void TraceStreamerSelector::WaitForParserEnd() } #endif traceDataCache_->UpdateTraceRange(); - if (traceDataCache_->AnimationTraceEnabled()) { + if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled()) { streamFilters_->animationFilter_->UpdateFrameInfo(); streamFilters_->animationFilter_->UpdateDynamicFrameInfo(); } @@ -203,7 +210,17 @@ void TraceStreamerSelector::WaitForParserEnd() ComputeDataDictStrHash(); #endif } - +void TraceStreamerSelector ::GetConfigFile() +{ + std::ifstream configReading("config/config.json"); + if (!configReading.is_open()) { + TS_LOGE("Open config file failed!Please make sure that config/config.json exists."); + return; + } + std::stringstream buffer; + buffer << configReading.rdbuf(); + streamFilters_->configFilter_->SetConfig(buffer.str()); +} MetaData *TraceStreamerSelector::GetMetaData() { return traceDataCache_->GetMetaData(); @@ -530,6 +547,14 @@ void TraceStreamerSelector::UpdateRawTraceCutStartTsStatus(bool status) { traceDataCache_->UpdateRawTraceCutStartTsStatus(status); } +void TraceStreamerSelector::SetConfigFile(std::string &filePath) +{ + streamFilters_->configFilter_->SetConfig(filePath); +} +bool TraceStreamerSelector::GetFfrtConfig() +{ + return streamFilters_->configFilter_->GetSwitchConfig().FfrtConfigEnabled(); +} bool TraceStreamerSelector::LoadQueryFile(const std::string &sqlOperator, std::vector &sqlStrings) { std::ifstream file(sqlOperator); diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.h b/trace_streamer/src/trace_streamer/trace_streamer_selector.h index 3187a8170e195dc34055f449f6d53e072ba9c00d..bc8d4786c258434894e2417b6ae4221d9346b72f 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.h +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.h @@ -71,6 +71,9 @@ public: void UpdateHMKernelTraceStatus(bool status); void UpdateRawTraceCutStartTsStatus(bool status); void InitMetricsMap(std::map &metricsMap); + void SetConfigFile(std::string &filePath); + bool GetFfrtConfig(); + void GetConfigFile(); const std::string MetricsSqlQuery(const std::string &metrics); auto GetPtreaderParser() { diff --git a/trace_streamer/src/version.cpp b/trace_streamer/src/version.cpp index 9544e6498e01649b5442a02d199c414bfe7986de..98b29dd9ea923d93e12d9a2e7ac05d6fe9db37d7 100644 --- a/trace_streamer/src/version.cpp +++ b/trace_streamer/src/version.cpp @@ -17,7 +17,7 @@ namespace SysTuning { namespace TraceStreamer { size_t g_loadSize = 0; size_t g_fileSize = 0; -const std::string TRACE_STREAMER_VERSION = "4.2.9"; // version -const std::string TRACE_STREAMER_PUBLISH_VERSION = "2025/1/2"; // publish datetime +const std::string TRACE_STREAMER_VERSION = "4.3.5"; // version +const std::string TRACE_STREAMER_PUBLISH_VERSION = "2025/5/15"; // publish datetime } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/test/BUILD.gn b/trace_streamer/test/BUILD.gn index 723d016712aabd9494aca4652dd7c45f115859e4..f5c7033bc38e2f187ab608d172b91ce358177981 100644 --- a/trace_streamer/test/BUILD.gn +++ b/trace_streamer/test/BUILD.gn @@ -90,8 +90,8 @@ if (is_test) { "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/process_data:ts_process_data_cpp", "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/test_data:test_data_cpp", "${OHOS_TRACE_STREAMER_PROTOS_DIR}/protos/types/plugins/xpower_data:ts_xpower_data_cpp", + "${SRC}/parser/hiperf_parser:libsec_static", "${SRC}/parser/rawtrace_parser:rawtrace_parser", - "${THIRD_PARTY}/bounds_checking_function:libsec_static", "${THIRD_PARTY}/googletest:gtest", "${THIRD_PARTY}/googletest:gtest_main", "${THIRD_PARTY}/protobuf:protobuf_lite_static",