diff --git a/README_zh.md b/README_zh.md index 38e2cebaeb239a565687682defad1e7cb7f6742b..2cb805c9e0319a0b704a7ceac15c1e04ea18a992 100644 --- a/README_zh.md +++ b/README_zh.md @@ -2,6 +2,7 @@ - [简介](#简介) - [目录](#目录) +- [ts二进制](#ts二进制) - [约束](#约束) - [相关文档](#相关文档) @@ -42,7 +43,8 @@ │ │ ├── trace_streamer # traceStreamer 结构 │ │ │   └── kits # js/napi接口存放目录 ``` - +## ts二进制 +bin.zip ## 约束 @@ -62,4 +64,4 @@ host端构建约束 - [compile_trace_streamer](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/compile_trace_streamer.md) - [des_stat](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/des_stat.md) - [des_support_event](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/des_support_event.md) -- [des_tables](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/des_tables.md) \ No newline at end of file +- [des_tables](https://gitee.com/openharmony/developtools_profiler/blob/master/host/smartperf/doc/des_tables.md) diff --git a/host/doc/bin.zip b/host/doc/bin.zip new file mode 100644 index 0000000000000000000000000000000000000000..96dad5396bd82740be20b58b8ca294a58ddb38c6 Binary files /dev/null and b/host/doc/bin.zip differ diff --git a/host/ide/src/base-ui/table/lit-table.ts b/host/ide/src/base-ui/table/lit-table.ts index 4eaeebfed3abf66f01881f0ff21d2f88062c2da7..e1c7ba7e77bfdeb3e174ff81070fb9dd125b4c85 100644 --- a/host/ide/src/base-ui/table/lit-table.ts +++ b/host/ide/src/base-ui/table/lit-table.ts @@ -49,6 +49,7 @@ export class LitTable extends HTMLElement { display: grid; grid-template-columns: repeat(1,1fr); width: 100%; + font-weight: 500; flex:1; } .tr{ @@ -58,13 +59,18 @@ export class LitTable extends HTMLElement { } .tr:nth-of-type(even){ } - .tr{ background-color: var(--dark-background,#FFFFFF); } .tr:hover{ background-color: var(--dark-background6,#DEEDFF); } + .tr[selected]{ + background-color: var(--dark-background6,#DEEDFF); + } + .tr[high-light]{ + font-weight: 600; + } .td{ box-sizing: border-box; padding: 3px; @@ -80,9 +86,6 @@ export class LitTable extends HTMLElement { text-overflow: ellipsis; white-space: nowrap; } - .tr[selected]{ - background-color: var(--dark-background6,#DEEDFF); - } .td-order{ } .td-order:before{ @@ -137,8 +140,12 @@ export class LitTable extends HTMLElement { display:flex; align-items:center; white-space: nowrap; + font-weight: 500; cursor: pointer; } + .tree-first-body[high-light]{ + font-weight: 600; + } .tree-first-body:hover{ background-color: var(--dark-background6,#DEEDFF); /*antd #fafafa 42b983*/ } @@ -999,6 +1006,7 @@ export class LitTable extends HTMLElement { let indexOf = this.currentTreeDivList.indexOf(td); this.dispatchRowClickEvent(rowData, [(this.treeElement?.children[indexOf] as HTMLElement), newTableElement]) } + this.setHighLight(rowData.data.isSearch,td) this.treeElement!.style.width = column.getAttribute('width') this.treeElement?.append(td) this.currentTreeDivList.push(td) @@ -1028,6 +1036,7 @@ export class LitTable extends HTMLElement { newTableElement.style.top = '0px' newTableElement.style.left = '0px' newTableElement.style.cursor = 'pointer' + this.setHighLight(rowData.data.isSearch,newTableElement) newTableElement.onmouseenter = () => { if ((newTableElement as any).data.isSelected) return; let indexOf = this.currentRecycleList.indexOf(newTableElement); @@ -1199,12 +1208,14 @@ export class LitTable extends HTMLElement { return } let childIndex = -1 + this.setHighLight(rowObject.data.isSearch,element); element.childNodes.forEach((child) => { if (child.nodeType != 1) return childIndex++; let idx = firstElement != undefined ? childIndex + 1 : childIndex; if (firstElement != undefined && childIndex == 0) { - (firstElement as any).data = rowObject.data + this.setHighLight(rowObject.data.isSearch,firstElement); + (firstElement as any).data = rowObject.data; if ((this.columns![0] as any).template) { firstElement.innerHTML = (this.columns![0] as any).template.render(rowObject.data).content.cloneNode(true).innerHTML } else { @@ -1389,4 +1400,12 @@ export class LitTable extends HTMLElement { } return "" } + + setHighLight(isSearch:boolean,element:any){ + if(isSearch){ + element.setAttribute("high-light","") + }else { + element.removeAttribute("high-light") + } + } } diff --git a/host/ide/src/doc/quickstart_smartperf.html b/host/ide/src/doc/quickstart_smartperf.html index 483594174e330e3f9dd8131d7a056de925a68e66..2dd22e0e2cf6dddab756fd7dbf2ded37d032136e 100644 --- a/host/ide/src/doc/quickstart_smartperf.html +++ b/host/ide/src/doc/quickstart_smartperf.html @@ -791,25 +791,15 @@

单选CPU使用情况数据,单击方法会在选中的方法外层加上深色边框,能够突出当前选中色块,弹出层中会展示当前CPU上的进程名,线程名,开始时间和运行时长,线程运行状态等信息
GitHub Logo

-

3.FPS数据

-

FPS是帧率的显示,每秒产生画面的个数
- GitHub Logo

-

3.1FPS的框选功能

- -

可以对fps的数据进行框选,框选后在最下方的弹出层中会展示框选时间区间内的统计表格,主要显示了time(时间),FPS(帧率)
- GitHub Logo

-

3.2.FPS的鼠标悬浮功能

-

鼠标移动到帧率的柱状图上,悬浮框会显示当前时间的FPS的值
- GitHub Logo

-

4.进程,线程和方法数据

+

3.进程,线程和方法数据

下图是进程数据,左边部分展示进程名称和id
GitHub Logo
点击进程名前面向下箭头可以展开对应的线程进行查看,展开后的线程如下图,如果存在堆内存占用情况,就会显示在第一行,如果出现两个名字和id一样的线程,则第一个为线程的使用情况,第二为线程内的方法栈调用情况
GitHub Logo

- 4.1进程,线程和方法数据的框选功能

+ 3.1进程,线程和方法数据的框选功能

可以对线程的数据进行框选,框选后在最下方的弹出层中会展示框选数据的统计表格,包含线程运行状态,线程调用栈的统计情况。当框选的数据中同时存在线程运行状态和线程调用栈数据,下方的弹出层中就会出现多个tab选项,可以进行切换

下图是线程运行状态框选统计信息,包括进程名,进程号,线程名,线程号,线程状态,状态持续时间,平均持续时间,该线程状态发生的次数
@@ -817,7 +807,7 @@

下图是线程调用栈框选统计信息,包括方法名,持续时间,平均持续时间,调用的次数
GitHub Logo

- 4.2进程,线程和方法数据的单选功能

+ 3.2进程,线程和方法数据的单选功能

单选线程的state数据时,会展示当前选中线程的状态数据,开始时间和持续时长,线程状态,所在进程名称、
GitHub Logo
@@ -825,32 +815,32 @@ GitHub Logo

- 4.3.线程的跳转功能

+ 3.3.线程的跳转功能

点击画红框处的带箭头的标志,会从CPU的线程概览视图跳转到线程的详情视图,同时从线程的详情视图也能跳转到CPU的线程概览视图
GitHub Logo
-

5.trace的其他功能

+

4.trace的其他功能

- 5.1.小旗标志的功能

+ 4.1.小旗标志的功能

将选中数据的时间点通过小旗的方式在时间轴上展示,直观的展示选中数据的时间
GitHub Logo
在下方输入空输入文字:我是trace,可以给小旗打备注
GitHub Logo

- 5.2.收藏置顶功能

+ 4.2.收藏置顶功能

鼠标移动到某个页签,会出现星形的标志,点击该星形,可以将该行收藏置顶
GitHub Logo

- 5.3.勾选功能

+ 4.3.勾选功能

框选某一区域,该区域左边会出现CheckBox的复选框。选中的区域的复选框会出现打勾的状态。可以取消勾选,也可以重新勾选
GitHub Logo

- 5.4.搜索功能

+ 4.4.搜索功能

在搜索框中,可以输入线程,线程号等搜索自己想要的信息,搜索完成会高亮显示
GitHub Logo

在搜索框中输入调用栈的方法名,会跳转到对应的调用栈
GitHub Logo

- 5.5.M键测量功能

+ 4.5.M键测量功能

放大trace中的色块,选中色块,键盘按下M,会出现像尺子一样的形状
GitHub Logo
diff --git a/host/ide/src/trace/bean/FrameChartStruct.ts b/host/ide/src/trace/bean/FrameChartStruct.ts index 5df31fe64012795547a933cf4e01472e0e00abaf..c7c00b48db4ce007d7a990dbff94dcd846f8aebd 100644 --- a/host/ide/src/trace/bean/FrameChartStruct.ts +++ b/host/ide/src/trace/bean/FrameChartStruct.ts @@ -19,6 +19,12 @@ import { Rect } from "../component/trace/timer-shaft/Rect.js"; import { info } from "../../log/Log.js"; const padding: number = 1; +const lightBlue = { + r: 82, + g: 145, + b: 255, + a: 0.9 +}; export class ChartStruct extends BaseStruct { static hoverFuncStruct: ChartStruct | undefined; @@ -35,7 +41,8 @@ export class ChartStruct extends BaseStruct { parent: ChartStruct | undefined; children: Array = []; percent: number = 0; - addr : string = ""; + addr: string = ""; + isSearch: boolean = false; } @@ -90,13 +97,14 @@ export function draw(ctx: CanvasRenderingContext2D, data: ChartStruct) { // draw rect let miniHeight = 20; if (isSelected(data)) { - ctx.fillStyle = `rgba(${82}, ${145}, ${255}, 0.9)`; + ctx.fillStyle = `rgba(${lightBlue.r}, ${lightBlue.g}, ${lightBlue.b}, ${lightBlue.a})`; } else { let color = getHeatColor(data.percent); ctx.fillStyle = `rgba(${color.r}, ${color.g}, ${color.b}, 0.9)`; } ctx.fillRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2); //draw border + ctx.lineWidth = 0.4; if (isHover(data)) { if (spApplication.dark) { ctx.strokeStyle = "#fff"; @@ -109,8 +117,11 @@ export function draw(ctx: CanvasRenderingContext2D, data: ChartStruct) { } else { ctx.strokeStyle = "#fff"; } + if (data.isSearch) { + ctx.strokeStyle = `rgb(${lightBlue.r}, ${lightBlue.g}, ${lightBlue.b})`; + ctx.lineWidth = 1; + } } - ctx.lineWidth = 0.4; ctx.strokeRect(data.frame.x, data.frame.y, data.frame.width, miniHeight - padding * 2); //draw symbol name diff --git a/host/ide/src/trace/component/trace/TimerShaftElement.ts b/host/ide/src/trace/component/trace/TimerShaftElement.ts index 30b1fc5b669342c16aac869d8e830f39dcc2080c..1d31e926e4da852f9c5625511dc4ba25f992788a 100644 --- a/host/ide/src/trace/component/trace/TimerShaftElement.ts +++ b/host/ide/src/trace/component/trace/TimerShaftElement.ts @@ -21,7 +21,6 @@ import {SportRuler} from "./timer-shaft/SportRuler.js"; import {procedurePool} from "../../database/Procedure.js"; import {Flag} from "./timer-shaft/Flag.js"; import {info} from "../../../log/Log.js"; -import {LitIcon} from "../../../base-ui/icon/LitIcon"; //随机生成十六位进制颜色 export function randomRgbColor() { @@ -368,7 +367,7 @@ export class TimerShaftElement extends BaseElement { box-sizing: border-box; display: flex; width: 100%; - height: 147px; + height: 148px; border-bottom: 1px solid var(--dark-background,#dadada); border-top: 1px solid var(--dark-background,#dadada); } @@ -431,7 +430,6 @@ export class TimerShaftElement extends BaseElement {

- diff --git a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.ts b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.ts index e6cf6b7ecd2748f4163bfdf97eb4c8299c005011..6e9baad4e825df2e7c761def085c42fc1a491132 100644 --- a/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.ts +++ b/host/ide/src/trace/component/trace/sheet/file-system/TabPaneFileSystemEvents.ts @@ -85,6 +85,7 @@ export class TabPaneFileSystemEvents extends BaseElement { setProcessFilter(){ this.processList = ["All Process"]; + this.pathList = ["All Path"] this.source.map(it => { if(this.processList!.findIndex(a => a === it.process) == -1){ this.processList!.push(it.process); @@ -152,7 +153,7 @@ export class TabPaneFileSystemEvents extends BaseElement { this.filter = this.shadowRoot?.querySelector("#filter"); this.eventList = ['All Event','All Open Event','All Close Event','All Read Event','All Write Event']; this.processList = ['All Process']; - this.pathList = ["All Path"] + this.pathList = ["All Path"]; this.filter!.setSelectList(this.eventList,this.processList,"","",this.pathList,""); this.filter!.firstSelect = "0"; this.filter!.getFilterData((data: FilterData) => { diff --git a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts index 81c072c184d194d9c5c0b1a7a57904f858a88329..3b5b8fba4708c7b8bac36cd777cc9d936e844ee0 100644 --- a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts +++ b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerCommon.ts @@ -25,6 +25,7 @@ export class ChartStruct { dur:number = 0; parent: ChartStruct | undefined; children: Array = []; + isSearch: boolean = false; } export class Msg{ @@ -200,6 +201,7 @@ class MerageBeanDataSplit{ this.clearSearchNode(currentTreeList) data.forEach((process) => { process.searchShow = true + process.isSearch = false }) this.resetNewAllNode(data,currentTreeList) if (searchValue != "") { @@ -236,6 +238,7 @@ class MerageBeanDataSplit{ data.forEach((node) => { if ((node.symbolName!=undefined&&node.symbolName.includes(search)) || parentSearch) { node.searchShow = true + node.isSearch = (node.symbolName!=undefined&&node.symbolName.includes(search)) let parentNode = node.currentTreeParentNode while (parentNode != undefined && !parentNode.searchShow) { parentNode.searchShow = true @@ -243,6 +246,7 @@ class MerageBeanDataSplit{ } } else { node.searchShow = false + node.isSearch = false } if (node.children.length > 0) { this.findSearchNode(node.children, search, node.searchShow) @@ -253,6 +257,7 @@ class MerageBeanDataSplit{ clearSearchNode(currentTreeList:any[]) { currentTreeList.forEach((node) => { node.searchShow = true + node.isSearch = false }) } diff --git a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts index f06b7bd8ed20c7614018339c46ec36f6da5fa718..0d378b574d197f79855777c0ee6f64ed2c02a857 100644 --- a/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts +++ b/host/ide/src/trace/database/logic-worker/ProcedureLogicWorkerPerf.ts @@ -546,7 +546,8 @@ group by callchain_id,s.thread_id,thread_state,process_id) p` resetAllNode(data: PerfCallChainMerageData[]) { this.clearSearchNode() data.forEach((process) => { - process.searchShow = true + process.searchShow = true; + process.isSearch = false }) this.resetNewAllNode(data) if (this.searchValue != "") { @@ -584,12 +585,14 @@ group by callchain_id,s.thread_id,thread_state,process_id) p` if ((node.symbol&&node.symbol.includes(search)) || parentSearch) { node.searchShow = true let parentNode = node.currentTreeParentNode + node.isSearch = (node.symbol!=undefined&&node.symbol.includes(search)) while (parentNode != undefined && !parentNode.searchShow) { parentNode.searchShow = true parentNode = parentNode.currentTreeParentNode } } else { node.searchShow = false + node.isSearch = false } if (node.children.length > 0) { this.findSearchNode(node.children, search, node.searchShow) @@ -600,6 +603,7 @@ group by callchain_id,s.thread_id,thread_state,process_id) p` clearSearchNode() { this.currentTreeList.forEach((node) => { node.searchShow = true + node.isSearch = false }) } @@ -775,7 +779,7 @@ export class PerfCallChainMerageData extends ChartStruct { vaddrInFile: number = 0; isSelected: boolean = false; searchShow: boolean = true; - + isSearch: boolean = false; set parentNode(data: PerfCallChainMerageData | undefined) { this.currentTreeParentNode = data; this.#parentNode = data; diff --git a/host/trace_streamer/BUILD.gn b/host/trace_streamer/BUILD.gn index 092bb98c46e3328169c387349de1c53cf88bb3d3..2f41a95604d7fb300fb8ca8f392779a735b5dfa2 100644 --- a/host/trace_streamer/BUILD.gn +++ b/host/trace_streamer/BUILD.gn @@ -12,11 +12,20 @@ # limitations under the License. group("trace_streamer") { - if (use_wasm) { - deps = [ "src:trace_streamer_builtin" ] - } else if (is_test) { + if (is_test) { deps = [ "test:unittest" ] testonly = true + } else if (is_fuzz) { + deps = [ "test:fuzztest" ] + testonly = true + } else if (is_protoc) { + deps = [ "//third_party/protobuf:protoc" ] + } else if (is_sdkdemo) { + deps = [ "sdk:trace_streamer_sdk_builtin" ] + } else if (is_sdkdemo_test) { + deps = [ "sdk/test:sdkunittest" ] + } else if (use_wasm) { + deps = [ "src:trace_streamer_builtin" ] } else { deps = [ "src:trace_streamer" ] } diff --git a/host/trace_streamer/README.md b/host/trace_streamer/README.md index eb0deec07b8f4c55fed4152454f49cad6d721cb9..c1b9b5c9710e99d7afed00f1b2595ed638dfb2f4 100644 --- a/host/trace_streamer/README.md +++ b/host/trace_streamer/README.md @@ -1,309 +1,168 @@ -# trace_streamer工具说明 -trace_streamer工具可以2种方式使用 +# TraceStreamer工具说明 +TraceStreamer是一个trace数据解析程序,可以将一个trace文本文件或者基于proto序列化的二进制文件转换成为sqlite数据库的形式。 TraceStreamer使用C++实现,支持在ohos, linux, mac等系统上使用,具有良好的跨平台特性。 +![GitHub Logo](./figures/trace_streamer_stream.png) +## 关于TraceStreamer的使用说明 +TraceStreamer工具可以2种方式使用 1. 可以将系统离线trace文件解析并转为db,此工具支持基于文本的trace和基于proto的trace。 -2. trace_streamer工具还可以WebAssembly的方式在浏览器中运行,需暴露相关接口给js文件。 - -## 关于trace解析工具的使用说明: +2. TraceStreamer工具还可以WebAssembly的方式在浏览器中运行,需提供相关接口给js文件。 + ### 导出db模式 -在导出db模式下,trace_streamer.exe trace文件路径名 -e 导出db路径名.db -此命令可以将trace文件转为db -本应用支持在ohos, linux, windows, mac使用。 -关于db文件的说明: -使用db查看工具查看stat表,可以浏览当前数据一共有多少类数据,各类数据都收到多少条,数据是否正常等情况。在meta表会记录数据库导出时的一些系统信息,比如导入和导出的文件全路径,解析时间等信息。 -meta表可以选择不导出(有些情况下会暴露系统敏感信息),在导出时添加 -nm选项即可。 -在数据导出之后,会在本地目录下生成一个trace_streamer.log文件,在导出db的目录下生成一个数据库文件同名,.db.ohos.ts后缀的文件 -文件内容如下: -时间戳:执行结果(数字) -应用运行时间 +在导出db模式下,通过下面的指令: +``` +./trace_streamer trace文件路径名 -e 导出db路径名.db +``` +可以将trace文件转为db文件。 +本应用支持在ohos, linux, mac使用。 +在数据导出之后,会在本地目录下生成一个trace_streamer.log文件,在导出db的目录下生成一个数据库文件同名,.db.ohos.ts后缀的文件。 +文件内容如下: +``` +当前时间戳:执行结果(数字) +应用运行时间 +``` +执行结果解释如下: +``` +0 代表执行成功 1 表示输入文件不匹配, 2 表示解析错误, 3其他错误。 +``` +#### __关于db文件的说明__ +可以使用sqliteexport或DB Browser for SQLite工具加载生成的db,通过查看stat表,可以浏览当前数据一共有多少类数据,各类数据都收到多少条,数据是否正常等情况。在meta表会记录数据库导出时的一些系统信息,比如导入和导出的文件全路径,解析时间等信息。 +meta表可以选择不导出(有些情况下会暴露系统敏感信息),在导出时添加 -nm选项即可。 +更多db文件的介绍,可以参考[doc/des_tables.md](./doc/des_tables.md)。 -执行结果解释如下:0 代表执行成功 1 表示输入文件不匹配, 2 表示解析错误, 3其他错误 -### 内置浏览器方式 -trace_streamer可以WebAssembly方式在浏览器中运行,暴露如下接口给js +### 内置浏览器模式 +TraceStreamer可以WebAssembly方式在浏览器中运行,相关接口在wasm模式下生成的trace_streamer_builtin.js文件中,js可以使用的接口如下使用如下接口访问trace_streamer: ``` extern "C" { -/* 上传trace数据 +/* 初始化wasm,在JS中注册回调函数,并返回一段可复用的内存空间,由JS调用 * - * @data: 数据的缓冲区 - * @dataLen: 数据长度 + * @ replyFunction: 回调函数 +* @ reqBufferSize: 返回的内存长度 +* return: 返回一段内存地址给JS +*/ +EMSCRIPTEN_KEEPALIVE uint8_t* Initialize(ReplyFunction replyFunction, uint32_t reqBufferSize) + +/* 更新起始结束时间,由JS调用 * - * return: 0:成功; -1:失败 + * @ len: 起始和结束时间组成的字符串长度 +* return: 成功返回0。 */ -EMSCRIPTEN_KEEPALIVE int TraceStreamerParseData(const uint8_t* data, int dataLen); +EMSCRIPTEN_KEEPALIVE int UpdateTraceTime(int len) -/* 通知TS上传trace数据结束 - * - * return: 0:成功; -1:失败 +/* 设置TraceStreamer和第三方wasm通信的回调函数,并返回一段内存,由JS调用 + * + * @ sendDataCallBack:与第三方wasm通信的回调函数 +* @ reqBufferSize: 返回的内存长度 +* return: 成功返回0 */ -EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver(); +EMSCRIPTEN_KEEPALIVE uint8_t* TraceStreamer_Set_ThirdParty_DataDealer(SendDataCallBack sendDataCallBack, uint32_t reqBufferSize) -/* 通过sql语句操作数据库 +/* TraceStreamer的数据解析接口,由JS调用 * - * @sql: sql语句 - * @sqlLen: sql语句长度 +* @ dataLen: 需要解析的数据源长度 +* return: 成功返回0,失败返回-1 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataEx(int dataLen) + +/* TraceStreamer停止解析数据,由JS调用 * - * return: 0:成功; -1:失败 +* return: 成功返回0,失败返回-1 */ -EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen); +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver() -/* 通过sql语句查询数据库 +/* 数据库操作接口,由JS调用 * - * @sql: sql语句 - * @sqlLen: sql语句长度 - * @out: 查询结果的缓冲区,查询结果为json - * @outLen: 缓冲区长度 +* @ sqlLen: 需要执行的操作类sql语句长度 +* return: 成功返回0,失败返回-1 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperateEx(int sqlLen) + +/*清空wasm内存中的内容,由JS调用 + * +* return: 成功返回0,失败返回-1 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerReset() + +/*执行查询类sql语句,由JS调用 + * +* @ sqlLen: 需要执行的查询类sql语句长度 +* return: 成功返回0,失败返回-1 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQueryEx(int sqlLen) + +/*取消sql查询,由JS调用。 * - * return: >0:查询成功,返回查询结果数据长度; -1:失败 +* return: 成功返回0。 */ -EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, uint8_t* out, int outLen); +EMSCRIPTEN_KEEPALIVE int TraceStreamerCancel() + +/*发送数据给第三方wasm解析,由TraceStreamer调用 + * +* @ pluginData: 第三方插件的数据源 +* @ len: 数据源长度 +* @ componentName: 第三方插件名称 +* return: 成功返回0 +*/ +int TraceStreamer_Plugin_Out_SendData(const char* pluginData, int len, const std::string componentName) + +/* 初始化配置接口,由JS调用 + * +* @ dataLen: 配置字符串的长度 +* return: 成功返回0 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamer_Init_ThirdParty_Config(int dataLen) } // extern "C" ``` ### 你也可以执行如下命令查看应用帮助 -./trace_streamer --help --i 选项可查看应用支持的事件源和具体的事件名列表 +```./trace_streamer --help``` -#### trace_streamer支持的事件解析 -本工具支持基于文本的trace(# TRACE)和基于proto的二进制日志文件的解析,支持的事件列表如下: -##### ftrace事件 -``` -binder_transaction -binder_transaction_received -binder_transaction_alloc_buf -binder_transaction_lock -binder_transaction_locked -binder_transaction_unlock -sched_switch -task_rename -task_newtask -tracing_mark_write -print -sched_wakeup -sched_waking -cpu_idle -cpu_frequency -suspend_resume -workqueue_execute_start -workqueue_execute_end -clock_set_rate -clock_enable -clock_disable -clk_set_rate -clk_enable -clk_disable -sys_enter -sys_exit -regulator_set_voltage -regulator_set_voltage_complete -regulator_disable -regulator_disable_complete -ipi_entry -ipi_exit -irq_handler_entry -irq_handler_exit -softirq_raise -softirq_entry -softirq_exit -sched_wakeup_new -sched_process_exit -trace_event_clock_sync -``` -##### 内存事件 -``` -mem.vm.size -mem.rss -mem.rss.anon -mem.rss.file -mem.rss.schem -mem.swap -mem.locked -mem.hwm -mem.oom_score_adj +### TraceStreamer支持解析的事件列表 +通过```./trace_streamer -i``` +查看支持的事件列表。 +支持的事件列表参见[SupportEventList.md](./doc/des_support_event.md)。 +## TraceStreamer重要概念介绍 +### 进程和线程标识符 ``` -##### 系统内存事件 -``` -sys.mem.unspecified -sys.mem.total -sys.mem.free -sys.mem.avaiable -sys.mem.buffers -sys.mem.cached -sys.mem.swap.chard -sys.mem.active -sys.mem.inactive -sys.mem.active.anon -sys.mem.inactive.anon -sys.mem.active_file -sys.mem.inactive_file -sys.mem.unevictable -sys.mem.mlocked -sys.mem.swap.total -sys.mem.swap.free -sys.mem.dirty -sys.mem.writeback -sys.mem.anon.pages -sys.mem.mapped -sys.mem.shmem -sys.mem.slab -sys.mem.slab.reclaimable -sys.mem.slab.unreclaimable -sys.mem.kernel.stack -sys.mem.page.tables -sys.mem.commit.limit -sys.mem.commited.as -sys.mem.vmalloc.total -sys.mem.vmalloc.used -sys.mem.vmalloc.chunk -sys.mem.cma.total -sys.mem.cma.free -``` -##### 系统虚拟内存事件 -``` -sys.virtual.mem.unspecified -sys.virtual.mem.nr.free.pages -sys.virtual.mem.nr.alloc.batch -sys.virtual.mem.nr.inactive.anon -sys.virtual.mem.nr.active_anon -sys.virtual.mem.nr.inactive.file -sys.virtual.mem.nr.active_file -sys.virtual.mem.nr.unevictable -sys.virtual.mem.nr.mlock -sys.virtual.mem.anon.pages -sys.virtual.mem.nr.mapped -sys.virtual.mem.nr.file.pages -sys.virtual.mem.nr.dirty -sys.virtual.mem.nr.writeback -sys.virtual.mem.nr.slab.reclaimable -sys.virtual.mem.nr.slab.unreclaimable -sys.virtual.mem.nr.page_table.pages -sys.virtual.mem.nr_kernel.stack -sys.virtual.mem.nr.overhead -sys.virtual.mem.nr.unstable -sys.virtual.mem.nr.bounce -sys.virtual.mem.nr.vmscan.write -sys.virtual.mem.nr.vmscan.immediate.reclaim -sys.virtual.mem.nr.writeback_temp -sys.virtual.mem.nr.isolated_anon -sys.virtual.mem.nr.isolated_file -sys.virtual.mem.nr.shmem -sys.virtual.mem.nr.dirtied -sys.virtual.mem.nr.written -sys.virtual.mem.nr.pages.scanned -sys.virtual.mem.workingset.refault -sys.virtual.mem.workingset.activate -sys.virtual.mem.workingset_nodereclaim -sys.virtual.mem.nr_anon.transparent.hugepages -sys.virtual.mem.nr.free_cma -sys.virtual.mem.nr.swapcache -sys.virtual.mem.nr.dirty.threshold -sys.virtual.mem.nr.dirty.background.threshold -sys.virtual.mem.vmeminfo.pgpgin -sys.virtual.mem.pgpgout -sys.virtual.mem.pgpgoutclean -sys.virtual.mem.pswpin -sys.virtual.mem.pswpout -sys.virtual.mem.pgalloc.dma -sys.virtual.mem.pgalloc.normal -sys.virtual.mem.pgalloc.movable -sys.virtual.mem.pgfree -sys.virtual.mem.pgactivate -sys.virtual.mem.pgdeactivate -sys.virtual.mem.pgfault -sys.virtual.mem.pgmajfault -sys.virtual.mem.pgrefill.dma -sys.virtual.mem.pgrefill.normal -sys.virtual.mem.pgrefill.movable -sys.virtual.mem.pgsteal.kswapd.dma -sys.virtual.mem.pgsteal.kswapd.normal -sys.virtual.mem.pgsteal.kswapd.movable -sys.virtual.mem.pgsteal.direct.dma -sys.virtual.mem.pgsteal.direct.normal -sys.virtual.mem.pgsteal_direct.movable -sys.virtual.mem.pgscan.kswapd.dma -sys.virtual.mem.pgscan_kswapd.normal -sys.virtual.mem.pgscan.kswapd.movable -sys.virtual.mem.pgscan.direct.dma -sys.virtual.mem.pgscan.direct.normal -sys.virtual.mem.pgscan.direct.movable -sys.virtual.mem.pgscan.direct.throttle -sys.virtual.mem.pginodesteal -sys.virtual.mem.slabs_scanned -sys.virtual.mem.kswapd.inodesteal -sys.virtual.mem.kswapd.low.wmark.hit.quickly -sys.virtual.mem.high.wmark.hit.quickly -sys.virtual.mem.pageoutrun -sys.virtual.mem.allocstall -sys.virtual.mem.pgrotated -sys.virtual.mem.drop.pagecache -sys.virtual.mem.drop.slab -sys.virtual.mem.pgmigrate.success -sys.virtual.mem.pgmigrate.fail -sys.virtual.mem.compact.migrate.scanned -sys.virtual.mem.compact.free.scanned -sys.virtual.mem.compact.isolated -sys.virtual.mem.compact.stall -sys.virtual.mem.compact.fail -sys.virtual.mem.compact.success -sys.virtual.mem.compact.daemon.wake -sys.virtual.mem.unevictable.pgs.culled -sys.virtual.mem.unevictable.pgs.scanned -sys.virtual.mem.unevictable.pgs.rescued -sys.virtual.mem.unevictable.pgs.mlocked -sys.virtual.mem.unevictable.pgs.munlocked -sys.virtual.mem.unevictable.pgs.cleared -sys.virtual.mem.unevictable.pgs.stranded -sys.virtual.mem.nr.zspages -sys.virtual.mem.nr.ion.heap -sys.virtual.mem.nr.gpu.heap -sys.virtual.mem.allocstall.dma -sys.virtual.mem.allocstall.movable -sys.virtual.mem.allocstall.normal -sys.virtual.mem.compact_daemon.free.scanned -sys.virtual.mem.compact.daemon.migrate.scanned -sys.virtual.mem.nr.fastrpc -sys.virtual.mem.nr.indirectly.reclaimable -sys.virtual.mem.nr_ion_heap_pool -sys.virtual.mem.nr.kernel_misc.reclaimable -sys.virtual.mem.nr.shadow_call.stack_bytes -sys.virtual.mem.nr.shmem.hugepages -sys.virtual.mem.nr.shmem.pmdmapped -sys.virtual.mem.nr.unreclaimable.pages -sys.virtual.mem.nr.zone.active.anon -sys.virtual.mem.nr.zone.active.file -ys.virtual.mem.nr.zone.inactive_anon -sys.virtual.mem.nr.zone.inactive_file -sys.virtual.mem.nr.zone.unevictable -sys.virtual.mem.nr.zone.write_pending -sys.virtual.mem.oom.kill -sys.virtual.mem.pglazyfree -sys.virtual.mem.pglazyfreed -sys.virtual.mem.pgrefill -sys.virtual.mem.pgscan.direct -sys.virtual.mem.pgscan.kswapd -sys.virtual.mem.pgskip.dma -sys.virtual.mem.pgskip.movable -sys.virtual.mem.pgskip.normal -sys.virtual.mem.pgsteal.direct -sys.virtual.mem.pgsteal.kswapd -sys.virtual.mem.swap.ra -sys.virtual.mem.swap.ra.hit +在通用操作系统中,进程号(pid/tgid)和线程号(tid)可能会被重复用于标识不同的进程或者线程。所以在trace数据源中,进程号(pid)和线程号(tid)也可能被重用。 +TraceStreamer在解析数据过程中,使用ipid(internal pid)唯一标识进程, itid(internal tid)唯一标识线程。 ``` +### 计量器 +用来记录系统中各种随时间连续变化的数值。例如: CPU的频率, 内存的使用量, 界面刷新频率。 +#### 举例 +CPU频率: +![GitHub Logo](./figures/cpu_frequency.png) +内存占用: +![GitHub Logo](./figures/mem_usage.png) -## trace_streamer开发环境搭建和编译运行指引 +### 过滤器 +TraceStreamer设计过程中使用了流式处理的思想,数据从入口进入以后,就像进入一条河流,从上游流向下游,在河道中央有很多过滤器,每种过滤器会将流过的数据中自己关注的内容吸附捕捉到。最终,每个过滤器都拥有了大量同类型的数据,而且这些数据都是按时间序列排列的。TraceStreamer使用filterid来标识同一种用途的数据,可以方便在UI中绘制。 +![GitHub Logo](./figures/filters.png) -本应用使用gn作为构建工具,支持在linux环境同时编译linux,windows和mac使用QtCreator作为开发IDE -### 1、开发环境 -ubuntu使用vscode,windows和mac使用QtCreator -# 对外部的依赖 -本应用依赖与sqlite,protobuf(htrace解析部分依赖) +## Stat表设计 +具体内容参见 [des_stat](../doc/des_stat.md) +## TraceStreamer开发环境搭建和编译运行指引 -本应用同时依赖于src/protos目录下文件来生成相关pb.h,pb.cc文件 +本应用使用gn作为构建工具。 +### 开发环境 +可以在ubuntu、mac、windows下执行开发和编译,建议使用vscode开发工具。 +在windows平台上,需使用支持c++17标准的clang编译器。 +# 对外部的依赖 +本应用依赖与sqlite、protobuf(htrace解析部分依赖)、nlohmann_json。 +本应用同时依赖于src/protos/protogen.sh目录下文件来生成相关pb.h,pb.cc文件 +_____ -### 2.1、 编译linux版应用 -在根目录下执行相关命令进行编译 +### 编译linux和Mac应用 +在目录下有build.sh脚本,在不同的平台上会判断系统版本,编译相应系统的应用 +``` +./build.sh linux +./build.sh macx +``` -### 2.2、编译Windows版和Mac应用 -在项目目录下有pro文件,为QtCreator的工程文件,但部分内容赖在于上面所添加的外部依赖,如果要编译相关平台应用,开发者需自行补充相关工程文件,或者在论坛留言 +### 编译wasm +``` +./build.sh wasm +``` -### 2.3、开始编译 -具体方法可参考《compile_trace_streamer.md》 \ No newline at end of file +### 开始编译 +本工具建议独立编译, 通过部署第三方依赖库,emsdk,可编译出支持不同平台的应用。 +具体方法可参考[compile_trace_streamer](./doc/compile_trace_streamer.md)。 \ No newline at end of file diff --git a/host/trace_streamer/build.sh b/host/trace_streamer/build.sh old mode 100644 new mode 100755 index 9e183eeac90d0bd477bbe47f73d14a24b5a55d3c..87911841b8731a2753a0ac5ecedf6851ded79622 --- a/host/trace_streamer/build.sh +++ b/host/trace_streamer/build.sh @@ -1,4 +1,4 @@ -#! /bin/bash +#!/bin/bash # 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. @@ -11,18 +11,44 @@ # 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. +set -e PARAMS=$* echo $PARAMS echo "begin to check input" target_os='linux' +target_dir='linux' +gn_path='linux' is_debug='false' is_clean='false' +target='trace_streamer' +gn='gn' +ninja='ninja' +case "$OSTYPE" in + solaris*) echo "SOLARIS" ;; + darwin*) gn_path='macx' target_os='macx' ;; + linux*) gn_path='linux' target_os='linux' ;; + bsd*) echo "is bsd os" ;; + msys*) gn_path='windows' target_os='windows' gn='gn.exe' ninja='ninja.exe' ;; + *) echo "unknown: $OSTYPE" ;; +esac +usage="Usage: $basename $0 wasm/test/fuzz/protoc debug/release/clean" + + +if [ "$1" == 'windows' ];then + echo "gn only support linux and wasm build currently" + if [ ! -d "out/windows" ];then + mkdir out/windows + fi + touch out/windows/trace_streamer.exe + exit +fi + if [ "$#" -ne "0" ];then - if [ $1 == "wasm" ];then + if [ "$1" == "wasm" ];then if [ ! -d "prebuilts/emsdk" ];then echo "you need emsdk to compile wasm" - mv emsdk.tar.gz prebuilts/ - mv ../emsdk.tar.gz prebuilts/ + #mv emsdk.tar.gz prebuilts/ + #mv ../emsdk.tar.gz prebuilts/ if [ ! -f "prebuilts/emsdk.tar.gz" ];then # consider # you need to get emsdk.tar.gz some where @@ -32,44 +58,59 @@ if [ "$#" -ne "0" ];then tar -zxvf prebuilts/emsdk.tar.gz -C prebuilts/ fi fi - target_os='wasm' + target='wasm' + fi + if [ "$1" == "test" ];then + target='test' fi - if [ $1 == "test" ];then - target_os='test' + if [ "$1" == "fuzz" ];then + target='fuzz' fi + if [ "$1" == "protoc" ];then + target='protoc' + fi + if [ "$1" == "sdkdemo" ];then + target='sdkdemo' + fi + if [ "$1" == "sdkdemotest" ];then + target='sdkdemotest' + fi +fi +if [ $target == "wasm" ] && [ $target_os == "windows" ];then + echo "!!!build wasm on winows will occur unknown error, strongly suggest you build wasm on linux(Ubuntu)" + exit fi if [ "$#" -eq "2" ];then - if [ "$1" != 'windows' ] && [ $1 != "linux" ] && [ $1 != "wasm" ] && [ $1 != "test" ];then + if [ "$1" != 'trace' ] && [ "$1" != "linux" ] && [ "$1" != "windows" ] && [ "$1" != "macx" ] && [ "$1" != "trace_streamer" ] && [ "$1" != "wasm" ] && [ "$1" != "test" ] && [ "$1" != "fuzz" ] && [ "$1" != "protoc" ];then echo "failed" - echo "Usage: `basename $0` windows/linux/wasm/test debug/release/clean" + echo "$usage" exit fi - if [ $2 != "debug" -a $2 != "release" -a $2 != "clean" ];then + if [ "$2" != "debug" -a "$2" != "release" -a "$2" != "clean" ];then + if [ "$2" == "protoc" ];then + target="$2" + else echo "failed" - echo "Usage: `basename $0` windows/linux debug/release/clean" + echo "$usage" exit fi - if [ $2 == "debug" ];then + fi + if [ "$2" == "debug" ];then is_debug='true' - elif [ $2 == "clean" ];then + elif [ "$2" == "clean" ];then is_clean='true' else is_debug='false' fi - target_os=$1 - if [ $target_os == "windows" ];then - echo "gn only support linux and wasm build currently" - mkdir out/windows - touch out/windows/trace_streamer.exe - exit - fi echo "platform is $target_os" echo "isdebug: $is_debug" + echo "isclean: $is_clean" else - echo "Usage: `basename $0` windows/linux/wasm debug/release wasm[optional]" + echo "$usage" echo "You provided $# parameters,but 2 are required." echo "use default input paramter" echo "platform is $target_os" + echo "target is $target" echo "is_debug:$is_debug" fi echo "gen ..." @@ -86,34 +127,50 @@ echo "" echo "if you are compiling first time, or your proto has changed, you need to run ./src/protos/protogen.sh" echo "" echo "" -echo +echo #./src/protos/protogen.sh -mkdir prebuilts/$target_os -if [ ! -f "prebuilts/$target_os/gn" ];then +if [ ! -d "prebuilts/$gn_path" ];then + mkdir prebuilts/$gn_path +fi +if [ ! -f "prebuilts/$gn_path/gn" ];then echo "you may get gn for $target_os and place it in prebuilts/$target_os" - ehco "the file can be get at https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/gn, you need to download it manually" - #wget https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/gn + echo "the file can be get at https://gitee.com/su_ze1688/public_tools/raw/master/gn/$target_os/gn, you need to download it manually" + #wget https://gitee.com/su_ze1688/public_tools/raw/master/gn/$target_os/gn #mv gn prebuilts/$target_os/ #chmod +x prebuilts/$target_os/gn exit fi -if [ ! -f "prebuilts/$target_os/ninja" ];then +if [ ! -f "prebuilts/$gn_path/ninja" ];then echo "you may get ninja for $target_os and place it in prebuilts/$target_os" - ehco "the file can be get at https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/ninja, you need to download it manually" - #wget "https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/ninja" - #wget https://gitee.com/su_fu/public_tools/raw/master/gn/$target_os/ninja + ehco "the file can be get at https://gitee.com/su_ze1688/public_tools/raw/master/gn/$target_os/ninja, you need to download it manually" + #wget "https://gitee.com/su_ze1688/public_tools/raw/master/gn/$target_os/ninja" + #wget https://gitee.com/su_ze1688/public_tools/raw/master/gn/$target_os/ninja #mv ninja prebuilts/$target_os/ #chmod +x prebuilts/$target_os/* exit fi echo "$is_clean" +if [ $target == 'test' ] || [ $target == 'fuzz' ] || [ $target='wasm' ] || [ $target='sdkdemo' ] || [ $target='sdkdemotest' ];then + target_dir=$target +else + target_dir=$target_os +fi +if [ $target == 'trace_streamer' ] || [ $target == 'trace' ];then + target_dir=$target_os +fi +echo "target_dir:" $target_dir +# exit if [ "$is_clean" == 'true' ];then - prebuilts/$target_os/gn gen out/"$target_os""$ext" --clean - prebuilts/$target_os/ninja -C out/"$target_os""$ext" -t clean + prebuilts/$gn_path/$gn gen out/"$target_dir""$ext" --clean + prebuilts/$gn_path/$ninja -C out/"$target_dir""$ext" -t clean else - prebuilts/$target_os/gn gen out/"$target_os""$ext" --args='is_debug='"$is_debug"' target_os="'"$target_os"'"' + prebuilts/$gn_path/$gn gen out/"$target_dir""$ext" --args='is_debug='"$is_debug"' target="'"$target"'" target_os="'"$target_os"'"' echo "begin to build ..." mkdir -p out/windows touch out/windows/trace_streamer.exe - prebuilts/$target_os/ninja -v -C out/"$target_os""$ext" + prebuilts/$gn_path/$ninja -C out/"$target_dir""$ext" + if [ $target_dir == 'protoc' ];then + mv out/"$target_dir""$ext"/$target_dir out/$target_os/ + fi + # prebuilts/$gn_path/ninja -C out/"$target_os""$ext" fi diff --git a/host/trace_streamer/build/test.gni b/host/trace_streamer/build/test.gni index 6912354f710b31f32341dfbd16e51f3d78cef2be..8bdf099d0885508f019e08b7d705a0acd5ea229e 100644 --- a/host/trace_streamer/build/test.gni +++ b/host/trace_streamer/build/test.gni @@ -21,5 +21,28 @@ template("ohos_unittest") { if (defined(invoker.ldflags)) { print(invoker.ldflags) } + if (defined(invoker.cflags)) { + print(invoker.cflags) + cflags += invoker.cflags + } + } +} + +template("ohos_fuzztest") { + executable(target_name) { + forward_variables_from(invoker, "*") + testonly = true + deps = [] + if (defined(invoker.deps)) { + deps += invoker.deps + } + if (defined(invoker.cflags)) { + cflags += invoker.cflags + } + ldflags += [ "-fsanitize=fuzzer" ] + cflags += [ + "-fno-sanitize-coverage=trace-pc-guard,edge,trace-cmp,indirect-calls,8bit-counters", + "-fsanitize=fuzzer", + ] } } diff --git a/host/trace_streamer/doc/README.md b/host/trace_streamer/doc/README.md index eb0deec07b8f4c55fed4152454f49cad6d721cb9..0e4093eef3b2d8f65ccf69e1eacacc5db6bf9027 100644 --- a/host/trace_streamer/doc/README.md +++ b/host/trace_streamer/doc/README.md @@ -1,309 +1,167 @@ -# trace_streamer工具说明 -trace_streamer工具可以2种方式使用 +# TraceStreamer工具说明 +TraceStreamer是一个trace数据解析程序,可以将一个trace文本文件或者基于proto序列化的二进制文件转换成为sqlite数据库的形式。 TraceStreamer使用C++实现,支持在ohos, linux, mac等系统上使用,具有良好的跨平台特性。 +![GitHub Logo](../figures/trace_streamer_stream.png) +## 关于TraceStreamer的使用说明 +TraceStreamer工具可以2种方式使用 1. 可以将系统离线trace文件解析并转为db,此工具支持基于文本的trace和基于proto的trace。 -2. trace_streamer工具还可以WebAssembly的方式在浏览器中运行,需暴露相关接口给js文件。 - -## 关于trace解析工具的使用说明: +2. TraceStreamer工具还可以WebAssembly的方式在浏览器中运行,提供相关接口给js文件调用。 + ### 导出db模式 -在导出db模式下,trace_streamer.exe trace文件路径名 -e 导出db路径名.db -此命令可以将trace文件转为db -本应用支持在ohos, linux, windows, mac使用。 -关于db文件的说明: -使用db查看工具查看stat表,可以浏览当前数据一共有多少类数据,各类数据都收到多少条,数据是否正常等情况。在meta表会记录数据库导出时的一些系统信息,比如导入和导出的文件全路径,解析时间等信息。 -meta表可以选择不导出(有些情况下会暴露系统敏感信息),在导出时添加 -nm选项即可。 -在数据导出之后,会在本地目录下生成一个trace_streamer.log文件,在导出db的目录下生成一个数据库文件同名,.db.ohos.ts后缀的文件 -文件内容如下: -时间戳:执行结果(数字) -应用运行时间 +在导出db模式下,通过下面的指令: +``` +./trace_streamer trace文件路径名 -e 导出db路径名.db +``` +可以将trace文件转为db文件。 +本应用支持在ohos, linux, mac使用。 +在数据导出之后,会在本地目录下生成一个trace_streamer.log文件,在导出db的目录下生成一个数据库文件同名,.db.ohos.ts后缀的文件。 +文件内容如下: +``` +当前时间戳:执行结果(数字) +应用运行时间 +``` +执行结果解释如下: +``` +0 代表执行成功 1 表示输入文件不匹配, 2 表示解析错误, 3其他错误。 +``` +#### __关于db文件的说明__ +可以使用sqliteexport或DB Browser for SQLite工具加载生成的db,通过查看stat表,可以浏览当前数据一共有多少类数据,各类数据都收到多少条,数据是否正常等情况。在meta表会记录数据库导出时的一些系统信息,比如导入和导出的文件全路径,解析时间等信息。 +meta表可以选择不导出,在导出时添加 -nm选项即可。 +更多db文件的介绍,可以参考[des_tables.md](des_tables.md)。 -执行结果解释如下:0 代表执行成功 1 表示输入文件不匹配, 2 表示解析错误, 3其他错误 -### 内置浏览器方式 -trace_streamer可以WebAssembly方式在浏览器中运行,暴露如下接口给js +### 内置浏览器模式 +TraceStreamer可以WebAssembly方式在浏览器中运行,相关接口在wasm模式下生成的trace_streamer_builtin.js文件中,js可以使用的接口如下使用如下接口访问trace_streamer: ``` extern "C" { -/* 上传trace数据 +/* 初始化wasm,在JS中注册回调函数,并返回一段可复用的内存空间,由JS调用 * - * @data: 数据的缓冲区 - * @dataLen: 数据长度 + * @ replyFunction: 回调函数 +* @ reqBufferSize: 返回的内存长度 +* return: 返回一段内存地址给JS +*/ +EMSCRIPTEN_KEEPALIVE uint8_t* Initialize(ReplyFunction replyFunction, uint32_t reqBufferSize) + +/* 更新起始结束时间,由JS调用 + * + * @ len: 起始和结束时间组成的字符串长度 +* return: 成功返回0。 +*/ +EMSCRIPTEN_KEEPALIVE int UpdateTraceTime(int len) + +/* 设置TraceStreamer和第三方wasm通信的回调函数,并返回一段内存,由JS调用 * - * return: 0:成功; -1:失败 + * @ sendDataCallBack:与第三方wasm通信的回调函数 +* @ reqBufferSize: 返回的内存长度 +* return: 成功返回0 */ -EMSCRIPTEN_KEEPALIVE int TraceStreamerParseData(const uint8_t* data, int dataLen); +EMSCRIPTEN_KEEPALIVE uint8_t* TraceStreamer_Set_ThirdParty_DataDealer(SendDataCallBack sendDataCallBack, uint32_t reqBufferSize) -/* 通知TS上传trace数据结束 - * - * return: 0:成功; -1:失败 +/* TraceStreamer的数据解析接口,由JS调用 + * +* @ dataLen: 需要解析的数据源长度 +* return: 成功返回0,失败返回-1 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataEx(int dataLen) + +/* TraceStreamer停止解析数据,由JS调用 + * +* return: 成功返回0,失败返回-1 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver() + +/* 数据库操作接口,由JS调用 + * +* @ sqlLen: 需要执行的操作类sql语句长度 +* return: 成功返回0,失败返回-1 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperateEx(int sqlLen) + +/*清空wasm内存中的内容,由JS调用 + * +* return: 成功返回0,失败返回-1 */ -EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver(); +EMSCRIPTEN_KEEPALIVE int TraceStreamerReset() -/* 通过sql语句操作数据库 +/*执行查询类sql语句,由JS调用 * - * @sql: sql语句 - * @sqlLen: sql语句长度 +* @ sqlLen: 需要执行的查询类sql语句长度 +* return: 成功返回0,失败返回-1 +*/ +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQueryEx(int sqlLen) + +/*取消sql查询,由JS调用。 * - * return: 0:成功; -1:失败 +* return: 成功返回0。 */ -EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen); +EMSCRIPTEN_KEEPALIVE int TraceStreamerCancel() -/* 通过sql语句查询数据库 +/*发送数据给第三方wasm解析,由TraceStreamer调用 * - * @sql: sql语句 - * @sqlLen: sql语句长度 - * @out: 查询结果的缓冲区,查询结果为json - * @outLen: 缓冲区长度 +* @ pluginData: 第三方插件的数据源 +* @ len: 数据源长度 +* @ componentName: 第三方插件名称 +* return: 成功返回0 +*/ +int TraceStreamer_Plugin_Out_SendData(const char* pluginData, int len, const std::string componentName) + +/* 初始化配置接口,由JS调用 * - * return: >0:查询成功,返回查询结果数据长度; -1:失败 +* @ dataLen: 配置字符串的长度 +* return: 成功返回0 */ -EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, uint8_t* out, int outLen); +EMSCRIPTEN_KEEPALIVE int TraceStreamer_Init_ThirdParty_Config(int dataLen) } // extern "C" ``` - ### 你也可以执行如下命令查看应用帮助 -./trace_streamer --help --i 选项可查看应用支持的事件源和具体的事件名列表 +```./trace_streamer --help``` -#### trace_streamer支持的事件解析 -本工具支持基于文本的trace(# TRACE)和基于proto的二进制日志文件的解析,支持的事件列表如下: -##### ftrace事件 -``` -binder_transaction -binder_transaction_received -binder_transaction_alloc_buf -binder_transaction_lock -binder_transaction_locked -binder_transaction_unlock -sched_switch -task_rename -task_newtask -tracing_mark_write -print -sched_wakeup -sched_waking -cpu_idle -cpu_frequency -suspend_resume -workqueue_execute_start -workqueue_execute_end -clock_set_rate -clock_enable -clock_disable -clk_set_rate -clk_enable -clk_disable -sys_enter -sys_exit -regulator_set_voltage -regulator_set_voltage_complete -regulator_disable -regulator_disable_complete -ipi_entry -ipi_exit -irq_handler_entry -irq_handler_exit -softirq_raise -softirq_entry -softirq_exit -sched_wakeup_new -sched_process_exit -trace_event_clock_sync -``` -##### 内存事件 -``` -mem.vm.size -mem.rss -mem.rss.anon -mem.rss.file -mem.rss.schem -mem.swap -mem.locked -mem.hwm -mem.oom_score_adj -``` -##### 系统内存事件 -``` -sys.mem.unspecified -sys.mem.total -sys.mem.free -sys.mem.avaiable -sys.mem.buffers -sys.mem.cached -sys.mem.swap.chard -sys.mem.active -sys.mem.inactive -sys.mem.active.anon -sys.mem.inactive.anon -sys.mem.active_file -sys.mem.inactive_file -sys.mem.unevictable -sys.mem.mlocked -sys.mem.swap.total -sys.mem.swap.free -sys.mem.dirty -sys.mem.writeback -sys.mem.anon.pages -sys.mem.mapped -sys.mem.shmem -sys.mem.slab -sys.mem.slab.reclaimable -sys.mem.slab.unreclaimable -sys.mem.kernel.stack -sys.mem.page.tables -sys.mem.commit.limit -sys.mem.commited.as -sys.mem.vmalloc.total -sys.mem.vmalloc.used -sys.mem.vmalloc.chunk -sys.mem.cma.total -sys.mem.cma.free -``` -##### 系统虚拟内存事件 -``` -sys.virtual.mem.unspecified -sys.virtual.mem.nr.free.pages -sys.virtual.mem.nr.alloc.batch -sys.virtual.mem.nr.inactive.anon -sys.virtual.mem.nr.active_anon -sys.virtual.mem.nr.inactive.file -sys.virtual.mem.nr.active_file -sys.virtual.mem.nr.unevictable -sys.virtual.mem.nr.mlock -sys.virtual.mem.anon.pages -sys.virtual.mem.nr.mapped -sys.virtual.mem.nr.file.pages -sys.virtual.mem.nr.dirty -sys.virtual.mem.nr.writeback -sys.virtual.mem.nr.slab.reclaimable -sys.virtual.mem.nr.slab.unreclaimable -sys.virtual.mem.nr.page_table.pages -sys.virtual.mem.nr_kernel.stack -sys.virtual.mem.nr.overhead -sys.virtual.mem.nr.unstable -sys.virtual.mem.nr.bounce -sys.virtual.mem.nr.vmscan.write -sys.virtual.mem.nr.vmscan.immediate.reclaim -sys.virtual.mem.nr.writeback_temp -sys.virtual.mem.nr.isolated_anon -sys.virtual.mem.nr.isolated_file -sys.virtual.mem.nr.shmem -sys.virtual.mem.nr.dirtied -sys.virtual.mem.nr.written -sys.virtual.mem.nr.pages.scanned -sys.virtual.mem.workingset.refault -sys.virtual.mem.workingset.activate -sys.virtual.mem.workingset_nodereclaim -sys.virtual.mem.nr_anon.transparent.hugepages -sys.virtual.mem.nr.free_cma -sys.virtual.mem.nr.swapcache -sys.virtual.mem.nr.dirty.threshold -sys.virtual.mem.nr.dirty.background.threshold -sys.virtual.mem.vmeminfo.pgpgin -sys.virtual.mem.pgpgout -sys.virtual.mem.pgpgoutclean -sys.virtual.mem.pswpin -sys.virtual.mem.pswpout -sys.virtual.mem.pgalloc.dma -sys.virtual.mem.pgalloc.normal -sys.virtual.mem.pgalloc.movable -sys.virtual.mem.pgfree -sys.virtual.mem.pgactivate -sys.virtual.mem.pgdeactivate -sys.virtual.mem.pgfault -sys.virtual.mem.pgmajfault -sys.virtual.mem.pgrefill.dma -sys.virtual.mem.pgrefill.normal -sys.virtual.mem.pgrefill.movable -sys.virtual.mem.pgsteal.kswapd.dma -sys.virtual.mem.pgsteal.kswapd.normal -sys.virtual.mem.pgsteal.kswapd.movable -sys.virtual.mem.pgsteal.direct.dma -sys.virtual.mem.pgsteal.direct.normal -sys.virtual.mem.pgsteal_direct.movable -sys.virtual.mem.pgscan.kswapd.dma -sys.virtual.mem.pgscan_kswapd.normal -sys.virtual.mem.pgscan.kswapd.movable -sys.virtual.mem.pgscan.direct.dma -sys.virtual.mem.pgscan.direct.normal -sys.virtual.mem.pgscan.direct.movable -sys.virtual.mem.pgscan.direct.throttle -sys.virtual.mem.pginodesteal -sys.virtual.mem.slabs_scanned -sys.virtual.mem.kswapd.inodesteal -sys.virtual.mem.kswapd.low.wmark.hit.quickly -sys.virtual.mem.high.wmark.hit.quickly -sys.virtual.mem.pageoutrun -sys.virtual.mem.allocstall -sys.virtual.mem.pgrotated -sys.virtual.mem.drop.pagecache -sys.virtual.mem.drop.slab -sys.virtual.mem.pgmigrate.success -sys.virtual.mem.pgmigrate.fail -sys.virtual.mem.compact.migrate.scanned -sys.virtual.mem.compact.free.scanned -sys.virtual.mem.compact.isolated -sys.virtual.mem.compact.stall -sys.virtual.mem.compact.fail -sys.virtual.mem.compact.success -sys.virtual.mem.compact.daemon.wake -sys.virtual.mem.unevictable.pgs.culled -sys.virtual.mem.unevictable.pgs.scanned -sys.virtual.mem.unevictable.pgs.rescued -sys.virtual.mem.unevictable.pgs.mlocked -sys.virtual.mem.unevictable.pgs.munlocked -sys.virtual.mem.unevictable.pgs.cleared -sys.virtual.mem.unevictable.pgs.stranded -sys.virtual.mem.nr.zspages -sys.virtual.mem.nr.ion.heap -sys.virtual.mem.nr.gpu.heap -sys.virtual.mem.allocstall.dma -sys.virtual.mem.allocstall.movable -sys.virtual.mem.allocstall.normal -sys.virtual.mem.compact_daemon.free.scanned -sys.virtual.mem.compact.daemon.migrate.scanned -sys.virtual.mem.nr.fastrpc -sys.virtual.mem.nr.indirectly.reclaimable -sys.virtual.mem.nr_ion_heap_pool -sys.virtual.mem.nr.kernel_misc.reclaimable -sys.virtual.mem.nr.shadow_call.stack_bytes -sys.virtual.mem.nr.shmem.hugepages -sys.virtual.mem.nr.shmem.pmdmapped -sys.virtual.mem.nr.unreclaimable.pages -sys.virtual.mem.nr.zone.active.anon -sys.virtual.mem.nr.zone.active.file -ys.virtual.mem.nr.zone.inactive_anon -sys.virtual.mem.nr.zone.inactive_file -sys.virtual.mem.nr.zone.unevictable -sys.virtual.mem.nr.zone.write_pending -sys.virtual.mem.oom.kill -sys.virtual.mem.pglazyfree -sys.virtual.mem.pglazyfreed -sys.virtual.mem.pgrefill -sys.virtual.mem.pgscan.direct -sys.virtual.mem.pgscan.kswapd -sys.virtual.mem.pgskip.dma -sys.virtual.mem.pgskip.movable -sys.virtual.mem.pgskip.normal -sys.virtual.mem.pgsteal.direct -sys.virtual.mem.pgsteal.kswapd -sys.virtual.mem.swap.ra -sys.virtual.mem.swap.ra.hit -``` +### TraceStreamer支持解析的事件列表 +通过```./trace_streamer -i``` +查看支持的事件列表。 +支持的事件列表参见[SupportEventList.md](des_support_event.md)。 -## trace_streamer开发环境搭建和编译运行指引 +## TraceStreamer重要概念介绍 +### 进程和线程标识符 +在通用操作系统中,进程号(pid/tgid)和线程号(tid)可能会被重复用于标识不同的进程或者线程。所以在trace数据源中,进程号(pid)和线程号(tid)也可能被重用。 +TraceStreamer在解析数据过程中,使用ipid(internal pid)唯一标识进程, itid(internal tid)唯一标识线程。 -本应用使用gn作为构建工具,支持在linux环境同时编译linux,windows和mac使用QtCreator作为开发IDE -### 1、开发环境 -ubuntu使用vscode,windows和mac使用QtCreator -# 对外部的依赖 -本应用依赖与sqlite,protobuf(htrace解析部分依赖) +### 计量器 +用来记录系统中各种随时间连续变化的数值。例如: CPU的频率, 内存的使用量, 界面刷新频率。 +#### 举例 +CPU频率: +![GitHub Logo](../figures/cpu_frequency.png) +内存占用: +![GitHub Logo](../figures/mem_usage.png) + +### 过滤器 +TraceStreamer设计过程中使用了流式处理的思想,数据从入口进入以后,就像进入一条河流,从上游流向下游,在河道中央有很多过滤器,每种过滤器会将流过的数据中自己关注的内容吸附捕捉到。最终,每个过滤器都拥有了大量同类型的数据,而且这些数据都是按时间序列排列的。TraceStreamer使用filterid来标识同一种用途的数据,可以方便在UI中绘制。 +![GitHub Logo](../figures/filters.png) + +## Stat表设计 +具体内容参见 [des_stat](des_stat.md) +## TraceStreamer开发环境搭建和编译运行指引 -本应用同时依赖于src/protos目录下文件来生成相关pb.h,pb.cc文件 +本应用使用gn作为构建工具。 +### 开发环境 +可以在ubuntu、mac、windows下执行开发和编译,建议使用vscode开发工具。 +在windows平台上,需使用支持c++17标准的clang编译器。 +# 对外部的依赖 +本应用依赖与sqlite、protobuf(htrace解析部分依赖)、nlohmann_json。 +本应用同时依赖于src/protos/protogen.sh目录下文件来生成相关pb.h,pb.cc文件 +_____ -### 2.1、 编译linux版应用 -在根目录下执行相关命令进行编译 +### 编译linux和Mac应用 +在目录下有build.sh脚本,在不同的平台上会判断系统版本,编译相应系统的应用 +``` +./build.sh linux +./build.sh macx +``` -### 2.2、编译Windows版和Mac应用 -在项目目录下有pro文件,为QtCreator的工程文件,但部分内容赖在于上面所添加的外部依赖,如果要编译相关平台应用,开发者需自行补充相关工程文件,或者在论坛留言 +### 编译wasm +``` +./build.sh wasm +``` -### 2.3、开始编译 -具体方法可参考《compile_trace_streamer.md》 \ No newline at end of file +### 开始编译 +本工具建议独立编译, 通过部署第三方依赖库,emsdk,可编译出支持不同平台的应用。 +具体方法可参考[compile_trace_streamer](compile_trace_streamer.md)。 \ No newline at end of file diff --git a/host/trace_streamer/doc/compile_trace_streamer.md b/host/trace_streamer/doc/compile_trace_streamer.md new file mode 100755 index 0000000000000000000000000000000000000000..b86f4aca6c41e5e2c8a4b2792c08e8b073df9116 --- /dev/null +++ b/host/trace_streamer/doc/compile_trace_streamer.md @@ -0,0 +1,195 @@ +# 如何独立编译TraceStreamer +尽管TraceStreamer是在ohos工具箱中的一员,但您依然可以独立编译此工具。 + +TraceStreamer可以编译为命令行下的可执行程序,或者WebAssembly程序。 + +本工具默认编译方式是使用gn。 +## 编译步骤 +### 处理第三方库 +处理第三方库,您可以使用pare_third_party.sh文件来下载第三方库并做适当的处理,您需要在码云上添加您的ssh公钥,也可以按下面的步骤。 +如果pare_third_party.sh脚本出现问题,您需要按如下的步骤做检查。 +因为需要同时支持pc和WebAssembly环境,TraceStreamer构造了一个独立编译编译的环境,需对第三方库的gn脚本做适当的修改,可按下面的步骤进行。 +third_party相关控件下载链接:https://gitee.com/organizations/openharmony/projects +在TraceStreamer的src同级目录下创建third_party目录。 +下面依次处理各个第三方库。 +#### sqlite +1. 在第三方库中,找到并下载sqlite组件(ssh clone git@gitee.com:openharmony/third_party_sqlite.git); +2. 把下载的文件解压后,文件夹命名为sqlite放入到third_party目录中; +3. 使用下面的命令,把sqlite的BUILD.gn修改为TraceStreamer适用的风格。 +``` +patch -p0 third_party/sqlite/BUILD.gn prebuilts/patch_sqlite/sqlite3build.gn.patch +``` +#### protobuf +1. 在第三方库中,找到并下载protobuf组件(git clone git@gitee.com:openharmony/third_party_protobuf.git); +2. 把下载的文件解压后,文件夹命名为protobuf,放入到third_party目录中; +3. 使用下面的命令,把protobuf的BUILD.gn修改为TraceStreamer适用的风格。 +``` +patch -p0 third_party/protobuf/BUILD.gn prebuilts/patch_protobuf/protobufbuild.gn.patch +``` +#### googletest +1. 在第三方库中,找到并下载googletest组件(git clone git@gitee.com:openharmony/third_party_googletest.git); +2. 把googletest文件夹放入third_party目录中; +3. 使用下面的命令,把googletest的BUILD.gn修改为TraceStreamer适用的风格。 +``` +patch -p0 third_party/googletest/BUILD.gn prebuilts/patch_googletest/googletestbuild.gn.patch +``` +4. 处理一系列public权限问题,处理原则是,但凡是有问题头文件的上下添加 +``` +#undef private +#define private private +#include // 加入这里是编译有问题的头文件 +#undef private +#define private public +``` +目前已知的需处理的地方有 +``` +gtest-message.h文件 ++#undef private ++#define private private + #include +- ++#undef private ++#define private public + +gtest.h文件 +- ++#undef private ++#define private private + #include "gtest/internal/gtest-internal.h" ++#undef private ++#define private public + + gtest-tag.h文件 + 第13行注释即可 +### nlohmann_json +gtest-internal.h ++#undef private ++#define private private + #include ++#undef private ++#define private public + +gtest-port.h文件 ++#undef private ++#define private private +#include // NOLINT ++#undef private ++#define private public +``` +#### json库 +1. 在第三方库中,找到并下载third_party_json库(git clone git@gitee.com:openharmony/third_party_json.git); +2. 把下载的文件解压后,文件夹命名为json-master,放入到third_party目录中。 + +#### libunwind +1. 在第三方库中,找到并下载libunwind组件(git clone git@gitee.com:openharmony/third_party_libunwind.git); +2. 把libunwind文件夹放入third_party目录中; +3. 使用下面的命令,把libunwind的BUILD.gn修改为TraceStreamer适用的风格。 +``` +patch -p0 third_party/libunwind/BUILD.gn prebuilts/patch_libunwind/libunwindbuild.gn.patch +``` +third_party/libunwind/src/x86_64/unwind_i.h +第60行,注释 +``` +// #define setcontext UNW_ARCH_OBJ (setcontext) +``` +#### 其他文件 +为了独立编译trace_streamer,你还需要在third_party目录下有2个文件 +``` +third_party/perf_include/ +├── libbpf +│ └── linux +│ └── perf_event.h +└── musl + └── elf.h +``` +perf_event.h文件位于如下目录,需打补丁 +wget https://gitee.com/openharmony/third_party_libbpf/raw/master/include/uapi/linux/perf_event.h +patch -p0 perf_event.h prebuilts/patch_perf_event/perf_event.h.patch +elf.h文件来自于musl/include/elf.h 使用原始文件,不用打补丁 +wget https://gitee.com/openharmony/third_party_musl/raw/master/include/elf.h + +### 开始编译 +#### 预置条件 +1. 您需要先获取一个可用的protoc可执行文件,或者在linux平台上执行: +``` +./build.sh protoc +``` +来生成可用的protoc可执行的程序。 + +2. 生成proto相关文件对应的pb.h或pb.cc文件 +可执行如下脚本来完成: +``` +./src/protos/protogen.sh +``` +#### 编译linux、mac、windows平台的TraceStreamer +编译不同平台的程序,您需要在各自的PC环境编译,编译脚本会自行识别平台并编译程序。 +目前wasm版本仅支持在linux平台编译。 +编译不同版本:linux, windows, mac +注意,windows上目前支持Mingw编译,使用的mingw版本为 gcc version 8.1.0 (i686-posix-dwarf-rev0, Built by MinGW-W64 project) +``` +./build.sh +``` +特别地,如果您需要编译debug版本的应用,只需要输入debug标识即可,否则,默认是release版本的应用。 +``` +./build.sh linux debug +``` +生成的可执行文件分别位于如下路径: +``` +out/linux +out/windows +out/macx +out/linux_debug +``` +___在不同的平台上,均需要gn和ninja的可执行文件来执行gn工程相关的操作,比如,windows上是gn.exe和ninja.exe。 +在https://gitee.com/su_ze1688/public_tools/tree/master/gn目录下,您可以获取不同平台下可用的gn和ninja可执行文件,同时,为linux平台下提供了protoc可执行文件。您可以下载并部署在本地的prebuilts目录下。您也可以在linux平台下执行:___ +``` +./build.sh protoc +``` +___来生成out/linux/protoc可执行文件。___ +#### 编译WebAssembly版本 +如果需要编译WebAssembly版本,您需要在prebuilts/目录下安装emsdk。 +步骤如下: +1. 在任何目录下载emsdk +``` +git clone https://github.com/juj/emsdk.git --depth=1 +cd emsdk +git pull +./emsdk update # this may not work, ignore it +./emsdk install latest +./emsdk activate latest +``` +2. 部署emsdk到编译工具目录 +您将刚刚下载和安装的emsdk目录下的 upstream/* 复制到prebuilts/emsdk/emsdk,node/* 复制到prebuilts/emsdk/node。 +安装之后,目录结构当如下: +``` +prebuilts/emsdk +├── prebuilts/emsdk/emsdk +│ ├── prebuilts/emsdk/emsdk/bin +│ ├── prebuilts/emsdk/emsdk/emscripten +│ │ ├── prebuilts/emsdk/emsdk/emscripten/cache +│ │ ├── prebuilts/emsdk/emsdk/emscripten/cmake +│ │ ├── prebuilts/emsdk/emsdk/emscripten/docs +│ │ ├── prebuilts/emsdk/emsdk/emscripten/media +│ │ ├── prebuilts/emsdk/emsdk/emscripten/node_modules +│ │ ├── prebuilts/emsdk/emsdk/emscripten/__pycache__ +│ │ ├── prebuilts/emsdk/emsdk/emscripten/src +│ │ ├── prebuilts/emsdk/emsdk/emscripten/system +│ │ ├── prebuilts/emsdk/emsdk/emscripten/tests +│ │ ├── prebuilts/emsdk/emsdk/emscripten/third_party +│ │ └── prebuilts/emsdk/emsdk/emscripten/tools +│ ├── prebuilts/emsdk/emsdk/include +│ │ └── prebuilts/emsdk/emsdk/include/c++ +│ └── prebuilts/emsdk/emsdk/lib +│ └── prebuilts/emsdk/emsdk/lib/clang +└── prebuilts/emsdk/node + └── prebuilts/emsdk/node/14.18.2_64bit + ├── prebuilts/emsdk/node/14.18.2_64bit/bin + ├── prebuilts/emsdk/node/14.18.2_64bit/include + ├── prebuilts/emsdk/node/14.18.2_64bit/lib + └── prebuilts/emsdk/node/14.18.2_64bit/share +``` +之后,在TraceStream代码根目录,也就是这个文档的上级目录下执行: +``` +./build.sh wasm +``` +您需要将sh脚本进行部分修改,因为这个脚本内置了一些库的下载和解析方式,您也可以在您的编译环境对此脚本做定制修改。 \ No newline at end of file diff --git a/host/trace_streamer/doc/compiler_ut.md b/host/trace_streamer/doc/compiler_ut.md new file mode 100644 index 0000000000000000000000000000000000000000..2c2accf3f9170f1406c80d182487d14e1278124c --- /dev/null +++ b/host/trace_streamer/doc/compiler_ut.md @@ -0,0 +1,27 @@ +# 编译UT +直接运行./build.sh test 即可编译ut代码,编译ut时,可能会遇到一些问题,需要将部分代码做如下处理: +v412.pb.h 大约第36行,添加如下内容 +``` +#ifdef major +#undef major +#endif +#ifdef minor +#undef minor +#endif +``` +gtest-port.h 第286行,在 +``` +#include +``` +修改为 +``` +#undef private +#define private private +#include +#undef private +#define private public +``` + +在ut代码编译完成之后,直接运行./test.sh,可以执行所有ut,显示正确与否。 +在ut执行之后,直接运行./lcov.sh,可以生成覆盖率报告。 +覆盖率报告位于out/test/html目录。 \ No newline at end of file diff --git a/host/trace_streamer/doc/des_binder.md b/host/trace_streamer/doc/des_binder.md new file mode 100644 index 0000000000000000000000000000000000000000..7af5fc8a159ce548f6b9d7d95dad4093ce5a265f --- /dev/null +++ b/host/trace_streamer/doc/des_binder.md @@ -0,0 +1,62 @@ +# binder事件上下文如何关联 +binder事件相对复杂,这里是从ftrace事件中抽离出来的binder相关消息,用来作为开发者或用户追踪binder事件的参考 +a binder event is identified by the sender and receive device, and a reply message only end +the last binder msg which reply the calling one. +the alloc_buf msg can always flow the binder_transaction, so we no need to identify the alloc msg with transactionID + +## TAG TT need reply!!! needReply = !isReply && !(flags & 0x01); +``` +RenderThread-2267 ( 1592) [003] ...1 168766.128108: binder_transaction: transaction=25155526 dest_node=25155471 dest_proc=506 dest_thread=0 reply=0 flags=0x10 code=0x9 +RenderThread-2267 ( 1592) [003] ...1 168766.128110: binder_transaction_alloc_buf: transaction=25155526 data_size=120 offsets_size=8 +``` +### received +``` +Binder:506_2-537 ( 506) [003] ...1 168766.128154: binder_transaction_received: transaction=25155526 +``` +### binder is in DB, TAG A needReply +``` +Binder:506_2-537 ( 506) [003] ...1 168766.128221: binder_transaction: transaction=25155529 dest_node=25155527 dest_proc=1592 dest_thread=2267 reply=0 flags=0x10 code=0x5f474854 +Binder:506_2-537 ( 506) [003] ...1 168766.128223: binder_transaction_alloc_buf: transaction=25155529 data_size=72 offsets_size=0 +``` +## +``` +RenderThread-2267 ( 1592) [003] ...1 168766.128243: binder_transaction_received: transaction=25155529 +``` +### the flowing is for TAG A, this is the reply for TAG A +``` +RenderThread-2267 ( 1592) [003] ...1 168766.128262: binder_transaction: transaction=25155530 dest_node=0 dest_proc=506 dest_thread=537 reply=1 flags=0x8 code=0x0 + +RenderThread-2267 ( 1592) [003] ...1 168766.128264: binder_transaction_alloc_buf: transaction=25155530 data_size=4 offsets_size=0 +``` +### calc the dur of TAG A +``` +Binder:506_2-537 ( 506) [003] ...1 168766.128288: binder_transaction_received: transaction=25155530 +``` +### binder last TAG A needReply, this is TAG B needReply!!! +``` +Binder:506_2-537 ( 506) [003] ...1 168766.128328: binder_transaction: transaction=25155532 dest_node=25155527 dest_proc=1592 dest_thread=2267 reply=0 flags=0x10 code=0x2 +Binder:506_2-537 ( 506) [003] ...1 168766.128330: binder_transaction_alloc_buf: transaction=25155532 data_size=72 offsets_size=0 +``` +## in db +``` +RenderThread-2267 ( 1592) [003] ...1 168766.128347: binder_transaction_received: transaction=25155532 +``` +## the reply message is not in db Session D, this is the reply for TAG B +``` +RenderThread-2267 ( 1592) [003] ...1 168766.128361: binder_transaction: transaction=25155533 dest_node=0 dest_proc=506 dest_thread=537 reply=1 flags=0x0 code=0x0 +RenderThread-2267 ( 1592) [003] ...1 168766.128363: binder_transaction_alloc_buf: transaction=25155533 data_size=4 offsets_size=0 +``` +### no this message in db, calcate the dur of TAG B +``` +Binder:506_2-537 ( 506) [003] ...1 168766.128385: binder_transaction_received: transaction=25155533 +``` +### no this message in db Session E, this is the reply for TAG TT +``` +Binder:506_2-537 ( 506) [003] ...1 168766.128412: binder_transaction: transaction=25155534 dest_node=0 dest_proc=1592 dest_thread=2267 reply=1 flags=0x0 code=0x0 + +Binder:506_2-537 ( 506) [003] ...1 168766.128413: binder_transaction_alloc_buf: transaction=25155534 data_size=68 offsets_size=0 +``` +## the dur of TAG TT is calcated by the flowing msg +``` +RenderThread-2267 ( 1592) [003] ...1 168766.128430: binder_transaction_received: transaction=25155534 +``` \ No newline at end of file diff --git a/host/trace_streamer/doc/des_stat.md b/host/trace_streamer/doc/des_stat.md index e1048f51e1dbb4e9fbe08a809856d2bba903a5d2..bc03e7c47d544a2e66799f2503ff586e9164a4fc 100644 --- a/host/trace_streamer/doc/des_stat.md +++ b/host/trace_streamer/doc/des_stat.md @@ -1,74 +1,8 @@ # TraceStreamer 解析数据状态表 -TraceStreamer使用stat表统计解析trace数据源过程遇到的重要事件状态。通过stat表可以对trace数据源中各个类型事件的数据有一个基本了解。 -## stat表支持统计的事件列表如下: -|event_name | -| ---- | -|binder_transaction | -|binder_transaction_alloc_buf | -|binder_transaction_lock | -|binder_transaction_locked | -|binder_transaction_received | -|binder_transaction_unlock | -|clk_disable | -|clk_enable | -|clk_set_rate | -|clock_disable | -|clock_enable | -|clock_set_rate | -|cpu_frequency | -|cpu_idle | -|hidump_fps | -|hilog | -|ipi_entry | -|ipi_exit | -|irq_handler_entry | -|irq_handler_exit | -|memory | -|native_hook_free | -|native_hook_malloc | -|oom_score_adj_update | -|other | -|print | -|regulator_disable | -|regulator_disable_complete | -|regulator_set_voltage | -|regulator_set_voltage_complete | -|sched_process_exit | -|sched_process_free | -|sched_switch | -|sched_wakeup | -|sched_wakeup_new | -|sched_waking | -|signal_deliver | -|signal_generate | -|softirq_entry | -|softirq_exit | -|softirq_raise | -|suspend_resume | -|sys_enter | -|sys_exit | -|sys_memory | -|sys_virtual_memory | -|task_newtask | -|task_rename | -|trace_bblock_bio_queue | -|trace_block_bio_backmerge | -|trace_block_bio_bounce | -|trace_block_bio_complete | -|trace_block_bio_frontmerge | -|trace_block_bio_remap | -|trace_block_dirty_buffer | -|trace_block_getrq | -|trace_block_plug | -|trace_block_rq_complete | -|trace_block_rq_insert | -|trace_block_rq_issue | -|trace_block_rq_remap | -|trace_event_clock_sync | -|tracing_mark_write | -|workqueue_execute_end | -|workqueue_execute_start | - +TraceStreamer使用stat表统计解析trace数据源过程遇到的重要事件状态。通过stat表可以对trace数据源中各个类型事件的数据的数量,数据质量有一个基本了解。 +我们对不同类型的数据,统计了收到多少条,数据逻辑是否匹配,是否有不合法数据,是否有数据丢失情况,所有这些,是基于对数据格式本身和数据前后关系的主观认识。欢迎开发者提供更多的思路来帮我们完善数据本身的校验工作。 +## stat表支持统计的事件 +如[des_support_event.md](des_support_event.md)中所描述 ## 事件对应解析状态: 每种事件解析数据都有5种状态,描述如下表: |stat_type|description| @@ -81,333 +15,18 @@ TraceStreamer使用stat表统计解析trace数据源过程遇到的重要事件 ## 数据状态级别 数据状态级别总共有4种,分别是:info, warn, error,fatal。由于数据的重要性不同,不同事件的同一种状态可能对应不同的级别。 -例如binder_transaction_received的 not_supported状态的数据为info级别,而binder_transaction_alloc_buf的not_supported状态数据为warn级别。 +例如binder_transaction_received的 not_supported状态的数据为info级别,而binder_transaction_alloc_buf的not_supported状态数据为warn级别。 + +您可以在src/cfg/trace_streamer_config.cpp的InitSecurityMap方法中自行定义相关事件的优先级。 ## 事件,状态与级别对应关系 -| event_name | stat_type | serverity | -|---- |---- |---- | -| binder_transaction | received | info | -| binder_transaction | data_lost | error | -| binder_transaction | not_match | info | -| binder_transaction | not_supported | info | -| binder_transaction | invalid_data | error | -| binder_transaction_received | received | info | -| binder_transaction_received | data_lost | error | -| binder_transaction_received | not_match | info | -| binder_transaction_received | not_supported | info | -| binder_transaction_received | invalid_data | error | -| binder_transaction_alloc_buf | received | info | -| binder_transaction_alloc_buf | data_lost | error | -| binder_transaction_alloc_buf | not_match | info | -| binder_transaction_alloc_buf | not_supported | warn | -| binder_transaction_alloc_buf | invalid_data | error | -| binder_transaction_lock | received | info | -| binder_transaction_lock | data_lost | error | -| binder_transaction_lock | not_match | info | -| binder_transaction_lock | not_supported | warn | -| binder_transaction_lock | invalid_data | error | -| binder_transaction_locked | received | info | -| binder_transaction_locked | data_lost | error | -| binder_transaction_locked | not_match | info | -| binder_transaction_locked | not_supported | warn | -| binder_transaction_locked | invalid_data | error | -| binder_transaction_unlock | received | info | -| binder_transaction_unlock | data_lost | error | -| binder_transaction_unlock | not_match | info | -| binder_transaction_unlock | not_supported | warn | -| binder_transaction_unlock | invalid_data | error | -| sched_switch | received | info | -| sched_switch | data_lost | error | -| sched_switch | not_match | info | -| sched_switch | not_supported | info | -| sched_switch | invalid_data | error | -| task_rename | received | info | -| task_rename | data_lost | error | -| task_rename | not_match | info | -| task_rename | not_supported | info | -| task_rename | invalid_data | error | -| task_newtask | received | info | -| task_newtask | data_lost | error | -| task_newtask | not_match | info | -| task_newtask | not_supported | info | -| task_newtask | invalid_data | error | -| tracing_mark_write | received | info | -| tracing_mark_write | data_lost | error | -| tracing_mark_write | not_match | info | -| tracing_mark_write | not_supported | info | -| tracing_mark_write | invalid_data | error | -| print | received | info | -| print | data_lost | error | -| print | not_match | info | -| print | not_supported | info | -| print | invalid_data | error | -| sched_wakeup | received | info | -| sched_wakeup | data_lost | error | -| sched_wakeup | not_match | info | -| sched_wakeup | not_supported | info | -| sched_wakeup | invalid_data | error | -| sched_waking | received | info | -| sched_waking | data_lost | error | -| sched_waking | not_match | info | -| sched_waking | not_supported | info | -| sched_waking | invalid_data | error | -| cpu_idle | received | info | -| cpu_idle | data_lost | error | -| cpu_idle | not_match | info | -| cpu_idle | not_supported | info | -| cpu_idle | invalid_data | error | -| cpu_frequency | received | info | -| cpu_frequency | data_lost | error | -| cpu_frequency | not_match | info | -| cpu_frequency | not_supported | info | -| cpu_frequency | invalid_data | error | -| suspend_resume | received | info | -| suspend_resume | data_lost | error | -| suspend_resume | not_match | info | -| suspend_resume | not_supported | info | -| suspend_resume | invalid_data | error | -| workqueue_execute_start | received | info | -| workqueue_execute_start | data_lost | error | -| workqueue_execute_start | not_match | info | -| workqueue_execute_start | not_supported | info | -| workqueue_execute_start | invalid_data | error | -| workqueue_execute_end | received | info | -| workqueue_execute_end | data_lost | error | -| workqueue_execute_end | not_match | info | -| workqueue_execute_end | not_supported | warn | -| workqueue_execute_end | invalid_data | error | -| clock_set_rate | received | info | -| clock_set_rate | data_lost | error | -| clock_set_rate | not_match | info | -| clock_set_rate | not_supported | warn | -| clock_set_rate | invalid_data | error | -| clock_enable | received | info | -| clock_enable | data_lost | error | -| clock_enable | not_match | info | -| clock_enable | not_supported | warn | -| clock_enable | invalid_data | error | -| clock_disable | received | info | -| clock_disable | data_lost | error | -| clock_disable | not_match | info | -| clock_disable | not_supported | warn | -| clock_disable | invalid_data | error | -| clk_set_rate | received | info | -| clk_set_rate | data_lost | error | -| clk_set_rate | not_match | info | -| clk_set_rate | not_supported | warn | -| clk_set_rate | invalid_data | error | -| clk_enable | received | info | -| clk_enable | data_lost | error | -| clk_enable | not_match | info | -| clk_enable | not_supported | warn | -| clk_enable | invalid_data | error | -| clk_disable | received | info | -| clk_disable | data_lost | error | -| clk_disable | not_match | info | -| clk_disable | not_supported | warn | -| clk_disable | invalid_data | error | -| sys_enter | received | info | -| sys_enter | data_lost | error | -| sys_enter | not_match | info | -| sys_enter | not_supported | warn | -| sys_enter | invalid_data | error | -| sys_exit | received | info | -| sys_exit | data_lost | error | -| sys_exit | not_match | info | -| sys_exit | not_supported | warn | -| sys_exit | invalid_data | error | -| regulator_set_voltage | received | info | -| regulator_set_voltage | data_lost | error | -| regulator_set_voltage | not_match | info | -| regulator_set_voltage | not_supported | warn | -| regulator_set_voltage | invalid_data | error | -| regulator_set_voltage_complete | received | info | -| regulator_set_voltage_complete | data_lost | error | -| regulator_set_voltage_complete | not_match | info | -| regulator_set_voltage_complete | not_supported | warn | -| regulator_set_voltage_complete | invalid_data | error | -| regulator_disable | received | info | -| regulator_disable | data_lost | error | -| regulator_disable | not_match | info | -| regulator_disable | not_supported | warn | -| regulator_disable | invalid_data | error | -| regulator_disable_complete | received | info | -| regulator_disable_complete | data_lost | error | -| regulator_disable_complete | not_match | info | -| regulator_disable_complete | not_supported | warn | -| regulator_disable_complete | invalid_data | error | -| ipi_entry | received | info | -| ipi_entry | data_lost | error | -| ipi_entry | not_match | info | -| ipi_entry | not_supported | warn | -| ipi_entry | invalid_data | error | -| ipi_exit | received | info | -| ipi_exit | data_lost | error | -| ipi_exit | not_match | info | -| ipi_exit | not_supported | warn | -| ipi_exit | invalid_data | error | -| irq_handler_entry | received | info | -| irq_handler_entry | data_lost | error | -| irq_handler_entry | not_match | info | -| irq_handler_entry | not_supported | warn | -| irq_handler_entry | invalid_data | error | -| irq_handler_exit | received | info | -| irq_handler_exit | data_lost | error | -| irq_handler_exit | not_match | info | -| irq_handler_exit | not_supported | warn | -| irq_handler_exit | invalid_data | error | -| softirq_raise | received | info | -| softirq_raise | data_lost | error | -| softirq_raise | not_match | info | -| softirq_raise | not_supported | warn | -| softirq_raise | invalid_data | error | -| softirq_entry | received | info | -| softirq_entry | data_lost | error | -| softirq_entry | not_match | info | -| softirq_entry | not_supported | warn | -| softirq_entry | invalid_data | error | -| softirq_exit | received | info | -| softirq_exit | data_lost | error | -| softirq_exit | not_match | info | -| softirq_exit | not_supported | warn | -| softirq_exit | invalid_data | error | -| oom_score_adj_update | received | info | -| oom_score_adj_update | data_lost | error | -| oom_score_adj_update | not_match | info | -| oom_score_adj_update | not_supported | warn | -| oom_score_adj_update | invalid_data | error | -| sched_wakeup_new | received | info | -| sched_wakeup_new | data_lost | error | -| sched_wakeup_new | not_match | info | -| sched_wakeup_new | not_supported | warn | -| sched_wakeup_new | invalid_data | error | -| sched_process_exit | received | info | -| sched_process_exit | data_lost | error | -| sched_process_exit | not_match | info | -| sched_process_exit | not_supported | warn | -| sched_process_exit | invalid_data | error | -| sched_process_free | received | info | -| sched_process_free | data_lost | error | -| sched_process_free | not_match | info | -| sched_process_free | not_supported | warn | -| sched_process_free | invalid_data | error | -| trace_event_clock_sync | received | info | -| trace_event_clock_sync | data_lost | error | -| trace_event_clock_sync | not_match | info | -| trace_event_clock_sync | not_supported | warn | -| trace_event_clock_sync | invalid_data | error | -| memory | received | info | -| memory | data_lost | error | -| memory | not_match | info | -| memory | not_supported | warn | -| memory | invalid_data | error | -| hilog | received | info | -| hilog | data_lost | error | -| hilog | not_match | info | -| hilog | not_supported | warn | -| hilog | invalid_data | error | -| hidump_fps | received | info | -| hidump_fps | data_lost | error | -| hidump_fps | not_match | info | -| hidump_fps | not_supported | warn | -| hidump_fps | invalid_data | error | -| native_hook_malloc | received | info | -| native_hook_malloc | data_lost | error | -| native_hook_malloc | not_match | info | -| native_hook_malloc | not_supported | warn | -| native_hook_malloc | invalid_data | error | -| native_hook_free | received | info | -| native_hook_free | data_lost | error | -| native_hook_free | not_match | info | -| native_hook_free | not_supported | warn | -| native_hook_free | invalid_data | error | -| sys_memory | received | info | -| sys_memory | data_lost | error | -| sys_memory | not_match | info | -| sys_memory | not_supported | warn | -| sys_memory | invalid_data | error | -| sys_virtual_memory | received | info | -| sys_virtual_memory | data_lost | error | -| sys_virtual_memory | not_match | info | -| sys_virtual_memory | not_supported | warn | -| sys_virtual_memory | invalid_data | error | -| signal_generate | received | info | -| signal_generate | data_lost | error | -| signal_generate | not_match | info | -| signal_generate | not_supported | warn | -| signal_generate | invalid_data | error | -| signal_deliver | received | info | -| signal_deliver | data_lost | error | -| signal_deliver | not_match | info | -| signal_deliver | not_supported | warn | -| signal_deliver | invalid_data | error | -| trace_block_bio_backmerge | received | info | -| trace_block_bio_backmerge | data_lost | error | -| trace_block_bio_backmerge | not_match | info | -| trace_block_bio_backmerge | not_supported | warn | -| trace_block_bio_backmerge | invalid_data | error | -| trace_block_bio_bounce | received | info | -| trace_block_bio_bounce | data_lost | error | -| trace_block_bio_bounce | not_match | info | -| trace_block_bio_bounce | not_supported | warn | -| trace_block_bio_bounce | invalid_data | error | -| trace_block_bio_complete | received | info | -| trace_block_bio_complete | data_lost | error | -| trace_block_bio_complete | not_match | info | -| trace_block_bio_complete | not_supported | warn | -| trace_block_bio_complete | invalid_data | error | -| trace_block_bio_frontmerge | received | info | -| trace_block_bio_frontmerge | data_lost | error | -| trace_block_bio_frontmerge | not_match | info | -| trace_block_bio_frontmerge | not_supported | warn | -| trace_block_bio_frontmerge | invalid_data | error | -| trace_bblock_bio_queue | received | info | -| trace_bblock_bio_queue | data_lost | error | -| trace_bblock_bio_queue | not_match | info | -| trace_bblock_bio_queue | not_supported | warn | -| trace_bblock_bio_queue | invalid_data | error | -| trace_block_bio_remap | received | info | -| trace_block_bio_remap | data_lost | error | -| trace_block_bio_remap | not_match | info | -| trace_block_bio_remap | not_supported | warn | -| trace_block_bio_remap | invalid_data | error | -| trace_block_dirty_buffer | received | info | -| trace_block_dirty_buffer | data_lost | error | -| trace_block_dirty_buffer | not_match | info | -| trace_block_dirty_buffer | not_supported | warn | -| trace_block_dirty_buffer | invalid_data | error | -| trace_block_getrq | received | info | -| trace_block_getrq | data_lost | error | -| trace_block_getrq | not_match | info | -| trace_block_getrq | not_supported | warn | -| trace_block_getrq | invalid_data | error | -| trace_block_plug | received | info | -| trace_block_plug | data_lost | error | -| trace_block_plug | not_match | info | -| trace_block_plug | not_supported | warn | -| trace_block_plug | invalid_data | error | -| trace_block_rq_complete | received | info | -| trace_block_rq_complete | data_lost | error | -| trace_block_rq_complete | not_match | info | -| trace_block_rq_complete | not_supported | warn | -| trace_block_rq_complete | invalid_data | error | -| trace_block_rq_insert | received | info | -| trace_block_rq_insert | data_lost | error | -| trace_block_rq_insert | not_match | info | -| trace_block_rq_insert | not_supported | warn | -| trace_block_rq_insert | invalid_data | error | -| trace_block_rq_remap | received | info | -| trace_block_rq_remap | data_lost | error | -| trace_block_rq_remap | not_match | info | -| trace_block_rq_remap | not_supported | warn | -| trace_block_rq_remap | invalid_data | error | -| trace_block_rq_issue | received | info | -| trace_block_rq_issue | data_lost | error | -| trace_block_rq_issue | not_match | info | -| trace_block_rq_issue | not_supported | warn | -| trace_block_rq_issue | invalid_data | error | -| other | received | info | -| other | data_lost | error | -| other | not_match | info | -| other | not_supported | warn | -| other | invalid_data | error | +我们通过一张表,来记录所有事件的解析情况,拿下面这条数据举例: +| event_name | count| stat_type | serverity | +|---- |---|---- |---- | +| binder_transaction |12| received | info | +| binder_transaction |1| data_lost | error | +| binder_transaction |3| not_match | info | +| binder_transaction |0| not_supported | info | +| binder_transaction |5| invalid_data | error | +| - | - |-|- | +上面的图表表示:一共收到了12条binder_transaction的数据,其中有3条数据业务上不匹配,有5条数据格式非法。 \ No newline at end of file diff --git a/host/trace_streamer/doc/des_support_eventlist.md b/host/trace_streamer/doc/des_support_event.md similarity index 80% rename from host/trace_streamer/doc/des_support_eventlist.md rename to host/trace_streamer/doc/des_support_event.md index bde55dce0c0d849fdf69f5ed882f6d12c9037228..f283a1d509892f746128d02713ab51efd508c663 100644 --- a/host/trace_streamer/doc/des_support_eventlist.md +++ b/host/trace_streamer/doc/des_support_event.md @@ -1,5 +1,9 @@ -# TraceStreamer支持解析事件列表 +# TraceStreamer支持识别事件列表 +trace事件是指系统在运行过程中输出的日志。trace事件有内核输出的,也有用户输出的,系统或用户在输出日志时,都可以添加特定的标识,以特定的格式输出。 +所谓事件,是指特定的标签,指定了其事件类型。 ## ftrace事件 +ftrace属于linux标准内核事件。 +ftrace相关事件属于系统内核事件,具体请参考linux内核相关技术网站(www.kernel.org)。 ``` binder_transaction binder_transaction_received @@ -27,12 +31,6 @@ clk_enable clk_disable sys_enter sys_exit -regulator_set_voltage -regulator_set_voltage_complete -regulator_disable -regulator_disable_complete -ipi_entry -ipi_exit irq_handler_entry irq_handler_exit softirq_raise @@ -41,8 +39,55 @@ softirq_exit sched_wakeup_new sched_process_exit trace_event_clock_sync +// 下面的事件,属于ftrace,TraceStream可以识别并记录,但并不做业务解析。 +ipi_entry +ipi_exit +regulator_set_voltage +regulator_set_voltage_complete +regulator_disable +regulator_disable_complete +signal_generate +signal_deliver +trace_block_bio_backmerge +trace_block_bio_bounce +trace_block_bio_complete +trace_block_bio_frontmerge +trace_bblock_bio_queue +trace_block_bio_remap +trace_block_dirty_buffer +trace_block_getrq +trace_block_plug +trace_block_rq_complete +trace_block_rq_insert +trace_block_rq_remap +trace_block_rq_issue +``` +## 其他插件数据 +以下的数据,来自于htrace(序列化后的trace)的其他插件。 +注:如果是文本的trace的话,只支持ftrace +``` +memory +hilog +hidump_fps +native_hook_malloc +native_hook_free +native_hook_mmap +native_hook_munmap +sys_memory +sys_virtual_memory +trace_diskio +trace_process +trace_cpu_usage +trace_network +trace_perf +trace_ebpf +trace_ebpf_file_system +trace_ebpf_paged_memory +trace_ebpf_bio_latency +trace_hisys_event +trace_smaps ``` -## 内存事件 +## 进程的内存事件 ``` mem.vm.size mem.rss diff --git a/host/trace_streamer/doc/des_tables.md b/host/trace_streamer/doc/des_tables.md index efe0a6f7b4ab4352fc1a9cce82963d86293d8a4e..71497f9b9212b76673640ad3046447e3cd779a5f 100644 --- a/host/trace_streamer/doc/des_tables.md +++ b/host/trace_streamer/doc/des_tables.md @@ -1,306 +1,1159 @@ -# ___概述TraceStreamer生成的数据库___ -``` - TraceStreamer虽然对外提供了各种各样的使用方式,但核心的业务仍是将trace数据源转化为易于理解和使用的数据库。用户可以通过SmartPerf界面直观的研究系统跟踪数据,也可在理解TraceStreamer生成的数据库的基础上,在TraceStreamer的交互模式或者Smartperf的数据库查询模式下,使用SQL查询语句自由组装查看用户关心的数据。 下文将对TraceStreamer生成的数据库进行详细描述,给用户使用SQL查询系统跟踪数据提供帮助。 -``` +# TraceStreamer数据表概述 +TraceStreamer可以将trace数据源转化为易于理解和使用的数据库。用户可以通过SmartPerf界面直观的研究系统跟踪数据,也可在理解TraceStreamer生成的数据库的基础上,在TraceStreamer的交互模式或者Smartperf的数据库查询模式下,使用SQL查询语句自由组装查看用户关心的数据。下文将对TraceStreamer生成的数据库进行详细描述,给用户使用SQL查询系统跟踪数据提供帮助。 -## ___TraceStreamer输出数据库包含以下表格___ -* trace_range : 记录ftrace数据与其他类型数据的时间交集,供前端展示数据时使用。 -* process : 记录进程信息。 -* thread : 记录线程信息。 -* thread_state : 记录线程状态信息。 -* instant : 记录Sched_waking, sched_wakeup事件, 用作ThreadState表的上下文使用。 -* raw : 此数据结构主要作为ThreadState的上下文使用,这张表是sched_waking,sched_wakup, cpu_idle事件的原始记录。 -* callstack : 记录调用堆栈和异步调用,其中depth,stack_id和parent_stack_id仅在非异步调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号。 -* irq : 记录中断相关事件。 -* measure : 记录所有的计量值。 -* log : 记录hilog打印日志数据。 -* heap : 记录堆内存申请与释放相关的数据。 -* heap_frame : 记录堆内存申请与释放相关的调用栈。 -* hidump : 记录FPS(Frame Per Second)数据。 -* symbols : 记录系统调用名称和其函数指针的对应关系,trace中用addr来映射function_name来节省存储空间 -* syscall : 记录用户空间函数与内核空间函数相互调用记录 -* args : 记录方法参数集合 -* sys_event_filter : 记录所有的filter -* clk_event_filter : 记录时钟事件 -* cpu_measure_filter : cpu事件过滤器表。 -* measure_filter : 记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录。 -* process_measure_filter : 将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id -* data_type : 记录数据类型和typeId的关联关系。 -* data_dict : 记录常用的字符串,将字符串和索引关联,降低程序运行的内存占用,用作辅助数据。 -* meta : 记录执行解析操作相关的基本信息。 +## TraceStreamer输出的数据表分类 +* 常规泳道图数据表 +![GitHub Logo](../figures/db_common.png) +* native memory数据源相关表 +![GitHub Logo](../figures/db_native_memory.png) +* perf相关数据表 +![GitHub Logo](../figures/db_hiperf.png) +* hisysevent相关数据表 +![GitHub Logo](../figures/db_hisys_event.png) +## TraceStreamer输出数据库包含以下表格 +| 表名称 |作用| +| ---- |---- | +| app_name | 记录HiSysEvent事件的事件名与IDE部分事件的字段名为APPNAME中存放的相关信息的映射关系 | +| args | 记录方法参数集合| +| bio_latency_sample | 记录IO操作相关方法调用,及调用栈数据| +| callstack | 记录调用堆栈和异步调用信息,其中depth,stack_id和parent_stack_id仅在非异步调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号| +| clk_event_filter | 记录时钟相关的信息| +| clock_event_filter | 此结构用来维护时钟事件,cpu与唯一的ID做关联| +| cpu_measure_filter | cpu事件过滤器表| +| cpu_usage | 记录CPU使用率事件| +| data_dict | 记录常用的字符串,将字符串和索引关联,降低程序运行的内存占用,用作辅助数据| +| data_type | 记录数据类型和typeId的关联关系| +| diskio | 记录磁盘读写数据事件| +| ebpf_callstack | 记录了采样相关信息| +| file_system_samp | 记录了调用栈的相关信息| +| hidump | 记录FPS(Frame Per Second)数据| +| hisys_event_measure | 记录了HiSysEvent事件相关数据,目前HiSysEvent事件包括了异常事件,IDE事件,器件状态事件 | +| instant | 记录Sched_waking, sched_wakeup事件, 用作ThreadState表的上下文使用 | +| irq | 记录中断相关事件| +| live_process | 记录了一些实时的进程中执行的一些数据| +| log | 记录hilog打印日志数据| +| measure_filter | 记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录| +| meta | 记录执行解析操作相关的基本信息| +| native_hook | 记录堆内存申请与释放相关的数据| +| native_hook_frame | 记录堆内存申请与释放相关的调用栈| +| network | 抓取网络信息传输时产生的一些相关信息| +| paged_memory_sample | 记录内存操作相关方法调用,及调用栈数据| +| perf_callchain | 记录Hiperf采样数据的调用栈信息| +| perf_files | 记录Hiperf工具采集到的函数符号表和文件名| +| perf_report | 记录Hiperf工具采集数据时的配置信息。包括|抓取的事件类型,抓取数据的命令, 抓数据时指定的进程名称| +| perf_sample | 记录Hiperf工具的采样信息| +| perf_thread | 记录Hiperf工具采集到的进程和线程数据| +| process | 记录所有的进程信息| +| process_filter | 过滤进程| +| process_measure | 保存进程的所有计量值| +| process_measure_filter | 将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id| +| raw | 此数据结构主要作为ThreadState的上下文使用,这张表是sched_waking,sched_wakup, cpu_idle事件的原始记录| +| sched_slice | 此数据结构主要作为ThreadState的上下文使用,这张表是sched_switch事件的原始记录| +| smaps | 记录进程的内存消耗的相关信息采样| +| stat | 此结果用来统计数据解析中各类数据的数据条数,数据和合法性,数据的匹配程度(begin-end),数据的损失等,查看此结构对应的表,可对数据源有基本的了解| +| symbols | 记录系统调用名称和其函数指针的对应关系,trace中用addr来映射function_name来节省存储空间| +| syscall | 记录用户空间函数与内核空间函数相互调用记录| +| sys_event_filter | 记录所有的filter| +| sys_mem_measure | 记录了所有的系统内存相关的测量信息| +| thread | 记录所有的线程信息| +| thread_filter | 过滤线程| +| thread_state | 记录线程状态信息| +| trace_range | 记录ftrace数据与其他类型数据的时间交集,供前端展示数据时使用| +| clock_snapshot | 时钟号和时间,时钟名的映射表| +| datasource_clockid | 数据源和时钟号的映射表| +## 表与事件来源 +| 表名称 | 事件源 | 插件名 | 备注 | +| ---- | ---- | ---- | ---- | +|app_name | - |hisysevent-plugin |JSON数据源 | +|args | - |ftrace-plugin |配合callstack使用 | +|callstack | - |ftrace-plugin |异步或非异步的调用 | +|cpu_measure_filter | - |ftrace-plugin |cpu跟踪器,cpu频率等 | +|cpu_usage | - |cpu-plugin |cpu使用率 | +|data_dict | 通用的 | - |所有字符串的记录 | +|data_type | 通用的 | - |辅助表 | +|file_system_callstack | - | - |ebpf文件系统 | +|file_system_sample | - | - |ebpf文件系统 | +|hidump | - |hidump-plugin |FPS数据 | +|hisys_event_measure | - |hisysevent-plugin |JSON数据源 | +|instant | - |ftrace-plugin |waking和wakeup事件 | +|irq | - |ftrace-plugin |记录中断事件 | +|live_process | - |process-plugin |Monitor数据 | +|network | - |network-plugin |Monitor数据 | +|diskio | - |diskio-plugin |Monitor数据 | +|log | - |hilog-plugin |系统日志 | +|measure | 通用的 | - |系统中的计量值(数值型)| +|measure_filter | 通用的 | - |计量值的查询辅助表 | +|meta | 通用的 | - |记录解析现场数据(解析时间,数据类型,解析工具等)| +|native_hook | - |nativehook/hookdaemon |内存数据 | +|native_hook_frame | - |nativehook/hookdaemon |内存数据 | +|perf_callchain | - |perf-plugin |perf数据(非插件模式) | +|perf_files | - | - |perf数据(非插件模式) | +|perf_report | - | - |perf数据(非插件模式) | +|perf_sample | - | - |perf数据(非插件模式) | +|perf_thread | - | - |perf数据(非插件模式) | +|process | - |ftrace-plugin |进程信息 | +|process_filter | - |ftrace-plugin |进程计量表的辅助表 | +|process_measure | - |ftrace-plugin |进程内存 | +|process_measure_filter| - |ftrace-plugin |process_measure的辅助表| +|raw | - |ftrace-plugin |线程唤醒信息 | +|sched_slice | - |ftrace-plugin |配合现场状态表使用,dsched_switch的原始数据| +|smaps | - |memory-plugin |进程的内存消耗 | +|stat | 通用的 | - |记录不同种类数据的数据量| +|symbols | - |ftrace-plugin |符号表(地址到字符串的映射)| +|syscall | - |ftrace-plugin |系统调用 sys_enter/exit| +|sys_event_filter | - |ftrace-plugin | | +|sys_mem_measure | - |memory-plugin |系统内存 | +|thread | 通用的 | - |线程信息(常用) | +|thread_state | 通用的 |ftrace-plugin |线程调度图(常用) | +|trace_range | 通用的 | - |trace数据的时长 | +|thread_filter | 通用的 |ftrace-plugin |线程计量跟踪表(比较少用)| +|clock_snapshot | 通用的 |通用的 |时钟号和时间,时钟名的映射表| +|datasource_clockid | 通用的 |通用的 |数据源和时钟号的映射表| ## ___表格关系图___ - -### 进程表与线程表关系图: -![GitHub Logo](../figures/process_thread.png) -### 描述: +--- +### 进程表与线程表关系 当一个进程或者线程结束后,系统可能再次将该进程号或者线程号分配给其他进程或者线程,造成一个进程号或线程号代表多个进程或线程的情况。 Process和Thread表中的id字段可以唯一标识进程和线程。process表中的id在其他表中用作ipid字段。thread表中的id在其他表中用作itid字段。 -thread表通过ipid字段关联process表的id字段,可以查询线程归属进程。 -### 举例: +thread表通过ipid字段关联process表的id字段,可以查询线程归属进程。 +![GitHub Logo](../figures/process_thread.png) +### 查询举例 已知pid = 123,查看当前进程下的所有线程信息,可以使用如下SQL语句: -select thread.* from thread, process where process.pid = 123 and thread.ipid = process.id +```select thread.* from thread, process where process.pid = 123 and thread.ipid = process.id``` ### 线程表与线程运行状态表关系图 +thread_state表记录所有线程的运行状态信息,包含ts(状态起始时间),dur(状态持续时间),cpu, itid, state(线程状态)。 thread表的id字段与thread_state表的itid字段相关联。 ![GitHub Logo](../figures/thread_state.png) -### 描述: -thread_state表记录所有线程的运行状态信息,包含ts(状态起始时间),dur(状态持续时间),cpu, itid, state(线程状态)。 thread表的id字段与thread_state表的itid字段相关联。 -### 举例: +### 查询举例 已知tid = 123, 查看当前线程的所有运行状态信息,可以使用如下SQL语句: -select thread_state.* from thread, thread_state where thread.tid = 123 and thread.id = thread_state.itid +```select thread_state.* from thread, thread_state where thread.tid = 123 and thread.id = thread_state.itid``` ### 堆内存数据变化表关系图 +native_hook表记录堆内存申请(AllocEvent)和释放(FreeEvent)数据。native_hook表通过ipid和itid字段分别与process和thread表的id字段关联,通过callChainId与native_hook_frame表的callChainId字段相关联。 +native_hook表字段解释如下: + callChainId: 唯一标识一次堆内存申请或释放, 通过与native_hook_frame表关联可以拿到当前申请或释放的函数调用堆栈。 + addr: 堆内存申请/释放的地址 + native_hook_size: 堆内存申请/释放的大小 +native_hook_frame表记录内存申请/释放的调用堆栈。通过callChainId区分一组调用堆栈,depth为堆栈深度,depth为0时,表示当前行为栈顶数据。 ![GitHub Logo](../figures/dump_and_mem.png) -### 描述: -heap表记录堆内存申请(AllocEvent)和释放(FreeEvent)数据。heap表通过ipid和itid字段分别与process和thread表的id字段关联,通过eventId与heap_frame表的eventId字段相关联。 -heap表字段解释如下: - eventId: 唯一标识一次堆内存申请或释放, 通过与heap_frame表关联可以拿到当前申请或释放的函数调用堆栈。 - addr: 堆内存申请/释放的地址 - heap_size: 堆内存申请/释放的大小 -heap_frame表记录内存申请/释放的调用堆栈。通过eventId区分一组调用堆栈,depth为堆栈深度,depth为0时,表示当前行为栈顶数据。 -### 举例: -已知tid = 123, 查看当前线程的所有堆内存变化信息,可以使用如下SQL语句: -select heap.* from thread, heap where thread.tid = 123 and thread.id = heap.itid -已知eventid = 0, 查看当前内存变化调用堆栈 -select * from heap_frame where eventId = 0 +### 查询举例 +- 已知tid = 123, 查看当前线程的所有堆内存变化信息,可以使用如下SQL语句: +```select native_hook.* from thread, native_hook where thread.tid = 123 and thread.id = native_hook.itid``` +- 已知callchainid = 0, 查看当前内存变化调用堆栈 +```select * from native_hook_frame where callChainId = 0``` ### 日志表与进程线程表关系图 -![GitHub Logo](../figures/log.png) -### 描述: -log表记录日志信息。可以根据seq字段的连续性,来判断是否存在日志丢失的情况。 -### 举例: +log表记录日志信息。可以根据seq字段的连续性,来判断是否存在日志丢失的情况。 +![GitHub Logo](../figures/log.png) +### 查询举例 已知tid = 123, 查看当前线程的所有error级别的日志,可以使用如下SQL语句: -select * from log where tid = 123 and level = "error" +```select * from log where tid = 123 and level = "error"``` + +### perf表之间关系图 +perf_report:此表记录Hiperf工具采集数据时的配置信息。 +perf_thread:此表记录hiperf采集到的进程和线程数据。 +perf_sample:此表中记录Hiperf工具的采样信息。sample_id唯一表识一次采样记录,与perf_callchain表中的sample_id字段相关联。thread_id为线程号。与perf_thread表中的thread_id字段相关联。event_type_id为当前采样的事件类型id,与perf_report表中的id字段相关联。 +perf_callchain:此表格记录的是调用栈信息。 +Perf_files:此表格主要存放着获取到的函数符号表和文件信息。file_id唯一表识一个文件,与perf_callchain表中的file_id字段相关联。 +![GitHub Logo](../figures/perf.png) +### 查询举例 +- 已知同步后的时间戳为28463134340470,查询采样数据 +```select * from perf_sample where timestamp_trace = 28463134340470``` + +- 已知同步后的时间戳为28463134340470,查询采样数据对应的的调用栈信息 +```select A.* from perf_callchain as A, perf_sample as B where B.timestamp_trace = 28463134340470 and A.sample_id = B.sample_id``` + +已知同步后的时间戳为28463134277762,查询采样数据的函数名及文件路径 +```select A.*, B.name, C.path from perf_sample as A, perf_callchain as B, perf_files as C where A.timestamp_trace = 28463134277762 and B.sample_id = A.sample_id and B.callchain_id = 0 and B.file_id = C.file_id and C.serial_id = 0``` + +已知线程号为6700,查询所有的采样记录 +```select * from perf_sample where thread_id = 6700``` +已知进程号为7863,查询所有的采样记录 +```select A.* from perf_sample as A, perf_thread as B where B.process_id = 7863 and A.thread_id = B.thread_id``` + +查询所有采样对应的事件类型 +```select A.*, B.report_value from perf_sample as A, perf_report as B where A.event_type_id = B.id``` ## TraceStreamer输出数据库表格详细介绍 -### trace_range表 -#### 表结构: +### app_name表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | -|start_ts |NUM | -|end_ts |INT | -#### 关键字段描述: -start_ts: trace的开始时间,纳秒为单位 -end_ts: trace的结束时间,纳秒为单位 -### process表 -#### 表结构: +|id |INT | +|flag |INT | +|app_name |INT | +|app_key |INT | +#### 表描述 +记录HiSysevent上报事件中的IDE相关事件中APPNAME的表关联信息。 +#### 字段详细描述 +id:用于与表hisys_event_measure表中的key_id字段做对应 +app_name:对应的事件的信息ID +app_key:对应的事件的APPNAME字段的信息ID + +### args表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | -|id |NUM | -|type |INT | -|pid |NUM | -|name |INT | -|start_ts |NUM | -#### 关键字段描述: -id: 进程在数据库重新重新定义的id,从0开始序列增长 -pid: 进程的真实id -name: 进程名字 -### thread表 -#### 表结构: +|id |INT | +|key |INT | +|datatype |INT | +|value |INT | +|argset |INT | +#### 表描述 +记录方法的参数集合 +#### 字段详细描述 +key:键 +datatype:数据类型 +value:取值 +argset:参数集合 + +### bio_latency_sample表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | -|id |INT | -|type |NUM | -|tid |INT | -|name |NUM | -|start_ts |INT | -|end_ts |INT | -|ipid |INT | -|is_main_thread|INT | -#### 字段详细描述: -id: 线程在数据库重新重新定义的id,从0开始序列增长 -ipid: 线程所属的进程id, 关联进程表中的ID -name: 线程名字 -is_main_thread: 是否主线程,主线程即该线程实际就是进程本身 +|id |INT | +|callchain_id |INT | +|datatype |INT | +|type |INT | +|ipid |INT | +|itid |INT | +|start_ts |INT | +|end_ts |INT | +|latency_dur |INT | +|tier |INT | +|size |INT | +|block_number |TEXT | +|path |TEXT | +|dur_per_4k |INT | +#### 表描述 +记录IO操作相关方法调用,及调用栈数据 +#### 字段详细描述 +callchain_id:调用栈的唯一标识。与ebpf_callstack表中Callchain_id字段关联 +type:事件类型其取值为枚举类型(DATA_READ,DATA_WRITE,METADATA_READ,METADATA_WRITE,PAGE_IN,PAGE_OUT) +ipid:TS内部进程号 +itid:TS内部线程号 +start_ts:开始时间 +end_ts:结束时间 +latency_dur:总延迟 +tier:优先级 +size:文件大小 +block_number:数据量大小(一般为4K) +path:路径id +dur_per_4k:每4k数据的平均延迟 -### thread_state表 -#### 表结构: +### callstack表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | |id |INT | -|type |NUM | |ts |INT | |dur |INT | +|callid |INT | +|cat |TEXT | +|identify |INT | +|name |TEXT | +|depth |INT | +|cookie |INT | +|parent_id |INT | +|argsetid |INT | +|chainId |TEXT | +|spanId |TEXT | +|parentSpanId |TEXT | +|flag |TEXT | +|args |TEXT | +#### 表描述 +记录调用堆栈和异步调用信息,其中depth,stack_id和parent_stack_id仅在非异步的调用中有效。当cookid不为空时,为异步调用,此时callid为进程唯一号,否则为线程唯一号。 +#### 字段详细描述 +dur:调用时长 +callid:调用者的ID,比如针对线程表里面的id +identify:调用栈的名字,与表dataDict相关联能够取出其string值 +name:调用名称 +depth:调用深度 +parent_id:父调用的id +spanId:分布式调用关联关系 +flag:C表示分布式调用发送方,S表示接受方 +args:分布式调用函数参数 + +### clk_event_filter表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |TEXT | +|name |TEXT | |cpu |INT | -|itid |INT | -|state |NUM | -#### 字段详细描述: -id: 线程状态在数据库中的id,从0开始序列增长 -ts: 该线程状态的起始时间 -dur: 该线程状态的持续时间 -cpu: 该线程在哪个cpu上执行(针对running状态的线程) -itid: 该状态所属的线程所属的进程id, 关联进程表中的ID -state: 线程实际的的状态值 -``` -'R', Runnable状态 -'S', interruptible sleep -'D', uninterruptible sleep -'T', Stoped -'t', Traced -'X', ExitedDead -'Z', ExitZombie -'x', TaskDead -'I', TaskDead -'K', WakeKill -'P', Parked -'N', NoLoad -``` -### instant表 -#### 表结构: +#### 表描述 +记录时钟信息 +#### 字段详细描述 +Type:时钟事件类型 +Name:时钟事件名称 + +### clock_event_filter表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |TEXT | +|name |TEXT | +|cpu |INT | +#### 表描述 +此结构用来维护时钟事件,cpu与唯一的ID做关联 +#### 主要字段描述 +Type:时钟事件类型 +Name:时钟事件名称 + +### cpu_measure_filter表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |TEXT | +|name |TEXT | +|cpu |INT | +#### 表描述 +将cpu号作为key1,cpu的频率,空闲等状态作为key2,唯一确定一个filter_id +#### 主要字段描述 +Id(filterid), cpu:事件名称,cpu号 + +### cpu_usage表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | |ts |INT | -|name |NUM | -|ref |INT | -|ref_type |NUM | -#### 表描述: -记录了系统中的waking和wakeup事件。 -### raw表 -#### 表结构: +|dur |INT | +|total_load |REAL | +|user_load |REAL | +|system_load |REAL | +|process_num |INT | +#### 表描述 +记录了与CPU使用率相关的数据 +#### 主要字段描述 +total_load:总负荷 +user_load:用户负载 +system_load:系统负载 +process_num:线程数 + +### data_dict表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|data |TEXT | +#### 表描述 +此表记录了一个数据类型ID和字符串的映射。 +#### 主要字段描述 +id:索引值 +data:字符串 + +### data_type表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | |id |INT | -|type |NUM | +|typeId |INT | +|desc |TEXT | +#### 表描述 +此表记录了一个数据类型ID和数据描述的映射。 +#### 主要字段描述 +typeId::数据类型id +Desc:数据类型描述 + +### diskio表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | |ts |INT | -|name |NUM | -|cpu |INT | +|dur |INT | +|rd |INT | +|wr |INT | +|rd_speed |REAL | +|wr_speed |REAL | +|rd_count |INT | +|wr_count |INT | +|rd_count_speed |REAL | +|wr_count_speed |REAL | +#### 表描述 +记录了与磁盘读写相关的数据 +#### 主要字段描述 +rd_sectors_kb:读数据的速度 +wr_sectors_kb:写入数据的速度 +ts:时间戳 + +### ebpf_callstack表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|callchain_id |INT | +|depth |TEXT | +|ip |TEXT | +|symbols_id |INT | +|file_path_id |INT | +#### 表描述 +记录了与磁盘读写相关的数据 +#### 主要字段描述 +callchain_id:调用栈的唯一标识。与ebpf_callstack表中Callchain_id字段关联 +depth:调用栈深度。取值为零时表示栈顶 +ip:调用栈ip +symbols_id:调用栈函数名称, 与data_dict中的id字段关联 +file_path_id:调用栈函数所属文件路径, 与data_dict中的id字段关联 + +### file_system_sample表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|callchain_id |INT | +|type |INT | +|ipid |INT | |itid |INT | -#### 表描述: -记录了系统中的waking、wakup、cpu_idel、cpu_frequency数据。 +|start_ts |INT | +|end_ts |INT | +|dur |INT | +|return_value |TEXT | +|error_code |TEXT | +|fd |INT | +|file_id |INT | +|size |INT | +|first_argument |TEXT | +|second_argument |TEXT | +|third_argument |TEXT | +|fourth_argument |TEXT | +#### 表描述 +记录了调用栈的相关信息。 +#### 主要字段描述 +callchain_id:调用栈信息ID与file_system_callstack表中call_chain_id字段相关联 +type:对应文件操作open,close,read,write +ipid:线程所属的进程ID +start_ts:开始时间 +end_ts:结束时间 +dur:耗时 +return_value:文件操作的返回值 +error_code:文件操作发生错误时的错误码 +fd:文件描述符fd +file_id:当type为open,close时为其操作的文件路径,当type为read,write时为固定字段(null) +size:在type为read,write时对应的文件的读或者写的大小 +first_argument:参数一 +second_argument:参数二 +third_argument:参数三 +fourth_argument:参数四 -### callstack表 -#### 表结构: +### hidump表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|ts |INT | +|fps |INT | +#### 表描述 +此表记录了设备的帧率信息,fps。 +#### 相关字段描述 +fps:帧率值 + +### hisys_event_measure表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|serial |INT | +|ts |INT | +|name_id |INT | +|key_id |INT | +|type |INT | +|int_value |REAL | +|string_value |TEXT | +#### 表描述 +记录所有的system event事件的相关数据,及其相关表的映射信息。 +#### 相关字段描述 +serial:每条数据过来携带唯一一条id作为标识 +name_id:存放事件对应的ID,与data_dict表相关联可以取出对应的字段 +key_id:存放事件包含的字段的ID,与表app_name的id字段相关联,找到app_name表的id字段对应行的app_key字段与表data_dict表相关联取出对应的字段 +type:存放事件所包含的字段的值所属的类型为int型还是string(0为int,1为string) +int_value:存放本事件所包含的字段的int型的值 +string_value:存放本事件所包含的字段的string型的值 + +### instant表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|ts |INT | +|name |TEXT | +|ref |INT | +|wakeup_from |INT | +|ref_type |TEXT | +|value |REAL | +#### 表描述 +记录了系统中的waking和wakeup事件。 +#### 字段描述 +ts:唤醒时间 +name:唤醒事件的名称 +ref:索引号 +wakeup_from:唤醒当前线程的内部线程号(itid) +ref_type:描述了value字段的类型(一般取值为itid) +value:一般为当前线程的内部线程号取值 + +### irq表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | |id |INT | |ts |INT | |dur |INT | |callid |INT | -|cat |NUM | -|name |NUM | +|cat |TEXT | +|name |TEXT | |depth |INT | |cookie |INT | |parent_id |INT | |argsetid |INT | -|chainId |NUM | -|spanId |NUM | -|parentSpanId |NUM | -|flag |NUM | -|args |NUM | -#### 字段详细描述: -dur: 调用时长 -callid: 调用者的ID,比如针对线程表里面的id -name: 调用名称 -depth: 调用深度 -parent_id: 父调用的id +|chainId |TEXT | +|spanId |TEXT | +|parentSpanId |TEXT | +|flag |TEXT | +|args |TEXT | +#### 表描述 +记录中断相关事件。 +#### 相关字段描述 +dur:调用中断时长 +callid:调用中断者的ID,比如针对线程表里面的id +cat:调用栈数据类型(取值范围:irq,softirq...) +name:调用中断的名称 +depth:中断调用的深度 +parent_id:父调用中断的id +spanId:分布式调用中断关联关系 + +### live_process表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|ts |INT | +|dur |INT | +|cpu_time |INT | +|process_id |INT | +|process_name |TEXT | +|parent_process_id |INT | +|uid |INT | +|user_name |TEXT | +|cpu_usage |REAL | +|pss_info |INT | +|thread_num |INT | +|disk_writes |INT | +|disk_reads |INT | +#### 表描述 +记录了一些实时的进程中执行的一些数据(Monitor)。 +#### 主要字段描述 +process_id:进程id +process_name:进程名 +parent_process_id:父进程的id +uid:用户id +user_name:用户名 +cpu_usage:cpu使用率 +pss_info:进程信息 +thread_num:线程数量 +disk_writes:磁盘写量 +disk_reads:磁盘读量 + +### log表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|seq |INT | +|ts |INT | +|pid |INT | +|tid |INT | +|level |TEXT | +|tag |TEXT | +|context |TEXT | +|origints |INT | +#### 表描述 +记录日志信息。 +#### 关键字段描述 +Seq:日志序号,保证日志解析的准确性 +Ts:打印日志时间 +Pid:日志的进程号 +Tid:日志的线程号 +Level:日志级别 +Tag:日志标签 +Context:日志内容 ### measure表 -#### 表结构: +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | -|type |NUM | +|type |TEXT | |ts |INT | |value |INT | |filter_id |INT | -#### 字段详细描述: +#### 表描述 +记录所有的计量值。 +#### 关键字段描述 +type:固定字段(measure) +ts:事件时间 +value:数值 +filter_id:对应filter表中的ID -### heap表 -#### 表结构: +### measure_filter表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |TEXT | +|name |TEXT | +|source_arg_set_id |INT | +#### 表描述 +记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录。 +#### 字段详细描述 +过滤分类(type),过滤名称(key2),数据ID(key1)。 +数据ID在process_measure_filter, sys_event_filter中作为id。 + +### meta表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | -|eventId |INT | +|name |TEXT | +|value |TEXT | +#### 表描述 +此表记录了数据解析或导出时的一些现场数据,比如使用的TraceStreamer版本, 工具的发布时间,数据解析的时间,数据的持续时长,以及原始数据的格式。 +#### 主要字段描述 +Name:指定元数据的key +Value:指定元数据的value + +### native_hook表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|callChainId |INT | |ipid |INT | |itid |INT | -|event_type |NUM | +|event_type |TEXT | +|sub_type_id |NUM | |start_ts |INT | |end_ts |INT | |dur |INT | |addr |INT | |heap_size |INT | |all_heap_size |INT | -#### 字段详细描述: +|current_size_dur |INT | +|last_lib_id |INT | +#### 表描述 +记录native_hook抓取的某个进程的堆内存,内存映射相关数据。 +#### 关键字段描述 +callChainId:唯一标识一条native_hook数据 +event_type:事件类型取值范围(AllocEvent,FreeEvent,MmapEvent, MunmapEvent) +sub_type_id:子事件类型(只有sub_type字段为MmapEvent时,该字段才会有值) +start_ts:申请内存开始时间 +end_ts:释放内存时间 +Dur:申请内存活跃时间 +Addr:申请内存地址 +mem_size:申请或释放内存大小 +all_mem_size:从采集数据开始到当前时刻,申请并活跃的内存总量。 event_type为AllocEvent或者FreeEvent时,表示活跃的堆内存总量。当event_type为MmapEvent或者MunmapEvent时,表示活跃的映射内存总量 +current_size_dur:表示当前活跃内存总量的持续时间 +last_lib_id:函数调用栈他最后一个函数所属的文件路径,除了文件名中带musl和libc++ -### heap_frame表 -#### 表结构: +### native_hook_frame表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | -|eventId |INT | +|id |INT | +|callchain_id |INT | |depth |INT | -|ip |INT | -|sp |INT | -|symbol_name |NUM | -|file_path |NUM | +|symbol_id |INT | +|file_id |INT | |offset |INT | |symbol_offset |INT | -#### 表描述: +#### 表描述 记录了内存的申请和释放的堆栈。 -### hidump表 -#### 表结构: +#### 相关字段描述 +callchain_id:标识一组调用堆栈 +depth:调用栈深度 +symbol_id:函数名 +file_id:函数所属文件 + +### network表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | |ts |INT | -|fps |INT | -#### 表描述: -此表记录了设备的帧率信息,fps。 -### symbols表 -#### 表结构: +|dur |INT | +|tx |INT | +|rx |INT | +|tx_speed |REAL | +|rx_speed |REAL | +|packet_in |INT | +|packet_in_sec |REAL | +|packet_out |INT | +|packet_out_sec |REAL | +|net_type |TEXT | +#### 表描述 +记录了网络数据传输相关的信息。 +#### 主要字段描述 +tv_sec:时间,秒为单位 +tv_nsec:时间,纳秒为单位 +tx_bytes:网络数据的写入量 +rx_bytes:网络数据的读取量 + +### paged_memory_sample表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | |id |INT | -|funcname |NUM | -|addr |INT | -#### 表描述: -此表记录了数值和函数调用名称的映射关系。 +|callchain_id |INT | +|type |INT | +|ipid |INT | +|start_ts |INT | +|end_ts |INT | +|dur |INT | +|size |INT | +|addr |TEXT | +|itid |INT | +#### 表描述 +记录了网络数据传输相关的信息。 +#### 主要字段描述 +callchain_id: 取值相同的一组数据,表示一个完整的调用栈 +type:事件类型 +ipid:TS内部进程号 +start_ts:开始时间 +end_ts:结束时间 +dur:持续时间 +size:操作页数 +itid:TS内部线程号 -### measure_filter表 -记录一个递增的filterid队列,所有其他的filter类型在获取过程中,均从此数据列表中获取下一个可用的filter_id并做记录。 -#### 表结构: -| Columns Name | SQL TYPE | -|---- |---- | -|id |NUM | -|type |NUM | -|name |INT | -|source_arg_set_id |INT | +### perf_callchain表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|callchain_id |INT | +|depth |INT | +|vaddr_in_file |INT | +|file_id |INT | +|symbol_id |INT | +|name |TEXT | +#### 表描述 +记录了Hiperf采样数据的调用栈信息。 +#### 主要字段描述 +callchain_id:标识一组调用堆栈 +depth:调用栈深度 +vaddr_in_file:函数在文件中的虚拟地址 +file_id:与PerfFiles中的file_id字段相关联 +symbol_id:与PerfFiles中的symbol_id相关联 +name:函数名 + +### perf_files表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|file_id |INT | +|serial_id |INT | +|symbol |TEXT | +|path |TEXT | +#### 表描述 +记录Hiperf工具采集到的函数符号表和文件名。 +#### 主要字段描述 +file_id:文件编号 +serial_id:一个文件中可能有多个函数,serial_id表示函数的编号 +symbol:函数名 +path:文件路径 + +### perf_report表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|report_type |TEXT | +|report_value |TEXT | +#### 表描述 +记录Hiperf工具采集数据时的配置信息。包括:抓取的事件类型,抓取数据的命令, 抓数据时指定的进程名称。 +#### 主要字段描述 +report_type:数据类型。取值只有三种类型:config_name(事件类型), workload(抓取的进程名), cmdline(抓取命令) +report_value:对应类型的取值 + +### perf_sample表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|callchain_id |INT | +|timestamp |INT | +|thread_id |INT | +|event_count |INT | +|event_type_id |INT | +|timestamp_trace |INT | +|cpu_id |INT | +|thread_state |TEXT | +#### 表描述 +记录Hiperf工具的采样信息。 +#### 主要字段描述 +timestamp:未进行时钟源同步的时间戳 +thread_id:线程号 +event_count:采样统计 +event_type_id:事件类型编号。与PerfReport表的id字段相关联 +timestamp_trace:时钟源同步后的时间戳 +cpu_id:cpu核编号 +thread_state:线程状态。采样对应Sched_Waking事件时,为Runing;对应Sched_Switch事件时,为Suspend。其余事件类型,为“-” + +### perf_thread表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|thread_id |INT | +|process_id |INT | +|thread_name |TEXT | +#### 表描述 +记录Hiperf工具采集到的进程和线程数据。 +#### 主要字段描述 +thread_id:线程号 +process_id:进程号 +thread_name:线程名 + +### process表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|ipid |INT | +|type |TEXT | +|pid |INT | +|name |TEXT | +|start_ts |INT | +|switch_count |INT | +|thread_count |INT | +|slice_count |INT | +|mem_count |INT | +#### 表描述 +记录了进程相关数据。 +#### 关键字段描述 +id:进程在数据库重新重新定义的id,从0开始序列增长 +ipid:TS内部进程id +type:固定取值:process +pid:进程的真实id +name:进程名字 +start_ts:开始时间 +switch_count:统计其切换次数 +thread_count:统计其线程个数 +slice_count:进程是否有线程和线程切换数据 +mem_count:进程是否有内存数据 + +### process_filter表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |TEXT | +|name |TEXT | +|ipid |INT | +#### 表描述 +将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id, filter_id同时被记录在filter表中。 +#### 主要字段描述 +id:进程id +type:固定取值:process_filter +name:进程名 +ipid:该进程表中的id与process表中的id相关联 + +### process_measure表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|type |TEXT | +|ts |INT | +|value |NUM | +|filter_id |INT | +#### 表描述 +保存进程的内存,堆栈值等所有计量值信息。 +#### 字段详细描述 +ts:事件时间 +value:数值 +filter_id:对应process_measure_filter表中的ID -#### 字段详细描述: -过滤分类(type),过滤名称(key2),数据ID(key1)。 -数据ID在process_measure_filter, sys_event_filter中作为id。 ### process_measure_filter表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |TEXT | +|name |TEXT | +|ipid |INT | +#### 表描述 将进程ID作为key1,进程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id, filter_id同时被记录在measure_filter表中。 -#### 表结构: +#### 字段详细描述 +type:固定取值:process_measure_filter +name:cpu状态名 +ipid:进程内部编号 + +### raw表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|type |TEXT | +|ts |INT | +|name |TEXT | +|cpu |INT | +|itid |INT | +#### 表描述 +记录了系统中的waking、wakup、cpu_idel、cpu_frequency数据。 +#### 相关字段描述 +type:固定字段(raw) +name:调度名称(取值:cpu_idle,sched_wakeup,sched_waking) +cpu:事件发生在哪个CPU +itid:时间对应哪个utid + +### sched_slice表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | |id |INT | -|type |NUM | -|name |NUM | +|type |TEXT | +|ts |INT | +|dur |INT | +|ts_end |INT | +|cpu |INT | +|itid |INT | +|end_state |TEXT | +|priority |INT | +#### 表描述 +此数据结构主要作为ThreadState的上下文使用,这张表是sched_switch事件的原始记录。 +#### 主要字段描述 +ts:事件发生事件 +type:固定字段(sched_slice) +dur:状态持续时长 +ts_end:状态结束时长 +cpu:事件发生在哪个cpu +itid:事件对应哪个utid +end_state:线程的终结状态 + +### smaps表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|timestamp |INT | +|start_addr |TEXT | +|end_addr |TEXT | +|dirty |INT | +|swapper |INT | +|resident_size |INT | +|pss |INT | +|virtaul_size |INT | +|reside |REAL | +|protection_id |INT | +|path_id |INT | +#### 表描述 +记录进程的内存消耗的相关信息采样。 +#### 主要字段描述 +id:状态持续时长 +timestamp:事件发生事件 +start_addr:内存段地址的起始位置 +end_addr:内存段地址的结束位置 +dirty:其他进程共享的被写的页的大小 + 已被改写的私有页面的大小 +swapper:存在于交换分区的数据大小 +resident_size:实际分配的内存大小 +pss:平摊计算后的实际物理使用内存 +virtaul_size:虚拟内存空间的大小 +reside:实际分配的内存大小与虚拟内存空间的大小的比 +protection_id:内存段的权限id与表data_dict的id字段相关联 +path_id:如果区域是从文件映射的,则这是文件的名称对应的id序号与表data_dict的id字段相关联 + +### stat表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|event_name |TEXT | +|stat_type |TEXT | +|count |INT | +|serverity |TEXT | +|source |TEXT | +#### 表描述 +此结果用来统计数据解析中各类数据的数据条数,数据和合法性,数据的匹配程度(begin-end),数据的损失等,查看此结构对应的表,可对数据源有基本的了解。 +#### 主要字段描述 +event_name:数据类型 +stat_type:数据状态 +count:数据条数 +severity:严重级别 +source:数据来源 + +### symbols表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|funcname |TEXT | +|addr |INT | +#### 表描述 +此表记录了被调用函数与其地址的映射关系。 +#### 相关字段描述 +funcname:系统调用名称 +adr:系统调用地址 + +### syscall表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|syscall_num |INT | +|type |TEXT | |ipid |INT | -#### 字段详细描述: -filterid: 来自measure_filter表 -name: cpu状态名 -ipid: 进程内部编号 -### data_type表 -#### 表结构: +|ts |INT | +|ret |INT | +#### 表描述 +记录用户空间函数与内核空间函数相互调用记录。 +#### 相关字段描述 +syscall_num:系统调用的序号 +type:固定取值:enter或者exit +ipid:线程所属的进程ID +ts:时间戳 +ret:返回值,在type为exit时有效 + +### sys_event_filter表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | |id |INT | -|typeId |INT | -|desc |NUM | -#### 表描述: -此表记录了一个数据类型ID和数据描述的映射。 -### data_dict表 -#### 表结构: +|type |TEXT | +|name |TEXT | +#### 表描述 +记录所有的filter。 +#### 相关字段描述 +type:文件类型 +name:文件名 + +### sys_mem_measure表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|type |TEXT | +|ts |INT | +|value |INT | +|filter_id |INT | +#### 表描述 +记录系统内存与系统虚拟内存。 +#### 相关字段描述 +ts:事件时间 +value:数值 +filter_id:对应filter表中的ID + +### thread表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|id |INT | +|itid |INT | +|type |TEXT | +|tid |INT | +|name |TEXT | +|start_ts |INT | +|end_ts |INT | +|ipid |INT | +|is_main_thread|INT | +|switch_count |INT | +#### 表描述 +记录了线程相关数据。 +#### 字段详细描述 +id:线程在数据库重新重新定义的id,从0开始序列增长 +itid:TS内部线程id +type:固定字段(thread) +tid:线程号 +name:线程名 +start_ts:开始时间 +end_ts:结束时间 +ipid:线程所属的进程id, 关联process表中的ID +is_main_thread:是否主线程,主线程即该线程实际就是进程本身 +switch_count:当前线程的切换次数 + +### thread_filter表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | |id |INT | -|data |NUM | -#### 表描述: -此表记录了一个数据类型ID和字符串的映射。 -### meta表 -#### 表结构: +|type |TEXT | +|name |TEXT | +|itid |INT | +#### 表描述 +将线程ID作为key1,线程的内存,界面刷新,屏幕亮度等信息作为key2,唯一确定一个filter_id, filter_id同时被记录在filter表中。 +#### 主要字段描述 +id:线程id +type:线程类型 +name:线程名称 +itid:该表中的tid与thread表中的tid相关联 + +### thread_state表 +#### 表结构 | Columns Name | SQL TYPE | |---- |---- | -|name |NUM | -|value |NUM | -#### 表描述: -此表记录了数据解析或导出时的一些现场数据,比如使用的trace_streamer版本, 工具的发布时间,数据解析的时间,数据的持续时长,以及原始数据的格式。 +|id |INT | +|type |TEXT | +|ts |INT | +|dur |INT | +|cpu |INT | +|itid |INT | +|tid |INT | +|pid |INT | +|state |TEXT | +#### 表描述 +记录了线程状态相关的数据。 +#### 字段详细描述 +id:线程状态在数据库中的id,从0开始序列增长 +ts:该线程状态的起始时间 +dur:该线程状态的持续时间 +cpu:该线程在哪个cpu上执行(针对running状态的线程) +itid:该状态所属的线程id, 关联线程表中的id +tid:线程号 +pid:进程号 +state:线程实际的的状态值 +``` +'R', Runnable状态 +'S', interruptible sleep +'D', uninterruptible sleep +'T', Stoped +'t', Traced +'X', ExitedDead +'Z', ExitZombie +'x', TaskDead +'I', TaskDead +'K', WakeKill +'P', Parked +'N', NoLoad +``` + +### clock_snapshot表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|clock_id |INT | +|ts |INT | +|clock_name |TEXT | +#### 表描述 +时钟号和时间,时钟名的映射表。 +#### 关键字段描述 +clock_id:时钟号 +ts:时钟快照报的时间 +clock_name:时钟号对应的时钟名字 +时钟快照是用来对齐不同时钟号的时间。 +比如,时钟号1的时间100,和时钟号2的时间200对齐。 +则时钟号为2 的250,转换为时钟号1的时间后,为150 + +### datasource_clockid表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|data_source_name |TEXT | +|clock_id |INT | +#### 表描述 +数据源和时钟号的映射表。 +#### 关键字段描述 +data_source_name:数据源的名称,和数据源的插件名保持一致 +clock_id:时钟号,对应clock_snapshot中的时钟号 +这个表是用来告诉IDE,不同的事件源的事件,原始时钟号是多少,在数据库中保存的事件,通常是转换为boottime后的时间,但有些情况下,IDE仍然需要知道原始的时钟号是怎样的 + +### trace_range表 +#### 表结构 +| Columns Name | SQL TYPE | +|---- |---- | +|start_ts |INT | +|end_ts |INT | +#### 表描述 +记录解析解析开始时间以及结束时间。 +#### 关键字段描述 +start_ts:trace的开始时间,纳秒为单位 +end_ts:trace的结束时间,纳秒为单位 \ No newline at end of file diff --git a/host/trace_streamer/doc/des_wakeup.md b/host/trace_streamer/doc/des_wakeup.md new file mode 100644 index 0000000000000000000000000000000000000000..c6675cef62c52e81be59a2cd0afb06802ed75c1c --- /dev/null +++ b/host/trace_streamer/doc/des_wakeup.md @@ -0,0 +1,4 @@ +# 关于wakeup事件和waking事件的处理说明 +对于trace事件的waking和wakeup处理,我们的策略如下: +waking是开始唤醒线程,wakeup是线程正式被唤醒,进入runnable(可运行状态); +我们的策略是:被唤醒才是真正进入runnable状态,在没有wakeup事件的情况下,以waking为准。 \ No newline at end of file diff --git a/host/trace_streamer/figures/db_common.png b/host/trace_streamer/figures/db_common.png new file mode 100755 index 0000000000000000000000000000000000000000..29dbb080e1d213672b74d553610f6a24445663ad Binary files /dev/null and b/host/trace_streamer/figures/db_common.png differ diff --git a/host/trace_streamer/figures/db_hiperf.png b/host/trace_streamer/figures/db_hiperf.png new file mode 100755 index 0000000000000000000000000000000000000000..85cacf15a7153a0853c7aeee2fe34fba1f8983a8 Binary files /dev/null and b/host/trace_streamer/figures/db_hiperf.png differ diff --git a/host/trace_streamer/figures/db_hisys_event.png b/host/trace_streamer/figures/db_hisys_event.png new file mode 100755 index 0000000000000000000000000000000000000000..215265182de684f1b4a31fd7158309f8c7532053 Binary files /dev/null and b/host/trace_streamer/figures/db_hisys_event.png differ diff --git a/host/trace_streamer/figures/db_native_memory.png b/host/trace_streamer/figures/db_native_memory.png new file mode 100755 index 0000000000000000000000000000000000000000..0e1403e958fbf76f3d2c31fc6304426de6579afb Binary files /dev/null and b/host/trace_streamer/figures/db_native_memory.png differ diff --git a/host/trace_streamer/figures/dump_and_mem.png b/host/trace_streamer/figures/dump_and_mem.png old mode 100644 new mode 100755 index b7e3cc26ca286702c9ca9869fc203aff34a8da39..2c3f59eef7476de91cafb8f59832c93fe4117e51 Binary files a/host/trace_streamer/figures/dump_and_mem.png and b/host/trace_streamer/figures/dump_and_mem.png differ diff --git a/host/trace_streamer/figures/log.png b/host/trace_streamer/figures/log.png old mode 100644 new mode 100755 index dbe3780eb647493dec252d69f23e71cf66ac15a8..0c9ac304183f2276454caeb2fea593a5e88bdc13 Binary files a/host/trace_streamer/figures/log.png and b/host/trace_streamer/figures/log.png differ diff --git a/host/trace_streamer/figures/perf.png b/host/trace_streamer/figures/perf.png new file mode 100755 index 0000000000000000000000000000000000000000..9fc88ad255cece0040093392329e639e261c8bd9 Binary files /dev/null and b/host/trace_streamer/figures/perf.png differ diff --git a/host/trace_streamer/figures/process_thread.png b/host/trace_streamer/figures/process_thread.png old mode 100644 new mode 100755 index abc3867130c10413197482d0156ce0ee00aca255..305a9bdb02d7776f086f8f13d5f6f72e72443226 Binary files a/host/trace_streamer/figures/process_thread.png and b/host/trace_streamer/figures/process_thread.png differ diff --git a/host/trace_streamer/figures/thread_state.png b/host/trace_streamer/figures/thread_state.png old mode 100644 new mode 100755 index 186ffb16905c7cfa0178f7c14a0189223f6c9e22..aa9f846fcc4b88c1b8e9df75e3aff7ada69537dc Binary files a/host/trace_streamer/figures/thread_state.png and b/host/trace_streamer/figures/thread_state.png differ diff --git a/host/trace_streamer/gn/BUILD.gn b/host/trace_streamer/gn/BUILD.gn old mode 100644 new mode 100755 index a44389bdd809eccfeeb146bb62d42242f4a1c6ae..53914a5d744d46531250393481a313460d524721 --- a/host/trace_streamer/gn/BUILD.gn +++ b/host/trace_streamer/gn/BUILD.gn @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. print("target_os", target_os) +print("target_name", target) group("default_deps") { public_configs = [ ":default_config" ] public_deps = [] @@ -24,10 +25,17 @@ config("default_config") { config("trace_cfg") { cflags_cc = [ "-std=c++17", - "-fno-rtti", - "-fno-exceptions", + + # "-std=gnu++17", "-fvisibility=hidden", + "-Wno-unused-variable", ] + if (!is_test) { + cflags_cc += [ + "-fno-rtti", + "-fno-exceptions", + ] + } } config("visibility_hidden") { @@ -41,12 +49,14 @@ config("default") { cflags = [ "-fstrict-aliasing", - "-fPIC", "-g", "-Wformat", + "-Wno-unused-variable", ] - - if (is_linux) { + if (is_debug && is_win) { + ldflags = [ "-fstack-protector" ] + } + if (is_linux || is_macx) { cflags += [ "-Wa,--noexecstack", "-fcolor-diagnostics", @@ -55,25 +65,73 @@ config("default") { ] if (!use_wasm) { cflags += [ - "-fPIE", "-fstack-protector-strong", "-fstack-protector-all", "-D_FORTIFY_SOURCE=2 -O2", + "-D SUPPORTTHREAD", # if support thread + + # "-D HAVE_ELF_H", + "-D target_cpu_x64", + + # "-D HAVE_LINK_H", + # "-D_GNU_SOURCE", + "-DHAVE_CONFIG_H", + "-DNDEBUG", + "-DCC_IS_CLANG", ] + # with_libunwind = true } - libs += [ - "pthread", - "rt", - ] - if (is_debug) { - libs += [ "dl" ] + if (!use_wasm && !is_win && !is_macx && !is_test) { + cflags += [ "-D HAVE_LIBUNWIND" ] + } + + cflags += [ "-D USE_VTABLE" ] + if (use_wasm) { + cflags += [ + "-D IS_WASM", + "-D GOOGLE_PROTOBUF_NO_RDTSC", + + # "-D HAVE_LIBUNWIND", + "-D target_cpu_x64", + "-DHAVE_CONFIG_H", + "-DNDEBUG", + "-DCC_IS_CLANG", + "-D__x86_64__", + ] + } + cflags += [ "-D BINDER_ASYNC" ] + libs += [ "pthread" ] + if (!is_macx) { + libs += [ "rt" ] + } + if (!is_win) { + cflags += [ + "-fPIE", + "-fPIC", + ] } } + if (is_win) { + cflags += [ "-D is_mingw" ] + defines = [ "WIN32_LEAN_AND_MEAN" ] + libs += [ "wsock32" ] + libs += [ "Ws2_32" ] + cflags += [ + "-D SECUREC_IS_DLL_LIBRARY", + "-D __KERNEL__", + ] + } + if (with_perf) { + cflags += [ "-D WITH_PERF" ] + } + if (with_ebpf_help_table) { + cflags += [ "-D WITH_EBPF_HELP" ] + } } config("symbols") { cflags = [ "-O0" ] - if (is_linux) { + if (is_linux || is_macx) { cflags += [ "-funwind-tables" ] } } @@ -85,42 +143,69 @@ config("release") { ] cflags += [ "-O3" ] - ldflags = [ - "-fuse-ld=gold", - "-fstack-protector", - "-Wl,--gc-sections", - "-Wl,-O1", - "-fpie", - "-pie", - ] + ldflags = [ "-fstack-protector" ] + if (!is_macx) { + ldflags += [ "-Wl,-O1" ] + if (!is_win) { + ldflags += [ + "-fuse-ld=gold", + "-Wl,--gc-sections", + ] + } + } + + if (!is_win && !is_macx) { + ldflags += [ + "-fPIC", + "-fpie", + "-pie", + ] + } defines = [ "NDEBUG" ] } config("shared_library") { - ldflags = [ "-fPIC" ] + if (!is_win) { + ldflags = [ "-fPIC" ] + } } config("executable") { print("use_wasm", use_wasm) ldflags = [] - if (is_linux && !use_wasm) { - ldflags += [ - # "-Wl,-rpath=\$ORIGIN/.", + if (is_linux || (is_macx && !use_wasm)) { + ldflags += [] + } + if (!is_macx && !use_wasm && !is_win) { + ldflags = [ + "-Wl,--disable-new-dtags", + "-Wl,-z,noexecstack", + "-lrt", + "-fuse-ld=gold", "-Wl,-z,now", - - # "-Wl,-rpath-link=.", "-Wl,-z,relro", - "-lrt", - "-fpie", - "-pie", - "-Wl,-z,noexecstack", - "-Wl,--disable-new-dtags", + ] + } + if (!is_macx && !use_wasm) { + ldflags += [ "-fpie" ] + } + if (!is_macx && !use_wasm && !is_win) { + ldflags += [ "-pie" ] + } - # "-s", # delete sambols + if (is_macx) { + ldflags += [ + "-fdata-sections", + "-ffunction-sections", ] + if (!use_wasm) { + ldflags += [ "-Wl,-U,__sanitizer_options_link_helper" ] + } } - if (!is_debug) { + if (!is_debug && !is_macx) { ldflags += [ "-s" ] + } else if (!is_debug && is_macx) { + ldflags += [ "-dead_strip" ] } } diff --git a/host/trace_streamer/gn/CONFIG.gn b/host/trace_streamer/gn/CONFIG.gn old mode 100644 new mode 100755 index babf9755e98d0478a5f2d895668a9d296c026c0d..fc52b2f69947f7aa1da034aeb7080fe14620aab1 --- a/host/trace_streamer/gn/CONFIG.gn +++ b/host/trace_streamer/gn/CONFIG.gn @@ -12,32 +12,59 @@ # limitations under the License. is_win = false is_linux = false +is_macx = false +is_protoc = false +with_perf = true +with_ebpf_help_table = false +is_mingw = false +with_libunwind = false +is_sdkdemo = false +is_sdkdemo_test = false +target_cpu = "x64" declare_args() { ar = "ar" is_debug = true use_wasm = false is_test = false + is_sdkdemo = false + is_sdkdemo_test = false + testonly = false + is_fuzz = false + is_macx = false + target = "trace_streamer" } if (target_os == "linux") { - is_win = false is_linux = true - is_test = false +} else if (target_os == "macx") { + is_macx = true } else if (target_os == "windows") { is_win = true - is_linux = false - is_test = false -} else if (target_os == "wasm") { - is_win = false - is_linux = true + is_mingw = true +} else { + print("unknown platform " + target_os) + exit(-1) +} + +if (target == "wasm") { use_wasm = true - is_test = false -} else if (target_os == "test") { - is_win = false - is_linux = true - use_wasm = false +} else if (target == "test") { is_test = true + testonly = true +} else if (target == "fuzz") { + is_fuzz = true + testonly = true +} else if (target == "protoc") { + is_protoc = true +} else if (target == "sdkdemo") { + is_sdkdemo = true + use_wasm = true +} else if (target == "sdkdemotest") { + is_sdkdemo_test = true + testonly = true +} else if (target == "trace_streamer" || target == "streamer") { + print("build " + target) } else { - print("unknown platform " + target_os) + print("unknown target " + target_os) exit(-1) } @@ -55,11 +82,16 @@ if (!is_debug) { default_configs -= [ "//gn:symbols" ] default_configs += [ "//gn:release" ] } +if (is_debug) { + with_ebpf_help_table = true +} set_defaults("ohos_source_set") { configs = default_configs } - +set_defaults("ohos_shared_library") { + configs = default_configs +} set_defaults("executable") { configs = default_configs configs += [ "//gn:executable" ] diff --git a/host/trace_streamer/gn/toolchain/BUILD.gn b/host/trace_streamer/gn/toolchain/BUILD.gn old mode 100644 new mode 100755 index e1b24fd43144cd73b0ff6dfff19499fef1b9f63c..3b31509464aa0660a9b73a9d08b4865bff5d292d --- a/host/trace_streamer/gn/toolchain/BUILD.gn +++ b/host/trace_streamer/gn/toolchain/BUILD.gn @@ -13,12 +13,20 @@ import("//gn/wasm.gni") declare_args() { - if (target_os == "linux" || target_os == "wasm" || target_os == "test") { + if (target_os == "linux" || target_os == "macx") { cc = "/usr/bin/clang" cxx = "/usr/bin/clang++" + pic = "-fPIC" + rebuild_string = "" + extra_asmflags = "" + asm = "/usr/bin/clang" } else if (target_os == "windows") { - cc = "~/mingw-w64/ohos/linux-x86_64/clang-mingw/bin/clang" - cxx = "~/mingw-w64/ohos/linux-x86_64/clang-mingw/bin/clang++" + cc = "gcc.exe" + cxx = "g++.exe" + rebuild_string = "" + extra_asmflags = "" + asm = "gcc.exe" + pic = "" } if (use_wasm == true) { print("make_wasm") @@ -26,12 +34,13 @@ declare_args() { print("no make_wasm") } cc_wrapper = "" - is_mac = false } toolchain("wasm") { # emsdk_dir and em_config are defined in wasm.gni. print("use gcc_like_chain wasm") - ar = "$emsdk_dir/emscripten/emar --em-config $em_config" + if (!is_macx) { + ar = "$emsdk_dir/emscripten/emar --em-config $em_config" + } cc = "$emsdk_dir/emscripten/emcc --em-config $em_config" cxx = "$emsdk_dir/emscripten/em++ --em-config $em_config" @@ -82,7 +91,11 @@ toolchain("wasm") { tool("alink") { rspfile = "{{output}}.rsp" # must be defined rspfile_content = "{{inputs}}" - command = "rm -rf {{output}} && $ar rcsD {{output}} @$rspfile" + if (is_macx) { + command = "rm -f {{output}} && libtool -static {{arflags}} -o {{output}} -filelist $rspfile" + } else { + command = "rm -rf {{output}} && $ar rcsD {{output}} @$rspfile" + } outputfiles = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" outputs = [ outputfiles ] output_prefix = "lib" @@ -124,7 +137,7 @@ toolchain("gcc_like") { tool("cxx") { depfile = "{{output}}.d" # must be defined - command = "$cxx -o {{output}} -MMD -MF $depfile {{defines}} -fPIC {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}}" + command = "$cxx -o {{output}} -MMD -MF $depfile {{defines}} $pic {{include_dirs}} {{cflags}} {{cflags_cc}} -c {{source}}" outputfiles = "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" outputs = [ outputfiles ] @@ -133,16 +146,29 @@ toolchain("gcc_like") { tool("cc") { depfile = "{{output}}.d" - command = "$cc -o {{output}} -MMD -MF $depfile {{defines}} -fPIC {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}}" + command = "$cc -o {{output}} -MMD -MF $depfile {{defines}} $pic {{include_dirs}} {{cflags}} {{cflags_c}} -c {{source}}" outputfiles = "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" outputs = [ outputfiles ] description = "step: compile {{source}}" } + tool("asm") { + depfile = "{{output}}.d" + command = "$asm -o {{output}} -MMD -MF $depfile ${rebuild_string}{{defines}} {{include_dirs}} {{asmflags}}${extra_asmflags} -c {{source}}" + depsformat = "gcc" + outputfiles = + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.o" + outputs = [ outputfiles ] + } tool("alink") { rspfile = "{{output}}.rsp" # this must be defined - rspfile_content = "{{inputs}}" # this must be defined - command = "rm -f {{output}} && $ar rcsD {{output}} @$rspfile" + if (is_macx) { + rspfile_content = "{{inputs_newline}}" + command = "rm -f {{output}} && libtool -static {{arflags}} -filelist $rspfile -o {{output}}" + } else { + rspfile_content = "{{inputs}}" # this must be defined + command = "rm -f {{output}} && $ar rcsD {{output}} @$rspfile" + } outputsfiles = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" outputs = [ outputsfiles ] default_output_extension = ".a" diff --git a/host/trace_streamer/gn/wasm.gni b/host/trace_streamer/gn/wasm.gni index 7209ff6666891129c98ee7cce901d63564e7bd88..b4c986495cbb7afe176ebaa0972e22e932b6fa75 100644 --- a/host/trace_streamer/gn/wasm.gni +++ b/host/trace_streamer/gn/wasm.gni @@ -46,6 +46,7 @@ template("wasm_lib") { "EXPORT_NAME=${target_name}", "-s", "MODULARIZE=1", + "-lworkerfs.js", # For FS.filesystems.WORKERFS ] _lib_name = invoker.name if (is_debug) { @@ -61,10 +62,10 @@ template("wasm_lib") { ] } else { _target_ldflags += [ - "-g2", # Required for getting C++ symbol names. + # "-g2", # Required for getting C++ symbol names. "-O3", - "-s", - "ASSERTIONS=1", + # "-s", + # "ASSERTIONS=1", ] } diff --git a/host/trace_streamer/pare_third_party.sh b/host/trace_streamer/pare_third_party.sh new file mode 100755 index 0000000000000000000000000000000000000000..7135a968dde59de998a6edc9bdf9a0d346ac473e --- /dev/null +++ b/host/trace_streamer/pare_third_party.sh @@ -0,0 +1,100 @@ +#!/bin/bash +# 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. + +patch='patch' +sed='sed' +case "$OSTYPE" in + msys*) patch='patch.exe' sed='sed.exe' ;; + darwin*) out='../../out/macx' ;; + linux*) out='../../out/linux' ;; + *) echo "other: $OSTYPE" ;; +esac + +if [ ! -d "third_party" ];then + mkdir third_party +fi +cd third_party + +if [ ! -f "sqlite/BUILD.gn" ];then + rm -rf sqlite + git clone git@gitee.com:openharmony/third_party_sqlite.git + if [ -d "third_party_sqlite" ];then + mv third_party_sqlite sqlite + $patch -p0 ../third_party/sqlite/BUILD.gn ../prebuilts/patch_sqlite/sqlite3build.gn.patch + else + echo 'third_party_sqlite not exist' + fi +fi +if [ ! -f "protobuf/BUILD.gn" ];then + rm -rf protobuf + git clone git@gitee.com:openharmony/third_party_protobuf.git + if [ -d "third_party_protobuf" ];then + mv third_party_protobuf protobuf + $patch -p0 ../third_party/protobuf/BUILD.gn ../prebuilts/patch_protobuf/protobufbuild.gn.patch + else + echo 'third_party_protobuf not exist' + fi +fi + +if [ ! -f "googletest/BUILD.gn" ];then + rm -rf googletest + git clone git@gitee.com:openharmony/third_party_googletest.git + if [ -d "third_party_googletest" ];then + mv third_party_googletest googletest + $patch -p0 ../third_party/googletest/BUILD.gn ../prebuilts/patch_googletest/googletestbuild.gn.patch + $patch -p0 ../third_party/googletest/googletest/include/gtest/internal/gtest-internal.h ../prebuilts/patch_googletest/gtest_internal.h.patch + $patch -p0 ../third_party/googletest/googletest/include/gtest/internal/gtest-port.h ../prebuilts/patch_googletest/gtest_port.h.patch + $patch -p0 ../third_party/googletest/googletest/include/gtest/gtest-message.h ../prebuilts/patch_googletest/gtest-message.h.patch + $sed -i "/using ::std::string/s/^\(.*\)$/\/\/\1/g" ../third_party/googletest/googletest/include/gtest/hwext/gtest-tag.h + + else + echo 'third_party_googletest not exist' + fi +fi + +if [ ! -f "json-master/BUILD.gn" ];then + rm -rf json-master + git clone git@gitee.com:openharmony/third_party_json.git + if [ -d "third_party_json" ];then + mv third_party_json json-master + else + echo 'third_party_json not exist' + 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 + $patch -p0 libunwind/BUILD.gn ../prebuilts/patch_libunwind/libunwindbuild.gn.patch + else + echo 'third_party_libunwind not exist' + fi +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/master/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 +fi + +if [ ! -f "perf_include/musl/elf.h" ];then + mkdir -p perf_include/musl + rm -rf elf.h + curl https://gitee.com/openharmony/third_party_musl/raw/master/include/elf.h > elf.h + mv elf.h perf_include/musl/elf.h +fi \ No newline at end of file diff --git a/host/trace_streamer/prebuilts/buildprotobuf/libprotobuf_lite_la_SOURCES.pri b/host/trace_streamer/prebuilts/buildprotobuf/libprotobuf_lite_la_SOURCES.pri deleted file mode 100644 index 39c051faf41b82d7cf1e62dda7c147eeb95d9494..0000000000000000000000000000000000000000 --- a/host/trace_streamer/prebuilts/buildprotobuf/libprotobuf_lite_la_SOURCES.pri +++ /dev/null @@ -1,64 +0,0 @@ -# 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. - message("qmake" $${PROTOBUDIR}"/src") -win32 { -SOURCES += $${PROTOBUDIR}/src/google/protobuf/io/io_win32.cc -} -SOURCES += \ - $${PROTOBUDIR}/src/google/protobuf/stubs/bytestream.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/common.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/int128.cc \ -# $${PROTOBUDIR}/src/google/protobuf/stubs/once.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/int128.h \ -# $${PROTOBUDIR}/src/google/protobuf/io/io_win32.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/status.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/statusor.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/statusor.h \ - $${PROTOBUDIR}/src/google/protobuf/stubs/stringpiece.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/stringprintf.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/structurally_valid.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/strutil.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/time.cc \ -# $${PROTOBUDIR}/src/google/protobuf/any_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/arena.cc \ -# $${PROTOBUDIR}/src/google/protobuf/arenastring.cc \ - $${PROTOBUDIR}/src/google/protobuf/extension_set.cc \ - $${PROTOBUDIR}/src/google/protobuf/generated_enum_util.cc \ - $${PROTOBUDIR}/src/google/protobuf/generated_message_util.cc \ -# $${PROTOBUDIR}/src/google/protobuf/generated_message_table_driven_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/implicit_weak_message.cc \ - $${PROTOBUDIR}/src/google/protobuf/message_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/parse_context.cc \ - $${PROTOBUDIR}/src/google/protobuf/repeated_field.cc \ -# $${PROTOBUDIR}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc \ -# $${PROTOBUDIR}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc \ - $${PROTOBUDIR}/src/google/protobuf/wire_format_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/io/coded_stream.cc \ - $${PROTOBUDIR}/src/google/protobuf/io/strtod.cc \ - $${PROTOBUDIR}/src/google/protobuf/io/zero_copy_stream.cc \ - $${PROTOBUDIR}/src/google/protobuf/io/zero_copy_stream_impl.cc \ - $${PROTOBUDIR}/src/google/protobuf/io/zero_copy_stream_impl_lite.cc - -HEADERS += \ - $${PROTOBUDIR}/src/google/protobuf/stubs/bytestream.h \ - $${PROTOBUDIR}/src/google/protobuf/stubs/hash.h \ - $${PROTOBUDIR}/src/google/protobuf/io/coded_stream_inl.h \ -# $${PROTOBUDIR}/src/google/protobuf/generated_message_table_driven_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/stubs/time.h \ - $${PROTOBUDIR}/src/google/protobuf/stubs/stringprintf.h \ - $${PROTOBUDIR}/src/google/protobuf/stubs/stringpiece.h \ - $${PROTOBUDIR}/src/google/protobuf/stubs/status.h \ - $${PROTOBUDIR}/src/google/protobuf/stubs/status_macros.h \ -# $${PROTOBUDIR}/src/google/protobuf/io/io_win32.h \ - $${PROTOBUDIR}/src/google/protobuf/stubs/map_util.h \ - $${PROTOBUDIR}/src/google/protobuf/stubs/mathutil.h diff --git a/host/trace_streamer/prebuilts/buildprotobuf/libprotoc_la_SOURCES.pri b/host/trace_streamer/prebuilts/buildprotobuf/libprotoc_la_SOURCES.pri deleted file mode 100644 index ed1da78266e36cf066115d956dfe442f8c2743d2..0000000000000000000000000000000000000000 --- a/host/trace_streamer/prebuilts/buildprotobuf/libprotoc_la_SOURCES.pri +++ /dev/null @@ -1,173 +0,0 @@ -# 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. - message("qmake" $${PROTOBUDIR}"/src/google/protobuf/compiler/") -SOURCES += \ - $${PROTOBUDIR}/src/google/protobuf/compiler/code_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/command_line_interface.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/plugin.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/plugin.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/subprocess.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/zip_writer.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_enum.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_enum_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_extension.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_file.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_helpers.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_map_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_service.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_string_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_context.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_field_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_extension.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_extension_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_file.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_generator_factory.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_helpers.cc \ -# $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_lazy_message_field.cc \ -# $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_map_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_map_field_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_builder.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_builder_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_field_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_name_resolver.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_primitive_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_primitive_field_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_shared_code_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_service.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_string_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_string_field_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_doc_comment.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/js/js_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/js/well_known_types_embed.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_enum.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_extension.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_file.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_message.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc \ -# $${PROTOBUDIR}/src/google/protobuf/compiler/php/php_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/python/python_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/ruby/ruby_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_enum.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_enum_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_field_base.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_generator.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_helpers.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_map_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_message.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_message_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc \ - -HEADERS += \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_padding_optimizer.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_primitive_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_options.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_service.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_string_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_field_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_context.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_enum_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_extension.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_map_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_map_field_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_helpers.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_file.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_generator_factory.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_extension_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_field_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_builder.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_message_builder_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_name_resolver.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_options.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_primitive_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_primitive_field_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_shared_code_generator.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_service.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_string_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_enum.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_string_field_lite.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/scc.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/subprocess.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/zip_writer.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_enum.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_enum_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_extension.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_file.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_helpers.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_map_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/cpp/cpp_message_layout_helper.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/java/java_doc_comment.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_extension.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_file.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_map_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_message.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_message_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_oneof.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_message_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_options.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_primitive_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_reflection_class.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_enum.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_enum_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_field_base.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_helpers.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_map_field.h \ - $${PROTOBUDIR}/src/google/protobuf/compiler/csharp/csharp_message.h \ diff --git a/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pri b/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pri deleted file mode 100644 index 1bfc0847435faaf99b4e88841f30d67c37d65530..0000000000000000000000000000000000000000 --- a/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pri +++ /dev/null @@ -1,69 +0,0 @@ -# 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. -PROTOBUDIR = $$PWD/../../third_party/protobuf - message("qmake" $${PROTOBUDIR}"/src/google/protobuf/") -SOURCES += \ -$${PROTOBUDIR}/src/google/protobuf/any.cc \ -$${PROTOBUDIR}/src/google/protobuf/any_lite.cc \ - $${PROTOBUDIR}/src/google/protobuf/any.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/api.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/importer.cc \ - $${PROTOBUDIR}/src/google/protobuf/compiler/parser.cc \ - $${PROTOBUDIR}/src/google/protobuf/descriptor.cc \ - $${PROTOBUDIR}/src/google/protobuf/descriptor.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/descriptor_database.cc \ - $${PROTOBUDIR}/src/google/protobuf/duration.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/dynamic_message.cc \ - $${PROTOBUDIR}/src/google/protobuf/empty.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/extension_set_heavy.cc \ - $${PROTOBUDIR}/src/google/protobuf/field_mask.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/generated_message_reflection.cc \ - $${PROTOBUDIR}/src/google/protobuf/generated_message_table_driven.cc \ - $${PROTOBUDIR}/src/google/protobuf/io/gzip_stream.cc \ - $${PROTOBUDIR}/src/google/protobuf/io/printer.cc \ - $${PROTOBUDIR}/src/google/protobuf/io/tokenizer.cc \ - $${PROTOBUDIR}/src/google/protobuf/map_field.cc \ - $${PROTOBUDIR}/src/google/protobuf/message.cc \ - $${PROTOBUDIR}/src/google/protobuf/reflection_ops.cc \ - $${PROTOBUDIR}/src/google/protobuf/service.cc \ - $${PROTOBUDIR}/src/google/protobuf/source_context.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/struct.pb.cc \ -# $${PROTOBUDIR}/src/google/protobuf/stubs/mathlimits.cc \ - $${PROTOBUDIR}/src/google/protobuf/stubs/substitute.cc \ - $${PROTOBUDIR}/src/google/protobuf/text_format.cc \ - $${PROTOBUDIR}/src/google/protobuf/timestamp.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/type.pb.cc \ - $${PROTOBUDIR}/src/google/protobuf/unknown_field_set.cc \ -# $${PROTOBUDIR}/src/google/protobuf/util/delimited_message_util.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/field_comparator.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/field_mask_util.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/datapiece.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/default_value_objectwriter.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/error_listener.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/field_mask_utility.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/json_escaping.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/json_objectwriter.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/json_stream_parser.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/object_writer.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/proto_writer.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/protostream_objectsource.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/protostream_objectwriter.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/type_info.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/type_info_test_helper.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/internal/utility.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/json_util.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/message_differencer.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/time_util.cc \ - $${PROTOBUDIR}/src/google/protobuf/util/type_resolver_util.cc \ - $${PROTOBUDIR}/src/google/protobuf/wire_format.cc \ - $${PROTOBUDIR}/src/google/protobuf/wrappers.pb.cc diff --git a/host/trace_streamer/prebuilts/patch_googletest/googletestbuild.gn.patch b/host/trace_streamer/prebuilts/patch_googletest/googletestbuild.gn.patch new file mode 100644 index 0000000000000000000000000000000000000000..7efd6627c4ec9f2ca379132b2141b72d1447d43c --- /dev/null +++ b/host/trace_streamer/prebuilts/patch_googletest/googletestbuild.gn.patch @@ -0,0 +1,191 @@ +--- googletest/BUILD.gn 2023-01-04 17:01:37.911633386 +0800 ++++ ../prebuilts/buildgoogletest/googletestbuild.gn 2022-11-29 14:31:52.355999207 +0800 +@@ -9,12 +9,6 @@ + + config("gtest_config") { + include_dirs = [ "googletest/include" ] +- if (is_mingw) { +- cflags_cc = [ +- "-Wno-unused-const-variable", +- "-Wno-unused-private-field", +- ] +- } + } + + static_library("gtest") { +@@ -23,9 +17,24 @@ + "googletest/include/gtest/gtest-spi.h", + "googletest/include/gtest/gtest.h", + ] ++ ++ cflags = [ ++ "-Wno-inconsistent-missing-override", ++ ++ # "-Dprivate=public", #allow test code access private members ++ "-fprofile-arcs", ++ "-ftest-coverage", ++ "-Wno-unused-command-line-argument", ++ "-Wno-format", ++ "-Wno-unused-const-variable", ++ "-Wno-unused-variable", ++ "-Wno-used-but-marked-unused", ++ "-Wno-exit-time-destructors", ++ "-Wno-missing-noreturn", ++ "-Wno-missing-noreturn", ++ ] + sources = [ + "googletest/include/gtest/gtest-death-test.h", +- "googletest/include/gtest/gtest-matchers.h", + "googletest/include/gtest/gtest-message.h", + "googletest/include/gtest/gtest-param-test.h", + "googletest/include/gtest/gtest-printers.h", +@@ -43,16 +52,18 @@ + "googletest/include/gtest/internal/gtest-death-test-internal.h", + "googletest/include/gtest/internal/gtest-filepath.h", + "googletest/include/gtest/internal/gtest-internal.h", ++ "googletest/include/gtest/internal/gtest-linked_ptr.h", ++ "googletest/include/gtest/internal/gtest-param-util-generated.h", + "googletest/include/gtest/internal/gtest-param-util.h", + "googletest/include/gtest/internal/gtest-port-arch.h", + "googletest/include/gtest/internal/gtest-port.h", + "googletest/include/gtest/internal/gtest-string.h", ++ "googletest/include/gtest/internal/gtest-tuple.h", + "googletest/include/gtest/internal/gtest-type-util.h", + "googletest/src/gtest-all.cc", + "googletest/src/gtest-death-test.cc", + "googletest/src/gtest-filepath.cc", + "googletest/src/gtest-internal-inl.h", +- "googletest/src/gtest-matchers.cc", + "googletest/src/gtest-port.cc", + "googletest/src/gtest-printers.cc", + "googletest/src/gtest-test-part.cc", +@@ -66,14 +77,31 @@ + sources -= [ "googletest/src/gtest-all.cc" ] + public_configs = [ ":gtest_config" ] + configs += [ ":gtest_private_config" ] +- configs -= [ "//build/config/coverage:default_coverage" ] ++ ++ # configs -= ["//build/config/coverage:default_coverage"] + } + + static_library("gtest_main") { + testonly = true + sources = [ "googletest/src/gtest_main.cc" ] ++ ++ cflags = [ ++ "-Wno-inconsistent-missing-override", ++ ++ # "-Dprivate=public", #allow test code access private members ++ "-fprofile-arcs", ++ "-ftest-coverage", ++ "-Wno-unused-command-line-argument", ++ "-Wno-format", ++ "-Wno-unused-const-variable", ++ "-Wno-unused-variable", ++ "-Wno-used-but-marked-unused", ++ "-Wno-exit-time-destructors", ++ "-Wno-missing-noreturn", ++ ] + public_deps = [ ":gtest" ] +- configs -= [ "//build/config/coverage:default_coverage" ] ++ ++ # configs -= ["//build/config/coverage:default_coverage"] + } + + config("gmock_private_config") { +@@ -92,26 +120,56 @@ + # fixed. + "-Wno-inconsistent-missing-override", + ] ++ cflags = [ ++ "-Wno-inconsistent-missing-override", ++ ++ # "-Dprivate=public", #allow test code access private members ++ "-fprofile-arcs", ++ "-ftest-coverage", ++ "-Wno-unused-command-line-argument", ++ "-Wno-format", ++ "-Wno-unused-const-variable", ++ "-Wno-unused-variable", ++ "-Wno-used-but-marked-unused", ++ "-Wno-exit-time-destructors", ++ "-Wno-missing-noreturn", ++ ] + } + + static_library("gmock") { + testonly = true + public = [ "googlemock/include/gmock/gmock.h" ] ++ cflags = [ ++ "-Wno-inconsistent-missing-override", ++ ++ # "-Dprivate=public", #allow test code access private members ++ "-fprofile-arcs", ++ "-ftest-coverage", ++ "-Wno-unused-command-line-argument", ++ "-Wno-format", ++ "-Wno-unused-const-variable", ++ "-Wno-unused-variable", ++ "-Wno-used-but-marked-unused", ++ "-Wno-exit-time-destructors", ++ "-Wno-missing-noreturn", ++ ] + sources = [ + "googlemock/include/gmock/gmock-actions.h", + "googlemock/include/gmock/gmock-cardinalities.h", +- "googlemock/include/gmock/gmock-function-mocker.h", ++ "googlemock/include/gmock/gmock-generated-actions.h", ++ "googlemock/include/gmock/gmock-generated-function-mockers.h", ++ "googlemock/include/gmock/gmock-generated-matchers.h", ++ "googlemock/include/gmock/gmock-generated-nice-strict.h", + "googlemock/include/gmock/gmock-matchers.h", + "googlemock/include/gmock/gmock-more-actions.h", + "googlemock/include/gmock/gmock-more-matchers.h", +- "googlemock/include/gmock/gmock-nice-strict.h", + "googlemock/include/gmock/gmock-spec-builders.h", + "googlemock/include/gmock/internal/custom/gmock-generated-actions.h", + "googlemock/include/gmock/internal/custom/gmock-matchers.h", + "googlemock/include/gmock/internal/custom/gmock-port.h", ++ "googlemock/include/gmock/internal/gmock-generated-internal-utils.h", + "googlemock/include/gmock/internal/gmock-internal-utils.h", + "googlemock/include/gmock/internal/gmock-port.h", +- "googlemock/include/gmock/internal/gmock-pp.h", + "googlemock/src/gmock-all.cc", + "googlemock/src/gmock-cardinalities.cc", + "googlemock/src/gmock-internal-utils.cc", +@@ -122,16 +180,33 @@ + sources -= [ "googlemock/src/gmock-all.cc" ] + public_configs = [ ":gmock_config" ] + configs += [ ":gmock_private_config" ] +- configs -= [ "//build/config/coverage:default_coverage" ] ++ ++ # configs -= ["//build/config/coverage:default_coverage"] + deps = [ ":gtest" ] + } + + static_library("gmock_main") { + testonly = true ++ ++ cflags = [ ++ "-Wno-inconsistent-missing-override", ++ ++ # "-Dprivate=public", #allow test code access private members ++ "-fprofile-arcs", ++ "-ftest-coverage", ++ "-Wno-unused-command-line-argument", ++ "-Wno-format", ++ "-Wno-unused-const-variable", ++ "-Wno-unused-variable", ++ "-Wno-used-but-marked-unused", ++ "-Wno-exit-time-destructors", ++ "-Wno-missing-noreturn", ++ ] + sources = [ "googlemock/src/gmock_main.cc" ] + public_deps = [ + ":gmock", + ":gtest", + ] +- configs -= [ "//build/config/coverage:default_coverage" ] ++ ++ # configs -= ["//build/config/coverage:default_coverage"] + } diff --git a/host/trace_streamer/prebuilts/patch_googletest/gtest-message.h.patch b/host/trace_streamer/prebuilts/patch_googletest/gtest-message.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..266103762b66274a49f8321cb336c2ccb017ab2d --- /dev/null +++ b/host/trace_streamer/prebuilts/patch_googletest/gtest-message.h.patch @@ -0,0 +1,15 @@ +--- third_party/googletest/googletest/include/gtest/gtest-message.h 2023-01-17 16:10:56.252360383 +0800 ++++ /home/suze/tp/code/ohos_devtools_trace_resolver/third_party/googletest/googletest/include/gtest/gtest-message.h 2023-01-06 17:58:25.830759482 +0800 +@@ -49,8 +49,11 @@ + + #include + #include ++#undef private ++#define private private + #include +- ++#undef private ++#define private public + #include "gtest/internal/gtest-port.h" + + GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ diff --git a/host/trace_streamer/prebuilts/patch_googletest/gtest_internal.h.patch b/host/trace_streamer/prebuilts/patch_googletest/gtest_internal.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..e47ac4faa2343fc71ba90adae8cccb66b8cf0fa4 --- /dev/null +++ b/host/trace_streamer/prebuilts/patch_googletest/gtest_internal.h.patch @@ -0,0 +1,14 @@ +--- third_party/googletest/googletest/include/gtest/internal/gtest-internal.h 2023-01-17 16:10:56.252360383 +0800 ++++ /home/suze/tp/code/ohos_devtools_trace_resolver/third_party/googletest/googletest/include/gtest/internal/gtest-internal.h 2023-01-06 17:58:25.830759482 +0800 +@@ -54,7 +54,11 @@ + #include + #include + #include ++#undef private ++#define private private + #include ++#undef private ++#define private public + #include + #include + #include diff --git a/host/trace_streamer/prebuilts/patch_googletest/gtest_port.h.patch b/host/trace_streamer/prebuilts/patch_googletest/gtest_port.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb5d1e2d3d316b0fd53355268072c2a620c54022 --- /dev/null +++ b/host/trace_streamer/prebuilts/patch_googletest/gtest_port.h.patch @@ -0,0 +1,23 @@ +--- third_party/googletest/googletest/include/gtest/internal/gtest-port.h 2023-01-17 16:10:56.252360383 +0800 ++++ /home/suze/tp/code/ohos_devtools_trace_resolver/third_party/googletest/googletest/include/gtest/internal/gtest-port.h 2023-01-06 17:58:25.834759489 +0800 +@@ -276,7 +276,6 @@ + # include + # include + #endif +- + #include // NOLINT + #include + #include +@@ -2287,7 +2286,11 @@ using Any = ::absl::any; + // Otherwise for C++17 and higher use std::any for UniversalPrinter<> + // specializations. + #define GTEST_INTERNAL_HAS_ANY 1 +-#include ++#undef private ++#define private private ++#include // NOLINT ++#undef private ++#define private public + namespace testing { + namespace internal { + using Any = ::std::any; diff --git a/host/trace_streamer/prebuilts/patch_libunwind/libunwindbuild.gn.patch b/host/trace_streamer/prebuilts/patch_libunwind/libunwindbuild.gn.patch new file mode 100644 index 0000000000000000000000000000000000000000..371e30bd8c7c9f292f6c58bca6788dceb3972cc8 --- /dev/null +++ b/host/trace_streamer/prebuilts/patch_libunwind/libunwindbuild.gn.patch @@ -0,0 +1,863 @@ +--- third_party/libunwind/BUILD.gn 2023-01-17 13:58:11.209820400 +0800 ++++ prebuilts/patch_libunwind/libunwindbuild.gn 2023-01-17 11:02:37.478105100 +0800 +@@ -11,13 +11,7 @@ + # See the License for the specific language governing permissions and + # limitations under the License. + +-if (defined(ohos_lite)) { +- import("//build/lite/config/component/lite_component.gni") +-} else { +- import("//build/ohos.gni") +- import("//third_party/libunwind/libunwind.gni") +-} +- ++import("//build/ohos.gni") + common_source = [ + "src/dwarf/Gexpr.c", + "src/dwarf/Gfde.c", +@@ -85,111 +79,116 @@ common_source = [ + + # as libc++ is static linked with libunwind.a + # we remove the Gstep.c for duplicated symbol violation +-arm_source = [ +- "src/arm/Gapply_reg_state.c", +- "src/arm/Gcreate_addr_space.c", +- "src/arm/Gex_tables.c", +- "src/arm/Gget_proc_info.c", +- "src/arm/Gget_save_loc.c", +- "src/arm/Gglobal.c", +- "src/arm/Ginit.c", +- "src/arm/Ginit_local.c", +- "src/arm/Ginit_remote.c", +- "src/arm/Gos-linux.c", +- "src/arm/Greg_states_iterate.c", +- "src/arm/Gregs.c", +- "src/arm/Gresume.c", +- "src/arm/Gstash_frame.c", +- "src/arm/Gstep.c", +- "src/arm/Gtrace.c", +- "src/arm/Lcreate_addr_space.c", +- "src/arm/Lex_tables.c", +- "src/arm/Lget_proc_info.c", +- "src/arm/Lget_save_loc.c", +- "src/arm/Lglobal.c", +- "src/arm/Linit.c", +- "src/arm/Linit_local.c", +- "src/arm/Linit_remote.c", +- "src/arm/Los-linux.c", +- "src/arm/Lregs.c", +- "src/arm/Lresume.c", +- "src/arm/Lstash_frame.c", +- "src/arm/Lstep.c", +- "src/arm/Ltrace.c", +- "src/arm/getcontext.S", +- "src/arm/is_fpreg.c", +- "src/arm/regname.c", +- "src/arm/siglongjmp.S", +- "src/elf32.c", +-] +- +-arm64_source = [ +- "src/aarch64/Gcreate_addr_space.c", +- "src/aarch64/Gget_proc_info.c", +- "src/aarch64/Gget_save_loc.c", +- "src/aarch64/Gglobal.c", +- "src/aarch64/Ginit.c", +- "src/aarch64/Ginit_local.c", +- "src/aarch64/Ginit_remote.c", +- "src/aarch64/Gis_signal_frame.c", +- "src/aarch64/Gregs.c", +- "src/aarch64/Gresume.c", +- "src/aarch64/Gstash_frame.c", +- "src/aarch64/Gstep.c", +- "src/aarch64/Gtrace.c", +- "src/aarch64/Lcreate_addr_space.c", +- "src/aarch64/Lget_proc_info.c", +- "src/aarch64/Lget_save_loc.c", +- "src/aarch64/Lglobal.c", +- "src/aarch64/Linit.c", +- "src/aarch64/Linit_local.c", +- "src/aarch64/Linit_remote.c", +- "src/aarch64/Lis_signal_frame.c", +- "src/aarch64/Lregs.c", +- "src/aarch64/Lresume.c", +- "src/aarch64/Lstash_frame.c", +- "src/aarch64/Lstep.c", +- "src/aarch64/Ltrace.c", +- "src/aarch64/getcontext.S", +- "src/aarch64/is_fpreg.c", +- "src/aarch64/regname.c", +- "src/elf64.c", +-] +- +-x64_source = [ +- "src/elf64.c", +- "src/x86_64/Gcreate_addr_space.c", +- "src/x86_64/Gget_proc_info.c", +- "src/x86_64/Gget_save_loc.c", +- "src/x86_64/Gglobal.c", +- "src/x86_64/Ginit.c", +- "src/x86_64/Ginit_local.c", +- "src/x86_64/Ginit_remote.c", +- "src/x86_64/Gos-linux.c", +- "src/x86_64/Gregs.c", +- "src/x86_64/Gresume.c", +- "src/x86_64/Gstash_frame.c", +- "src/x86_64/Gstep.c", +- "src/x86_64/Gtrace.c", +- "src/x86_64/Lcreate_addr_space.c", +- "src/x86_64/Lget_proc_info.c", +- "src/x86_64/Lget_save_loc.c", +- "src/x86_64/Lglobal.c", +- "src/x86_64/Linit.c", +- "src/x86_64/Linit_local.c", +- "src/x86_64/Linit_remote.c", +- "src/x86_64/Los-linux.c", +- "src/x86_64/Lregs.c", +- "src/x86_64/Lresume.c", +- "src/x86_64/Lstash_frame.c", +- "src/x86_64/Lstep.c", +- "src/x86_64/Ltrace.c", +- "src/x86_64/getcontext.S", +- "src/x86_64/is_fpreg.c", +- "src/x86_64/regname.c", +- "src/x86_64/setcontext.S", +-] ++if (target_cpu == "arm") { ++ arm_source = [ ++ "src/arm/Gapply_reg_state.c", ++ "src/arm/Gcreate_addr_space.c", ++ "src/arm/Gex_tables.c", ++ "src/arm/Gget_proc_info.c", ++ "src/arm/Gget_save_loc.c", ++ "src/arm/Gglobal.c", ++ "src/arm/Ginit.c", ++ "src/arm/Ginit_local.c", ++ "src/arm/Ginit_remote.c", ++ "src/arm/Gos-linux.c", ++ "src/arm/Greg_states_iterate.c", ++ "src/arm/Gregs.c", ++ "src/arm/Gresume.c", ++ "src/arm/Gstash_frame.c", ++ "src/arm/Gstep.c", ++ "src/arm/Gtrace.c", ++ "src/arm/Lcreate_addr_space.c", ++ "src/arm/Lex_tables.c", ++ "src/arm/Lget_proc_info.c", ++ "src/arm/Lget_save_loc.c", ++ "src/arm/Lglobal.c", ++ "src/arm/Linit.c", ++ "src/arm/Linit_local.c", ++ "src/arm/Linit_remote.c", ++ "src/arm/Los-linux.c", ++ "src/arm/Lregs.c", ++ "src/arm/Lresume.c", ++ "src/arm/Lstash_frame.c", ++ "src/arm/Lstep.c", ++ "src/arm/Ltrace.c", ++ "src/arm/gen-offsets.c", ++ "src/arm/getcontext.S", ++ "src/arm/is_fpreg.c", ++ "src/arm/regname.c", ++ "src/arm/siglongjmp.S", ++ "src/elf32.c", ++ ] ++} ++if (target_cpu == "arm64") { ++ arm64_source = [ ++ "src/aarch64/Gcreate_addr_space.c", ++ "src/aarch64/Gget_proc_info.c", ++ "src/aarch64/Gget_save_loc.c", ++ "src/aarch64/Gglobal.c", ++ "src/aarch64/Ginit.c", ++ "src/aarch64/Ginit_local.c", ++ "src/aarch64/Ginit_remote.c", ++ "src/aarch64/Gis_signal_frame.c", ++ "src/aarch64/Gregs.c", ++ "src/aarch64/Gresume.c", ++ "src/aarch64/Gstash_frame.c", ++ "src/aarch64/Gstep.c", ++ "src/aarch64/Gtrace.c", ++ "src/aarch64/Lcreate_addr_space.c", ++ "src/aarch64/Lget_proc_info.c", ++ "src/aarch64/Lget_save_loc.c", ++ "src/aarch64/Lglobal.c", ++ "src/aarch64/Linit.c", ++ "src/aarch64/Linit_local.c", ++ "src/aarch64/Linit_remote.c", ++ "src/aarch64/Lis_signal_frame.c", ++ "src/aarch64/Lregs.c", ++ "src/aarch64/Lresume.c", ++ "src/aarch64/Lstash_frame.c", ++ "src/aarch64/Lstep.c", ++ "src/aarch64/Ltrace.c", ++ "src/aarch64/getcontext.S", ++ "src/aarch64/is_fpreg.c", ++ "src/aarch64/regname.c", ++ "src/elf64.c", ++ ] ++} + ++if (target_cpu == "x64") { ++ x64_source = [ ++ "src/elf64.c", ++ "src/x86_64/Gcreate_addr_space.c", ++ "src/x86_64/Gget_proc_info.c", ++ "src/x86_64/Gget_save_loc.c", ++ "src/x86_64/Gglobal.c", ++ "src/x86_64/Ginit.c", ++ "src/x86_64/Ginit_local.c", ++ "src/x86_64/Ginit_remote.c", ++ "src/x86_64/Gos-linux.c", ++ "src/x86_64/Gregs.c", ++ "src/x86_64/Gresume.c", ++ "src/x86_64/Gstash_frame.c", ++ "src/x86_64/Gstep.c", ++ "src/x86_64/Gtrace.c", ++ "src/x86_64/Lcreate_addr_space.c", ++ "src/x86_64/Lget_proc_info.c", ++ "src/x86_64/Lget_save_loc.c", ++ "src/x86_64/Lglobal.c", ++ "src/x86_64/Linit.c", ++ "src/x86_64/Linit_local.c", ++ "src/x86_64/Linit_remote.c", ++ "src/x86_64/Los-linux.c", ++ "src/x86_64/Lregs.c", ++ "src/x86_64/Lresume.c", ++ "src/x86_64/Lstash_frame.c", ++ "src/x86_64/Lstep.c", ++ "src/x86_64/Ltrace.c", ++ "src/x86_64/getcontext.S", ++ "src/x86_64/is_fpreg.c", ++ "src/x86_64/regname.c", ++ "src/x86_64/setcontext.S", ++ ] ++} + remove_sources = [] + + ptrace_sources = [ +@@ -255,7 +254,8 @@ config("unwind_config_public") { + cflags = [ + "-D_GNU_SOURCE", + "-DHAVE_CONFIG_H", +- "-DNDEBUG", ++ ++ # "-DNDEBUG", + "-DCC_IS_CLANG", + "-fcommon", + "-Werror", +@@ -263,9 +263,32 @@ config("unwind_config_public") { + "-Wno-header-guard", + "-Wno-unused-parameter", + "-Wno-unused-variable", +- "-Wno-int-to-pointer-cast", +- "-Wno-pointer-to-int-cast", ++ "-Wno-unused-result", ++ "-Wno-tautological-constant-out-of-range-compare", + ] ++ if (use_wasm) { ++ cflags += [ "-Wno-incompatible-pointer-types" ] ++ } ++ if (is_mingw) { ++ cflags += [ ++ "-Wno-attributes", ++ "-Wno-pointer-to-int-cast", ++ "-Wno-implicit-function-declaration", ++ ++ # "-Wno-absolute-value", ++ # "-Wno-header-guard", ++ # "-Wno-tautological-constant-out-of-range-compare", ++ # "-Wno-sometimes-uninitialized", ++ # "-Wno-int-to-void-pointer-cast", ++ ] ++ } ++ ++ if (use_wasm) { ++ cflags += [ ++ # "-D __mips__" ++ # "-D WASM", ++ ] ++ } + + if (defined(ohos_lite)) { + cflags += [ "-fPIC" ] +@@ -282,18 +305,14 @@ config("unwind_config_public") { + } else if (target_cpu == "arm64") { + include_dirs += [ "include/tdep-aarch64" ] + cflags += [ "-Wno-incompatible-pointer-types" ] +- } else if (target_cpu == "x64" || target_cpu == "x86_64") { ++ } else if (target_cpu == "x64") { + include_dirs += [ "include/tdep-x86_64" ] +- } else if (target_cpu == "mipsel") { +- include_dirs += [ "include/tdep-mips" ] + } + } +- + config("unwind_config_remote") { + cflags = + [ "-Wno-format" ] # some debug feature will warning in host x64 build + } +- + config("unwind_config_remote_public") { + cflags = [] + include_dirs = [] +@@ -320,9 +339,10 @@ config("unwind_config_remote_public") { + + defines += [ "build_remote=1" ] + defines += [ "target_cpu=${target_cpu}" ] +- defines += [ "host_toolchain=${host_toolchain}" ] +- defines += [ "current_toolchain=${current_toolchain}" ] +- defines += [ "default_toolchain=${default_toolchain}" ] ++ ++ # defines += [ "host_toolchain=${host_toolchain}" ] ++ # defines += [ "current_toolchain=${current_toolchain}" ] ++ # defines += [ "default_toolchain=${default_toolchain}" ] + } + + config("unwind_config_arm") { +@@ -337,14 +357,8 @@ config("unwind_config_x64") { + defines = [ "UNW_TARGET_X86_64" ] + defines += [ "UNW_TARGET_X86_64_LINUX" ] + } +- +-config("unwind_config_x86_64") { +- defines = [ "UNW_TARGET_X86_64" ] +- defines += [ "UNW_TARGET_X86_64_LINUX" ] +-} +- +-if (defined(ohos_lite)) { +- source_set("unwind_source_arm") { ++if (target_cpu == "arm") { ++ ohos_source_set("unwind_source_arm") { + configs += [ ":unwind_config_remote" ] + public_configs = [ + ":unwind_config_public", +@@ -353,6 +367,10 @@ if (defined(ohos_lite)) { + ] + sources = common_source + ++ # there is a main function in this file ++ # for a lib we dont need this ++ arm_source -= [ "src/arm/gen-offsets.c" ] ++ + # no jump lib + arm_source -= [ + "src/arm/getcontext.S", +@@ -361,8 +379,9 @@ if (defined(ohos_lite)) { + sources += arm_source + sources -= remove_sources + } +- +- source_set("unwind_source_arm64") { ++} ++if (target_cpu == "arm64") { ++ ohos_source_set("unwind_source_arm64") { + configs += [ ":unwind_config_remote" ] + public_configs = [ + ":unwind_config_public", +@@ -376,8 +395,9 @@ if (defined(ohos_lite)) { + sources += arm64_source + sources -= remove_sources + } +- +- source_set("unwind_source_x64") { ++} ++if (target_cpu == "x86") { ++ ohos_source_set("unwind_source_x64") { + configs += [ ":unwind_config_remote" ] + public_configs = [ + ":unwind_config_public", +@@ -394,460 +414,51 @@ if (defined(ohos_lite)) { + sources += x64_source + sources -= remove_sources + } +- +- source_set("unwind_source") { +- configs += [ ":unwind_config_public" ] +- sources = common_source +- +- if (target_cpu == "arm") { +- # no jump lib +- arm_source -= [ +- "src/arm/getcontext.S", +- "src/arm/siglongjmp.S", +- ] +- +- # as libc++ is static linked with libunwind.a +- # we remove the Gstep.c for duplicated symbol violation +- sources += arm_source +- public_configs = [ ":unwind_config_arm" ] +- } else if (target_cpu == "arm64") { +- sources += arm64_source +- public_configs = [ ":unwind_config_arm64" ] +- } else if (target_cpu == "x64") { +- sources += x64_source +- public_configs = [ ":unwind_config_x64" ] +- } else if (target_cpu == "x86_64") { +- sources += x64_source +- public_configs = [ ":unwind_config_x86_64" ] +- } +- +- sources += [ "src/os-ohos.c" ] +- } +- +- shared_library("libunwind") { +- deps = [ ":unwind_source" ] +- public_configs = [ ":unwind_config_public" ] +- } +-} else { +- ohos_source_set("unwind_source_arm") { +- configs = [ ":unwind_config_remote" ] +- public_configs = [ +- ":unwind_config_public", +- ":unwind_config_remote_public", +- ":unwind_config_arm", +- ] +- sources = common_source +- +- # no jump lib +- arm_source -= [ +- "src/arm/getcontext.S", +- "src/arm/siglongjmp.S", +- ] ++} ++ohos_source_set("unwind_source") { ++ configs += [ ":unwind_config_public" ] ++ sources = common_source ++ if (target_cpu == "arm") { ++ # as libc++ is static linked with libunwind.a ++ # we remove the Gstep.c for duplicated symbol violation + sources += arm_source +- sources -= remove_sources +- } +- +- ohos_source_set("unwind_source_arm64") { +- configs = [ ":unwind_config_remote" ] +- public_configs = [ +- ":unwind_config_public", +- ":unwind_config_remote_public", +- ":unwind_config_arm64", +- ] +- sources = common_source +- +- arm64_source -= [ "src/aarch64/getcontext.S" ] +- ++ public_configs = [ ":unwind_config_arm" ] ++ } else if (target_cpu == "arm64") { + sources += arm64_source +- sources -= remove_sources +- } +- +- ohos_source_set("unwind_source_x64") { +- configs = [ ":unwind_config_remote" ] +- public_configs = [ +- ":unwind_config_public", +- ":unwind_config_remote_public", +- ":unwind_config_x64", +- ] +- sources = common_source +- +- # no jump lib +- x64_source -= [ +- "src/x86_64/getcontext.S", +- "src/x86_64/setcontext.S", +- ] ++ public_configs = [ ":unwind_config_arm64" ] ++ } else if (target_cpu == "x64") { ++ # deps = [ "unwind_source_x64" ] + sources += x64_source +- sources -= remove_sources +- } +- +- ohos_source_set("unwind_source_x86_64") { +- configs = [ ":unwind_config_remote" ] +- public_configs = [ +- ":unwind_config_public", +- ":unwind_config_remote_public", +- ":unwind_config_x86_64", +- ] +- sources = common_source ++ public_configs = [ ":unwind_config_x64" ] + +- # no jump lib +- x64_source -= [ +- "src/x86_64/getcontext.S", +- "src/x86_64/setcontext.S", +- ] +- sources += x64_source +- sources -= remove_sources ++ # public_configs = [ ++ # ":unwind_config_public", ++ # ":unwind_config_remote_public", ++ # ":unwind_config_x64", ++ # ] + } + +- ohos_source_set("unwind_source") { +- configs = [ ":unwind_config_public" ] +- sources = common_source +- +- if (target_cpu == "arm") { +- # as libc++ is static linked with libunwind.a +- # we remove the Gstep.c for duplicated symbol violation +- sources += arm_source +- public_configs = [ ":unwind_config_arm" ] +- } else if (target_cpu == "arm64") { +- sources += arm64_source +- public_configs = [ ":unwind_config_arm64" ] +- } else if (target_cpu == "x64") { +- sources += x64_source +- public_configs = [ ":unwind_config_x64" ] +- } else if (target_cpu == "x86_64") { +- sources += x64_source +- public_configs = [ ":unwind_config_x86_64" ] +- } +- +- sources += [ "src/os-ohos.c" ] +- cflags = [ +- "-DHAS_ARK_FRAME", +- "-DPARSE_BUILD_ID", +- "-DIS_VALIDATE_MEM", +- ] +- } ++ sources += [ "src/os-ohos.c" ] ++} + +- ohos_shared_library("libunwind") { ++if (defined(ohos_lite)) { ++ # shared_library("libunwind") { ++ source_set("libunwind") { + deps = [ ":unwind_source" ] +- install_images = [ +- "system", +- "updater", +- ] + public_configs = [ ":unwind_config_public" ] +- part_name = "faultloggerd" +- subsystem_name = "hiviewdfx" +- } +- +- config("unwind_config_local_only") { +- defines = [ "UNW_LOCAL_ONLY" ] + } ++} else { ++ # ohos_shared_library("libunwind") { ++ source_set("libunwind") { ++ deps = [ ":unwind_source" ] + +- ohos_static_library("libunwind_local") { +- sources = common_source ++ # install_images = [ ++ # "system", ++ # "updater", ++ # ] + public_configs = [ ":unwind_config_public" ] +- public_configs += [ ":unwind_config_local_only" ] +- +- if (target_cpu == "arm") { +- sources += arm_source +- sources -= arm_source_local +- public_configs += [ ":unwind_config_arm" ] +- } else if (target_cpu == "arm64") { +- sources += arm64_source +- sources -= arm64_source_local +- public_configs += [ ":unwind_config_arm64" ] +- } else if (target_cpu == "x64") { +- sources += x64_source +- sources -= x64_source_local +- public_configs += [ ":unwind_config_x64" ] +- } else if (target_cpu == "x86_64") { +- sources += x64_source +- sources -= x64_source_local +- public_configs += [ ":unwind_config_x86_64" ] +- } +- +- sources += [ "src/os-ohos.c" ] +- sources -= libunwind_dwarf_local_la_SOURCES +- sources -= libunwind_la_SOURCES_local +- sources -= ptrace_sources +- +- cflags = [ +- "-DHAS_ARK_FRAME", +- "-DPARSE_BUILD_ID", +- "-DIS_VALIDATE_MEM", +- "-DUNW_LOCAL_ONLY", +- "-DNO_RESERVE_CACHE", +- ] +- +- part_name = "faultloggerd" +- subsystem_name = "hiviewdfx" +- } +-} + +-if (!defined(ohos_lite)) { +- import("//build/test.gni") +- module_output_path = "hiviewdfx/faultloggerd" +- group("unittest") { +- testonly = true +- deps = [ +- ":Gtest_bt", +- ":Gtest_dyn1", +- ":Gtest_init", +- ":Gtest_trace", +- ":Ltest_bt", +- ":Ltest_cxx_exceptions", +- ":Ltest_dyn1", +- ":Ltest_init", +- ":Ltest_init_local_signal", +- ":Ltest_mem_validate", +- ":Ltest_nocalloc", +- ":Ltest_nomalloc", +- ":Ltest_trace", +- ":test_ptrace_misc", +- ":test_static_link", +- ] +- } +- config("unwind_test") { +- cflags = [ "-O0" ] +- } +- +- ohos_unittest("Gtest_init") { +- module_out_path = module_output_path +- sources = [ "tests/Gtest-init.cxx" ] +- include_dirs = [ +- "tests", +- "include", +- ] +- +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Ltest_init") { +- module_out_path = module_output_path +- sources = [ "tests/Ltest-init.cxx" ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Ltest_cxx_exceptions") { +- module_out_path = module_output_path +- sources = [ "tests/Ltest-cxx-exceptions.cxx" ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- cflags = [ "-fexceptions" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- remove_configs = [ "//build/config/compiler:no_exceptions" ] +- } +- +- ohos_unittest("Ltest_init_local_signal") { +- module_out_path = module_output_path +- sources = [ +- "tests/Ltest-init-local-signal-lib.c", +- "tests/Ltest-init-local-signal.c", +- ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Gtest_dyn1") { +- module_out_path = module_output_path +- sources = [ +- "tests/Gtest-dyn1.c", +- "tests/flush-cache.h", +- ] +- if (target_cpu == "arm") { +- sources += [ "tests/flush-cache.S" ] +- } +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- cflags = [ "-DHAVE__BUILTIN___CLEAR_CACHE" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Ltest_dyn1") { +- module_out_path = module_output_path +- sources = [ +- "tests/Ltest-dyn1.c", +- "tests/flush-cache.h", +- ] +- if (target_cpu == "arm") { +- sources += [ "tests/flush-cache.S" ] +- } +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- cflags = [ "-DHAVE__BUILTIN___CLEAR_CACHE" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("test_static_link") { +- module_out_path = module_output_path +- sources = [ +- "tests/test-static-link-gen.c", +- "tests/test-static-link-loc.c", +- ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Gtest_bt") { +- module_out_path = module_output_path +- sources = [ +- "tests/Gtest-bt.c", +- "tests/dummy_backtrace.c", +- "tests/ident.c", +- ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Ltest_bt") { +- module_out_path = module_output_path +- sources = [ +- "tests/Ltest-bt.c", +- "tests/dummy_backtrace.c", +- "tests/ident.c", +- ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("test_ptrace_misc") { +- module_out_path = module_output_path +- sources = [ +- "tests/ident.c", +- "tests/test-ptrace-misc.c", +- ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Ltest_nomalloc") { +- module_out_path = module_output_path +- sources = [ "tests/Ltest-nomalloc.c" ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Ltest_nocalloc") { +- module_out_path = module_output_path +- sources = [ "tests/Ltest-nocalloc.c" ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Gtest_trace") { +- module_out_path = module_output_path +- sources = [ +- "tests/Gtest-trace.c", +- "tests/dummy_backtrace.c", +- "tests/ident.c", +- ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Ltest_trace") { +- module_out_path = module_output_path +- sources = [ +- "tests/Ltest-trace.c", +- "tests/dummy_backtrace.c", +- "tests/ident.c", +- ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +- +- ohos_unittest("Ltest_mem_validate") { +- module_out_path = module_output_path +- sources = [ "tests/Ltest-mem-validate.c" ] +- include_dirs = [ +- "tests", +- "include", +- ] +- configs = [ ":unwind_test" ] +- deps = [ ":libunwind" ] +- subsystem_name = "hiviewdfx" +- part_name = "faultloggerd" +- } +-} else { +- group("unittest") { +- testonly = true +- deps = [] ++ # part_name = "faultloggerd" ++ # subsystem_name = "hiviewdfx" + } + } diff --git a/host/trace_streamer/prebuilts/patch_perf_event/perf_event.h.patch b/host/trace_streamer/prebuilts/patch_perf_event/perf_event.h.patch new file mode 100644 index 0000000000000000000000000000000000000000..657adda6d8d71c3dc9395fcc78e0e6012d2779ff --- /dev/null +++ b/host/trace_streamer/prebuilts/patch_perf_event/perf_event.h.patch @@ -0,0 +1,611 @@ +--- prebuilts/other/perf_event.h 2023-01-16 15:50:19.155934716 +0800 ++++ third_party/perf_include/linux/perf_event.h 2023-01-16 15:52:07.091731926 +0800 +@@ -1,4 +1,3 @@ +-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ + /* + * Performance events: + * +@@ -12,12 +11,9 @@ + * + * For licencing details see kernel-base/COPYING + */ +-#ifndef _UAPI_LINUX_PERF_EVENT_H +-#define _UAPI_LINUX_PERF_EVENT_H +- +-#include +-#include +-#include ++#ifndef _TS_PERF_EVENT_H ++#define _TS_PERF_EVENT_H ++#include "types.h" + + /* + * User-space ABI bits: +@@ -38,21 +34,6 @@ enum perf_type_id { + }; + + /* +- * attr.config layout for type PERF_TYPE_HARDWARE and PERF_TYPE_HW_CACHE +- * PERF_TYPE_HARDWARE: 0xEEEEEEEE000000AA +- * AA: hardware event ID +- * EEEEEEEE: PMU type ID +- * PERF_TYPE_HW_CACHE: 0xEEEEEEEE00DDCCBB +- * BB: hardware cache ID +- * CC: hardware cache op ID +- * DD: hardware cache op result ID +- * EEEEEEEE: PMU type ID +- * If the PMU type ID is 0, the PERF_TYPE_RAW will be applied. +- */ +-#define PERF_PMU_TYPE_SHIFT 32 +-#define PERF_HW_EVENT_MASK 0xffffffff +- +-/* + * Generalized performance event event_id types, used by the + * attr.event_id parameter of the sys_perf_event_open() + * syscall: +@@ -127,7 +108,6 @@ enum perf_sw_ids { + PERF_COUNT_SW_EMULATION_FAULTS = 8, + PERF_COUNT_SW_DUMMY = 9, + PERF_COUNT_SW_BPF_OUTPUT = 10, +- PERF_COUNT_SW_CGROUP_SWITCHES = 11, + + PERF_COUNT_SW_MAX, /* non-ABI */ + }; +@@ -157,18 +137,10 @@ enum perf_event_sample_format { + PERF_SAMPLE_TRANSACTION = 1U << 17, + PERF_SAMPLE_REGS_INTR = 1U << 18, + PERF_SAMPLE_PHYS_ADDR = 1U << 19, +- PERF_SAMPLE_AUX = 1U << 20, +- PERF_SAMPLE_CGROUP = 1U << 21, +- PERF_SAMPLE_DATA_PAGE_SIZE = 1U << 22, +- PERF_SAMPLE_CODE_PAGE_SIZE = 1U << 23, +- PERF_SAMPLE_WEIGHT_STRUCT = 1U << 24, + +- PERF_SAMPLE_MAX = 1U << 25, /* non-ABI */ +- +- __PERF_SAMPLE_CALLCHAIN_EARLY = 1ULL << 63, /* non-ABI; internal use */ ++ PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */ + }; + +-#define PERF_SAMPLE_WEIGHT_TYPE (PERF_SAMPLE_WEIGHT | PERF_SAMPLE_WEIGHT_STRUCT) + /* + * values to program into branch_sample_type when PERF_SAMPLE_BRANCH is set + * +@@ -202,8 +174,6 @@ enum perf_branch_sample_type_shift { + + PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16, /* save branch type */ + +- PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 17, /* save low level index of raw branch records */ +- + PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */ + }; + +@@ -231,8 +201,6 @@ enum perf_branch_sample_type { + PERF_SAMPLE_BRANCH_TYPE_SAVE = + 1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT, + +- PERF_SAMPLE_BRANCH_HW_INDEX = 1U << PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT, +- + PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT, + }; + +@@ -326,8 +294,6 @@ enum perf_event_read_format { + /* add: sample_stack_user */ + #define PERF_ATTR_SIZE_VER4 104 /* add: sample_regs_intr */ + #define PERF_ATTR_SIZE_VER5 112 /* add: aux_watermark */ +-#define PERF_ATTR_SIZE_VER6 120 /* add: aux_sample_size */ +-#define PERF_ATTR_SIZE_VER7 128 /* add: sig_data */ + + /* + * Hardware event_id to monitor via a performance monitoring event: +@@ -400,16 +366,7 @@ struct perf_event_attr { + context_switch : 1, /* context switch data */ + write_backward : 1, /* Write ring buffer from end to beginning */ + namespaces : 1, /* include namespaces data */ +- ksymbol : 1, /* include ksymbol events */ +- bpf_event : 1, /* include bpf events */ +- aux_output : 1, /* generate AUX records instead of events */ +- cgroup : 1, /* include cgroup events */ +- text_poke : 1, /* include text poke events */ +- build_id : 1, /* use build id in mmap2 events */ +- inherit_thread : 1, /* children only inherit if cloned with CLONE_THREAD */ +- remove_on_exec : 1, /* event is removed from task on exec */ +- sigtrap : 1, /* send synchronous SIGTRAP on event */ +- __reserved_1 : 26; ++ __reserved_1 : 35; + + union { + __u32 wakeup_events; /* wakeup every n events */ +@@ -419,14 +376,10 @@ struct perf_event_attr { + __u32 bp_type; + union { + __u64 bp_addr; +- __u64 kprobe_func; /* for perf_kprobe */ +- __u64 uprobe_path; /* for perf_uprobe */ + __u64 config1; /* extension of config */ + }; + union { + __u64 bp_len; +- __u64 kprobe_addr; /* when kprobe_func == NULL */ +- __u64 probe_offset; /* for perf_[k,u]probe */ + __u64 config2; /* extension of config1 */ + }; + __u64 branch_sample_type; /* enum perf_branch_sample_type */ +@@ -458,53 +411,24 @@ struct perf_event_attr { + */ + __u32 aux_watermark; + __u16 sample_max_stack; +- __u16 __reserved_2; +- __u32 aux_sample_size; +- __u32 __reserved_3; +- +- /* +- * User provided data if sigtrap=1, passed back to user via +- * siginfo_t::si_perf_data, e.g. to permit user to identify the event. +- */ +- __u64 sig_data; ++ __u16 __reserved_2; /* align to __u64 */ + }; + +-/* +- * Structure used by below PERF_EVENT_IOC_QUERY_BPF command +- * to query bpf programs attached to the same perf tracepoint +- * as the given perf event. +- */ +-struct perf_event_query_bpf { +- /* +- * The below ids array length +- */ +- __u32 ids_len; +- /* +- * Set by the kernel to indicate the number of +- * available programs +- */ +- __u32 prog_cnt; +- /* +- * User provided buffer to store program ids +- */ +- __u32 ids[0]; +-}; ++#define perf_flags(attr) (*(&(attr)->read_format + 1)) + + /* + * Ioctls that can be done on a perf event fd: + */ +-#define PERF_EVENT_IOC_ENABLE _IO ('$', 0) +-#define PERF_EVENT_IOC_DISABLE _IO ('$', 1) +-#define PERF_EVENT_IOC_REFRESH _IO ('$', 2) +-#define PERF_EVENT_IOC_RESET _IO ('$', 3) +-#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64) +-#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) +-#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *) +-#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *) +-#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32) +-#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) +-#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *) +-#define PERF_EVENT_IOC_MODIFY_ATTRIBUTES _IOW('$', 11, struct perf_event_attr *) ++#define PERF_EVENT_IOC_ENABLE _IO ('$', 0) ++#define PERF_EVENT_IOC_DISABLE _IO ('$', 1) ++#define PERF_EVENT_IOC_REFRESH _IO ('$', 2) ++#define PERF_EVENT_IOC_RESET _IO ('$', 3) ++#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64) ++#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5) ++#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *) ++#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *) ++#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32) ++#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) + + enum perf_event_ioc_flags { + PERF_IOC_FLAG_GROUP = 1U << 0, +@@ -564,10 +488,9 @@ struct perf_event_mmap_page { + cap_bit0_is_deprecated : 1, /* Always 1, signals that bit 0 is zero */ + + cap_user_rdpmc : 1, /* The RDPMC instruction can be used to read counts */ +- cap_user_time : 1, /* The time_{shift,mult,offset} fields are used */ ++ cap_user_time : 1, /* The time_* fields are used */ + cap_user_time_zero : 1, /* The time_zero field is used */ +- cap_user_time_short : 1, /* the time_{cycle,mask} fields are used */ +- cap_____res : 58; ++ cap_____res : 59; + }; + }; + +@@ -626,29 +549,13 @@ struct perf_event_mmap_page { + * ((rem * time_mult) >> time_shift); + */ + __u64 time_zero; +- + __u32 size; /* Header size up to __reserved[] fields. */ +- __u32 __reserved_1; +- +- /* +- * If cap_usr_time_short, the hardware clock is less than 64bit wide +- * and we must compute the 'cyc' value, as used by cap_usr_time, as: +- * +- * cyc = time_cycles + ((cyc - time_cycles) & time_mask) +- * +- * NOTE: this form is explicitly chosen such that cap_usr_time_short +- * is a correction on top of cap_usr_time, and code that doesn't +- * know about cap_usr_time_short still works under the assumption +- * the counter doesn't wrap. +- */ +- __u64 time_cycles; +- __u64 time_mask; + + /* + * Hole for extension of the self monitor capabilities + */ + +- __u8 __reserved[116*8]; /* align to 1k. */ ++ __u8 __reserved[118*8+4]; /* align to 1k. */ + + /* + * Control data for the mmap() data buffer. +@@ -688,22 +595,6 @@ struct perf_event_mmap_page { + __u64 aux_size; + }; + +-/* +- * The current state of perf_event_header::misc bits usage: +- * ('|' used bit, '-' unused bit) +- * +- * 012 CDEF +- * |||---------|||| +- * +- * Where: +- * 0-2 CPUMODE_MASK +- * +- * C PROC_MAP_PARSE_TIMEOUT +- * D MMAP_DATA / COMM_EXEC / FORK_EXEC / SWITCH_OUT +- * E MMAP_BUILD_ID / EXACT_IP / SCHED_OUT_PREEMPT +- * F (reserved) +- */ +- + #define PERF_RECORD_MISC_CPUMODE_MASK (7 << 0) + #define PERF_RECORD_MISC_CPUMODE_UNKNOWN (0 << 0) + #define PERF_RECORD_MISC_KERNEL (1 << 0) +@@ -717,41 +608,19 @@ struct perf_event_mmap_page { + */ + #define PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT (1 << 12) + /* +- * Following PERF_RECORD_MISC_* are used on different +- * events, so can reuse the same bit position: +- * +- * PERF_RECORD_MISC_MMAP_DATA - PERF_RECORD_MMAP* events +- * PERF_RECORD_MISC_COMM_EXEC - PERF_RECORD_COMM event +- * PERF_RECORD_MISC_FORK_EXEC - PERF_RECORD_FORK event (perf internal) +- * PERF_RECORD_MISC_SWITCH_OUT - PERF_RECORD_SWITCH* events ++ * PERF_RECORD_MISC_MMAP_DATA and PERF_RECORD_MISC_COMM_EXEC are used on ++ * different events so can reuse the same bit position. ++ * Ditto PERF_RECORD_MISC_SWITCH_OUT. + */ + #define PERF_RECORD_MISC_MMAP_DATA (1 << 13) + #define PERF_RECORD_MISC_COMM_EXEC (1 << 13) +-#define PERF_RECORD_MISC_FORK_EXEC (1 << 13) + #define PERF_RECORD_MISC_SWITCH_OUT (1 << 13) + /* +- * These PERF_RECORD_MISC_* flags below are safely reused +- * for the following events: +- * +- * PERF_RECORD_MISC_EXACT_IP - PERF_RECORD_SAMPLE of precise events +- * PERF_RECORD_MISC_SWITCH_OUT_PREEMPT - PERF_RECORD_SWITCH* events +- * PERF_RECORD_MISC_MMAP_BUILD_ID - PERF_RECORD_MMAP2 event +- * +- * +- * PERF_RECORD_MISC_EXACT_IP: +- * Indicates that the content of PERF_SAMPLE_IP points to +- * the actual instruction that triggered the event. See also +- * perf_event_attr::precise_ip. +- * +- * PERF_RECORD_MISC_SWITCH_OUT_PREEMPT: +- * Indicates that thread was preempted in TASK_RUNNING state. +- * +- * PERF_RECORD_MISC_MMAP_BUILD_ID: +- * Indicates that mmap2 event carries build id data. ++ * Indicates that the content of PERF_SAMPLE_IP points to ++ * the actual instruction that triggered the event. See also ++ * perf_event_attr::precise_ip. + */ + #define PERF_RECORD_MISC_EXACT_IP (1 << 14) +-#define PERF_RECORD_MISC_SWITCH_OUT_PREEMPT (1 << 14) +-#define PERF_RECORD_MISC_MMAP_BUILD_ID (1 << 14) + /* + * Reserve the last bit to indicate some extended misc field + */ +@@ -929,9 +798,7 @@ enum perf_event_type { + * char data[size];}&& PERF_SAMPLE_RAW + * + * { u64 nr; +- * { u64 hw_idx; } && PERF_SAMPLE_BRANCH_HW_INDEX +- * { u64 from, to, flags } lbr[nr]; +- * } && PERF_SAMPLE_BRANCH_STACK ++ * { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK + * + * { u64 abi; # enum perf_sample_regs_abi + * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER +@@ -940,33 +807,12 @@ enum perf_event_type { + * char data[size]; + * u64 dyn_size; } && PERF_SAMPLE_STACK_USER + * +- * { union perf_sample_weight +- * { +- * u64 full; && PERF_SAMPLE_WEIGHT +- * #if defined(__LITTLE_ENDIAN_BITFIELD) +- * struct { +- * u32 var1_dw; +- * u16 var2_w; +- * u16 var3_w; +- * } && PERF_SAMPLE_WEIGHT_STRUCT +- * #elif defined(__BIG_ENDIAN_BITFIELD) +- * struct { +- * u16 var3_w; +- * u16 var2_w; +- * u32 var1_dw; +- * } && PERF_SAMPLE_WEIGHT_STRUCT +- * #endif +- * } +- * } ++ * { u64 weight; } && PERF_SAMPLE_WEIGHT + * { u64 data_src; } && PERF_SAMPLE_DATA_SRC + * { u64 transaction; } && PERF_SAMPLE_TRANSACTION + * { u64 abi; # enum perf_sample_regs_abi + * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR + * { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR +- * { u64 size; +- * char data[size]; } && PERF_SAMPLE_AUX +- * { u64 data_page_size;} && PERF_SAMPLE_DATA_PAGE_SIZE +- * { u64 code_page_size;} && PERF_SAMPLE_CODE_PAGE_SIZE + * }; + */ + PERF_RECORD_SAMPLE = 9, +@@ -982,20 +828,10 @@ enum perf_event_type { + * u64 addr; + * u64 len; + * u64 pgoff; +- * union { +- * struct { +- * u32 maj; +- * u32 min; +- * u64 ino; +- * u64 ino_generation; +- * }; +- * struct { +- * u8 build_id_size; +- * u8 __reserved_1; +- * u16 __reserved_2; +- * u8 build_id[20]; +- * }; +- * }; ++ * u32 maj; ++ * u32 min; ++ * u64 ino; ++ * u64 ino_generation; + * u32 prot, flags; + * char filename[]; + * struct sample_id sample_id; +@@ -1024,7 +860,6 @@ enum perf_event_type { + * struct perf_event_header header; + * u32 pid; + * u32 tid; +- * struct sample_id sample_id; + * }; + */ + PERF_RECORD_ITRACE_START = 12, +@@ -1079,106 +914,9 @@ enum perf_event_type { + */ + PERF_RECORD_NAMESPACES = 16, + +- /* +- * Record ksymbol register/unregister events: +- * +- * struct { +- * struct perf_event_header header; +- * u64 addr; +- * u32 len; +- * u16 ksym_type; +- * u16 flags; +- * char name[]; +- * struct sample_id sample_id; +- * }; +- */ +- PERF_RECORD_KSYMBOL = 17, +- +- /* +- * Record bpf events: +- * enum perf_bpf_event_type { +- * PERF_BPF_EVENT_UNKNOWN = 0, +- * PERF_BPF_EVENT_PROG_LOAD = 1, +- * PERF_BPF_EVENT_PROG_UNLOAD = 2, +- * }; +- * +- * struct { +- * struct perf_event_header header; +- * u16 type; +- * u16 flags; +- * u32 id; +- * u8 tag[BPF_TAG_SIZE]; +- * struct sample_id sample_id; +- * }; +- */ +- PERF_RECORD_BPF_EVENT = 18, +- +- /* +- * struct { +- * struct perf_event_header header; +- * u64 id; +- * char path[]; +- * struct sample_id sample_id; +- * }; +- */ +- PERF_RECORD_CGROUP = 19, +- +- /* +- * Records changes to kernel text i.e. self-modified code. 'old_len' is +- * the number of old bytes, 'new_len' is the number of new bytes. Either +- * 'old_len' or 'new_len' may be zero to indicate, for example, the +- * addition or removal of a trampoline. 'bytes' contains the old bytes +- * followed immediately by the new bytes. +- * +- * struct { +- * struct perf_event_header header; +- * u64 addr; +- * u16 old_len; +- * u16 new_len; +- * u8 bytes[]; +- * struct sample_id sample_id; +- * }; +- */ +- PERF_RECORD_TEXT_POKE = 20, +- +- /* +- * Data written to the AUX area by hardware due to aux_output, may need +- * to be matched to the event by an architecture-specific hardware ID. +- * This records the hardware ID, but requires sample_id to provide the +- * event ID. e.g. Intel PT uses this record to disambiguate PEBS-via-PT +- * records from multiple events. +- * +- * struct { +- * struct perf_event_header header; +- * u64 hw_id; +- * struct sample_id sample_id; +- * }; +- */ +- PERF_RECORD_AUX_OUTPUT_HW_ID = 21, +- + PERF_RECORD_MAX, /* non-ABI */ + }; + +-enum perf_record_ksymbol_type { +- PERF_RECORD_KSYMBOL_TYPE_UNKNOWN = 0, +- PERF_RECORD_KSYMBOL_TYPE_BPF = 1, +- /* +- * Out of line code such as kprobe-replaced instructions or optimized +- * kprobes or ftrace trampolines. +- */ +- PERF_RECORD_KSYMBOL_TYPE_OOL = 2, +- PERF_RECORD_KSYMBOL_TYPE_MAX /* non-ABI */ +-}; +- +-#define PERF_RECORD_KSYMBOL_FLAGS_UNREGISTER (1 << 0) +- +-enum perf_bpf_event_type { +- PERF_BPF_EVENT_UNKNOWN = 0, +- PERF_BPF_EVENT_PROG_LOAD = 1, +- PERF_BPF_EVENT_PROG_UNLOAD = 2, +- PERF_BPF_EVENT_MAX, /* non-ABI */ +-}; +- + #define PERF_MAX_STACK_DEPTH 127 + #define PERF_MAX_CONTEXTS_PER_STACK 8 + +@@ -1197,15 +935,10 @@ enum perf_callchain_context { + /** + * PERF_RECORD_AUX::flags bits + */ +-#define PERF_AUX_FLAG_TRUNCATED 0x01 /* record was truncated to fit */ +-#define PERF_AUX_FLAG_OVERWRITE 0x02 /* snapshot from overwrite mode */ +-#define PERF_AUX_FLAG_PARTIAL 0x04 /* record contains gaps */ +-#define PERF_AUX_FLAG_COLLISION 0x08 /* sample collided with another */ +-#define PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK 0xff00 /* PMU specific trace format type */ +- +-/* CoreSight PMU AUX buffer formats */ +-#define PERF_AUX_FLAG_CORESIGHT_FORMAT_CORESIGHT 0x0000 /* Default for backward compatibility */ +-#define PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW 0x0100 /* Raw format of the source */ ++#define PERF_AUX_FLAG_TRUNCATED 0x01 /* record was truncated to fit */ ++#define PERF_AUX_FLAG_OVERWRITE 0x02 /* snapshot from overwrite mode */ ++#define PERF_AUX_FLAG_PARTIAL 0x04 /* record contains gaps */ ++#define PERF_AUX_FLAG_COLLISION 0x08 /* sample collided with another */ + + #define PERF_FLAG_FD_NO_GROUP (1UL << 0) + #define PERF_FLAG_FD_OUTPUT (1UL << 1) +@@ -1224,18 +957,14 @@ union perf_mem_data_src { + mem_lvl_num:4, /* memory hierarchy level number */ + mem_remote:1, /* remote */ + mem_snoopx:2, /* snoop mode, ext */ +- mem_blk:3, /* access blocked */ +- mem_hops:3, /* hop level */ +- mem_rsvd:18; ++ mem_rsvd:24; + }; + }; + #elif defined(__BIG_ENDIAN_BITFIELD) + union perf_mem_data_src { + __u64 val; + struct { +- __u64 mem_rsvd:18, +- mem_hops:3, /* hop level */ +- mem_blk:3, /* access blocked */ ++ __u64 mem_rsvd:24, + mem_snoopx:2, /* snoop mode, ext */ + mem_remote:1, /* remote */ + mem_lvl_num:4, /* memory hierarchy level number */ +@@ -1247,7 +976,7 @@ union perf_mem_data_src { + }; + }; + #else +-#error "Unknown endianness" ++// #error "Unknown endianness" + #endif + + /* type of opcode (load/store/prefetch,code) */ +@@ -1258,13 +987,7 @@ union perf_mem_data_src { + #define PERF_MEM_OP_EXEC 0x10 /* code (execution) */ + #define PERF_MEM_OP_SHIFT 0 + +-/* +- * PERF_MEM_LVL_* namespace being depricated to some extent in the +- * favour of newer composite PERF_MEM_{LVLNUM_,REMOTE_,SNOOPX_} fields. +- * Supporting this namespace inorder to not break defined ABIs. +- * +- * memory hierarchy (memory level, hit or miss) +- */ ++/* memory hierarchy (memory level, hit or miss) */ + #define PERF_MEM_LVL_NA 0x01 /* not available */ + #define PERF_MEM_LVL_HIT 0x02 /* hit level */ + #define PERF_MEM_LVL_MISS 0x04 /* miss level */ +@@ -1324,20 +1047,6 @@ union perf_mem_data_src { + #define PERF_MEM_TLB_OS 0x40 /* OS fault handler */ + #define PERF_MEM_TLB_SHIFT 26 + +-/* Access blocked */ +-#define PERF_MEM_BLK_NA 0x01 /* not available */ +-#define PERF_MEM_BLK_DATA 0x02 /* data could not be forwarded */ +-#define PERF_MEM_BLK_ADDR 0x04 /* address conflict */ +-#define PERF_MEM_BLK_SHIFT 40 +- +-/* hop level */ +-#define PERF_MEM_HOPS_0 0x01 /* remote core, same node */ +-#define PERF_MEM_HOPS_1 0x02 /* remote node, same socket */ +-#define PERF_MEM_HOPS_2 0x03 /* remote socket, same board */ +-#define PERF_MEM_HOPS_3 0x04 /* remote board */ +-/* 5-7 available */ +-#define PERF_MEM_HOPS_SHIFT 43 +- + #define PERF_MEM_S(a, s) \ + (((__u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT) + +@@ -1369,23 +1078,4 @@ struct perf_branch_entry { + reserved:40; + }; + +-union perf_sample_weight { +- __u64 full; +-#if defined(__LITTLE_ENDIAN_BITFIELD) +- struct { +- __u32 var1_dw; +- __u16 var2_w; +- __u16 var3_w; +- }; +-#elif defined(__BIG_ENDIAN_BITFIELD) +- struct { +- __u16 var3_w; +- __u16 var2_w; +- __u32 var1_dw; +- }; +-#else +-#error "Unknown endianness" +-#endif +-}; +- +-#endif /* _UAPI_LINUX_PERF_EVENT_H */ ++#endif /* _TS_PERF_EVENT_H */ diff --git a/host/trace_streamer/prebuilts/patch_protobuf/protobufbuild.gn.patch b/host/trace_streamer/prebuilts/patch_protobuf/protobufbuild.gn.patch new file mode 100644 index 0000000000000000000000000000000000000000..1764919fdaa08b24ece6bfaa76904b46e13e189c --- /dev/null +++ b/host/trace_streamer/prebuilts/patch_protobuf/protobufbuild.gn.patch @@ -0,0 +1,796 @@ +--- protobuf/BUILD.gn 2023-01-04 16:29:38.034468696 +0800 ++++ ../prebuilts/buildprotobuf/protobufbuild.gn 2022-11-29 14:31:52.359999197 +0800 +@@ -12,508 +12,343 @@ + # limitations under the License. + + import("//build/ohos.gni") +-import("//developtools/profiler/build/config.gni") + + config("protobuf_config") { + include_dirs = [ "src" ] + } ++protobuf_dir = "src/google/protobuf" ++protobuf_lite_src = [ ++ "$protobuf_dir/any_lite.cc", ++ "$protobuf_dir/arena.cc", ++ "$protobuf_dir/extension_set.cc", ++ "$protobuf_dir/generated_enum_util.cc", ++ "$protobuf_dir/generated_message_table_driven_lite.cc", ++ "$protobuf_dir/generated_message_util.cc", ++ "$protobuf_dir/implicit_weak_message.cc", ++ "$protobuf_dir/io/coded_stream.cc", ++ "$protobuf_dir/io/io_win32.cc", ++ "$protobuf_dir/io/strtod.cc", ++ "$protobuf_dir/io/zero_copy_stream.cc", ++ "$protobuf_dir/io/zero_copy_stream_impl.cc", ++ "$protobuf_dir/io/zero_copy_stream_impl_lite.cc", ++ "$protobuf_dir/message_lite.cc", ++ "$protobuf_dir/parse_context.cc", ++ "$protobuf_dir/repeated_field.cc", ++ "$protobuf_dir/stubs/bytestream.cc", ++ "$protobuf_dir/stubs/common.cc", ++ "$protobuf_dir/stubs/int128.cc", ++ "$protobuf_dir/stubs/status.cc", ++ "$protobuf_dir/stubs/statusor.cc", ++ "$protobuf_dir/stubs/stringpiece.cc", ++ "$protobuf_dir/stubs/stringprintf.cc", ++ "$protobuf_dir/stubs/structurally_valid.cc", ++ "$protobuf_dir/stubs/strutil.cc", ++ "$protobuf_dir/stubs/time.cc", ++ "$protobuf_dir/wire_format_lite.cc", ++] ++ ++protobuf_src = [ ++ "$protobuf_dir/any.cc", ++ "$protobuf_dir/any.pb.cc", ++ "$protobuf_dir/api.pb.cc", ++ "$protobuf_dir/compiler/importer.cc", ++ "$protobuf_dir/compiler/parser.cc", ++ "$protobuf_dir/descriptor.cc", ++ "$protobuf_dir/descriptor.pb.cc", ++ "$protobuf_dir/descriptor_database.cc", ++ "$protobuf_dir/duration.pb.cc", ++ "$protobuf_dir/dynamic_message.cc", ++ "$protobuf_dir/empty.pb.cc", ++ "$protobuf_dir/extension_set_heavy.cc", ++ "$protobuf_dir/field_mask.pb.cc", ++ "$protobuf_dir/generated_message_reflection.cc", ++ "$protobuf_dir/generated_message_table_driven.cc", ++ "$protobuf_dir/io/gzip_stream.cc", ++ "$protobuf_dir/io/printer.cc", ++ "$protobuf_dir/io/tokenizer.cc", ++ "$protobuf_dir/map_field.cc", ++ "$protobuf_dir/message.cc", ++ "$protobuf_dir/reflection_ops.cc", ++ "$protobuf_dir/service.cc", ++ "$protobuf_dir/source_context.pb.cc", ++ "$protobuf_dir/struct.pb.cc", ++ "$protobuf_dir/stubs/substitute.cc", ++ "$protobuf_dir/text_format.cc", ++ "$protobuf_dir/timestamp.pb.cc", ++ "$protobuf_dir/type.pb.cc", ++ "$protobuf_dir/unknown_field_set.cc", ++ "$protobuf_dir/util/delimited_message_util.cc", ++ "$protobuf_dir/util/field_comparator.cc", ++ "$protobuf_dir/util/field_mask_util.cc", ++ "$protobuf_dir/util/internal/datapiece.cc", ++ "$protobuf_dir/util/internal/default_value_objectwriter.cc", ++ "$protobuf_dir/util/internal/error_listener.cc", ++ "$protobuf_dir/util/internal/field_mask_utility.cc", ++ "$protobuf_dir/util/internal/json_escaping.cc", ++ "$protobuf_dir/util/internal/json_objectwriter.cc", ++ "$protobuf_dir/util/internal/json_stream_parser.cc", ++ "$protobuf_dir/util/internal/object_writer.cc", ++ "$protobuf_dir/util/internal/proto_writer.cc", ++ "$protobuf_dir/util/internal/protostream_objectsource.cc", ++ "$protobuf_dir/util/internal/protostream_objectwriter.cc", ++ "$protobuf_dir/util/internal/type_info.cc", ++ "$protobuf_dir/util/internal/type_info_test_helper.cc", ++ "$protobuf_dir/util/internal/utility.cc", ++ "$protobuf_dir/util/json_util.cc", ++ "$protobuf_dir/util/message_differencer.cc", ++ "$protobuf_dir/util/time_util.cc", ++ "$protobuf_dir/util/type_resolver_util.cc", ++ "$protobuf_dir/wire_format.cc", ++ "$protobuf_dir/wrappers.pb.cc", ++] ++if (use_wasm) { ++ source_set("protobuf_lite") { ++ sources = protobuf_lite_src ++ include_dirs = [ ++ "$protobuf_dir/**/*.h", ++ "$protobuf_dir/**/*.inc", ++ "src", ++ ] + +-ohos_shared_library("protobuf_lite") { +- sources = [ +- "src/google/protobuf/any_lite.cc", +- "src/google/protobuf/arena.cc", +- "src/google/protobuf/extension_set.cc", +- "src/google/protobuf/generated_enum_util.cc", +- "src/google/protobuf/generated_message_table_driven_lite.cc", +- "src/google/protobuf/generated_message_util.cc", +- "src/google/protobuf/implicit_weak_message.cc", +- "src/google/protobuf/io/coded_stream.cc", +- "src/google/protobuf/io/io_win32.cc", +- "src/google/protobuf/io/strtod.cc", +- "src/google/protobuf/io/zero_copy_stream.cc", +- "src/google/protobuf/io/zero_copy_stream_impl.cc", +- "src/google/protobuf/io/zero_copy_stream_impl_lite.cc", +- "src/google/protobuf/message_lite.cc", +- "src/google/protobuf/parse_context.cc", +- "src/google/protobuf/repeated_field.cc", +- "src/google/protobuf/stubs/bytestream.cc", +- "src/google/protobuf/stubs/common.cc", +- "src/google/protobuf/stubs/int128.cc", +- "src/google/protobuf/stubs/status.cc", +- "src/google/protobuf/stubs/statusor.cc", +- "src/google/protobuf/stubs/stringpiece.cc", +- "src/google/protobuf/stubs/stringprintf.cc", +- "src/google/protobuf/stubs/structurally_valid.cc", +- "src/google/protobuf/stubs/strutil.cc", +- "src/google/protobuf/stubs/time.cc", +- "src/google/protobuf/wire_format_lite.cc", +- ] +- include_dirs = [ +- "src/google/protobuf/**/*.h", +- "src/google/protobuf/**/*.inc", +- "src", +- ] +- if (!is_mingw) { +- if (current_toolchain != host_toolchain) { +- external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +- } +- } else { +- defines = [ "_FILE_OFFSET_BITS_SET_LSEEK" ] +- } +- +- cflags_cc = [ "-Wno-sign-compare" ] +- cflags = [ +- "-Wno-sign-compare", +- "-D HAVE_PTHREAD", +- ] +- +- public_configs = [ ":protobuf_config" ] +- install_enable = true +- subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" +- part_name = "${OHOS_PROFILER_PART_NAME}" +-} ++ cflags_cc = [ "-Wno-sign-compare" ] ++ cflags = [ ++ "-Wno-sign-compare", ++ "-D HAVE_PTHREAD", ++ "-std=c++17", ++ ] + +-ohos_static_library("protobuf_lite_static") { +- sources = [ +- "src/google/protobuf/any_lite.cc", +- "src/google/protobuf/arena.cc", +- "src/google/protobuf/extension_set.cc", +- "src/google/protobuf/generated_enum_util.cc", +- "src/google/protobuf/generated_message_table_driven_lite.cc", +- "src/google/protobuf/generated_message_util.cc", +- "src/google/protobuf/implicit_weak_message.cc", +- "src/google/protobuf/io/coded_stream.cc", +- "src/google/protobuf/io/io_win32.cc", +- "src/google/protobuf/io/strtod.cc", +- "src/google/protobuf/io/zero_copy_stream.cc", +- "src/google/protobuf/io/zero_copy_stream_impl.cc", +- "src/google/protobuf/io/zero_copy_stream_impl_lite.cc", +- "src/google/protobuf/message_lite.cc", +- "src/google/protobuf/parse_context.cc", +- "src/google/protobuf/repeated_field.cc", +- "src/google/protobuf/stubs/bytestream.cc", +- "src/google/protobuf/stubs/common.cc", +- "src/google/protobuf/stubs/int128.cc", +- "src/google/protobuf/stubs/status.cc", +- "src/google/protobuf/stubs/statusor.cc", +- "src/google/protobuf/stubs/stringpiece.cc", +- "src/google/protobuf/stubs/stringprintf.cc", +- "src/google/protobuf/stubs/structurally_valid.cc", +- "src/google/protobuf/stubs/strutil.cc", +- "src/google/protobuf/stubs/time.cc", +- "src/google/protobuf/wire_format_lite.cc", +- ] +- include_dirs = [ +- "src/google/protobuf/**/*.h", +- "src/google/protobuf/**/*.inc", +- "src", +- ] +- if (!is_mingw) { +- if (default_toolchain == current_toolchain) { +- # target build, not host build +- defines = [ "HAVE_HILOG" ] +- external_deps = [ "hiviewdfx_hilog_native:libhilog" ] +- } +- } else { +- defines = [ "_FILE_OFFSET_BITS_SET_LSEEK" ] +- } ++ #configs = default_configs + +- cflags_cc = [ "-Wno-sign-compare" ] +- cflags = [ +- "-Wno-sign-compare", +- "-D HAVE_PTHREAD", +- ] +- if (is_mingw) { +- # ../../third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc:60:9: error: 'lseek' macro redefined [-Werror,-Wmacro-redefined] +- cflags += [ "-Wno-macro-redefined" ] ++ public_configs = [ ":protobuf_config" ] + } +- public_configs = [ ":protobuf_config" ] +-} +- +-ohos_shared_library("protobuf") { +- sources = [ +- "src/google/protobuf/any.cc", +- "src/google/protobuf/any.pb.cc", +- "src/google/protobuf/api.pb.cc", +- "src/google/protobuf/compiler/importer.cc", +- "src/google/protobuf/compiler/parser.cc", +- "src/google/protobuf/descriptor.cc", +- "src/google/protobuf/descriptor.pb.cc", +- "src/google/protobuf/descriptor_database.cc", +- "src/google/protobuf/duration.pb.cc", +- "src/google/protobuf/dynamic_message.cc", +- "src/google/protobuf/empty.pb.cc", +- "src/google/protobuf/extension_set_heavy.cc", +- "src/google/protobuf/field_mask.pb.cc", +- "src/google/protobuf/generated_message_reflection.cc", +- "src/google/protobuf/generated_message_table_driven.cc", +- "src/google/protobuf/io/gzip_stream.cc", +- "src/google/protobuf/io/printer.cc", +- "src/google/protobuf/io/tokenizer.cc", +- "src/google/protobuf/map_field.cc", +- "src/google/protobuf/message.cc", +- "src/google/protobuf/reflection_ops.cc", +- "src/google/protobuf/service.cc", +- "src/google/protobuf/source_context.pb.cc", +- "src/google/protobuf/struct.pb.cc", +- "src/google/protobuf/stubs/substitute.cc", +- "src/google/protobuf/text_format.cc", +- "src/google/protobuf/timestamp.pb.cc", +- "src/google/protobuf/type.pb.cc", +- "src/google/protobuf/unknown_field_set.cc", +- "src/google/protobuf/util/delimited_message_util.cc", +- "src/google/protobuf/util/field_comparator.cc", +- "src/google/protobuf/util/field_mask_util.cc", +- "src/google/protobuf/util/internal/datapiece.cc", +- "src/google/protobuf/util/internal/default_value_objectwriter.cc", +- "src/google/protobuf/util/internal/error_listener.cc", +- "src/google/protobuf/util/internal/field_mask_utility.cc", +- "src/google/protobuf/util/internal/json_escaping.cc", +- "src/google/protobuf/util/internal/json_objectwriter.cc", +- "src/google/protobuf/util/internal/json_stream_parser.cc", +- "src/google/protobuf/util/internal/object_writer.cc", +- "src/google/protobuf/util/internal/proto_writer.cc", +- "src/google/protobuf/util/internal/protostream_objectsource.cc", +- "src/google/protobuf/util/internal/protostream_objectwriter.cc", +- "src/google/protobuf/util/internal/type_info.cc", +- "src/google/protobuf/util/internal/type_info_test_helper.cc", +- "src/google/protobuf/util/internal/utility.cc", +- "src/google/protobuf/util/json_util.cc", +- "src/google/protobuf/util/message_differencer.cc", +- "src/google/protobuf/util/time_util.cc", +- "src/google/protobuf/util/type_resolver_util.cc", +- "src/google/protobuf/wire_format.cc", +- "src/google/protobuf/wrappers.pb.cc", +- ] +- include_dirs = [ +- "src/google/protobuf/**/*.h", +- "src/google/protobuf/**/*.inc", +- "src", +- ] +- cflags_cc = [ "-Wno-sign-compare" ] +- cflags = [ +- "-Wno-sign-compare", +- "-D HAVE_PTHREAD", +- ] +- +- deps = [ ":protobuf_lite" ] +- +- public_configs = [ ":protobuf_config" ] +- install_enable = true +- subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" +- part_name = "${OHOS_PROFILER_PART_NAME}" +-} ++} else { ++ source_set("protobuf_lite") { ++ sources = protobuf_lite_src ++ include_dirs = [ ++ "$protobuf_dir/**/*.h", ++ "$protobuf_dir/**/*.inc", ++ "src", ++ ] + +-ohos_static_library("protobuf_static") { +- sources = [ +- "src/google/protobuf/any.cc", +- "src/google/protobuf/any.pb.cc", +- "src/google/protobuf/api.pb.cc", +- "src/google/protobuf/compiler/importer.cc", +- "src/google/protobuf/compiler/parser.cc", +- "src/google/protobuf/descriptor.cc", +- "src/google/protobuf/descriptor.pb.cc", +- "src/google/protobuf/descriptor_database.cc", +- "src/google/protobuf/duration.pb.cc", +- "src/google/protobuf/dynamic_message.cc", +- "src/google/protobuf/empty.pb.cc", +- "src/google/protobuf/extension_set_heavy.cc", +- "src/google/protobuf/field_mask.pb.cc", +- "src/google/protobuf/generated_message_reflection.cc", +- "src/google/protobuf/generated_message_table_driven.cc", +- "src/google/protobuf/io/gzip_stream.cc", +- "src/google/protobuf/io/printer.cc", +- "src/google/protobuf/io/tokenizer.cc", +- "src/google/protobuf/map_field.cc", +- "src/google/protobuf/message.cc", +- "src/google/protobuf/reflection_ops.cc", +- "src/google/protobuf/service.cc", +- "src/google/protobuf/source_context.pb.cc", +- "src/google/protobuf/struct.pb.cc", +- "src/google/protobuf/stubs/substitute.cc", +- "src/google/protobuf/text_format.cc", +- "src/google/protobuf/timestamp.pb.cc", +- "src/google/protobuf/type.pb.cc", +- "src/google/protobuf/unknown_field_set.cc", +- "src/google/protobuf/util/delimited_message_util.cc", +- "src/google/protobuf/util/field_comparator.cc", +- "src/google/protobuf/util/field_mask_util.cc", +- "src/google/protobuf/util/internal/datapiece.cc", +- "src/google/protobuf/util/internal/default_value_objectwriter.cc", +- "src/google/protobuf/util/internal/error_listener.cc", +- "src/google/protobuf/util/internal/field_mask_utility.cc", +- "src/google/protobuf/util/internal/json_escaping.cc", +- "src/google/protobuf/util/internal/json_objectwriter.cc", +- "src/google/protobuf/util/internal/json_stream_parser.cc", +- "src/google/protobuf/util/internal/object_writer.cc", +- "src/google/protobuf/util/internal/proto_writer.cc", +- "src/google/protobuf/util/internal/protostream_objectsource.cc", +- "src/google/protobuf/util/internal/protostream_objectwriter.cc", +- "src/google/protobuf/util/internal/type_info.cc", +- "src/google/protobuf/util/internal/type_info_test_helper.cc", +- "src/google/protobuf/util/internal/utility.cc", +- "src/google/protobuf/util/json_util.cc", +- "src/google/protobuf/util/message_differencer.cc", +- "src/google/protobuf/util/time_util.cc", +- "src/google/protobuf/util/type_resolver_util.cc", +- "src/google/protobuf/wire_format.cc", +- "src/google/protobuf/wrappers.pb.cc", +- ] +- include_dirs = [ +- "src/google/protobuf/**/*.h", +- "src/google/protobuf/**/*.inc", +- "src", +- ] +- cflags_cc = [ "-Wno-sign-compare" ] +- cflags = [ +- "-Wno-sign-compare", +- "-D HAVE_PTHREAD", +- ] ++ cflags_cc = [ "-Wno-sign-compare" ] ++ cflags = [ ++ "-Wno-sign-compare", ++ "-D HAVE_PTHREAD", ++ "-std=c++17", ++ ] + +- deps = [ ":protobuf_lite_static" ] ++ # configs = default_configs + +- public_configs = [ ":protobuf_config" ] ++ public_configs = [ ":protobuf_config" ] ++ } + } +- +-if (current_toolchain == host_toolchain) { +- ohos_shared_library("protoc_lib") { +- sources = [ +- "src/google/protobuf/compiler/code_generator.cc", +- "src/google/protobuf/compiler/command_line_interface.cc", +- "src/google/protobuf/compiler/cpp/cpp_enum.cc", +- "src/google/protobuf/compiler/cpp/cpp_enum_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_extension.cc", +- "src/google/protobuf/compiler/cpp/cpp_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_file.cc", +- "src/google/protobuf/compiler/cpp/cpp_generator.cc", +- "src/google/protobuf/compiler/cpp/cpp_helpers.cc", +- "src/google/protobuf/compiler/cpp/cpp_map_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_message.cc", +- "src/google/protobuf/compiler/cpp/cpp_message_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc", +- "src/google/protobuf/compiler/cpp/cpp_primitive_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_service.cc", +- "src/google/protobuf/compiler/cpp/cpp_string_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_doc_comment.cc", +- "src/google/protobuf/compiler/csharp/csharp_enum.cc", +- "src/google/protobuf/compiler/csharp/csharp_enum_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_field_base.cc", +- "src/google/protobuf/compiler/csharp/csharp_generator.cc", +- "src/google/protobuf/compiler/csharp/csharp_helpers.cc", +- "src/google/protobuf/compiler/csharp/csharp_map_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_message.cc", +- "src/google/protobuf/compiler/csharp/csharp_message_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_primitive_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_reflection_class.cc", +- "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc", +- "src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc", +- "src/google/protobuf/compiler/java/java_context.cc", +- "src/google/protobuf/compiler/java/java_doc_comment.cc", +- "src/google/protobuf/compiler/java/java_enum.cc", +- "src/google/protobuf/compiler/java/java_enum_field.cc", +- "src/google/protobuf/compiler/java/java_enum_field_lite.cc", +- "src/google/protobuf/compiler/java/java_enum_lite.cc", +- "src/google/protobuf/compiler/java/java_extension.cc", +- "src/google/protobuf/compiler/java/java_extension_lite.cc", +- "src/google/protobuf/compiler/java/java_field.cc", +- "src/google/protobuf/compiler/java/java_file.cc", +- "src/google/protobuf/compiler/java/java_generator.cc", +- "src/google/protobuf/compiler/java/java_generator_factory.cc", +- "src/google/protobuf/compiler/java/java_helpers.cc", +- "src/google/protobuf/compiler/java/java_map_field.cc", +- "src/google/protobuf/compiler/java/java_map_field_lite.cc", +- "src/google/protobuf/compiler/java/java_message.cc", +- "src/google/protobuf/compiler/java/java_message_builder.cc", +- "src/google/protobuf/compiler/java/java_message_builder_lite.cc", +- "src/google/protobuf/compiler/java/java_message_field.cc", +- "src/google/protobuf/compiler/java/java_message_field_lite.cc", +- "src/google/protobuf/compiler/java/java_message_lite.cc", +- "src/google/protobuf/compiler/java/java_name_resolver.cc", +- "src/google/protobuf/compiler/java/java_primitive_field.cc", +- "src/google/protobuf/compiler/java/java_primitive_field_lite.cc", +- "src/google/protobuf/compiler/java/java_service.cc", +- "src/google/protobuf/compiler/java/java_shared_code_generator.cc", +- "src/google/protobuf/compiler/java/java_string_field.cc", +- "src/google/protobuf/compiler/java/java_string_field_lite.cc", +- "src/google/protobuf/compiler/js/js_generator.cc", +- "src/google/protobuf/compiler/js/well_known_types_embed.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_enum.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_extension.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_field.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_file.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_generator.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_helpers.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_map_field.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_message.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_message_field.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_oneof.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc", +- "src/google/protobuf/compiler/php/php_generator.cc", +- "src/google/protobuf/compiler/plugin.cc", +- "src/google/protobuf/compiler/plugin.pb.cc", +- "src/google/protobuf/compiler/python/python_generator.cc", +- "src/google/protobuf/compiler/ruby/ruby_generator.cc", +- "src/google/protobuf/compiler/subprocess.cc", +- "src/google/protobuf/compiler/zip_writer.cc", +- ] ++if (use_wasm) { ++ source_set("protobuf") { ++ sources = protobuf_src + include_dirs = [ +- "src/google/protobuf/**/*.h", +- "src/google/protobuf/**/*.inc", ++ "$protobuf_dir/**/*.h", ++ "$protobuf_dir/**/*.inc", + "src", + ] +- cflags_cc = [ +- "-Wno-sign-compare", +- "-Wno-unused-function", +- "-Wno-unused-private-field", +- ] ++ cflags_cc = [ "-Wno-sign-compare" ] + cflags = [ + "-Wno-sign-compare", + "-D HAVE_PTHREAD", +- "-Wno-unused-function", ++ "-std=c++17", + ] + +- deps = [ +- ":protobuf", +- ":protobuf_lite", +- ] ++ deps = [ ":protobuf_lite" ] ++ ++ #configs = default_configs + + public_configs = [ ":protobuf_config" ] +- subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" +- part_name = "${OHOS_PROFILER_PART_NAME}" + } ++} else { ++ source_set("protobuf") { ++ sources = protobuf_src ++ include_dirs = [ ++ "$protobuf_dir/**/*.h", ++ "$protobuf_dir/**/*.inc", ++ "src", ++ ] + +- ohos_static_library("protoc_static_lib") { ++ #cflags_cc = [ ++ # "-Wno-sign-compare", ++ # "-ftrapv", ++ # "-fstack-protector-strong", ++ # "-fstack-protector-all", ++ # "-D_FORTIFY_SOURCE=2 -O2", ++ ++ #] ++ cflags = [ ++ "-Wno-sign-compare", ++ "-D HAVE_PTHREAD", ++ "-ftrapv", ++ "-fstack-protector-strong", ++ "-fstack-protector-all", ++ "-D_FORTIFY_SOURCE=2 -O2", ++ "-std=c++17", ++ ++ # "-Wl,--disable-new-dtags,--rpath,/libpath1:/libpath2" ++ ] ++ ++ ldflags = [ "-fstack-protector" ] ++ if (!is_macx) { ++ ldflags += [ ++ "-fuse-ld=gold", ++ "-Wl,--gc-sections", ++ "-Wl,-O1", ++ "-fpie", ++ "-pie", ++ ] ++ } ++ ++ if (!is_win) { ++ cflags += [ ++ "-fPIE", ++ "-fPIC", ++ ] ++ } ++ ++ deps = [ ":protobuf_lite" ] ++ ++ public_configs = [ ":protobuf_config" ] ++ } ++ source_set("protoc_lib") { + sources = [ +- "src/google/protobuf/compiler/code_generator.cc", +- "src/google/protobuf/compiler/command_line_interface.cc", +- "src/google/protobuf/compiler/cpp/cpp_enum.cc", +- "src/google/protobuf/compiler/cpp/cpp_enum_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_extension.cc", +- "src/google/protobuf/compiler/cpp/cpp_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_file.cc", +- "src/google/protobuf/compiler/cpp/cpp_generator.cc", +- "src/google/protobuf/compiler/cpp/cpp_helpers.cc", +- "src/google/protobuf/compiler/cpp/cpp_map_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_message.cc", +- "src/google/protobuf/compiler/cpp/cpp_message_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_padding_optimizer.cc", +- "src/google/protobuf/compiler/cpp/cpp_primitive_field.cc", +- "src/google/protobuf/compiler/cpp/cpp_service.cc", +- "src/google/protobuf/compiler/cpp/cpp_string_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_doc_comment.cc", +- "src/google/protobuf/compiler/csharp/csharp_enum.cc", +- "src/google/protobuf/compiler/csharp/csharp_enum_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_field_base.cc", +- "src/google/protobuf/compiler/csharp/csharp_generator.cc", +- "src/google/protobuf/compiler/csharp/csharp_helpers.cc", +- "src/google/protobuf/compiler/csharp/csharp_map_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_message.cc", +- "src/google/protobuf/compiler/csharp/csharp_message_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_primitive_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_reflection_class.cc", +- "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc", +- "src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc", +- "src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc", +- "src/google/protobuf/compiler/java/java_context.cc", +- "src/google/protobuf/compiler/java/java_doc_comment.cc", +- "src/google/protobuf/compiler/java/java_enum.cc", +- "src/google/protobuf/compiler/java/java_enum_field.cc", +- "src/google/protobuf/compiler/java/java_enum_field_lite.cc", +- "src/google/protobuf/compiler/java/java_enum_lite.cc", +- "src/google/protobuf/compiler/java/java_extension.cc", +- "src/google/protobuf/compiler/java/java_extension_lite.cc", +- "src/google/protobuf/compiler/java/java_field.cc", +- "src/google/protobuf/compiler/java/java_file.cc", +- "src/google/protobuf/compiler/java/java_generator.cc", +- "src/google/protobuf/compiler/java/java_generator_factory.cc", +- "src/google/protobuf/compiler/java/java_helpers.cc", +- "src/google/protobuf/compiler/java/java_map_field.cc", +- "src/google/protobuf/compiler/java/java_map_field_lite.cc", +- "src/google/protobuf/compiler/java/java_message.cc", +- "src/google/protobuf/compiler/java/java_message_builder.cc", +- "src/google/protobuf/compiler/java/java_message_builder_lite.cc", +- "src/google/protobuf/compiler/java/java_message_field.cc", +- "src/google/protobuf/compiler/java/java_message_field_lite.cc", +- "src/google/protobuf/compiler/java/java_message_lite.cc", +- "src/google/protobuf/compiler/java/java_name_resolver.cc", +- "src/google/protobuf/compiler/java/java_primitive_field.cc", +- "src/google/protobuf/compiler/java/java_primitive_field_lite.cc", +- "src/google/protobuf/compiler/java/java_service.cc", +- "src/google/protobuf/compiler/java/java_shared_code_generator.cc", +- "src/google/protobuf/compiler/java/java_string_field.cc", +- "src/google/protobuf/compiler/java/java_string_field_lite.cc", +- "src/google/protobuf/compiler/js/js_generator.cc", +- "src/google/protobuf/compiler/js/well_known_types_embed.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_enum.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_extension.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_field.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_file.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_generator.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_helpers.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_map_field.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_message.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_message_field.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_oneof.cc", +- "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc", +- "src/google/protobuf/compiler/php/php_generator.cc", +- "src/google/protobuf/compiler/plugin.cc", +- "src/google/protobuf/compiler/plugin.pb.cc", +- "src/google/protobuf/compiler/python/python_generator.cc", +- "src/google/protobuf/compiler/ruby/ruby_generator.cc", +- "src/google/protobuf/compiler/subprocess.cc", +- "src/google/protobuf/compiler/zip_writer.cc", ++ "$protobuf_dir/compiler/code_generator.cc", ++ "$protobuf_dir/compiler/command_line_interface.cc", ++ "$protobuf_dir/compiler/cpp/cpp_enum.cc", ++ "$protobuf_dir/compiler/cpp/cpp_enum_field.cc", ++ "$protobuf_dir/compiler/cpp/cpp_extension.cc", ++ "$protobuf_dir/compiler/cpp/cpp_field.cc", ++ "$protobuf_dir/compiler/cpp/cpp_file.cc", ++ "$protobuf_dir/compiler/cpp/cpp_generator.cc", ++ "$protobuf_dir/compiler/cpp/cpp_helpers.cc", ++ "$protobuf_dir/compiler/cpp/cpp_map_field.cc", ++ "$protobuf_dir/compiler/cpp/cpp_message.cc", ++ "$protobuf_dir/compiler/cpp/cpp_message_field.cc", ++ "$protobuf_dir/compiler/cpp/cpp_padding_optimizer.cc", ++ "$protobuf_dir/compiler/cpp/cpp_primitive_field.cc", ++ "$protobuf_dir/compiler/cpp/cpp_service.cc", ++ "$protobuf_dir/compiler/cpp/cpp_string_field.cc", ++ "$protobuf_dir/compiler/csharp/csharp_doc_comment.cc", ++ "$protobuf_dir/compiler/csharp/csharp_enum.cc", ++ "$protobuf_dir/compiler/csharp/csharp_enum_field.cc", ++ "$protobuf_dir/compiler/csharp/csharp_field_base.cc", ++ "$protobuf_dir/compiler/csharp/csharp_generator.cc", ++ "$protobuf_dir/compiler/csharp/csharp_helpers.cc", ++ "$protobuf_dir/compiler/csharp/csharp_map_field.cc", ++ "$protobuf_dir/compiler/csharp/csharp_message.cc", ++ "$protobuf_dir/compiler/csharp/csharp_message_field.cc", ++ "$protobuf_dir/compiler/csharp/csharp_primitive_field.cc", ++ "$protobuf_dir/compiler/csharp/csharp_reflection_class.cc", ++ "$protobuf_dir/compiler/csharp/csharp_repeated_enum_field.cc", ++ "$protobuf_dir/compiler/csharp/csharp_repeated_message_field.cc", ++ "$protobuf_dir/compiler/csharp/csharp_repeated_primitive_field.cc", ++ "$protobuf_dir/compiler/csharp/csharp_source_generator_base.cc", ++ "$protobuf_dir/compiler/csharp/csharp_wrapper_field.cc", ++ "$protobuf_dir/compiler/java/java_context.cc", ++ "$protobuf_dir/compiler/java/java_doc_comment.cc", ++ "$protobuf_dir/compiler/java/java_enum.cc", ++ "$protobuf_dir/compiler/java/java_enum_field.cc", ++ "$protobuf_dir/compiler/java/java_enum_field_lite.cc", ++ "$protobuf_dir/compiler/java/java_enum_lite.cc", ++ "$protobuf_dir/compiler/java/java_extension.cc", ++ "$protobuf_dir/compiler/java/java_extension_lite.cc", ++ "$protobuf_dir/compiler/java/java_field.cc", ++ "$protobuf_dir/compiler/java/java_file.cc", ++ "$protobuf_dir/compiler/java/java_generator.cc", ++ "$protobuf_dir/compiler/java/java_generator_factory.cc", ++ "$protobuf_dir/compiler/java/java_helpers.cc", ++ "$protobuf_dir/compiler/java/java_map_field.cc", ++ "$protobuf_dir/compiler/java/java_map_field_lite.cc", ++ "$protobuf_dir/compiler/java/java_message.cc", ++ "$protobuf_dir/compiler/java/java_message_builder.cc", ++ "$protobuf_dir/compiler/java/java_message_builder_lite.cc", ++ "$protobuf_dir/compiler/java/java_message_field.cc", ++ "$protobuf_dir/compiler/java/java_message_field_lite.cc", ++ "$protobuf_dir/compiler/java/java_message_lite.cc", ++ "$protobuf_dir/compiler/java/java_name_resolver.cc", ++ "$protobuf_dir/compiler/java/java_primitive_field.cc", ++ "$protobuf_dir/compiler/java/java_primitive_field_lite.cc", ++ "$protobuf_dir/compiler/java/java_service.cc", ++ "$protobuf_dir/compiler/java/java_shared_code_generator.cc", ++ "$protobuf_dir/compiler/java/java_string_field.cc", ++ "$protobuf_dir/compiler/java/java_string_field_lite.cc", ++ "$protobuf_dir/compiler/js/js_generator.cc", ++ "$protobuf_dir/compiler/js/well_known_types_embed.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_enum.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_enum_field.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_extension.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_field.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_file.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_generator.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_helpers.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_map_field.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_message.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_message_field.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_oneof.cc", ++ "$protobuf_dir/compiler/objectivec/objectivec_primitive_field.cc", ++ "$protobuf_dir/compiler/php/php_generator.cc", ++ "$protobuf_dir/compiler/plugin.cc", ++ "$protobuf_dir/compiler/plugin.pb.cc", ++ "$protobuf_dir/compiler/python/python_generator.cc", ++ "$protobuf_dir/compiler/ruby/ruby_generator.cc", ++ "$protobuf_dir/compiler/subprocess.cc", ++ "$protobuf_dir/compiler/zip_writer.cc", + ] + include_dirs = [ +- "src/google/protobuf/**/*.h", +- "src/google/protobuf/**/*.inc", ++ "$protobuf_dir/**/*.h", ++ "$protobuf_dir/**/*.inc", + "src", ++ ++ # "/opt/clang-mingw/i686-w64-mingw32/x86_64-linux-gnu", ++ # "/opt/clang-mingw/i686-w64-mingw32/x86_64-linux-gnu/c++/7", ++ # "/opt/clang-mingw/i686-w64-mingw32/include/c++/7", ++ # "/usr/include", ++ # "/usr/include/c++/7", ++ # "/usr/include/x86_64-linux-gnu/c++/7", + ] ++ if (!use_wasm) { ++ configs = default_configs ++ } + cflags_cc = [ + "-Wno-sign-compare", + "-Wno-unused-function", + "-Wno-unused-private-field", ++ ++ # "-std=gnu++17", + ] + cflags = [ + "-Wno-sign-compare", + "-D HAVE_PTHREAD", + "-Wno-unused-function", ++ "-std=c++17", ++ ++ # "-Wl,--disable-new-dtags,--rpath,/libpath1:/libpath2" + ] + + deps = [ +- ":protobuf_lite_static", +- ":protobuf_static", ++ ":protobuf", ++ ":protobuf_lite", + ] + + public_configs = [ ":protobuf_config" ] +- subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" +- part_name = "${OHOS_PROFILER_PART_NAME}" + } +-} +- +-# Only compile the plugin for the host architecture. +-if (current_toolchain == host_toolchain) { +- ohos_executable("protoc") { +- sources = [ "src/google/protobuf/compiler/main.cc" ] ++ executable("protoc") { ++ sources = [ "$protobuf_dir/compiler/main.cc" ] + include_dirs = [ +- "src/google/protobuf/**/*.h", +- "src/google/protobuf/**/*.inc", ++ "$protobuf_dir/**/*.h", ++ "$protobuf_dir/**/*.inc", + "src", ++ "/usr/include", + ] +- deps = [ ":protoc_static_lib" ] ++ deps = [ ":protoc_lib" ] + cflags_cc = [ "-Wno-sign-compare" ] + cflags = [ + "-Wno-sign-compare", + "-D HAVE_PTHREAD", + ] +- +- subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" +- part_name = "${OHOS_PROFILER_PART_NAME}" + } + } diff --git a/host/trace_streamer/prebuilts/patch_sqlite/sqlite3build.gn.patch b/host/trace_streamer/prebuilts/patch_sqlite/sqlite3build.gn.patch new file mode 100644 index 0000000000000000000000000000000000000000..b813a4389abab7577b9aba23effd7e1e51bf7e87 --- /dev/null +++ b/host/trace_streamer/prebuilts/patch_sqlite/sqlite3build.gn.patch @@ -0,0 +1,206 @@ +--- third_party/third_party_sqlite/BUILD.gn 2023-01-04 16:21:39.506997978 +0800 ++++ prebuilts/buildsqlite/sqlite3build.gn 2022-11-29 14:31:52.359999197 +0800 +@@ -1,4 +1,4 @@ +-# Copyright (C) 2022 Huawei Device Co., Ltd. ++# 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 +@@ -12,169 +12,37 @@ + # limitations under the License. + + import("//build/ohos.gni") +- +-# Lets callers do '#include ' + config("sqlite_config") { +- include_dirs = [ +- "include", +- "//commonlibrary/c_utils/base/include", +- ] +-} +- +-# This is the configuration used to build sqlite itself. +-# It should not be needed outside of this library. +-config("sqlite3_private_config") { +- visibility = [ ":*" ] +- include_dirs = [ "include" ] +-} +- +-group("libsqlite") { +- public_deps = [ ":sqlite" ] +-} +- +-ohos_shared_library("sqlite") { +- visibility = [ "//foundation/distributeddatamgr/*" ] +- visibility += [ "//foundation/multimodalinput/*" ] +- visibility += +- [ "//hit/fuzzing_test/projects/multimodal_InputService_fuzzer/*" ] +- visibility += [ "//foundation/communication/*" ] +- visibility += [ "//build/common/*" ] +- visibility += [ ":*" ] +- visibility += [ "//base/security/permission/*" ] +- visibility += [ "//third_party/libsoup/*" ] +- visibility += [ "//base/security/access_token/*" ] +- visibility += [ "//foundation/resourceschedule/resource_schedule_service/*" ] +- visibility += [ "//base/update/dupdate_engine/services/engine/*" ] +- +- sources = [ "src/sqlite3.c" ] +- +- defines = [ +- "NDEBUG=1", +- "HAVE_USLEEP=1", +- "SQLITE_HAVE_ISNAN", +- "SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576", +- "SQLITE_THREADSAFE=2", +- "SQLITE_TEMP_STORE=3", +- "SQLITE_POWERSAFE_OVERWRITE=1", +- "SQLITE_DEFAULT_FILE_FORMAT=4", +- "SQLITE_DEFAULT_AUTOVACUUM=1", +- "SQLITE_ENABLE_MEMORY_MANAGEMENT=1", +- "SQLITE_ENABLE_FTS3", +- "SQLITE_ENABLE_FTS4", +- "SQLITE_ENABLE_FTS5", +- "SQLITE_OMIT_COMPILEOPTION_DIAGS", +- "SQLITE_OMIT_LOAD_EXTENSION", +- "SQLITE_DEFAULT_FILE_PERMISSIONS=0660", +- "SQLITE_SECURE_DELETE", +- "SQLITE_ENABLE_BATCH_ATOMIC_WRITE", +- "USE_PREAD64", +- "fdatasync=fdatasync", +- "HAVE_MALLOC_H=1", +- "HAVE_MALLOC_USABLE_SIZE", +- "SQLITE_DIRECT_OVERFLOW_READ", +- "SQLITE_HAS_CODEC", +- "SQLITE_EXPORT_SYMBOLS", +- "SQLITE_SHARED_BLOCK_OPTIMIZATION", +- "SQLITE_CODEC_ATTACH_CHANGED", +- "SQLITE_ENABLE_DROPTABLE_CALLBACK", +- ] +- cflags_c = [ +- "-fvisibility=hidden", +- "-Wno-implicit-fallthrough", +- ] +- ldflags = [ "-Wl,--exclude-libs,ALL" ] +- deps = [ "//third_party/openssl:libcrypto_shared" ] +- public_configs = [ ":sqlite_config" ] +- configs = [ ":sqlite3_private_config" ] +- part_name = "common" +- install_images = [ system_base_dir ] +- relative_install_dir = "platformsdk" +- external_deps = [ "c_utils:utils" ] +-} +- +-ohos_executable("sqlite3") { + include_dirs = [ "include" ] +- sources = [ +- "src/shell.c", +- "src/sqlite3.c", +- ] +- +- defines = [ +- "NDEBUG=1", +- "HAVE_USLEEP=1", +- "SQLITE_HAVE_ISNAN", +- "SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576", +- "SQLITE_THREADSAFE=2", +- "SQLITE_TEMP_STORE=3", +- "SQLITE_POWERSAFE_OVERWRITE=1", +- "SQLITE_DEFAULT_FILE_FORMAT=4", +- "SQLITE_DEFAULT_AUTOVACUUM=1", +- "SQLITE_ENABLE_MEMORY_MANAGEMENT=1", +- "SQLITE_ENABLE_FTS3", +- "SQLITE_ENABLE_FTS4", +- "SQLITE_OMIT_COMPILEOPTION_DIAGS", +- "SQLITE_OMIT_LOAD_EXTENSION", +- "SQLITE_DEFAULT_FILE_PERMISSIONS=0600", +- "SQLITE_SECURE_DELETE", +- "SQLITE_ENABLE_BATCH_ATOMIC_WRITE", +- "USE_PREAD64", +- "fdatasync=fdatasync", +- "SQLITE_DIRECT_OVERFLOW_READ", +- "SQLITE_SHARED_BLOCK_OPTIMIZATION", +- ] +- + cflags = [ +- "-Wno-error=implicit-function-declaration", +- "-Wno-implicit-fallthrough", ++ "-Wno-shorten-64-to-32", ++ "-Wno-double-promotion", ++ "-Wno-disabled-macro-expansion", ++ "-Wno-float-equal", ++ "-Wno-cast-qual", ++ "-Wno-conversion", ++ "-Wno-cast-align", ++ "-Wno-unused-macros", ++ "-Wno-comma", ++ "-Wno-unreachable-code-break", ++ "-Wno-unreachable-code", ++ "-Wno-unreachable-code-return", ++ "-DSQLITE_THREADSAFE=1", ++ "-DQLITE_DEFAULT_MEMSTATUS=0", ++ "-DSQLITE_LIKE_DOESNT_MATCH_BLOBS", ++ "-DSQLITE_OMIT_DEPRECATED", ++ "-DSQLITE_OMIT_SHARED_CACHE", ++ "-DHAVE_USLEEP", ++ "-DHAVE_UTIME", ++ "-DSQLITE_BYTEORDER=1234", ++ "-DSQLITE_DEFAULT_AUTOVACUUM=0", ++ "-DSQLITE_DEFAULT_MMAP_SIZE=0", ++ "-DSQLITE_CORE", ++ "-DSQLITE_TEMP_STORE=3", ++ "-DSQLITE_OMIT_LOAD_EXTENSION", + ] + } +- +-if (is_mingw || is_mac) { +- ohos_shared_library("sqlite_sdk") { +- include_dirs = [ +- "include", +- "//third_party/bounds_checking_function/include", +- "//third_party/openssl/include", +- ] +- +- sources = [ "src/sqlite3.c" ] +- +- defines = [ +- "NDEBUG=1", +- "HAVE_USLEEP=1", +- "SQLITE_HAVE_ISNAN", +- "SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576", +- "SQLITE_THREADSAFE=2", +- "SQLITE_TEMP_STORE=3", +- "SQLITE_POWERSAFE_OVERWRITE=1", +- "SQLITE_DEFAULT_FILE_FORMAT=4", +- "SQLITE_DEFAULT_AUTOVACUUM=1", +- "SQLITE_ENABLE_MEMORY_MANAGEMENT=1", +- "SQLITE_ENABLE_FTS3", +- "SQLITE_ENABLE_FTS4", +- "SQLITE_OMIT_COMPILEOPTION_DIAGS", +- "SQLITE_OMIT_LOAD_EXTENSION", +- "SQLITE_DEFAULT_FILE_PERMISSIONS=0600", +- "SQLITE_SECURE_DELETE", +- "SQLITE_ENABLE_BATCH_ATOMIC_WRITE", +- "USE_PREAD64", +- "fdatasync=fdatasync", +- "SQLITE_DIRECT_OVERFLOW_READ", +- "SQLITE_HAS_CODEC", +- "SQLITE_EXPORT_SYMBOLS", +- "SQLITE_SHARED_BLOCK_OPTIMIZATION", +- ] +- remove_configs = [ "//build/config/compiler:chromium_code" ] +- deps = [ +- "//third_party/bounds_checking_function:libsec_shared", +- "//third_party/openssl:libcrypto_restool", +- ] +- if (is_mingw) { +- libs = [ "//prebuilts/mingw-w64/ohos/linux-x86_64/clang-mingw/x86_64-w64-mingw32/lib/libws2_32.a" ] +- } +- cflags = [ +- "-Wno-error=implicit-function-declaration", +- "-Wno-implicit-fallthrough", +- ] +- } ++ohos_source_set("sqlite") { ++ sources = [ "src/sqlite3.c" ] ++ public_configs = [ ":sqlite_config" ] + } diff --git a/host/trace_streamer/prebuilts/protos/BUILD.gn b/host/trace_streamer/prebuilts/protos/BUILD.gn old mode 100644 new mode 100755 index 760af44d8dc6aec956d492d366aaa61bbc1b4a66..5209497b81c40854bc12d584e1c17ea2dd9b4b13 --- a/host/trace_streamer/prebuilts/protos/BUILD.gn +++ b/host/trace_streamer/prebuilts/protos/BUILD.gn @@ -12,15 +12,20 @@ # limitations under the License. import("//build/ohos.gni") +import("../../src/ts.gni") OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = "//third_party/protobuf" proto_dir = "//third_party/protogen" services_dir = "$proto_dir/services" -ftrace_data_dir = "$proto_dir/types/plugins/ftrace_data" +ftrace_data_dir = "$proto_dir/types/plugins/ftrace_data/${kernel_version}" memory_data_dir = "$proto_dir/types/plugins/memory_data" hilog_data_dir = "$proto_dir/types/plugins/hilog_data" native_hook_dir = "$proto_dir/types/plugins/native_hook" hidump_data_dir = "$proto_dir/types/plugins/hidump_data" - +network_data_dir = "$proto_dir/types/plugins/network_data" +cpu_data_dir = "$proto_dir/types/plugins/cpu_data" +diskio_data_dir = "$proto_dir/types/plugins/diskio_data" +process_data_dir = "$proto_dir/types/plugins/process_data" +hisysevent_data_dir = "$proto_dir/types/plugins/hisysevent_data" config("ts_proto_include_config") { include_dirs = [ "$ftrace_data_dir", @@ -28,6 +33,7 @@ config("ts_proto_include_config") { "$hilog_data_dir", "$native_hook_dir", "$hidump_data_dir", + "$hisysevent_data_dir", ] } source_set("ts_proto_data_cpp") { @@ -36,14 +42,19 @@ source_set("ts_proto_data_cpp") { "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", ] cflags = [ - "-fPIC", "-ftrapv", - "-fPIE", "-D_FORTIFY_SOURCE=2 -O2", "-Wno-zero-length-array", - - # "-Wl,--disable-new-dtags,--rpath,/libpath1:/libpath2" + "-std=c++17", ] + + if (!is_win) { + print("xxx") + cflags += [ + "-fPIE", + "-fPIC", + ] + } if (!use_wasm) { cflags += [ "-fstack-protector-strong", # @@ -71,6 +82,11 @@ source_set("ts_proto_data_cpp") { "$ftrace_data_dir/irq.pb.cc", "$ftrace_data_dir/kmem.pb.cc", "$ftrace_data_dir/net.pb.cc", + + # "$ftrace_data_dir/mmc.pb.cc", + # "$ftrace_data_dir/f2fs.pb.cc", + # "$ftrace_data_dir/gpu_mem.pb.cc", + # "$ftrace_data_dir/regulator.pb.cc", "$ftrace_data_dir/oom.pb.cc", "$ftrace_data_dir/pagemap.pb.cc", "$ftrace_data_dir/power.pb.cc", @@ -87,7 +103,6 @@ source_set("ts_proto_data_cpp") { "$ftrace_data_dir/vmscan.pb.cc", "$ftrace_data_dir/workqueue.pb.cc", "$ftrace_data_dir/writeback.pb.cc", - "$hidump_data_dir/hidump_plugin_config.pb.cc", "$hidump_data_dir/hidump_plugin_result.pb.cc", "$hilog_data_dir/hilog_plugin_result.pb.cc", "$memory_data_dir/memory_plugin_common.pb.cc", @@ -95,6 +110,12 @@ source_set("ts_proto_data_cpp") { "$memory_data_dir/memory_plugin_result.pb.cc", "$native_hook_dir/native_hook_config.pb.cc", "$native_hook_dir/native_hook_result.pb.cc", + "${cpu_data_dir}/cpu_plugin_result.pb.cc", + "${diskio_data_dir}/diskio_plugin_result.pb.cc", + "${hisysevent_data_dir}/hisysevent_plugin_config.pb.cc", + "${hisysevent_data_dir}/hisysevent_plugin_result.pb.cc", + "${network_data_dir}/network_plugin_result.pb.cc", + "${process_data_dir}/process_plugin_result.pb.cc", "${services_dir}/common_types.pb.cc", ] } diff --git a/host/trace_streamer/sdk/BUILD.gn b/host/trace_streamer/sdk/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..35b6f5432fd37583180c76a5f13f8a44eef1e987 --- /dev/null +++ b/host/trace_streamer/sdk/BUILD.gn @@ -0,0 +1,173 @@ +# 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("//build/ohos.gni") +import("ts.gni") +if (use_wasm) { + import("//gn/wasm.gni") +} +if (use_wasm) { + ohos_source_set("trace_streamer_sdk_builtin") { + sources = [] + include_dirs = [] + deps = [] + public_deps = [] + } +} +ohos_source_set("lib") { + sources = [ "main.cpp" ] + deps = [ + ":trace_streamer_sdk", + "protos:ts_proto_data_cpp", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + ] + include_dirs = [ + "base", + "..", + "trace_streamer", + "table", + "trace_data", + "include", + "plugin", + "filter", + "rpc", + "./", + "parser", + "cfg", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}/types/plugins/mock_data", + "${OHOS_PROTO_GEN}", + "//third_party/protobuf/src", + ] + if (with_perf) { + include_dirs += [] + } + public_deps = [] +} +ohos_source_set("trace_streamer_sdk") { + sources = [ + "filter/clock_filter.cpp", + "filter/clock_filter.h", + "parser/event_parser_base.cpp", + "parser/event_parser_base.h", + "parser/htrace_plugin_time_parser.cpp", + "rpc/http_socket.cpp", + "rpc/rpc_server.cpp", + "rpc/rpc_server.h", + "sdk/sdk_data_parser.cpp", + "sdk/sdk_data_parser.h", + "sdk/ts_sdk_api.cpp", + "sdk/ts_sdk_api.h", + "table/filter_constraints.cpp", + "table/gpu_counter_object_table.cpp", + "table/gpu_counter_object_table.h", + "table/gpu_counter_table.cpp", + "table/gpu_counter_table.h", + "table/index_map.cpp", + "table/index_map.h", + "table/meta_table.cpp", + "table/meta_table.h", + "table/slice_object_table.cpp", + "table/slice_object_table.h", + "table/slice_table.cpp", + "table/slice_table.h", + "table/table_base.cpp", + "trace_data/trace_data_cache.cpp", + "trace_data/trace_data_cache.h", + "trace_data/trace_data_cache_base.cpp", + "trace_data/trace_data_cache_base.h", + "trace_data/trace_data_cache_reader.cpp", + "trace_data/trace_data_cache_reader.h", + "trace_data/trace_data_cache_writer.cpp", + "trace_data/trace_data_cache_writer.h", + "trace_data/trace_data_db.cpp", + "trace_data/trace_data_db.h", + "trace_data/trace_stdtype.cpp", + "trace_data/trace_stdtype.h", + "trace_streamer/trace_streamer_selector.cpp", + "trace_streamer/trace_streamer_selector.h", + ] + include_dirs = [ + "base", + "..", + "trace_streamer", + "filter", + "table", + "trace_data", + "include", + "plugin", + "rpc", + "sdk", + "./", + "parser", + "cfg", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}", + "${OHOS_PROTO_GEN}/types/plugins/mock_data", + "//third_party/protobuf/src", + "//third_party/json-master/include", + "//third_party/json-master/include/nlohmann", + ] + if (!use_wasm) { + include_dirs += [ + "//third_party/libunwind/include", + "//third_party/libunwind/src", + ] + } + if (with_perf) { + sources += [] + include_dirs += [] + } + deps = [ + "base:base", + "ext:sqliteext", + "include:ibase", + "plugin:sdk_plugin", + "protos:ts_proto_data_cpp", + "//third_party/sqlite:sqlite", + ] + if (with_perf) { + } + + if (use_wasm || enable_ts_utest) { + sources += [ + "sdk/wasm_func.cpp", + "sdk/wasm_func.h", + ] + } + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + } + public_deps = [] +} +if (use_wasm) { + wasm_lib("trace_streamer_sdk_builtin_wasm") { + name = "trace_streamer_sdk_builtin" + deps = [ ":lib" ] + } +} else { + if (!is_test && !is_fuzz) { + executable("trace_streamer111") { + deps = [ ":lib" ] + } + } +} diff --git a/host/trace_streamer/prebuilts/buildsqlite/sqlite.pro b/host/trace_streamer/sdk/base/BUILD.gn old mode 100644 new mode 100755 similarity index 53% rename from host/trace_streamer/prebuilts/buildsqlite/sqlite.pro rename to host/trace_streamer/sdk/base/BUILD.gn index 50d80823e05b0cec037bc7efd38601b13f277508..31c10f4c2f46fd23607e22b1f22d2bc6d07356ce --- a/host/trace_streamer/prebuilts/buildsqlite/sqlite.pro +++ b/host/trace_streamer/sdk/base/BUILD.gn @@ -10,22 +10,31 @@ # 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. -QT -= gui core -TEMPLATE = lib -#TEMPLATE = app -CONFIG += c++14 lib -#CONFIG += c++14 -TARGET = sqlite -DEFINES += HAVE_PTHREAD -LIBDIR = $$PWD/../../third_party/sqlite -ROOTSRCDIR = $$PWD/../../src/ -include($$PWD/../../src/multi_platform/global.pri) +import("//build/ohos.gni") +import("../ts.gni") +ohos_source_set("base") { + deps = [] + public_deps = [ "../include:ibase" ] + include_dirs = [ "../include" ] + sources = [ + # "codec_cov.cpp", + # "file.cpp", + "log.cpp", + "meta.cpp", -LIBS += -L$$DESTDIR/ -lstdc++ - -#INCLUDEPATH += $$PWD/$${PROTOBUDIR}/src -INCLUDEPATH += $$PWD/../../third_party/sqlite/include - -message("includepath is:"$$INCLUDEPATH) -SOURCES += $${LIBDIR}/src/sqlite3.c + # "parting_string.cpp", + "string_help.cpp", + ] + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + } +} diff --git a/host/trace_streamer/sdk/base/args_set.h b/host/trace_streamer/sdk/base/args_set.h new file mode 100755 index 0000000000000000000000000000000000000000..6148fd25be100805820643594e7a5a9bfc27174b --- /dev/null +++ b/host/trace_streamer/sdk/base/args_set.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef SRC_TRACE_BASE_ARGS_SET_H +#define SRC_TRACE_BASE_ARGS_SET_H + +#include +#include +#include "ts_common.h" +namespace SysTuning { +namespace TraceStreamer { +class ArgsSet { +public: + ArgsSet() {} + ~ArgsSet() {} + ArgsSet& operator=(const ArgsSet& other) + { + this->valuesMap_ = other.valuesMap_; + this->argSetId_ = other.argSetId_; + this->sliceId_ = other.sliceId_; + this->inserted_ = other.inserted_; + return *this; + } + void AppendArg(DataIndex dataIndex, BaseDataType datatype, uint64_t value) + { + ArgsData data; + data.type = datatype; + data.value = value; + valuesMap_.emplace(dataIndex, data); + } + std::map valuesMap_; + uint32_t argSetId_ = 0; + uint32_t sliceId_ = 0; + bool inserted_ = false; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/sdk/base/log.cpp b/host/trace_streamer/sdk/base/log.cpp new file mode 100755 index 0000000000000000000000000000000000000000..7d167a90cb4f5f1678b59e23518ddce9873b89d1 --- /dev/null +++ b/host/trace_streamer/sdk/base/log.cpp @@ -0,0 +1,17 @@ +/* + * 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. + */ + +#include "log.h" +bool g_cleanMode = false; diff --git a/host/trace_streamer/sdk/base/meta.cpp b/host/trace_streamer/sdk/base/meta.cpp new file mode 100755 index 0000000000000000000000000000000000000000..426307745fa81440502fda7e18d71ae746fbea48 --- /dev/null +++ b/host/trace_streamer/sdk/base/meta.cpp @@ -0,0 +1,18 @@ +/* + * 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. + */ +#include "meta.h" +size_t g_loadSize = 0; +std::string SDK_VERSION = "1.0.0"; // version +std::string SDK_PUBLISHVERSION = "2022/9/24"; // publish datetime diff --git a/host/trace_streamer/sdk/base/meta.h b/host/trace_streamer/sdk/base/meta.h new file mode 100755 index 0000000000000000000000000000000000000000..99ca44232a458eabe8dc22561a22d92f126a2353 --- /dev/null +++ b/host/trace_streamer/sdk/base/meta.h @@ -0,0 +1,23 @@ +/* + * 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. + */ + +#ifndef META_H +#define META_H +#include +#include +extern size_t g_loadSize; +extern std::string SDK_VERSION; // version +extern std::string SDK_PUBLISHVERSION; // publish datetime +#endif diff --git a/host/trace_streamer/sdk/base/quatra_map.h b/host/trace_streamer/sdk/base/quatra_map.h new file mode 100755 index 0000000000000000000000000000000000000000..df344bd08bf91b71c2d5be8f86921b0c058068a4 --- /dev/null +++ b/host/trace_streamer/sdk/base/quatra_map.h @@ -0,0 +1,90 @@ +/* + * 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. + */ + +#ifndef SRC_TRACE_BASE_QUATRAMAP_H +#define SRC_TRACE_BASE_QUATRAMAP_H + +#include "triple_map.h" + +template +class QuatraMap { +public: + QuatraMap(T5 invalidValue) + { + invalidValue_ = invalidValue; + } + void SetInvalidRet(T5 invalidValue) + { + invalidValue_ = invalidValue; + } + void Insert(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Insert(t2, t3, t4, t5); + } else { + TripleMap mm(invalidValue_); + mm.Insert(t2, t3, t4, t5); + internalMap_.insert(std::make_pair(t1, mm)); + } + } + T5 Find(T1 t1, T2 t2, T3 t3, T4 t4) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + return (*streamIdHookidMap).second.Find(t2, t3, t4); + } else { + return invalidValue_; + } + } + void Erase(T1 t1) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + internalMap_.erase(streamIdHookidMap); + } + } + void Erase(T1 t1, T2 t2) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2); + } + } + void Erase(T1 t1, T2 t2, T3 t3) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2, t3); + } + } + void Erase(T1 t1, T2 t2, T3 t3, T4 t4) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2, t3, t4); + } + } + void Clear() + { + internalMap_.clear(); + } + +private: + std::map> internalMap_; + T5 invalidValue_; +}; + +#endif // SRC_TRACE_BASE_QUATRAMAP_H diff --git a/host/trace_streamer/sdk/base/string_help.cpp b/host/trace_streamer/sdk/base/string_help.cpp new file mode 100755 index 0000000000000000000000000000000000000000..dbee8cb69d881a7dcc44b66506635f7311e1641d --- /dev/null +++ b/host/trace_streamer/sdk/base/string_help.cpp @@ -0,0 +1,81 @@ +/* + * 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. + */ +#include "string_help.h" +#include +#include +#include +#include +namespace SysTuning { +namespace base { +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) +#if !is_mingw +int memcpy_s(void* dest, uint32_t destSize, const void* src, size_t srcSize) +{ + if (srcSize > destSize || src == nullptr || dest == nullptr) { + return -1; + } else { + if (!memcpy(dest, src, srcSize)) { + printf("memcpy fail\n"); + return -1; + } + } + return 0; +} +int sscanf_s(const char* buffer, const char* format, ...) +{ + va_list ap; + __builtin_va_start(ap, format); + int ret = scanf(buffer, format, ap); + __builtin_va_end(ap); + return ret; +} + +int strncpy_s(char* strDest, size_t destMax, const char* strSrc, size_t count) +{ + return memcpy_s(strDest, destMax, strSrc, count); +} +#endif +void* memset_s(void* dest, size_t destSize, int ch, size_t n) +{ + UNUSED(destSize); + UNUSED(ch); + return memset(dest, 0, n); +} + +int snprintf_s(char* strDest, size_t destMax, size_t count, const char* format, ...) +{ + UNUSED(count); + int ret; + va_list ap; + __builtin_va_start(ap, format); + ret = vsnprintf(strDest, destMax, format, ap); + __builtin_va_end(ap); + return ret; +} + +int sprintf_s(char* strDest, size_t destMax, const char* format, ...) +{ + UNUSED(destMax); + va_list ap; + __builtin_va_start(ap, format); + int ret = sprintf(strDest, format, ap); + __builtin_va_end(ap); + return ret; +} +} // namespace base +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/base/string_help.h b/host/trace_streamer/sdk/base/string_help.h new file mode 100755 index 0000000000000000000000000000000000000000..09323834a7d6d092860e1012e5c1ddbc892b147f --- /dev/null +++ b/host/trace_streamer/sdk/base/string_help.h @@ -0,0 +1,32 @@ +/* + * 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. + */ +#ifndef SRC_TRACE_BASE_STRINGHELP_H +#define SRC_TRACE_BASE_STRINGHELP_H + +#include +#include +namespace SysTuning { +namespace base { +#if !is_mingw +int memcpy_s(void* dest, uint32_t destSize, const void* src, size_t srcSize); +int sscanf_s(const char* buffer, const char* format, ...); +int strncpy_s(char* strDest, size_t destMax, const char* strSrc, size_t count); +#endif +void* memset_s(void* dest, size_t destSize, int ch, size_t n); +int snprintf_s(char* strDest, size_t destMax, size_t count, const char* format, ...); +int sprintf_s(char* strDest, size_t destMax, const char* format, ...); +} // namespace base +} // namespace SysTuning +#endif // SRC_TRACE_BASE_STRINGHELP_H diff --git a/host/trace_streamer/sdk/base/triple_map.h b/host/trace_streamer/sdk/base/triple_map.h new file mode 100755 index 0000000000000000000000000000000000000000..b9c30f8402fa067e3ae1f3bb9644c2f622a5ae06 --- /dev/null +++ b/host/trace_streamer/sdk/base/triple_map.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#ifndef SRC_TRACE_BASE_TRIPLEMAP_H +#define SRC_TRACE_BASE_TRIPLEMAP_H + +#include "double_map.h" + +template +class TripleMap { +public: + TripleMap(T4 invalidValue) + { + invalidValue_ = invalidValue; + } + void SetInvalidRet(T4 invalidValue) + { + invalidValue_ = invalidValue; + } + void Insert(T1 t1, T2 t2, T3 t3, T4 t4) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Insert(t2, t3, t4); + } else { + DoubleMap mm(invalidValue_); + mm.Insert(t2, t3, t4); + internalMap_.insert(std::make_pair(t1, mm)); + } + } + T4 Find(T1 t1, T2 t2, T3 t3) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + return (*streamIdHookidMap).second.Find(t2, t3); + } else { + return invalidValue_; + } + } + void Erase(T1 t1) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + internalMap_.erase(streamIdHookidMap); + } + } + void Erase(T1 t1, T2 t2) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2); + } + } + void Erase(T1 t1, T2 t2, T3 t3) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2, t3); + } + } + void Clear() + { + internalMap_.clear(); + } + +private: + std::map> internalMap_; + T4 invalidValue_; +}; + +#endif // SRC_TRACE_BASE_TRIPLEMAP_H diff --git a/host/trace_streamer/sdk/base/ts_common.h b/host/trace_streamer/sdk/base/ts_common.h new file mode 100755 index 0000000000000000000000000000000000000000..98521e494ca37499e895f4588858778d8af9767f --- /dev/null +++ b/host/trace_streamer/sdk/base/ts_common.h @@ -0,0 +1,125 @@ +/* + * 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. + */ + +#ifndef SRC_TRACE_BASE_TS_COMMON_H +#define SRC_TRACE_BASE_TS_COMMON_H + +#include +#include +#include +#include + +const uint64_t INVALID_UTID = std::numeric_limits::max(); +const uint64_t INVALID_UINT64 = std::numeric_limits::max(); +const uint64_t MAX_UINT32 = std::numeric_limits::max(); +const uint64_t MAX_UINT64 = std::numeric_limits::max(); +const uint32_t INVALID_UINT32 = std::numeric_limits::max(); +const uint32_t INVALID_INT32 = std::numeric_limits::max(); +const uint64_t INVALID_DATAINDEX = std::numeric_limits::max(); +const size_t MAX_SIZE_T = std::numeric_limits::max(); +const uint32_t INVALID_ID = std::numeric_limits::max(); +const uint64_t SEC_TO_NS = 1000 * 1000 * 1000; +const int STR_DEFAULT_LEN = -1; +const auto INVALID_CPU = INVALID_UINT32; +const auto INVALID_TIME = INVALID_UINT64; +enum BuiltinClocks { + TS_CLOCK_UNKNOW = 0, + TS_CLOCK_BOOTTIME = 1, + TS_CLOCK_REALTIME = 2, + TS_CLOCK_REALTIME_COARSE = 3, + TS_MONOTONIC = 4, + TS_MONOTONIC_COARSE = 5, + TS_MONOTONIC_RAW = 6, +}; + +enum RefType { + K_REF_NO_REF = 0, + K_REF_ITID = 1, + K_REF_CPUID = 2, + K_REF_IRQ = 3, + K_REF_SOFT_IRQ = 4, + K_REF_IPID = 5, + K_REF_ITID_LOOKUP_IPID = 6, + K_REF_MAX +}; + +enum EndState { + // (R) ready state or running state, the process is ready to run, but not necessarily occupying the CPU + TASK_RUNNABLE = 0, + // (S) Indicates that the process is in light sleep, waiting for the resource state, and can respond to the signal. + // Generally, the process actively sleeps into 'S' state. + TASK_INTERRUPTIBLE = 1, + // (D) Indicates that the process is in deep sleep, waiting for resources, and does not respond to signals. + // Typical scenario: process acquisition semaphore blocking. + TASK_UNINTERRUPTIBLE = 2, + // (Running) Indicates that the thread is running + TASK_RUNNING = 3, + // (I) Thread in interrupt state + TASK_INTERRUPTED = 4, + // (T) Task being traced + TASK_TRACED = 8, + // (X) Exit status, the process is about to be destroyed. + TASK_EXIT_DEAD = 16, + // (Z) Zombie state + TASK_ZOMBIE = 32, + // (I) clone thread + TASK_CLONE = 64, + // (K) Process killed + TASK_KILLED = 128, + // (DK) + TASK_DK = 130, + // the process is being debug now + TASK_TRACED_KILL = 136, + // (W) The process is in a deep sleep state and will be killed directly after waking up + TASK_WAKEKILL = 256, + // (R+) Process groups in the foreground + TASK_FOREGROUND = 2048, + TASK_MAX = 4096, + TASK_INVALID = 9999 +}; +enum TSLogLevel { + TS_DEBUG = 68, // Debug + TS_ERROR = 69, // Error + TS_INFO = 73, // Info + TS_VERBOSE = 86, // Verbose + TS_WARN = 87 // Warn +}; +enum SchedWakeType { + SCHED_WAKING = 0, // sched_waking + SCHED_WAKEUP = 1, // sched_wakeup +}; +using DataIndex = uint64_t; +using TableRowId = uint32_t; +using InternalPid = uint32_t; +using InternalTid = uint32_t; +using InternalTime = uint64_t; +using FilterId = uint32_t; +using InternalCpu = uint32_t; // how many cpus? could change to int8_t? + +enum BaseDataType { + BASE_DATA_TYPE_INT, + BASE_DATA_TYPE_STRING, + BASE_DATA_TYPE_DOUBLE, + BASE_DATA_TYPE_BOOLEAN +}; +namespace SysTuning { +namespace TraceStreamer { +struct ArgsData { + BaseDataType type; + int64_t value; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git "a/host/trace_streamer/sdk/doc/TraceStreamerSDK\350\257\246\347\273\206\350\256\276\350\256\241\350\257\264\346\230\216\344\271\246.doc" "b/host/trace_streamer/sdk/doc/TraceStreamerSDK\350\257\246\347\273\206\350\256\276\350\256\241\350\257\264\346\230\216\344\271\246.doc" new file mode 100644 index 0000000000000000000000000000000000000000..bcbb486f11a2e7db4cb29f0039a23f1deddf7257 Binary files /dev/null and "b/host/trace_streamer/sdk/doc/TraceStreamerSDK\350\257\246\347\273\206\350\256\276\350\256\241\350\257\264\346\230\216\344\271\246.doc" differ diff --git a/host/trace_streamer/doc/des_compile_trace_streamer.md b/host/trace_streamer/sdk/doc/wasm.md similarity index 31% rename from host/trace_streamer/doc/des_compile_trace_streamer.md rename to host/trace_streamer/sdk/doc/wasm.md index dd1f00ff4a9805c45a94254c90ca3e4069accf21..1dff98542e339e7c9f6c7f2ea6a5d7c0c2889aed 100644 --- a/host/trace_streamer/doc/des_compile_trace_streamer.md +++ b/host/trace_streamer/sdk/doc/wasm.md @@ -1,14 +1,5 @@ -# 如何独立编译Trace_streamer -尽管本工具(trace_streamer)是在ohos工具箱中的一员,但你依然可以独立编译此工具。 - -本工具可以编译linux, mac, windows, WebAssembly版本。 - -本工具默认编译方式是使用gn -+ 编译方式 -``` -./build.sh linux/wasm -``` -如果需要编译WebAssembly版本,您需要在prebuilts/目录下安装emsdk +为了方便传输此sdk开发包,位于prebuilts目录下的emsdk目录已经被删除,您可以通过下面的 +为了编译WebAssembly版本,您需要在prebuilts/目录下安装emsdk ``` git clone https://github.com/juj/emsdk.git --depth=1 cd emsdk @@ -48,86 +39,5 @@ prebuilts/emsdk ``` 之后调用 ``` -./build.sh wasm进行编译,您需要将sh脚本进行部分修改,因为这个脚本内置了一些库的下载和解析方式 -``` -本工具还支持使用QtCreator来编译。 - -src/trace_streamer.pro 是工程文件,编译本工具需要依赖Sqlite库和一些基于proto的pb.h文件 -## 2 准备工程 -### 2.1 基于proto文件生成pb文件 -您需要自行下载并编译一个当前系统(linux)可用的proobuf/protoc程序,此全路径为位于out/linux/protoc -src/protos目录下有一个protogen.sh文件,运行该文件可以在third_party/protogen目录下生成项目需要的pb相关文件 -序列化二进制的解析依赖于基于proto生成的.pb.cc文件。 -在执行protogen.sh脚本之后 -你的目录结构当类似如下结构: -``` -third_party/protogen/types/plugins/ftrace_data/*.pb.cc -third_party/sqlite/*. -third_party/protobuf/* -``` -### 2.2 获取第三方依赖库 -从 -https://gitee.com/openharmony/third_party_sqlite -获取sqlite3目录到代码根目录的third_party目录 -从 -https://gitee.com/openharmony/third_party_protobuf -获取protobuf目录到代码根目录的third_party目录 -之后,你的目录当如下所示 -trace_streamer/third_party/protobuf -trace_streamer/third_party/sqlite -# 3 (linux和ohos平台)使用gn编译TraceStreamer -在编译WebAssembly目标时,需要将sqlite3和protobuf里面相关的ohos_xxx_library统一修改为source_set -## 3.2 准备gn -在自己的项目中使用gn,必须遵循以下要求: -在根目录创建.gn文件,该文件用于指定CONFIG.gn文件的位置; -在BUILDCONFIG.gn中指定编译时使用的编译工具链; -在独立的gn文件中定义编译使用的工具链; -在项目根目录下创建BUILD.gn文件,指定编译的目标。 -``` -cp prebuilts/gn ./ -``` -不同的操作系统下,你需要获取不同的gn -## 3.3 执行编译 -./build.sh linux debug -或./build.sh linux debug -./build.sh将直接编译linux的release版本 -build.sh wasm 命令将可以编译WebAssembly版本 -特别说明:编译WebAssembly版本需要emSDK支持,你需要将build.sh里面的相关路径做更改,以保证编译时必须的文件是存在的 -# 4 编译Windows版本或Mac版本 -## 4.1 编译依赖文件 -### 4.1.1 编译SqliteLib -使用QtCreator打开prebuiltsprebuilts/buildprotobuf/sqlite.pro -### 4.1.2 编译ProtobufLib -使用QtCreator打开prebuilts/buildprotobuf/protobuf.pro -编译之后,文件结构当如下所示: -``` -lib -├── linux -│ ├── libdl.so -│ └── libsqlite.a -├── linux_debug -│ ├── libprotobuf.a -│ └── libsqlite.a -├── macx -│ ├── libprotobuf.a -│ └── libsqlite.a -├── macx_debug -│ ├── libprotobuf.a -│ └── libsqlite.a -├── windows -│ ├── libprotobuf.a -│ └── libsqlite.a -└── windows_debug - ├── libprotobuf.a - └── libsqlite.a -``` -## 4.2 编译TraceStreamer -之后,使用QtCreator打开src/trace_streamer.pro,选择合适的构建工具,执行 Ctrl + b 即可编译 - -编译之后的可执行文件位于out目录 -``` -- out ----- linux (Linux平台下QtCreator或gn生成) ----- macx (mac平台下QtCreator或gn生成) ----- windows (windows平台下QtCreator或gn生成) +./build.sh sdkdemo 进行编译demo ``` \ No newline at end of file diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer.pri b/host/trace_streamer/sdk/ext/BUILD.gn old mode 100644 new mode 100755 similarity index 67% rename from host/trace_streamer/src/trace_streamer/trace_streamer.pri rename to host/trace_streamer/sdk/ext/BUILD.gn index 9b33d314fe33af24bfe6409b2d61751a3c83e308..09643024743e6ad5e9a3aa9cb7d33317d975534d --- a/host/trace_streamer/src/trace_streamer/trace_streamer.pri +++ b/host/trace_streamer/sdk/ext/BUILD.gn @@ -11,11 +11,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -INCLUDEPATH += $$PWD -HEADERS += \ - $$PWD/trace_streamer_selector.h \ - $$PWD/trace_streamer_filters.h - -SOURCES += \ - $$PWD/trace_streamer_selector.cpp \ - $$PWD/trace_streamer_filters.cpp +import("//build/ohos.gni") +config("sqlite_config") { + include_dirs = [ + "../../third_party/sqlite/include", + "../include", + ] + cflags = [ "-Wno-writable-strings" ] +} +source_set("sqliteext") { + sources = [ "sqlite_ext_funcs.cpp" ] + public_configs = [ ":sqlite_config" ] +} diff --git a/host/trace_streamer/sdk/ext/sqlite_ext_funcs.cpp b/host/trace_streamer/sdk/ext/sqlite_ext_funcs.cpp new file mode 100755 index 0000000000000000000000000000000000000000..d3326cd4899fd517d0936a028c67d30a67324b08 --- /dev/null +++ b/host/trace_streamer/sdk/ext/sqlite_ext_funcs.cpp @@ -0,0 +1,358 @@ +/* + * 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. + */ +#include "sqlite_ext_funcs.h" +#include +#include +#include "log.h" +#include "sqlite3.h" +namespace SysTuning { +namespace base { +/* +** Return a stdev value +*/ +static void sqliteExtStdevFinalize(sqlite3_context* context) +{ + StdevCtx* ptr = static_cast(sqlite3_aggregate_context(context, 0)); + if (ptr && ptr->cntValue > 1) { + sqlite3_result_double(context, sqrt(ptr->rSValue / (ptr->cntValue - 1))); + } else { + sqlite3_result_double(context, 0.0); + } +} +/* +** called each value received during a calculation of stdev or variance +*/ +static void sqliteExtStdevNextStep(sqlite3_context* context, int argc, sqlite3_value** argv) +{ + TS_ASSERT(argc == 1); + StdevCtx* ptr = static_cast(sqlite3_aggregate_context(context, sizeof(StdevCtx))); + if (SQLITE_NULL != sqlite3_value_numeric_type(argv[0])) { + ptr->cntValue++; + double x = sqlite3_value_double(argv[0]); + double deltaValue = (x - ptr->rMValue); + ptr->rMValue += deltaValue / ptr->cntValue; + ptr->rSValue += deltaValue * (x - ptr->rMValue); + } +} + +enum Type { + tsNull = 0, + tsLong, + tsDouble, + tsString, + tsBytes, +}; + +struct TSSqlValue { + TSSqlValue() = default; + + static TSSqlValue Long(int64_t v) + { + TSSqlValue value; + value.longValue = v; + value.type = Type::tsLong; + return value; + } + + static TSSqlValue Double(double v) + { + TSSqlValue value; + value.doubleValue = v; + value.type = Type::tsDouble; + return value; + } + + static TSSqlValue String(const char* v) + { + TSSqlValue value; + value.stringValue = v; + value.type = Type::tsString; + return value; + } + + static TSSqlValue Bytes(const void* v, size_t size) + { + TSSqlValue value; + value.bytesValue = v; + value.bytesCount = size; + value.type = Type::tsBytes; + return value; + } + + double GetDouble() const + { + return doubleValue; + } + int64_t GetLong() const + { + return longValue; + } + const char* GetString() const + { + return stringValue; + } + const void* GetBytes() const + { + return bytesValue; + } + + bool isNull() const + { + return type == Type::tsNull; + } + + union { + const char* stringValue; + int64_t longValue; + double doubleValue; + const void* bytesValue; + }; + size_t bytesCount = 0; + Type type = tsNull; +}; + +TSSqlValue SqliteValueToTSSqlValue(sqlite3_value* value) +{ + TSSqlValue sqlValue; + switch (sqlite3_value_type(value)) { + case SQLITE_INTEGER: + sqlValue.type = Type::tsLong; + sqlValue.longValue = sqlite3_value_int64(value); + break; + case SQLITE_FLOAT: + sqlValue.type = Type::tsDouble; + sqlValue.doubleValue = sqlite3_value_double(value); + break; + case SQLITE_TEXT: + sqlValue.type = Type::tsString; + sqlValue.stringValue = reinterpret_cast(sqlite3_value_text(value)); + break; + case SQLITE_BLOB: + sqlValue.type = Type::tsBytes; + sqlValue.bytesValue = sqlite3_value_blob(value); + sqlValue.bytesCount = static_cast(sqlite3_value_bytes(value)); + break; + } + return sqlValue; +} +class JsonBuild { +public: + JsonBuild() = default; + void AppendHead() + { + body_ += "{"; + } + void AppendTail() + { + body_ += "}"; + } + void AppendCommon() + { + body_ += ","; + } + bool AppendSqlValue(const std::string& field_name, const TSSqlValue& value) + { + body_ += "\"" + field_name + "\":"; + return AppendSqlValue(value); + } + bool AppendSqlValue(const TSSqlValue& value) + { + switch (value.type) { + case tsLong: + body_ += std::to_string(value.longValue) + ","; + break; + case tsDouble: + body_ += std::to_string(value.doubleValue) + ","; + break; + case tsString: + body_ += "\"" + std::string(value.stringValue) + "\"" + ","; + break; + case tsBytes: + body_ += "\"" + std::string(static_cast(value.bytesValue), value.bytesCount) + "\"" + ","; + break; + case tsNull: + body_ += std::to_string(0) + ","; + break; + } + return true; + } + std::string body_; + bool poped_ = false; + void PopLast() + { + body_.pop_back(); + } + const std::string& Body() + { + return body_; + } +}; + +void BuildJson(sqlite3_context* ctx, int argc, sqlite3_value** argv) +{ + const int PAIR_ARGS_SIZE = 2; + if (argc % PAIR_ARGS_SIZE != 0) { + TS_LOGI("BuildJson arg number error"); + sqlite3_result_error(ctx, "BuildJson arg number error", -1); + return; + } + + JsonBuild builder; + builder.AppendHead(); + for (int i = 0; i < argc; i += PAIR_ARGS_SIZE) { + if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) { + TS_LOGI("BuildJson: Invalid args argc:%d, %d", argc, sqlite3_value_type(argv[i])); + sqlite3_result_error(ctx, "BuildJson: Invalid args", -1); + return; + } + + auto* key = reinterpret_cast(sqlite3_value_text(argv[i])); + auto value = SqliteValueToTSSqlValue(argv[i + 1]); + auto status = builder.AppendSqlValue(key, value); + if (!status) { + TS_LOGI("AppendSqlValueError"); + sqlite3_result_error(ctx, "AppendSqlValueError", -1); + return; + } + } + builder.PopLast(); + builder.AppendTail(); + std::string raw = builder.Body(); + if (raw.empty()) { + sqlite3_result_blob(ctx, "", 0, nullptr); + return; + } + std::unique_ptr data = std::make_unique(raw.size()); + memcpy(data.get(), raw.data(), raw.size()); + sqlite3_result_blob(ctx, data.release(), static_cast(raw.size()), free); +} + +void RepeatedJsonStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) +{ + const int PAIR_ARGS_SIZE = 2; + auto** jsonBuild = static_cast(sqlite3_aggregate_context(ctx, sizeof(JsonBuild*))); + + if (*jsonBuild == nullptr) { + *jsonBuild = new JsonBuild(); + } + JsonBuild* builder = *jsonBuild; + builder->AppendHead(); + for (int i = 0; i < argc; i += PAIR_ARGS_SIZE) { + if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) { + TS_LOGI("BuildJson: Invalid args argc:%d, %d", argc, sqlite3_value_type(argv[i])); + sqlite3_result_error(ctx, "BuildJson: Invalid args", -1); + return; + } + + auto* key = reinterpret_cast(sqlite3_value_text(argv[i])); + auto value = SqliteValueToTSSqlValue(argv[i + 1]); + auto status = builder->AppendSqlValue(key, value); + if (!status) { + TS_LOGI("AppendSqlValueError"); + sqlite3_result_error(ctx, "AppendSqlValueError", -1); + return; + } + } + builder->PopLast(); + builder->AppendTail(); + builder->AppendCommon(); +} +void RepeatedFieldStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) +{ + if (argc != 1) { + TS_LOGE( + "RepeatedField only support one arg, you can use BuildJson or BuildRepeatedJson function for multi args"); + return; + } + auto** jsonBuild = static_cast(sqlite3_aggregate_context(ctx, sizeof(JsonBuild*))); + + if (*jsonBuild == nullptr) { + *jsonBuild = new JsonBuild(); + } + JsonBuild* builder = *jsonBuild; + for (int i = 0; i < argc; i++) { + auto value = SqliteValueToTSSqlValue(argv[i]); + auto status = builder->AppendSqlValue(value); + if (!status) { + sqlite3_result_error(ctx, "error", -1); + } + } +} + +void RepeatedFieldFinal(sqlite3_context* ctx) +{ + auto** jsonBuilder = static_cast(sqlite3_aggregate_context(ctx, 0)); + + if (jsonBuilder == nullptr) { + sqlite3_result_null(ctx); + return; + } + + std::unique_ptr builder(*jsonBuilder); + std::string raw = builder->Body(); + raw.pop_back(); + if (raw.empty()) { + sqlite3_result_null(ctx); + return; + } + + std::unique_ptr data = std::make_unique(raw.size()); + memcpy(data.get(), raw.data(), raw.size()); + sqlite3_result_blob(ctx, data.release(), static_cast(raw.size()), free); +} + +void RepeatedJsonFinal(sqlite3_context* ctx) +{ + auto** jsonBuilder = static_cast(sqlite3_aggregate_context(ctx, 0)); + + if (jsonBuilder == nullptr) { + sqlite3_result_null(ctx); + return; + } + + std::unique_ptr builder(*jsonBuilder); + builder->PopLast(); + std::string raw = builder->Body(); + if (raw.empty()) { + sqlite3_result_null(ctx); + return; + } + + std::unique_ptr data = std::make_unique(raw.size()); + memcpy(data.get(), raw.data(), raw.size()); + sqlite3_result_blob(ctx, data.release(), static_cast(raw.size()), free); +} +void ts_create_extend_function(sqlite3* db) +{ + sqlite3_create_function(db, "stdev", -1, SQLITE_UTF8, nullptr, 0, sqliteExtStdevNextStep, sqliteExtStdevFinalize); + auto ret = sqlite3_create_function_v2(db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr, RepeatedFieldStep, + RepeatedFieldFinal, nullptr); + if (ret) { + TS_LOGF("Error while initializing RepeatedField"); + } + ret = sqlite3_create_function_v2(db, "BuildRepeatedJson", -1, SQLITE_UTF8, nullptr, nullptr, RepeatedJsonStep, + RepeatedJsonFinal, nullptr); + if (ret) { + TS_LOGF("Error while initializing BuildRepeatedJson"); + } + std::unique_ptr ctx = std::make_unique(); + ret = sqlite3_create_function_v2(db, "BuildJson", -1, SQLITE_UTF8, ctx.release(), BuildJson, nullptr, nullptr, + [](void* ptr) { delete static_cast(ptr); }); + if (ret != SQLITE_OK) { + TS_LOGF("Error while initializing BuildJson"); + } +} +} // namespace base +} // namespace SysTuning \ No newline at end of file diff --git a/host/trace_streamer/sdk/ext/sqlite_ext_funcs.h b/host/trace_streamer/sdk/ext/sqlite_ext_funcs.h new file mode 100755 index 0000000000000000000000000000000000000000..e1ce74a727d69a10d177682f38f54ac943c0687c --- /dev/null +++ b/host/trace_streamer/sdk/ext/sqlite_ext_funcs.h @@ -0,0 +1,30 @@ +/* + * 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. + */ +#ifndef SQLITE_EXT_FUNCS_H +#define SQLITE_EXT_FUNCS_H 1 +#include +#include "sqlite3.h" +namespace SysTuning { +namespace base { +typedef struct StdevCtx StdevCtx; +struct StdevCtx { + double rMValue; + double rSValue; + int64_t cntValue; +}; +void ts_create_extend_function(sqlite3* db); +} // namespace base +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/sdk/filter/clock_filter.cpp b/host/trace_streamer/sdk/filter/clock_filter.cpp new file mode 100755 index 0000000000000000000000000000000000000000..d21c79490ae23e5f36d9ffdf86e2e9eb297bbdf1 --- /dev/null +++ b/host/trace_streamer/sdk/filter/clock_filter.cpp @@ -0,0 +1,147 @@ +/* + * 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. + */ + +#include "clock_filter.h" +#include +#include +#include "string_help.h" + +namespace SysTuning { +namespace TraceStreamer { +ClockFilter::ClockFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) +{ + profilerSDKTraceFileHeader_ = std::make_unique().get(); +} +ClockFilter::~ClockFilter() {} + +std::string ClockFilter::GenClockKey(ClockId srcClockId, ClockId desClockId) +{ + std::string ret; + ret += std::to_string(srcClockId); + ret += ","; + ret += std::to_string(desClockId); + return ret; +} + +uint64_t ClockFilter::ToPrimaryTraceTime(ClockId srcClockId, uint64_t srcTs) const +{ + if (srcClockId == primaryClock_) { + return srcTs; + } + return Convert(srcClockId, srcTs, primaryClock_); +} + +uint64_t ClockFilter::Convert(ClockId srcClockId, uint64_t srcTs, ClockId desClockId) const +{ + std::string&& clockKey = GenClockKey(srcClockId, desClockId); + auto keyIt = clockMaps_.find(clockKey); + if (keyIt == clockMaps_.end()) { + return srcTs; + } + + auto tsIt = keyIt->second.upper_bound(srcTs); + if (tsIt != keyIt->second.begin()) { + tsIt--; + } + + if (tsIt->second >= 0) { + return srcTs + static_cast(tsIt->second); + } else { + return srcTs - static_cast(0 - tsIt->second); + } +} + +void ClockFilter::AddConvertClockMap(ClockId srcClockId, ClockId dstClockId, uint64_t srcTs, uint64_t dstTs) +{ + std::string&& clockKey = GenClockKey(srcClockId, dstClockId); + auto keyIt = clockMaps_.find(clockKey); + if (keyIt == clockMaps_.end()) { + ConvertClockMap newConvertMap = {{srcTs, dstTs - srcTs}}; + clockMaps_[clockKey] = newConvertMap; + } else { + clockMaps_[clockKey].insert(std::make_pair(srcTs, dstTs - srcTs)); + } +} +void ClockFilter::AddClockSnapshot(const std::vector& snapShot) +{ + ClockId srcId, desId; + for (srcId = 0; srcId < snapShot.size() - 1; srcId++) { + for (desId = srcId + 1; desId < snapShot.size(); desId++) { + ClockId srcClockId = snapShot[srcId].clockId; + ClockId desClockId = snapShot[desId].clockId; + uint64_t srcTs = snapShot[srcId].ts; + uint64_t desTs = snapShot[desId].ts; + + AddConvertClockMap(srcClockId, desClockId, srcTs, desTs); + AddConvertClockMap(desClockId, srcClockId, desTs, srcTs); + } + } + hasInitSnapShot_ = true; +} + +int ClockFilter::InitSnapShotTimeRange(const uint8_t* data, int len) +{ + std::unique_ptr buf = std::make_unique(len); + std::copy(data, data + len, buf.get()); + profilerSDKTraceFileHeader_ = reinterpret_cast(buf.get()); + + if (HasInitSnapShot()) { + TS_LOGE("SDK already has clock snapshot!!!"); + return -1; + } + if (!profilerSDKTraceFileHeader_->data.boottime) { + TS_LOGE("SDK Profiler header has no clock snapshot!!!"); + return -1; + } + + std::vector snapShot; + + TS_LOGE("SDK clockid: TS_CLOCK_BOOTTIME, ts:%llu", profilerSDKTraceFileHeader_->data.boottime); + if (profilerSDKTraceFileHeader_->data.boottime) { + snapShot.push_back(SnapShot{TS_CLOCK_BOOTTIME, profilerSDKTraceFileHeader_->data.boottime}); + } + + TS_LOGE("SDK clockid: TS_CLOCK_REALTIME, ts:%llu", profilerSDKTraceFileHeader_->data.realtime); + if (profilerSDKTraceFileHeader_->data.realtime) { + snapShot.push_back(SnapShot{TS_CLOCK_REALTIME, profilerSDKTraceFileHeader_->data.realtime}); + } + + TS_LOGE("SDK clockid: TS_CLOCK_REALTIME_COARSE, ts:%llu", profilerSDKTraceFileHeader_->data.realtimeCoarse); + if (profilerSDKTraceFileHeader_->data.realtimeCoarse) { + snapShot.push_back(SnapShot{TS_CLOCK_REALTIME_COARSE, profilerSDKTraceFileHeader_->data.realtimeCoarse}); + } + + TS_LOGE("SDK clockid: TS_MONOTONIC, ts:%llu", profilerSDKTraceFileHeader_->data.monotonic); + if (profilerSDKTraceFileHeader_->data.monotonic) { + snapShot.push_back(SnapShot{TS_MONOTONIC, profilerSDKTraceFileHeader_->data.monotonic}); + } + + TS_LOGE("SDK clockid: TS_MONOTONIC_COARSE, ts:%llu", profilerSDKTraceFileHeader_->data.monotonicCoarse); + if (profilerSDKTraceFileHeader_->data.monotonicCoarse) { + snapShot.push_back(SnapShot{TS_MONOTONIC_COARSE, profilerSDKTraceFileHeader_->data.monotonicCoarse}); + } + + TS_LOGE("SDK clockid: TS_MONOTONIC_RAW, ts:%llu", profilerSDKTraceFileHeader_->data.monotonicRaw); + if (profilerSDKTraceFileHeader_->data.monotonicRaw) { + snapShot.push_back(SnapShot{TS_MONOTONIC_RAW, profilerSDKTraceFileHeader_->data.monotonicRaw}); + } + + if (snapShot.size()) { + AddClockSnapshot(snapShot); + } + return 0; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/filter/clock_filter.h b/host/trace_streamer/sdk/filter/clock_filter.h new file mode 100755 index 0000000000000000000000000000000000000000..cd546133e0279c8e5825872c0b7c95f9b5a2474f --- /dev/null +++ b/host/trace_streamer/sdk/filter/clock_filter.h @@ -0,0 +1,89 @@ +/* + * 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. + */ + +#ifndef CLOCK_FILTER_H +#define CLOCK_FILTER_H + +#include +#include +#include +#include +#include +#include "file.h" +#include "trace_data_cache.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +/* + * TS_REALTIME: A settable system-wide clock that measures real time. Its time represents seconds and nanoseconds + * since the Epoch. + * TS_REALTIME_COARSE: A faster but less precise version of TS_REALTIME. This clock is not settable. + * TS_MONOTONIC: The number of seconds that the system has been running since it was booted.The CLOCK_MONOTONIC + * clock is not affected by discontinuous jumps in the system time ,but is affected by the incremental adjustments + * performed by adjtime(3) and NTP. This clock does not count time that the system is suspended. + * TS_MONOTONIC_COARSE: A faster but less precise version of TS_MONOTONIC. + * TS_MONOTONIC_RAW: Similar to TS_MONOTONIC, but provides access to a raw hardware-based time that is not subject + * to NTP adjustments or the incremental adjustments performed by adjtime(3). This clock does not count time that the + * system is suspended. + * TS_BOOTTIME: A nonsettable system-wide clock that is identical to TS_MONOTONIC, except that it also includes + * any time that the system is suspended. + */ + +using ClockId = uint32_t; +struct SnapShot { + ClockId clockId; + uint64_t ts; +}; +class TraceStreamerFilters; +class ClockFilter { +public: + using ConvertClockMap = std::map; + ClockFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + ~ClockFilter(); + + void SetPrimaryClock(ClockId primary) + { + primaryClock_ = primary; + } + ClockId GetPrimaryClock() + { + return primaryClock_; + } + uint64_t ToPrimaryTraceTime(ClockId srcClockId, uint64_t srcTs) const; + uint64_t Convert(ClockId srcClockId, uint64_t srcTs, ClockId desClockId) const; + void UpdatePluginTimeRange(ClockId clockId, uint64_t asyncTimestamp, uint64_t syncTimestamp); + void AddClockSnapshot(const std::vector& snapShot); + int InitSnapShotTimeRange(const uint8_t* data, int len); + bool HasInitSnapShot() + { + return hasInitSnapShot_; + } + +private: + static std::string GenClockKey(ClockId srcClockId, ClockId desClockId); + void AddConvertClockMap(ClockId srcClockId, ClockId dstClockId, uint64_t srcTs, uint64_t dstTs); + +private: + std::unordered_map clockMaps_ = {}; + base::ProfilerTraceFileHeader* profilerSDKTraceFileHeader_; + + ClockId primaryClock_ = BuiltinClocks::TS_CLOCK_BOOTTIME; + bool hasInitSnapShot_ = false; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // CLOCK_FILTER_H diff --git a/host/trace_streamer/src/ext/sqlite_ext.pri b/host/trace_streamer/sdk/include/BUILD.gn old mode 100644 new mode 100755 similarity index 67% rename from host/trace_streamer/src/ext/sqlite_ext.pri rename to host/trace_streamer/sdk/include/BUILD.gn index 6d1a82c69bc447f9b6b9260de2aaa6a427c8a0cb..e0f6aa748092c12737d8357c20351724f4c3a677 --- a/host/trace_streamer/src/ext/sqlite_ext.pri +++ b/host/trace_streamer/sdk/include/BUILD.gn @@ -10,7 +10,17 @@ # 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. -SOURCES += $$PWD/sqlite_ext_funcs.cpp -HEADERS += $$PWD/sqlite_ext_funcs.h -INCLUDEPATH += $$PWD/../../third_party/sqlite/include, - $$PWD/../include \ No newline at end of file +import("//build/ohos.gni") +ohos_source_set("ibase") { + sources = [ + "codec_cov.h", + "file.h", + "log.h", + "parting_string.h", + "string_to_numerical.h", + ] + include_dirs = [] + public_deps = [] + deps = [] + sources += [ "/usr/x86_64-w64-mingw32/include/windows.h" ] +} diff --git a/host/trace_streamer/sdk/include/file.h b/host/trace_streamer/sdk/include/file.h new file mode 100755 index 0000000000000000000000000000000000000000..71e15a05edf7949d30219d39eac4502275aeddf0 --- /dev/null +++ b/host/trace_streamer/sdk/include/file.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +#ifndef INCLUDE_TUNING_BASE_FILE_UTILS_H_ +#define INCLUDE_TUNING_BASE_FILE_UTILS_H_ + +#include + +namespace SysTuning { +namespace base { +constexpr uint32_t kFileModeInvalid = 0xFFFFFFFF; +enum TraceParserStatus { + TRACE_PARSER_NORMAL = 0, + TRACE_PARSER_FILE_TYPE_ERROR = 1, + TRACE_PARSE_ERROR = 2, + TRACE_PARSER_ABNORMAL = 3 +}; +struct ProfilerTraceFileHeader { + // Some space is reserved to facilitate the subsequent addition of fields in the header + static constexpr uint32_t HEADER_SIZE = 1024; + static constexpr uint32_t SHA256_SIZE = 256 / 8; + static constexpr uint64_t HEADER_MAGIC = 0x464F5250534F484FuLL; + static constexpr uint32_t V_MAJOR = 0x0001; + static constexpr uint32_t V_MAJOR_BITS = 16; + static constexpr uint32_t V_MINOR = 0x0000; + static constexpr uint32_t TRACE_VERSION = (V_MAJOR << V_MAJOR_BITS) | V_MINOR; + enum DataType { + HIPROFILER_PROTOBUF_BIN = 0, + HIPERF_DATA, + UNKNOW_TYPE = 1024, + }; + struct HeaderData { + // Magic number, used to distinguish offline files + uint64_t magic = HEADER_MAGIC; + // Total length, which can be used to check whether the document is truncated; + uint64_t length = HEADER_SIZE; + uint32_t version = TRACE_VERSION; + // The number of segments in the load data. The number of segments is even. One describes the length L and the + // other describes the next data v + uint32_t segments = 0; + // Sha256 of load data is used to verify whether the load data is complete; + uint8_t sha256[SHA256_SIZE] = {}; + uint32_t dataType = UNKNOW_TYPE; + // clock + uint64_t boottime = 0; + uint64_t realtime = 0; + uint64_t realtimeCoarse = 0; + uint64_t monotonic = 0; + uint64_t monotonicCoarse = 0; + uint64_t monotonicRaw = 0; + } __attribute__((packed)); + HeaderData data = {}; + uint8_t padding_[HEADER_SIZE - sizeof(data)] = {}; +}; + +void SetAnalysisResult(TraceParserStatus stat); + +TraceParserStatus GetAnalysisResult(); + +ssize_t Read(int fd, uint8_t* dst, size_t dstSize); + +int OpenFile(const std::string& path, int flags, uint32_t mode = kFileModeInvalid); + +std::string GetExecutionDirectoryPath(); +} // namespace base +} // namespace SysTuning +#endif // INCLUDE_TUNING_BASE_FILE_UTILS_H_ diff --git a/host/trace_streamer/sdk/include/log.h b/host/trace_streamer/sdk/include/log.h new file mode 100755 index 0000000000000000000000000000000000000000..fef94e664b845cb7715e4c7df202da47efad1789 --- /dev/null +++ b/host/trace_streamer/sdk/include/log.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef INCLUDE_TS_BASE_LOGGING_H_ +#define INCLUDE_TS_BASE_LOGGING_H_ + +#include +#include + +// namespace SysTuning { +// namespace base { +#define TS_CRASH \ + do { \ + __builtin_trap(); \ + __builtin_unreachable(); \ + } while (0) +enum LogLevel {LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL}; +const enum LogLevel g_currentLogLevel = LOG_DEBUG; +extern bool g_cleanMode; +#define LOGWITHLEVEL(level, motify, fmt, ...) \ + do { \ + if (level >= g_currentLogLevel) { \ + if (!g_cleanMode) { \ + fprintf(stdout, "[-%c][%s][%d]: " fmt "\n", motify, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__); \ + } \ + if (level == LOG_FATAL) { \ + TS_CRASH; \ + } \ + } \ + } while (0) +#define TS_LOGE(fmt, ...) LOGWITHLEVEL(LOG_ERROR, 'E', fmt, ##__VA_ARGS__) +#define TS_LOGF(fmt, ...) LOGWITHLEVEL(LOG_FATAL, 'F', fmt, ##__VA_ARGS__) +#define TS_LOGI(fmt, ...) LOGWITHLEVEL(LOG_INFO, 'I', fmt, ##__VA_ARGS__) +#ifdef NDEBUG +#define TS_LOGD(format, ...) +#define TS_LOGW(format, ...) +#define TS_ASSERT(x) +#else +#define TS_LOGD(fmt, ...) LOGWITHLEVEL(LOG_DEBUG, 'D', fmt, ##__VA_ARGS__) +#define TS_LOGW(fmt, ...) LOGWITHLEVEL(LOG_WARN, 'W', fmt, ##__VA_ARGS__) + +#define TS_ASSERT(x) \ + do { \ + if (!(x)) { \ + TS_CRASH; \ + } \ + } while (0) + +#endif +// } // namespace base +// } // namespace SysTuning + +#endif // INCLUDE_TS_BASE_LOGGING_H_ diff --git a/host/trace_streamer/sdk/include/string_to_numerical.h b/host/trace_streamer/sdk/include/string_to_numerical.h new file mode 100755 index 0000000000000000000000000000000000000000..ccfce4bc33612fde68c1a7b8a8a1c4a75bac6de9 --- /dev/null +++ b/host/trace_streamer/sdk/include/string_to_numerical.h @@ -0,0 +1,113 @@ +/* + * 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. + */ + +#ifndef INCLUDE_BASE_STRING_TO_NUMERICAL_H_ +#define INCLUDE_BASE_STRING_TO_NUMERICAL_H_ + +#include +#include +#include + +namespace SysTuning { +namespace base { +enum IntegerRadixType { + INTEGER_RADIX_TYPE_DEC = 10, + INTEGER_RADIX_TYPE_HEX = 16 +}; +inline uint16_t GetNameASCIISumNoNum(const std::string& str) +{ + uint32_t sum = 0; + int len = str.length() - 1; + while (len >= 0) { + sum += std::isdigit(str.at(len)) ? 0 : str.at(len); + len--; + } + return sum % INTEGER_RADIX_TYPE_HEX; +} +inline std::optional StrToUInt32(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) +{ + if (!str.empty()) { + char* endPtr = nullptr; + auto value = static_cast(std::strtoul(str.c_str(), &endPtr, base)); + if (!*endPtr) { + return std::make_optional(value); + } + } + + return std::nullopt; +} + +inline std::string number(uint64_t value, int base = INTEGER_RADIX_TYPE_DEC) +{ + std::stringstream ss; + if (base == INTEGER_RADIX_TYPE_DEC) { + ss << std::dec << value; + } else if (base == INTEGER_RADIX_TYPE_HEX) { + ss << std::hex << value; + } + return ss.str(); +} + +inline std::optional StrToInt32(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) +{ + if (!str.empty()) { + char* endPtr = nullptr; + auto value = static_cast(std::strtol(str.c_str(), &endPtr, base)); + if (!*endPtr) { + return std::make_optional(value); + } + } + + return std::nullopt; +} + +inline std::optional StrToUInt64(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) +{ + if (!str.empty()) { + char* endPtr = nullptr; + auto value = static_cast(std::strtoull(str.c_str(), &endPtr, base)); + if (!*endPtr) { + return std::make_optional(value); + } + } + + return std::nullopt; +} + +inline std::optional StrToInt64(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) +{ + if (!str.empty()) { + char* endPtr = nullptr; + int64_t value = static_cast(std::strtoll(str.c_str(), &endPtr, base)); + if (!*endPtr) { + return std::make_optional(value); + } + } + return std::nullopt; +} + +inline std::optional StrToDouble(const std::string& str) +{ + if (!str.empty()) { + double value = std::stod(str); + return std::make_optional(value); + } + + return std::nullopt; +} +} // namespace base +} // namespace SysTuning + +#endif // INCLUDE_TUNING_EXT_BASE_STRING_UTILS_H_ diff --git a/host/trace_streamer/sdk/main.cpp b/host/trace_streamer/sdk/main.cpp new file mode 100755 index 0000000000000000000000000000000000000000..59b9cf5d546a6c53ad08f31ceeb0568d5b11d972 --- /dev/null +++ b/host/trace_streamer/sdk/main.cpp @@ -0,0 +1,18 @@ +/* + * 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. + */ +int main(int argc, char** argv) +{ + return 0; +} diff --git a/host/trace_streamer/sdk/parser/event_parser_base.cpp b/host/trace_streamer/sdk/parser/event_parser_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4bdbf4f5e4e7ac919ecf6af18f1fe7b6e680f3d --- /dev/null +++ b/host/trace_streamer/sdk/parser/event_parser_base.cpp @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#include "event_parser_base.h" +namespace SysTuning { +namespace TraceStreamer { +EventParserBase::EventParserBase(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : streamFilters_(filter), traceDataCache_(dataCache) +{ +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/parser/event_parser_base.h b/host/trace_streamer/sdk/parser/event_parser_base.h new file mode 100755 index 0000000000000000000000000000000000000000..1d9313edfcd0557c8351d705b2e82639ac2e296e --- /dev/null +++ b/host/trace_streamer/sdk/parser/event_parser_base.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef SRC_EVENT_PARSER_BASE_H +#define SRC_EVENT_PARSER_BASE_H +#include "../trace_data/trace_data_cache.h" +#include "../trace_streamer/trace_streamer_filters.h" +namespace SysTuning { +namespace TraceStreamer { +class EventParserBase { +public: + EventParserBase(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + virtual ~EventParserBase() = default; + +public: + const TraceStreamerFilters* streamFilters_; + TraceDataCache* traceDataCache_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SRC_PARSER_BASE_H diff --git a/host/trace_streamer/sdk/parser/htrace_plugin_time_parser.cpp b/host/trace_streamer/sdk/parser/htrace_plugin_time_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..164c3b38aa631e7370ae926d3dc96d6227f1c261 --- /dev/null +++ b/host/trace_streamer/sdk/parser/htrace_plugin_time_parser.cpp @@ -0,0 +1,58 @@ +/* + * 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. + */ +#include "htrace_plugin_time_parser.h" +namespace SysTuning { +namespace TraceStreamer { +HtracePluginTimeParser::HtracePluginTimeParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : EventParserBase(dataCache, ctx) +{} +void HtracePluginTimeParser::UpdatePluginTimeRange(ClockId clockId, uint64_t asyncTimestamp, uint64_t syncTimestamp) +{ + minTs_ = std::min(minTs_, asyncTimestamp); + maxTs_ = std::max(maxTs_, asyncTimestamp); + if (clockId == streamFilters_->clockFilter_->GetPrimaryClock()) { + syncHtracePluginStartTime_ = std::min(syncHtracePluginStartTime_, syncTimestamp); + syncHtracePluginEndTime_ = std::max(syncHtracePluginEndTime_, syncTimestamp); + return; + } + if (syncTimestamp != asyncTimestamp) { + syncHtracePluginStartTime_ = std::min(syncHtracePluginStartTime_, syncTimestamp); + syncHtracePluginEndTime_ = std::max(syncHtracePluginEndTime_, syncTimestamp); + } else { + asyncHtracePluginStartTime_ = std::min(asyncHtracePluginStartTime_, syncTimestamp); + asyncHtracePluginEndTime_ = std::max(asyncHtracePluginEndTime_, syncTimestamp); + } +} +uint64_t HtracePluginTimeParser::GetPluginStartTime() +{ + if (syncHtracePluginStartTime_ != std::numeric_limits::max()) { + return syncHtracePluginStartTime_; + } else if (asyncHtracePluginStartTime_ != std::numeric_limits::max()) { + return asyncHtracePluginStartTime_; + } + return std::numeric_limits::max(); +} + +uint64_t HtracePluginTimeParser::GetPluginEndTime() +{ + if (syncHtracePluginEndTime_ != 0) { + return syncHtracePluginEndTime_; + } else if (asyncHtracePluginEndTime_ != 0) { + return asyncHtracePluginEndTime_; + } + return 0; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/parser/htrace_plugin_time_parser.h b/host/trace_streamer/sdk/parser/htrace_plugin_time_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..9fb1ab0766669630d6df9e7e7569b29392262041 --- /dev/null +++ b/host/trace_streamer/sdk/parser/htrace_plugin_time_parser.h @@ -0,0 +1,52 @@ +/* + * 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. + */ +#ifndef HTRACE_PLUGIN_TIME_PARSER_H +#define HTRACE_PLUGIN_TIME_PARSER_H +#include "clock_filter.h" +#include "event_parser_base.h" +#include "trace_data/trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class HtracePluginTimeParser : public EventParserBase { +public: + HtracePluginTimeParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + HtracePluginTimeParser(const HtracePluginTimeParser&) = delete; + HtracePluginTimeParser& operator=(const HtracePluginTimeParser&) = delete; + ~HtracePluginTimeParser() = default; + void UpdatePluginTimeRange(ClockId clockId, uint64_t asyncTimestamp, uint64_t syncTimestamep); + uint64_t GetPluginStartTime(); + uint64_t GetPluginEndTime(); + uint64_t MinTs() + { + return minTs_; + } + uint64_t MaxTs() + { + return maxTs_; + } + +private: + uint64_t syncHtracePluginStartTime_ = std::numeric_limits::max(); + uint64_t syncHtracePluginEndTime_ = 0; + uint64_t asyncHtracePluginStartTime_ = std::numeric_limits::max(); + uint64_t asyncHtracePluginEndTime_ = 0; + uint64_t minTs_ = std::numeric_limits::max(); + uint64_t maxTs_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_PLUGIN_TIME_PARSER_H diff --git a/host/trace_streamer/src/base/base.pri b/host/trace_streamer/sdk/plugin/BUILD.gn similarity index 57% rename from host/trace_streamer/src/base/base.pri rename to host/trace_streamer/sdk/plugin/BUILD.gn index e972a9228132e178c5b570e684b8fe7860f11f54..3166a8eb4d023944add851096d8e96ce1c11d7ff 100644 --- a/host/trace_streamer/src/base/base.pri +++ b/host/trace_streamer/sdk/plugin/BUILD.gn @@ -11,13 +11,24 @@ # See the License for the specific language governing permissions and # limitations under the License. -INCLUDEPATH +=$$PWD -HEADERS += \ - $$PWD/ts_common.h \ - $$PWD/double_map.h +import("//build/ohos.gni") +OHOS_PROTO_GEN = "//third_party/protogen" +ohos_source_set("sdk_plugin") { + sources = [ + "sdk_plugin_data_parser.cpp", + "sdk_plugin_data_parser.h", + ] + include_dirs = [ + "base", + "..", + "../include", + "../filter", + "../trace_data", + "../base", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}/types/plugins/mock_data", + "//third_party/protobuf/src", + ] -SOURCES += \ - $$PWD/codec_cov.cpp \ - $$PWD/file.cpp \ - $$PWD/parting_string.cpp \ - $$PWD/log.cpp + public_deps = [] +} diff --git a/host/trace_streamer/sdk/plugin/sdk_plugin_data_parser.cpp b/host/trace_streamer/sdk/plugin/sdk_plugin_data_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79e615ef763577a10b151b16cc250fb2b39b1b12 --- /dev/null +++ b/host/trace_streamer/sdk/plugin/sdk_plugin_data_parser.cpp @@ -0,0 +1,84 @@ +/* + * 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. + */ +#include "sdk_plugin_data_parser.h" +#include +#include "sdk/ts_sdk_api.h" + +namespace SysTuning { +namespace TraceStreamer { +extern "C" { +void sdk_plugin_init_table_name() +{ + SDK_SetTableName("counter_table", + "gpu_counter_object", + "slice_table", + "slice_object_table"); +} +int sdk_plugin_data_parser(const uint8_t* data, int len) +{ + std::unique_ptr buf = std::make_unique(len); + std::copy(data, data + len, buf.get()); + MockDataArr mockDataArr; + mockDataArr.ParseFromArray(buf.get(), len); + int size = mockDataArr.mockdata_size(); + if (size > 1) { + for (auto m = 0; m < size; m++) { + auto mockData = mockDataArr.mockdata().at(m); + sdk_plugin_parser(data, len, mockData); + } + } else { + MockData mockData; + mockData.ParseFromArray(buf.get(), len); + sdk_plugin_parser(data, len, mockData); + } + return 0; +} + +int sdk_plugin_parser(const uint8_t* data, int len, MockData mockData) +{ + // 解析counterObject + for (auto i = 0; i < mockData.counterobj_size(); i++) { + int counterId = mockData.counterobj(i).id(); + std::string counterName = mockData.counterobj(i).name(); + SDK_AppendCounterObject(counterId, counterName.c_str()); + } + + // 解析counterInfo + for (auto i = 0; i < mockData.counterinfo_size(); i++) { + CounterInfo counterInfo; + counterInfo = mockData.counterinfo(i); + SDK_AppendCounter(counterInfo.key(), counterInfo.ts(), counterInfo.value()); + } + + // 解析SliceObj + for (auto i = 0; i < mockData.sliceobj_size(); i++) { + int sliceId = mockData.sliceobj(i).id(); + std::string sliceName = mockData.sliceobj(i).name(); + SDK_AppendSliceObject(sliceId, sliceName.c_str()); + } + + // 解析SliceInfo + for (auto i = 0; i < mockData.sliceinfo_size(); i++) { + int sliceKey = mockData.sliceinfo(i).id(); + int sliceValue = mockData.sliceinfo(i).value(); + uint64_t startTime = mockData.sliceinfo(i).start_time(); + uint64_t endTime = mockData.sliceinfo(i).end_time(); + SDK_AppendSlice(sliceKey, startTime, endTime, sliceValue); + } + return 0; +} +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/plugin/sdk_plugin_data_parser.h b/host/trace_streamer/sdk/plugin/sdk_plugin_data_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..fd2f75ed43abe96c9f8cf79c1a548619b9c18fa0 --- /dev/null +++ b/host/trace_streamer/sdk/plugin/sdk_plugin_data_parser.h @@ -0,0 +1,31 @@ +/* + * 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. + */ +#ifndef SDK_PLUGIN_DATA_PARSER_H +#define SDK_PLUGIN_DATA_PARSER_H + +#include +#include "mock_plugin_result.pb.h" + +namespace SysTuning { +namespace TraceStreamer { +extern "C" { +// set table name +void sdk_plugin_init_table_name(); +int sdk_plugin_parser(const uint8_t* data, int len, MockData mockData); +int sdk_plugin_data_parser(const uint8_t* data, int len); +} +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pro b/host/trace_streamer/sdk/protos/BUILD.gn similarity index 41% rename from host/trace_streamer/prebuilts/buildprotobuf/protobuf.pro rename to host/trace_streamer/sdk/protos/BUILD.gn index 16afcce35f9128fe4cda5635837e2d5709de561a..0916cd9b338379bc7a3a56b1ce6e8164b66c958f 100644 --- a/host/trace_streamer/prebuilts/buildprotobuf/protobuf.pro +++ b/host/trace_streamer/sdk/protos/BUILD.gn @@ -10,26 +10,40 @@ # 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. -QT -= gui core -TEMPLATE = lib -#TEMPLATE = app -CONFIG += c++14 lib -#CONFIG += c++14 -TARGET = protobuf -DEFINES += HAVE_PTHREAD +import("//build/ohos.gni") +OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR = "//third_party/protobuf" +proto_dir = "//third_party/protogen" +mock_dir = "$proto_dir/types/plugins/mock_data" +config("ts_proto_include_config") { + include_dirs = [] +} +source_set("ts_proto_data_cpp") { + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + cflags = [ + "-ftrapv", + "-D_FORTIFY_SOURCE=2 -O2", + "-Wno-zero-length-array", + "-std=c++17", + ] -DEFINES += HAVE_PTHREAD -PROTOBUDIR = $$PWD/../../third_party/protobuf -ROOTSRCDIR = $$PWD/../../src/ -include($$PWD/../../src/multi_platform/global.pri) + if (!is_win) { + print("xxx") + cflags += [ + "-fPIE", + "-fPIC", + ] + } + if (!use_wasm) { + cflags += [ + "-fstack-protector-strong", # + "-fstack-protector-all", + ] + } -LIBS += -L$$DESTDIR/ -lstdc++ - -#INCLUDEPATH += $$PWD/$${PROTOBUDIR}/src -INCLUDEPATH += $$PWD/../../third_party/protobuf/src - -message("includepath is:"$$INCLUDEPATH) -include($$PWD/protobuf.pri) -include($$PWD/libprotobuf_lite_la_SOURCES.pri) -include($$PWD/libprotoc_la_SOURCES.pri) + public_configs = [ ":ts_proto_include_config" ] + sources = [ "${mock_dir}/mock_plugin_result.pb.cc" ] +} diff --git a/host/trace_streamer/sdk/protos/README_zh.md b/host/trace_streamer/sdk/protos/README_zh.md new file mode 100755 index 0000000000000000000000000000000000000000..6e49694e23aafe5dcfd18c921519b3f5edda1911 --- /dev/null +++ b/host/trace_streamer/sdk/protos/README_zh.md @@ -0,0 +1,10 @@ +# protos 代码仓 + + + +`services` 目录下存放的是 服务接口定义, + +`types` 目录下存放的是 具体插件业务相关的类型定义,主要为配置类型和结果类型定义。 + +例如,`types/plugins/cpu_data/` 目录存放CPU数据插件的配置类型和结果类型。 + diff --git a/host/trace_streamer/src/cfg/cfg.pri b/host/trace_streamer/sdk/protos/protogen.sh old mode 100644 new mode 100755 similarity index 42% rename from host/trace_streamer/src/cfg/cfg.pri rename to host/trace_streamer/sdk/protos/protogen.sh index 7833002efccdde1f36fe5cd2730085e4a687c623..35d9c3982cc5bbba330db5444eede65ea47a66ef --- a/host/trace_streamer/src/cfg/cfg.pri +++ b/host/trace_streamer/sdk/protos/protogen.sh @@ -1,4 +1,5 @@ -# Copyright (C) 2021 Huawei Device Co., Ltd. +#!/bin/bash +# 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 @@ -10,10 +11,25 @@ # 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. +set -e +SOURCE="${BASH_SOURCE[0]}" +cd $(dirname ${SOURCE}) +echo "begin to generate proto based files" +SOURCE=$(dirname ${SOURCE}) +proto_dir="." +services_dir="$proto_dir/services" +# kernel_version="5.10.79_aarch64" +kernel_version="." +mock_data_dir="$proto_dir/types/plugins/mock_data" +proto_array=("$mock_data_dir/mock_plugin_result.proto") -INCLUDEPATH +=$$PWD -HEADERS += \ - $$PWD/trace_streamer_config.h - -SOURCES += \ - $$PWD/trace_streamer_config.cpp +export LD_LIBRARY_PATH=../../out/linux +for ((i = 0; i < ${#proto_array[@]}; i ++)) +do + newpath=$(dirname ${proto_array[$i]}) + newpath=${newpath:2} + cppout=../../third_party/protogen/$newpath + mkdir -p $cppout + ../../out/linux/protoc --proto_path=$mock_data_dir --cpp_out=$cppout ${proto_array[$i]} +done +echo "generate proto based files over" diff --git a/host/trace_streamer/sdk/protos/protos.gni b/host/trace_streamer/sdk/protos/protos.gni new file mode 100755 index 0000000000000000000000000000000000000000..f8582402a8b542f4435fdeda2e18278b1bd725e7 --- /dev/null +++ b/host/trace_streamer/sdk/protos/protos.gni @@ -0,0 +1,36 @@ +# 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("../build/config.gni") + +subsys_name = OHOS_PROFILER_SUBSYS_NAME +part_name = OHOS_PROFILER_PART_NAME +subsys_x64_out = "clang_x64/$subsys_name/$part_name" +libc_dir_proto = rebase_path("$asdk_libs_dir", "//") +root_output_dir_proto = rebase_path("$root_out_dir", "//") + +#host:clang_x64 default:arm mingw:mingw_x86_64 +if (current_toolchain != host_toolchain) { + if (current_toolchain == default_toolchain) { + root_output_dir_proto = "$root_output_dir_proto/clang_x64" + } else { + root_output_dir_proto = + get_path_info("$root_output_dir_proto", "dir") + "/clang_x64" + } +} +protoc = root_output_dir_proto +print("default_toolchain = ", default_toolchain) +print("current_toolchain = ", current_toolchain) +print("host_toolchain = ", host_toolchain) +print("root_out_dir = ", root_out_dir) +print("root_output_dir_proto = ", root_output_dir_proto) diff --git a/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_config.proto b/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_config.proto new file mode 100755 index 0000000000000000000000000000000000000000..1f267cff59c12b1a2a37386930a546572eaeee22 --- /dev/null +++ b/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_config.proto @@ -0,0 +1,21 @@ +// 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. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message MockConfig { + uint32 version = 1; + string counters = 2; + bool stop_gator = 3; +} diff --git a/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_config_standard.proto b/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_config_standard.proto new file mode 100755 index 0000000000000000000000000000000000000000..8e62d2e991387156dd257d7ef840ccc452cc0434 --- /dev/null +++ b/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_config_standard.proto @@ -0,0 +1,19 @@ +// 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. +syntax = "proto3"; +package ForStandard; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; + +message MockConfig { + string msg = 1; +} diff --git a/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_result.proto b/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_result.proto new file mode 100755 index 0000000000000000000000000000000000000000..780c39196cd9a7fb55e57eb04b3241fbd6d56069 --- /dev/null +++ b/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_result.proto @@ -0,0 +1,51 @@ +// 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. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message SliceObj { + int32 id = 1; + string name = 2; +} + +message SliceInfo { + int32 id = 1; + int32 value = 2; + uint64 start_time = 3; + uint64 end_time = 4; +} + +message CounterObj { + int32 id = 1; + string name = 2; +} + +message CounterInfo { + int32 key = 1; + int32 value = 2; + uint64 ts = 3; +} + +message MockData { + repeated CounterObj counterobj = 1; + repeated CounterInfo counterinfo = 2; + repeated SliceObj sliceobj = 3; + repeated SliceInfo sliceinfo = 4; +} + +message MockDataArr { + repeated MockData mockdata = 1; +} diff --git a/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_result_standard.proto b/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_result_standard.proto new file mode 100755 index 0000000000000000000000000000000000000000..bebfd6b87f10d2616bc88ce5567dd838f3f8364e --- /dev/null +++ b/host/trace_streamer/sdk/protos/types/plugins/mock_data/mock_plugin_result_standard.proto @@ -0,0 +1,47 @@ +// 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. + +syntax = "proto3"; +package ForStandard; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; + +message SliceObj { + int32 id = 1; + string name = 2; +} + +message SliceInfo { + int32 id = 1; + int32 value = 2; + uint64 start_time = 3; + uint64 end_time = 4; +} + +message CounterObj { + int32 id = 1; + string name = 2; +} + +message CounterInfo { + int32 key = 1; + int32 value = 2; + uint64 ts = 3; +} + +message MockData { + repeated CounterObj counterobj = 1; + repeated CounterInfo counterinfo = 2; + repeated SliceObj sliceobj = 3; + repeated SliceInfo sliceinfo = 4; +} diff --git a/host/trace_streamer/sdk/rpc/http_server.cpp b/host/trace_streamer/sdk/rpc/http_server.cpp new file mode 100755 index 0000000000000000000000000000000000000000..44e0405d006d90b306d97cec08cc781730b879b0 --- /dev/null +++ b/host/trace_streamer/sdk/rpc/http_server.cpp @@ -0,0 +1,407 @@ +/* + * 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. + */ + +#include "http_server.h" +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#include "log.h" +#include "string_to_numerical.h" +namespace SysTuning { +namespace TraceStreamer { +void HttpServer::RegisterRpcFunction(RpcServer* rpc) +{ + rpcFunctions_.clear(); + + using std::placeholders::_1; + using std::placeholders::_2; + using std::placeholders::_3; + + auto parsedata = std::bind(&RpcServer::ParseData, rpc, _1, _2, _3); + rpcFunctions_["/parsedata"] = parsedata; + + auto parsedataover = std::bind(&RpcServer::ParseDataOver, rpc, _1, _2, _3); + rpcFunctions_["/parsedataover"] = parsedataover; + + auto sqlquery = std::bind(&RpcServer::SqlQuery, rpc, _1, _2, _3); + rpcFunctions_["/sqlquery"] = sqlquery; + + auto sqloperate = std::bind(&RpcServer::SqlOperate, rpc, _1, _2, _3); + rpcFunctions_["/sqloperate"] = sqloperate; + + auto reset = std::bind(&RpcServer::Reset, rpc, _1, _2, _3); + rpcFunctions_["/reset"] = reset; +} + +#ifdef _WIN32 +void HttpServer::Run(int port) +{ + WSADATA ws{}; + if (WSAStartup(MAKEWORD(WS_VERSION_FIRST, WS_VERSION_SEC), &ws) != 0) { + return; + } + if (!CreateSocket(port)) { + return; + } + WSAEVENT events[COUNT_SOCKET]; + for (int i = 0; i < COUNT_SOCKET; i++) { + if ((events[i] = WSACreateEvent()) == WSA_INVALID_EVENT) { + TS_LOGE("WSACreateEvent error %d", WSAGetLastError()); + return; + } + WSAEventSelect(sockets_[i].GetFd(), events[i], FD_ACCEPT | FD_CLOSE); + } + + while (!isExit_) { + ClearDeadClientThread(); + + int index = WSAWaitForMultipleEvents(COUNT_SOCKET, events, false, pollTimeOut_, false); + if (index == WSA_WAIT_FAILED) { + TS_LOGE("WSAWaitForMultipleEvents error %d", WSAGetLastError()); + break; + } else if (index == WSA_WAIT_TIMEOUT) { + continue; + } + + index = index - WSA_WAIT_EVENT_0; + WSANETWORKEVENTS event; + WSAEnumNetworkEvents(sockets_[index].GetFd(), events[index], &event); + if (event.lNetworkEvents & FD_ACCEPT) { + if (event.iErrorCode[FD_ACCEPT_BIT] != 0) { + continue; + } + + std::unique_ptr client = std::make_unique(); + if (sockets_[index].Accept(client->sock_)) { + client->thread_ = std::thread(&HttpServer::ProcessClient, this, std::ref(client->sock_)); + clientThreads_.push_back(std::move(client)); + } else { + TS_LOGE("http socket accept error"); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + } + + for (auto& it : clientThreads_) { + if (it->thread_.joinable()) { + it->sock_.Close(); + it->thread_.join(); + } + } + clientThreads_.clear(); + + WSACleanup(); +} +#else +void HttpServer::Run(int port) +{ + if (SIG_ERR == signal(SIGPIPE, SIG_IGN)) { + return; + } + + if (!CreateSocket(port)) { + return; + } + TS_LOGI("http server running"); + struct pollfd fds[COUNT_SOCKET]; + for (int i = 0; i < COUNT_SOCKET; i++) { + fds[i] = {sockets_[i].GetFd(), POLLIN, 0}; + } + while (!isExit_) { + ClearDeadClientThread(); + if (poll(fds, sizeof(fds) / sizeof(pollfd), pollTimeOut_) <= 0) { + continue; // try again + } + + for (int i = 0; i < 1; i++) { + if (fds[i].revents != POLLIN) { + continue; + } + std::unique_ptr client = std::make_unique(); + if (sockets_[i].Accept(client->sock_)) { + client->thread_ = std::thread(&HttpServer::ProcessClient, this, std::ref(client->sock_)); + clientThreads_.push_back(std::move(client)); + } else { + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + } + } + + for (auto& it : clientThreads_) { + if (it->thread_.joinable()) { + it->sock_.Close(); + it->thread_.join(); + } + } + clientThreads_.clear(); + + for (int i = 0; i < COUNT_SOCKET; i++) { + sockets_[i].Close(); + } + TS_LOGI("http server exit"); +} +#endif + +void HttpServer::Exit() +{ + isExit_ = true; + for (int i = 0; i < COUNT_SOCKET; i++) { + sockets_[i].Close(); + } +} + +bool HttpServer::CreateSocket(int port) +{ + for (int i = 0; i < COUNT_SOCKET; i++) { + if (!sockets_[i].CreateSocket(i == 0 ? AF_INET : AF_INET6)) { + TS_LOGE("Create http socket error"); + return false; + } + if (!sockets_[i].Bind(port)) { + TS_LOGE("bind http socket error"); + return false; + } + if (!sockets_[i].Listen(SOMAXCONN)) { + TS_LOGE("listen http socket error"); + return false; + } + } + + return true; +} + +void HttpServer::ClearDeadClientThread() +{ + for (auto it = clientThreads_.begin(); it != clientThreads_.end();) { + if (it->get()->sock_.GetFd() != -1) { + it++; + continue; + } + if (it->get()->thread_.joinable()) { + it->get()->thread_.join(); + } + it = clientThreads_.erase(it); + } +} + +#ifdef _WIN32 +void HttpServer::ProcessClient(HttpSocket& client) +{ + std::vector recvBuf(MAXLEN_REQUEST); + size_t recvLen = recvBuf.size(); + size_t recvPos = 0; + RequestST reqST; + WSAEVENT recvEvent = WSACreateEvent(); + if (recvEvent == WSA_INVALID_EVENT) { + TS_LOGE("WSACreateEvent error %d", WSAGetLastError()); + return; + } + WSAEventSelect(client.GetFd(), recvEvent, FD_READ | FD_CLOSE); + while (!isExit_) { + int index = WSAWaitForMultipleEvents(1, &recvEvent, false, pollTimeOut_, false); + if (index == WSA_WAIT_FAILED) { + TS_LOGE("WSAWaitForMultipleEvents error %d", WSAGetLastError()); + break; + } else if (index == WSA_WAIT_TIMEOUT) { + if (reqST.stat != RequstParseStat::INIT) { + ProcessRequest(client, reqST); + reqST.stat = RequstParseStat::INIT; + recvPos = 0; + recvLen = recvBuf.size(); + } + continue; + } + + WSANETWORKEVENTS event; + WSAEnumNetworkEvents(client.GetFd(), recvEvent, &event); + if (event.lNetworkEvents & FD_READ) { + if (event.iErrorCode[FD_READ_BIT] != 0) { + continue; + } + if (!client.Recv(recvBuf.data() + recvPos, recvLen)) { + break; + } + recvPos += recvLen; + ParseRequest(recvBuf.data(), recvPos, reqST); + recvLen = recvBuf.size() - recvPos; + if (reqST.stat == RequstParseStat::RECVING) { + continue; + } + ProcessRequest(client, reqST); + reqST.stat = RequstParseStat::INIT; + } else if (event.lNetworkEvents & FD_CLOSE) { + TS_LOGI("client close socket(%d)", client.GetFd()); + break; + } + } + TS_LOGI("recive client thread exit. socket(%d)", client.GetFd()); + + client.Close(); +} +#else +void HttpServer::ProcessClient(HttpSocket& client) +{ + std::vector recvBuf(MAXLEN_REQUEST); + size_t recvLen = recvBuf.size(); + size_t recvPos = 0; + RequestST reqST; + + struct pollfd fd = {client.GetFd(), POLLIN, 0}; + while (!isExit_) { + int pollRet = poll(&fd, sizeof(fd) / sizeof(pollfd), pollTimeOut_); + if (pollRet < 0) { + TS_LOGE("poll client socket(%d) error: %d:%s", client.GetFd(), errno, strerror(errno)); + break; + } + if (pollRet == 0) { + if (reqST.stat != RequstParseStat::INIT) { + ProcessRequest(client, reqST); + reqST.stat = RequstParseStat::INIT; + recvPos = 0; + recvLen = recvBuf.size(); + } + continue; + } + if (!client.Recv(recvBuf.data() + recvPos, recvLen)) { + TS_LOGI("client exit"); + break; + } + recvPos += recvLen; + ParseRequest(recvBuf.data(), recvPos, reqST); + recvLen = recvBuf.size() - recvPos; + if (reqST.stat == RequstParseStat::RECVING) { + continue; + } + ProcessRequest(client, reqST); + reqST.stat = RequstParseStat::INIT; + } + TS_LOGI("recive client thread exit. socket(%d)", client.GetFd()); + + client.Close(); + TS_LOGI("thread exit"); +} +#endif + +void HttpServer::ProcessRequest(HttpSocket& client, RequestST& request) +{} + +void HttpServer::ParseRequest(const uint8_t* requst, size_t& len, RequestST& httpReq) +{ + std::string_view reqStr(reinterpret_cast(requst), len); + size_t bodyPos = reqStr.find("\r\n\r\n"); + if (bodyPos == 0) { + len = 0; + httpReq.stat = RequstParseStat::BAD; + return; + } else if (bodyPos == std::string_view::npos) { + httpReq.stat = RequstParseStat::RECVING; + return; + } + std::string_view header = reqStr.substr(0, bodyPos); + bodyPos += strlen("\r\n\r\n"); + httpReq.bodyLen = reqStr.size() - bodyPos; + + std::vector headerlines = StringSplit(header, "\r\n"); + // at least 1 line in headerlines, such as "GET /parsedata HTTP/1.1" + std::vector requestItems = StringSplit(headerlines[0], " "); + const size_t indexHttpMethod = 0; + const size_t indexHttpUri = 1; + const size_t indexHttpVersion = 2; + const size_t countRequestItems = 3; + if (requestItems.size() != countRequestItems || requestItems[indexHttpVersion] != "HTTP/1.1") { + len = 0; + httpReq.stat = RequstParseStat::BAD; + return; + } + httpReq.method = requestItems[indexHttpMethod]; + httpReq.uri = requestItems[indexHttpUri]; + + for (size_t i = 1; i < headerlines.size(); i++) { + size_t tagPos = headerlines[i].find(":"); + if (tagPos == std::string_view::npos) { + len = 0; + httpReq.stat = RequstParseStat::BAD; + return; + } + std::string_view tag = headerlines[i].substr(0, tagPos); + if (strncasecmp(tag.data(), "Content-Length", tag.size()) == 0) { + std::string value(headerlines[i].data() + tagPos + strlen(":"), + headerlines[i].size() - tagPos - strlen(":")); + size_t conterntLen = atoi(value.c_str()); + if (conterntLen > httpReq.bodyLen) { + httpReq.stat = RequstParseStat::RECVING; + return; + } else if (conterntLen < httpReq.bodyLen) { + httpReq.bodyLen = conterntLen; + } + } + } + + if (httpReq.bodyLen > 0) { + httpReq.body = (requst + bodyPos); + } + httpReq.stat = RequstParseStat::OK; + len -= (bodyPos + httpReq.bodyLen); + return; +} + +void HttpServer::HttpResponse(HttpSocket& client, const std::string& status, bool hasBody) +{ + std::string res; + const size_t maxLenResponse = 1024; + res.reserve(maxLenResponse); + res += "HTTP/1.1 "; + res += status; + + res += "Connection: Keep-Alive\r\n"; + if (hasBody) { + res += "Content-Type: application/json\r\n"; + res += "Transfer-Encoding: chunked\r\n"; + } + res += "\r\n"; + if (!client.Send(res.data(), res.size())) { + TS_LOGE("send client socket(%d) error", client.GetFd()); + } +} + +std::vector HttpServer::StringSplit(std::string_view source, std::string_view split) +{ + std::vector result; + if (!split.empty()) { + size_t pos = 0; + while ((pos = source.find(split)) != std::string_view::npos) { + // split + std::string_view token = source.substr(0, pos); + if (!token.empty()) { + result.push_back(token); + } + source = source.substr(pos + split.size(), source.size() - token.size() - split.size()); + } + } + // add last token + if (!source.empty()) { + result.push_back(source); + } + return result; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/rpc/http_server.h b/host/trace_streamer/sdk/rpc/http_server.h new file mode 100755 index 0000000000000000000000000000000000000000..e1bd125567c8845c46d721786686d8ea6fc7f56b --- /dev/null +++ b/host/trace_streamer/sdk/rpc/http_server.h @@ -0,0 +1,80 @@ +/* + * 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. + */ + +#ifndef RPC_HTTPD_H +#define RPC_HTTPD_H + +#include +#include +#include +#include +#include +#include "http_socket.h" +#include "rpc_server.h" +namespace SysTuning { +namespace TraceStreamer { +class HttpServer { +public: + void RegisterRpcFunction(RpcServer* rpc); + void Run(int port = 9001); + void Exit(); + + static constexpr size_t MAXLEN_REQUEST = 2 * 1024 + 1024 * 1024; // header 2K + body 1M + +private: + struct ClientThread { + HttpSocket sock_; + std::thread thread_; + }; + + enum RequstParseStat { + INIT = 0, + OK, + BAD, + RECVING + }; + + struct RequestST { + int stat = RequstParseStat::INIT; + std::string method; + std::string uri; + const uint8_t* body; + size_t bodyLen; + }; + + bool CreateSocket(int port); + void ProcessClient(HttpSocket& client); + void ProcessRequest(HttpSocket& client, RequestST& request); + static void HttpResponse(HttpSocket& client, const std::string& status, bool hasBody = false); + void ParseRequest(const uint8_t* requst, size_t& len, RequestST& httpReq); + void ClearDeadClientThread(); + static std::vector StringSplit(std::string_view source, std::string_view split); + + static const int COUNT_SOCKET = 1; + HttpSocket sockets_[COUNT_SOCKET]; // ipv4 and ipv6 + std::atomic_bool isExit_ = {false}; + std::vector> clientThreads_; + using RpcFunction = std::function; + std::map rpcFunctions_; + const int pollTimeOut_ = 1000; +#ifdef _WIN32 + const uint32_t WS_VERSION_FIRST = 2; + const uint32_t WS_VERSION_SEC = 2; +#endif +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // RPC_HTTPD_H diff --git a/host/trace_streamer/sdk/rpc/http_socket.cpp b/host/trace_streamer/sdk/rpc/http_socket.cpp new file mode 100755 index 0000000000000000000000000000000000000000..e5e9cbe50cec847154d5ba11b5fdd4286dae0d27 --- /dev/null +++ b/host/trace_streamer/sdk/rpc/http_socket.cpp @@ -0,0 +1,173 @@ +/* + * 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. + */ + +#include "http_socket.h" +#include +#ifdef _WIN32 +#include +#include +#else +#include +#include +#include +#endif +#include "log.h" +namespace SysTuning { +namespace TraceStreamer { +HttpSocket::~HttpSocket() +{ + Close(); +} +bool HttpSocket::CreateSocket(int domain) +{ + SOCKET sockId = socket(domain, SOCK_STREAM, 0); + if (sockId == INVALID_SOCKET) { + TS_LOGE("CreateSocket socket error, domain %d: %d:%s", domain, errno, strerror(errno)); + return false; + } + sockId_ = sockId; + if (domain == AF_INET || domain == AF_INET6) { + int enable = 1; + if (setsockopt(sockId, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&enable), + sizeof(enable)) == SOCKET_ERROR) { + Close(); + return false; + } + if (domain == AF_INET6) { + if (setsockopt(sockId, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&enable), + sizeof(enable)) == SOCKET_ERROR) { + Close(); + return false; + } + } + } + domain_ = domain; + TS_LOGI("CreateSocket socket ok, socket %d domain %d", sockId_, domain); + return true; +} + +bool HttpSocket::Bind(int port) +{ + if (sockId_ == INVALID_SOCKET) { + TS_LOGE("the socket not created"); + return false; + } + + if (domain_ == AF_INET) { + struct sockaddr_in addr; + std::fill(reinterpret_cast(&addr), reinterpret_cast(&addr) + sizeof(addr), 0); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htons(INADDR_ANY); + addr.sin_port = htons(static_cast(port)); + if (bind(sockId_, reinterpret_cast(&addr), sizeof(addr)) == -1) { + TS_LOGE("bind ipv4 socket error, port %d: %d:%s", port, errno, strerror(errno)); + return false; + } + } else if (domain_ == AF_INET6) { + struct sockaddr_in6 addr; + std::fill(reinterpret_cast(&addr), reinterpret_cast(&addr) + sizeof(addr), 0); + addr.sin6_family = AF_INET6; + addr.sin6_addr = in6addr_any; + addr.sin6_port = htons(static_cast(port)); + if (bind(sockId_, reinterpret_cast(&addr), sizeof(addr)) == -1) { + TS_LOGE("bind ipv6 socket error, port %d: %d:%s", port, errno, strerror(errno)); + return false; + } + } else { + return false; + } + TS_LOGI("bind socket ok, port %d", port); + return true; +} + +bool HttpSocket::Listen(int maxConn) +{ + if (listen(sockId_, maxConn) == SOCKET_ERROR) { + TS_LOGE("listen socket error: %d:%s", errno, strerror(errno)); + return false; + } + TS_LOGI("listen socket ok, maxConn %d", maxConn); + return true; +} + +bool HttpSocket::Accept(HttpSocket& client) +{ + int clientId = accept(sockId_, nullptr, nullptr); + if (clientId == INVALID_SOCKET) { + TS_LOGE("accept socket error: %d:%s", errno, strerror(errno)); + return false; + } + + client.domain_ = domain_; + client.sockId_ = clientId; + TS_LOGI("accept client socket id %d domain %d", clientId, domain_); + return true; +} + +bool HttpSocket::Recv(void* data, size_t& len) +{ +#ifdef _WIN32 + ssize_t recvLen = recv(sockId_, static_cast(data), len, 0); +#else + ssize_t recvLen = recv(sockId_, data, len, 0); +#endif + if (recvLen == SOCKET_ERROR) { + if (errno == EAGAIN) { + recvLen = 0; + } else { + TS_LOGE("recv from socket(%d) error: %d:%s", sockId_, errno, strerror(errno)); + return false; + } + } else if (recvLen == 0) { + TS_LOGI("client socket(%d) closed", sockId_); + return false; + } + len = recvLen; + TS_LOGD("Recv from socket(%d) len %zu", sockId_, len); + return true; +} + +bool HttpSocket::Send(const void* data, size_t len) +{ +#ifdef _WIN32 + ssize_t sendLen = send(sockId_, static_cast(data), len, 0); +#else + ssize_t sendLen = send(sockId_, data, len, 0); +#endif + if (sendLen == SOCKET_ERROR) { + TS_LOGE("send to socket(%d) error: %d:%s", sockId_, errno, strerror(errno)); + return false; + } + TS_LOGI("send to socket(%d) len %zu", sockId_, len); + return true; +} + +void HttpSocket::Close() +{ + if (sockId_ == INVALID_SOCKET) { + return; + } + TS_LOGI("close socket(%d)", sockId_); +#ifdef _WIN32 + if (closesocket(sockId_) == SOCKET_ERROR) { +#else + if (close(sockId_) == SOCKET_ERROR) { +#endif + TS_LOGE("close socket(%d) error: %d:%s", sockId_, errno, strerror(errno)); + } + sockId_ = INVALID_SOCKET; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/rpc/http_socket.h b/host/trace_streamer/sdk/rpc/http_socket.h new file mode 100755 index 0000000000000000000000000000000000000000..25b124fe366074cf344d41f50915d48563f688ae --- /dev/null +++ b/host/trace_streamer/sdk/rpc/http_socket.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef RPC_HTTPSOCKET_H +#define RPC_HTTPSOCKET_H + +#include +namespace SysTuning { +namespace TraceStreamer { +class HttpSocket { +public: + HttpSocket() {} + HttpSocket(int sockId, int domain) : sockId_(sockId), domain_(domain) {} + ~HttpSocket(); + + bool CreateSocket(int domain); + bool Bind(int port); + bool Listen(int maxConn); + bool Accept(HttpSocket& client); + bool Recv(void* data, size_t& len); + bool Send(const void* data, size_t len); + void Close(); + bool IsValid() + { + return sockId_ != INVALID_SOCKET; + } + int GetFd() + { + return sockId_; + } + +private: + int sockId_ = -1; + int domain_ = 0; + using SOCKET = int; + const int SOCKET_ERROR = -1; + const SOCKET INVALID_SOCKET = -1; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // RPC_HTTPSOCKET_H diff --git a/host/trace_streamer/sdk/rpc/rpc_server.cpp b/host/trace_streamer/sdk/rpc/rpc_server.cpp new file mode 100755 index 0000000000000000000000000000000000000000..4765e3e6aa6eab2da9b0a17fc02288373e29a91c --- /dev/null +++ b/host/trace_streamer/sdk/rpc/rpc_server.cpp @@ -0,0 +1,103 @@ +/* + * 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. + */ + +#include "rpc_server.h" + +#include +#include +#include + +#include "log.h" +#include "meta.h" + +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) +namespace SysTuning { +namespace TraceStreamer { + +bool RpcServer::SqlOperate(const uint8_t* data, size_t len, ResultCallBack resultCallBack) +{ + ts_->SetCancel(false); + std::string sql(reinterpret_cast(data), len); + TS_LOGI("RPC SqlOperate(%s, %zu)", sql.c_str(), len); + + int ret = ts_->OperateDatabase(sql); + if (resultCallBack) { + std::string response = "ok\r\n"; + if (ret != 0) { + response = "dberror\r\n"; + } + resultCallBack(response, SEND_FINISH, 0); + } + return (ret == 0); +} + +bool RpcServer::SqlQuery(const uint8_t* data, size_t len, ResultCallBack resultCallBack) +{ + ts_->SetCancel(false); + std::string sql(reinterpret_cast(data), len); + TS_LOGI("RPC SqlQuery %zu:%s", len, sql.c_str()); + + int ret = ts_->SearchDatabase(sql, resultCallBack); + if (resultCallBack && ret != 0) { + resultCallBack("dberror\r\n", SEND_FINISH, 0); + } + ts_->SetCancel(false); + return (ret == 0); +} + +void RpcServer::CancelSqlQuery() +{ + ts_->SetCancel(true); +} + +bool RpcServer::Reset(const uint8_t* data, size_t len, ResultCallBack resultCallBack) +{ + UNUSED(data); + UNUSED(len); + TS_LOGI("RPC reset trace_streamer"); + + ts_->WaitForParserEnd(); + ts_ = std::make_unique(); + if (resultCallBack) { + resultCallBack("ok\r\n", SEND_FINISH, 0); + } + return true; +} + +int RpcServer::WasmSqlQuery(const uint8_t* data, size_t len, uint8_t* out, int outLen) +{ + ts_->SetCancel(false); + std::string sql(reinterpret_cast(data), len); + TS_LOGI("WASM RPC SqlQuery out(%p:%d) sql(%zu:%s)", reinterpret_cast(out), outLen, + len, sql.c_str()); + + int ret = ts_->SearchDatabase(sql, out, outLen); + return ret; +} +int RpcServer::WasmSqlQueryWithCallback(const uint8_t* data, size_t len, ResultCallBack callback) const +{ + ts_->SetCancel(false); + std::string sql(reinterpret_cast(data), len); + TS_LOGI("WASM RPC SqlQuery sql(%zu:%s)", len, sql.c_str()); + + int ret = ts_->SearchDatabase(sql, callback); + return ret; +} + +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/rpc/rpc_server.h b/host/trace_streamer/sdk/rpc/rpc_server.h new file mode 100755 index 0000000000000000000000000000000000000000..a784c440f134a1fd2bdc4c75e293ebc3293a7efd --- /dev/null +++ b/host/trace_streamer/sdk/rpc/rpc_server.h @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#ifndef RPC_RPC_H +#define RPC_RPC_H + +#include +#include +#include "../trace_streamer/trace_streamer_selector.h" +#include "../sdk/sdk_data_parser.h" +namespace SysTuning { +namespace TraceStreamer { +class RpcServer { +public: + using ResultCallBack = std::function; + using TraceRangeCallbackFunction = std::function; + // In order to bind HTTP, maintain a unified interface, even if some parameters are useless + bool SqlOperate(const uint8_t* data, size_t len, ResultCallBack resultCallBack); + bool SqlQuery(const uint8_t* data, size_t len, ResultCallBack resultCallBack); + bool Reset(const uint8_t* data, size_t len, ResultCallBack resultCallBack); + void CancelSqlQuery(); + + // only for wasm, no callback + int WasmSqlQuery(const uint8_t* data, size_t len, uint8_t* out, int outLen); + int WasmSqlQueryWithCallback(const uint8_t* data, size_t len, ResultCallBack callback) const; + +public: + std::unique_ptr ts_ = std::make_unique(); +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // RPC_RPC_H diff --git a/host/trace_streamer/sdk/sdk/sdk_data_parser.cpp b/host/trace_streamer/sdk/sdk/sdk_data_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15b2eac2b62ef2b694db554db566d8180df9a66a --- /dev/null +++ b/host/trace_streamer/sdk/sdk/sdk_data_parser.cpp @@ -0,0 +1,206 @@ +/* + * 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. + */ + +#include "sdk_data_parser.h" +#include +#include +#include +#include +#include "clock_filter.h" +#include "gpu_counter_object_table.h" +#include "gpu_counter_table.h" +#include "json.hpp" +#include "log.h" +#include "meta.h" +#include "meta_table.h" +#include "sdk_plugin_data_parser.h" +#include "slice_object_table.h" +#include "slice_table.h" +#include "ts_common.h" +#include "ts_sdk_api.h" + + +namespace SysTuning { +namespace TraceStreamer { +SDKDataParser::SDKDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : HtracePluginTimeParser(dataCache, ctx) +{ +} + +int SDKDataParser::GetPluginName(const uint8_t* data, int len) +{ + std::string pluginName(reinterpret_cast(data), len); + pluginName.replace(pluginName.find("-"), 1, "_"); + counterTableName_ = pluginName + "_" + "counter_table"; + counterObjectTableName_ = pluginName + "_" + "counterobj_table"; + sliceTableName_ = pluginName + "_" + "slice_table"; + sliceObjectName_ = pluginName + "_" + "sliceobj_table"; + return 0; +} +int SDKDataParser::ParseDataOver(TraceRangeCallbackFunction traceRangeCallbackFunction) +{ + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); + std::string traceRangeStr = + std::to_string(traceDataCache_->traceStartTime_) + ";" + std::to_string(traceDataCache_->traceEndTime_) + ";"; + traceRangeCallbackFunction(traceRangeStr); + return 0; +} + +int SDKDataParser::GetJsonConfig(QueryResultCallbackFunction queryResultCallbackFunction) +{ + queryResultCallbackFunction(jsonConfig_, 1, 1); + return 0; +} + +int SDKDataParser::ParserData(const uint8_t* data, int len, int componentId) +{ + if (componentId == DATA_TYPE_CLOCK) { + ParserClock(data, len); + return 0; + } + sdk_plugin_data_parser(data, len); + return 0; +} + +int SDKDataParser::ParserClock(const uint8_t* data, int len) +{ + return streamFilters_->clockFilter_->InitSnapShotTimeRange(data, len); +} + +int SDKDataParser::SetTableName(const char* counterTableName, + const char* counterObjectTableName, + const char* sliceTableName, + const char* sliceObjectName) +{ + if (!g_isUseExternalModify) { + counterTableName_ = counterTableName; + counterObjectTableName_ = counterObjectTableName; + sliceTableName_ = sliceTableName; + sliceObjectName_ = sliceObjectName; + } + UpdateJson(); + return 0; +} + +int SDKDataParser::UpdateJson() +{ + using json = nlohmann::json; + json jMessage = json::parse(jsonConfig_); + if (jMessage.is_discarded()) { + return -1; + } + + jMessage["tableConfig"]["showType"][0]["tableName"] = counterTableName_; + jMessage["tableConfig"]["showType"][0]["inner"]["tableName"] = counterObjectTableName_; + jMessage["tableConfig"]["showType"][1]["tableName"] = sliceTableName_; + jMessage["tableConfig"]["showType"][1]["inner"]["tableName"] = sliceObjectName_; + + jsonConfig_ = jMessage.dump(); + return 0; +} + +// 创建对应的表 +int SDKDataParser::CreateTableByJson() +{ +#ifdef USE_VTABLE + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, "meta"); +#else + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, "_meta"); +#endif + // 创建对应的表 + CreateCounterObjectTable(counterObjectTableName_); + CreateCounterTable(counterTableName_); + CreateSliceObjectTable(sliceObjectName_); + CreateSliceTable(sliceTableName_); + return 0; +} + +// 根据Json配置创建couter object表 +int SDKDataParser::CreateCounterObjectTable(std::string& tableName) +{ +#ifdef USE_VTABLE + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, tableName); +#else + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, "_" + tableName); +#endif + return 0; +} + +// 根据Json配置创建couter表 +int SDKDataParser::CreateCounterTable(std::string& tableName) +{ +#ifdef USE_VTABLE + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, tableName); +#else + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, "_" + tableName); +#endif + return 0; +} + +// 根据Json配置创建slice object表 +int SDKDataParser::CreateSliceObjectTable(std::string& tableName) +{ +#ifdef USE_VTABLE + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, tableName); +#else + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, "_" + tableName); +#endif + return 0; +} + +// 根据Json配置创建slice表 +int SDKDataParser::CreateSliceTable(std::string& tableName) +{ +#ifdef USE_VTABLE + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, tableName); +#else + TableBase::TableDeclare(*(traceDataCache_->db_), traceDataCache_, "_" + tableName); +#endif + return 0; +} + +// Counter业务 +int SDKDataParser::AppendCounterObject(int counterId, const char* columnName) +{ + traceDataCache_->GetGpuCounterObjectData()->AppendNewData(counterId, columnName); + return 0; +} + +int SDKDataParser::AppendCounter(int counterId, uint64_t ts, int value) +{ + auto newTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); + UpdatePluginTimeRange(TS_CLOCK_BOOTTIME, ts, newTs); + traceDataCache_->GetGpuCounterData()->AppendNewData(newTs, counterId, value); + return 0; +} + +// Slice业务 +int SDKDataParser::AppendSliceObject(int sliceId, const char* columnName) +{ + traceDataCache_->GetSliceObjectData()->AppendNewData(sliceId, columnName); + return 0; +} + +int SDKDataParser::AppendSlice(int sliceId, uint64_t ts, uint64_t endTs, int value) +{ + auto newTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); + auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, endTs); + UpdatePluginTimeRange(TS_CLOCK_BOOTTIME, ts, newTs); + UpdatePluginTimeRange(TS_CLOCK_BOOTTIME, endTs, newEndTs); + traceDataCache_->GetSliceTableData()->AppendNewData(sliceId, newTs, newEndTs, value); + return 0; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/sdk/sdk_data_parser.h b/host/trace_streamer/sdk/sdk/sdk_data_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..eec7f1befbf33b166453073e618937c1511f6271 --- /dev/null +++ b/host/trace_streamer/sdk/sdk/sdk_data_parser.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#ifndef SDK_DATA_PARSER_H +#define SDK_DATA_PARSER_H + +#include +#include +#include "file.h" +#include "../parser/htrace_plugin_time_parser.h" +#include "../table/table_base.h" +#include "../trace_streamer/trace_streamer_selector.h" + +namespace SysTuning { +namespace TraceStreamer { + +enum Third_Party_Wasm_Id { + DATA_TYPE_MOCK_PLUGIN = 0, + DATA_TYPE_CLOCK = 100, +}; +class SDKDataParser : public HtracePluginTimeParser { +public: + using TraceRangeCallbackFunction = std::function; + using QueryResultCallbackFunction = std::function; + SDKDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~SDKDataParser(){}; + + // third_party + int CreateTableByJson(); + int SetTableName(const char* counterTableName, + const char* counterObjectTableName, + const char* sliceTableName, + const char* sliceObjectName); + int GetJsonConfig(QueryResultCallbackFunction queryResultCallbackFunction); + int GetPluginName(const uint8_t* data, int len); + int ParseDataOver(TraceRangeCallbackFunction traceRangeCallbackFunction); + int ParserData(const uint8_t* data, int len, int componentId); + int AppendCounterObject(int counterId, const char* columnName); + int AppendCounter(int counterId, uint64_t ts, int value); + int AppendSliceObject(int sliceId, const char* columnName); + int AppendSlice(int sliceId, uint64_t ts, uint64_t endTs, int value); + +private: + int CreateCounterObjectTable(std::string& tableName); + int CreateCounterTable(std::string& tableName); + int CreateSliceObjectTable(std::string& tableName); + int CreateSliceTable(std::string& tableName); + int ParserClock(const uint8_t* data, int len); + int UpdateJson(); + +public: + std::string counterTableName_ = "counter_table"; + std::string counterObjectTableName_ = "gpu_counter_object"; + std::string sliceTableName_ = "slice_table"; + std::string sliceObjectName_ = "slice_object_table"; + std::string jsonConfig_ = + "{\"tableConfig\":{\"showType\":[{\"tableName\":\"counter_table\",\"inner\":{\"tableName\":\"gpu_counter_" + "object\"," + "\"columns\":[{\"column\":\"counter_name\",\"type\":\"STRING\",\"displayName\":\"\",\"showType\":[0]},{" + "\"column\":" + "\"counter_id\",\"type\":\"INTEGER\",\"displayName\":\"\",\"showType\":[0]}]},\"columns\":[{\"column\":\"ts\"," + "\"type\":\"INTEGER\",\"displayName\":\"TimeStamp\",\"showType\":[1,3]},{\"column\":\"counter_id\",\"type\":" + "\"INTEGER\",\"displayName\":\"MonitorValue\",\"showType\":[1,3]},{\"column\":\"value\",\"type\":\"INTEGER\"," + "\"displayName\":\"Value\",\"showType\":[1,3]}]},{\"tableName\":\"slice_table\",\"inner\":{\"tableName\":" + "\"slice_" + "object_table\",\"columns\":[{\"column\":\"slice_name\",\"type\":\"STRING\",\"displayName\":\"\",\"showType\":[" + "0]}," + "{\"column\":\"slice_id\",\"type\":\"INTEGER\",\"displayName\":\"\",\"showType\":[0]}]},\"columns\":[{" + "\"column\":" + "\"start_ts\",\"type\":\"INTEGER\",\"displayName\":\"startts\",\"showType\":[2,3]},{\"column\":\"end_ts\"," + "\"type\":" + "\"INTEGER\",\"displayName\":\"endts\",\"showType\":[2,3]},{\"column\":\"slice_id\",\"type\":\"INTEGER\"," + "\"displayName\":\"slice_id\",\"showType\":[2,3]},{\"column\":\"value\",\"type\":\"INTEGER\",\"displayName\":" + "\"Value\",\"showType\":[2,3]}]}]},\"settingConfig\":{\"name\":\"mailG77\",\"configuration\":{\"version\":{" + "\"type\":\"number\",\"default\":\"1\",\"description\":\"gatordversion\"},\"counters\":{\"type\":\"string\"," + "\"enum\":[\"ARM_Mali-TTRx_JS1_ACTIVE\",\"ARM_Mali-TTRx_JS0_ACTIVE\",\"ARM_Mali-TTRx_GPU_ACTIVE\",\"ARM_Mali-" + "TTRx_FRAG_ACTIVE\"]},\"stop_gator\":{\"type\":\"boolean\",\"default\":\"true\",\"description\":\"stop_gator\"}" + "}}}"; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // SDK_DATA_PARSER_H diff --git a/host/trace_streamer/sdk/sdk/ts.gni b/host/trace_streamer/sdk/sdk/ts.gni new file mode 100755 index 0000000000000000000000000000000000000000..16279772850e6b180cc5c0b02a8945bfef54999b --- /dev/null +++ b/host/trace_streamer/sdk/sdk/ts.gni @@ -0,0 +1,61 @@ +# 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. +OHOS_PROTO_DIR = "" + +if (target_os == "linux" || target_os == "macx" || target_os == "windows") { + # OHOS_FTRACE_PROTO_DIR="//third_party/protogen" + OHOS_FTRACE_PROTO_DIR = "//src/multi_platform" + + # OHOS_MEMORY_PROTO_DIR="//third_party/protogen" + OHOS_MEMORY_PROTO_DIR = "//src/multi_platform" + + # OHOS_HILOG_PROTO_DIR="//third_party/protogen" + OHOS_HILOG_PROTO_DIR = "//src/multi_platform" + + # OHOS_NATIVE_HOOK_PROTO_DIR="//third_party/protogen" + OHOS_NATIVE_HOOK_PROTO_DIR = "//src/multi_platform" + + # OHOS_HIDUMP_PROTO_DIR="//third_party/protogen" + OHOS_HIDUMP_PROTO_DIR = "//src/multi_platform" + + # OHOS_SERVICE_PROTO_DIR = "//third_party/protogen" + OHOS_SERVICE_PROTO_DIR = "//src/multi_platform" + OHOS_PROTO_GEN = "//third_party/protogen" + + # kernel_version = "5.10.79_aarch64" + kernel_version = "." + if (target == "test") { + enable_ts_utest = true + } else { + enable_ts_utest = false + } + is_openharmony = false +} else { + enable_ts_utest = true + use_wasm = false + kernel_version = "." + is_fuzz = false + target = "trace_streamer" + is_openharmony = true + OHOS_FTRACE_PROTO_DIR = "//developtools/profiler/protos/types/plugins/ftrace_data/${kernel_version}" + OHOS_MEMORY_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/memory_data" + OHOS_HILOG_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/hilog_data" + OHOS_NATIVE_HOOK_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/native_hook" + OHOS_HIDUMP_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/hidump_data" + OHOS_SERVICE_PROTO_DIR = "//developtools/profiler/protos/services" + OHOS_PROTO_GEN = "//out/ohos-arm-release/gen/cpp/developtools/profiler/protos" +} diff --git a/host/trace_streamer/sdk/sdk/ts_sdk_api.cpp b/host/trace_streamer/sdk/sdk/ts_sdk_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3bbe1eb1e7f53f39332e04248883f13a03600538 --- /dev/null +++ b/host/trace_streamer/sdk/sdk/ts_sdk_api.cpp @@ -0,0 +1,56 @@ +/* + * 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. + */ +#include "ts_sdk_api.h" +namespace SysTuning { +namespace TraceStreamer { +extern "C" { +RpcServer* rpcServer_; +bool g_isUseExternalModify = true; +int SDK_SetTableName(const char* counterTableName, + const char* counterObjectTableName, + const char* sliceTableName, + const char* sliceObjectName) +{ + rpcServer_->ts_->sdkDataParser_->SetTableName(counterTableName, counterObjectTableName, sliceTableName, + sliceObjectName); + if (g_isUseExternalModify) { + TS_LOGE("If you want to use the SDK_SetTableName, please modify g_isUseExternalModify to false."); + } + return 0; +} + +int SDK_AppendCounterObject(int counterId, const char* columnName) +{ + return rpcServer_->ts_->sdkDataParser_->AppendCounterObject(counterId, columnName); +} +int SDK_AppendCounter(int counterId, uint64_t ts, int value) +{ + return rpcServer_->ts_->sdkDataParser_->AppendCounter(counterId, ts, value); +} +int SDK_AppendSliceObject(int sliceId, const char* columnName) +{ + return rpcServer_->ts_->sdkDataParser_->AppendSliceObject(sliceId, columnName); +} +int SDK_AppendSlice(int sliceId, uint64_t ts, uint64_t endTs, int value) +{ + return rpcServer_->ts_->sdkDataParser_->AppendSlice(sliceId, ts, endTs, value); +} +void SetRpcServer(RpcServer* rpcServer) +{ + rpcServer_ = std::move(rpcServer); +} +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/sdk/ts_sdk_api.h b/host/trace_streamer/sdk/sdk/ts_sdk_api.h new file mode 100644 index 0000000000000000000000000000000000000000..fd30d07c388a25ad8466a264f14697cf5b9baa36 --- /dev/null +++ b/host/trace_streamer/sdk/sdk/ts_sdk_api.h @@ -0,0 +1,36 @@ +/* + * 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. + */ +#ifndef TS_SDK_API_H +#define TS_SDK_API_H +#include "../rpc/rpc_server.h" + +#include +namespace SysTuning { +namespace TraceStreamer { +extern "C" { +extern bool g_isUseExternalModify; +int SDK_SetTableName(const char* counterTableName, + const char* counterObjectTableName, + const char* sliceTableName, + const char* sliceObjectName); +int SDK_AppendCounterObject(int counterId, const char* columnName); +int SDK_AppendCounter(int counterId, uint64_t ts, int value); +int SDK_AppendSliceObject(int sliceId, const char* columnName); +int SDK_AppendSlice(int sliceId, uint64_t ts, uint64_t endTs, int value); +void SetRpcServer(RpcServer* rpcServer); +} +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/sdk/sdk/wasm_func.cpp b/host/trace_streamer/sdk/sdk/wasm_func.cpp new file mode 100755 index 0000000000000000000000000000000000000000..a43f461df509cb37e247b382e15656e695c858b8 --- /dev/null +++ b/host/trace_streamer/sdk/sdk/wasm_func.cpp @@ -0,0 +1,121 @@ +/* + * 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. + */ + +#include "wasm_func.h" +#include +#include "meta.h" +#include "sdk_data_parser.h" +#include "sdk_plugin_data_parser.h" +#include "table_base.h" +#include "trace_stdtype.h" +#include "ts_sdk_api.h" + +namespace SysTuning { +namespace TraceStreamer { +RpcServer g_wasmTraceStreamer; + +extern "C" { +using QueryResultCallbackFunction = void (*)(const char* data, uint32_t len, int finish, int isConfig); +using TraceRangeCallbackFunction = void (*)(const char* data, uint32_t len); +QueryResultCallbackFunction g_reply; +TraceRangeCallbackFunction g_traceRange; +uint8_t* g_reqBuf; +uint32_t g_reqBufferSize; +uint8_t* g_traceRangeBuf; +uint32_t g_traceRangeSize; + +void QueryResultCallback(const std::string& jsonResult, int finish, int isConfig) +{ + g_reply(jsonResult.data(), jsonResult.size(), finish, isConfig); +} +void TraceRangeCallback(const std::string& jsonResult) +{ + g_traceRange(jsonResult.data(), jsonResult.size()); +} +EMSCRIPTEN_KEEPALIVE uint8_t* Init(QueryResultCallbackFunction queryResultCallbackFunction, uint32_t reqBufferSize) +{ + SetRpcServer(&g_wasmTraceStreamer); + sdk_plugin_init_table_name(); + g_wasmTraceStreamer.ts_->sdkDataParser_->CreateTableByJson(); + g_reply = queryResultCallbackFunction; + g_reqBuf = new uint8_t[reqBufferSize]; + g_reqBufferSize = reqBufferSize; + return g_reqBuf; +} + +// Get PluginName +EMSCRIPTEN_KEEPALIVE int TraceStreamer_In_PluginName(const uint8_t* pluginName, int len) +{ + g_wasmTraceStreamer.ts_->sdkDataParser_->GetPluginName(pluginName, len); + return 0; +} + +EMSCRIPTEN_KEEPALIVE uint8_t* InitTraceRange(TraceRangeCallbackFunction traceRangeCallbackFunction, + uint32_t reqBufferSize) +{ + g_traceRange = traceRangeCallbackFunction; + g_traceRangeBuf = new uint8_t[reqBufferSize]; + g_traceRangeSize = reqBufferSize; + return g_traceRangeBuf; +} + +// The whole file is parsed, and the third party is notified by JS +EMSCRIPTEN_KEEPALIVE int TraceStreamer_In_ParseDataOver() +{ + MetaData* metaData = g_wasmTraceStreamer.ts_->GetMetaData(); + metaData->InitMetaData(); + metaData->SetParserToolVersion(SDK_VERSION); + metaData->SetParserToolPublishDateTime(SDK_PUBLISHVERSION); + g_wasmTraceStreamer.ts_->sdkDataParser_->ParseDataOver(&TraceRangeCallback); + return 0; +} + +// Get Json configuration interface +EMSCRIPTEN_KEEPALIVE int TraceStreamer_In_JsonConfig() +{ + g_wasmTraceStreamer.ts_->sdkDataParser_->GetJsonConfig(&QueryResultCallback); + return 0; +} + +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen) +{ + if (g_wasmTraceStreamer.SqlOperate(sql, sqlLen, nullptr)) { + return 0; + } + return -1; +} + +// JS calls third-party parsing interface +EMSCRIPTEN_KEEPALIVE int ParserData(int len, int componentId) +{ + TS_LOGI("wasm ParserData, len = %u", len); + g_wasmTraceStreamer.ts_->sdkDataParser_->ParserData(g_reqBuf, len, componentId); + return 0; +} + +// return the length of result, -1 while failed +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, uint8_t* out, int outLen) +{ + return g_wasmTraceStreamer.WasmSqlQuery(sql, sqlLen, out, outLen); +} +// return the length of result, -1 while failed +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQueryEx(int sqlLen) +{ + return g_wasmTraceStreamer.WasmSqlQueryWithCallback(g_reqBuf, sqlLen, &QueryResultCallback); +} + +} // extern "C" +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/sdk/wasm_func.h b/host/trace_streamer/sdk/sdk/wasm_func.h new file mode 100755 index 0000000000000000000000000000000000000000..a27267b113843425862a16efc55d4eb69c2a3402 --- /dev/null +++ b/host/trace_streamer/sdk/sdk/wasm_func.h @@ -0,0 +1,35 @@ +/* + * 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. + */ + +#ifndef WASM_FUNC_H +#define WASM_FUNC_H + +#include +#include +#include +#include "rpc_server.h" +#include "../trace_streamer/trace_streamer_selector.h" + + +namespace SysTuning { +namespace TraceStreamer { +extern "C" { +int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen); +} + +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // RPC_WASM_FUNC_H diff --git a/host/trace_streamer/sdk/table/filter_constraints.cpp b/host/trace_streamer/sdk/table/filter_constraints.cpp new file mode 100755 index 0000000000000000000000000000000000000000..914d4a81b790299e49abffe1892ae941e30665c2 --- /dev/null +++ b/host/trace_streamer/sdk/table/filter_constraints.cpp @@ -0,0 +1,132 @@ +/* + * 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. + */ + +#include "filter_constraints.h" + +#include "log.h" + +namespace SysTuning { +namespace TraceStreamer { +void FilterConstraints::AddConstraint(int idx, int col, unsigned char op, bool isSupport) +{ + Constraint& c = constraints_.emplace_back(); + c.idxInaConstraint = idx; + c.col = col; + c.op = op; + c.isSupport = isSupport; +} + +void FilterConstraints::UpdateConstraint(int idx, bool isSupport) +{ + if (idx >= 0 && static_cast(idx) < constraints_.size()) { + constraints_[idx].isSupport = isSupport; + } +} + +void FilterConstraints::AddOrderBy(int col, unsigned char desc) +{ + OrderBy& o = orderBys_.emplace_back(); + o.iColumn = col; + o.desc = desc; +} + +void FilterConstraints::Clear() +{ + constraints_.clear(); + orderBys_.clear(); +} + +void FilterConstraints::ToString(std::string& idxStr) const +{ + idxStr.clear(); + idxStr.reserve(idxStrSize_); + idxStr = "C" + std::to_string(constraints_.size()); + for (size_t i = 0; i < constraints_.size(); i++) { + idxStr += " " + std::to_string(constraints_[i].col); + idxStr += " " + std::to_string(constraints_[i].op); + } + idxStr += " O" + std::to_string(orderBys_.size()); + for (size_t i = 0; i < orderBys_.size(); i++) { + idxStr += " " + std::to_string(orderBys_[i].iColumn); + idxStr += " " + std::to_string(orderBys_[i].desc); + } +} + +void FilterConstraints::FromString(const std::string& idxStr) +{ + const char* p = static_cast(idxStr.c_str()); + char* pNext = nullptr; + TS_ASSERT(*p == 'C'); + errno = 0; + int constraintCount = static_cast(strtol(p + 1, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + for (int i = 0; i < constraintCount; i++) { + p = pNext; + errno = 0; + int col = static_cast(strtol(p, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + p = pNext; + errno = 0; + unsigned char op = static_cast(strtol(p, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + + AddConstraint(i, col, op); + } + + pNext++; // jump the ' ' + p = pNext; + TS_ASSERT(*p == 'O'); + errno = 0; + int orderbyCount = static_cast(strtol(p + 1, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + for (int i = 0; i < orderbyCount; i++) { + p = pNext; + errno = 0; + int col = static_cast(strtol(p, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + p = pNext; + errno = 0; + unsigned char desc = static_cast(strtol(p, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + + AddOrderBy(col, desc); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/table/filter_constraints.h b/host/trace_streamer/sdk/table/filter_constraints.h new file mode 100755 index 0000000000000000000000000000000000000000..4170aa661842304dcaf4ceeb851d06983d910aa8 --- /dev/null +++ b/host/trace_streamer/sdk/table/filter_constraints.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef TABLE_FILTER_CONSTRAINTS_H +#define TABLE_FILTER_CONSTRAINTS_H + +#include +#include + +#include + +namespace SysTuning { +namespace TraceStreamer { +class FilterConstraints { +public: + struct Constraint { + int idxInaConstraint; // index in sqlite3_index_info.aConstraint[] + int col; // Column this constraint refers to + unsigned char op; // SQLite op for the constraint + bool isSupport = false; + }; + using OrderBy = sqlite3_index_info::sqlite3_index_orderby; + + FilterConstraints() {} + ~FilterConstraints() {} + void AddConstraint(int idx, int col, unsigned char op, bool isSupport = false); + void UpdateConstraint(int idx, bool isSupport); + void AddOrderBy(int col, unsigned char desc); + void Clear(); + + const std::vector& GetOrderBys() const + { + return orderBys_; + } + + const std::vector& GetConstraints() const + { + return constraints_; + } + + // idxStr format: C col1 op1 ... colN opN O col1 desc1 ... colM descM + // like as "C2 0 2 1 4 O1 0 1" + void ToString(std::string& idxStr) const; + void FromString(const std::string& idxStr); + +private: + std::vector constraints_; + std::vector orderBys_; + const std::size_t idxStrSize_ = 512; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TABLE_FILTER_CONSTRAINTS_H diff --git a/host/trace_streamer/sdk/table/gpu_counter_object_table.cpp b/host/trace_streamer/sdk/table/gpu_counter_object_table.cpp new file mode 100755 index 0000000000000000000000000000000000000000..e2c3b410d65a715b95d43e58df3be4293ba6b87c --- /dev/null +++ b/host/trace_streamer/sdk/table/gpu_counter_object_table.cpp @@ -0,0 +1,183 @@ +/* + * 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. + */ + +#include "gpu_counter_object_table.h" +#include + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { COUNTER_ID = 0, COUNTER_NAME = 1 }; +} +GpuCounterObjectTable::GpuCounterObjectTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("counter_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("counter_name", "REAL")); + tablePriKey_.push_back("counter_id"); +} + +GpuCounterObjectTable::~GpuCounterObjectTable() {} + +// void GpuCounterObjectTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +// { +// constexpr double filterBaseCost = 1000.0; // set-up and tear-down +// constexpr double indexCost = 2.0; +// ei.estimatedCost = filterBaseCost; + +// auto rowCount = dataCache_->GetConstGpuCounterObjectData().Size(); +// if (rowCount == 0 || rowCount == 1) { +// ei.estimatedRows = rowCount; +// ei.estimatedCost += indexCost * rowCount; +// return; +// } + +// double filterCost = 0.0; +// auto constraints = fc.GetConstraints(); +// if (constraints.empty()) { // scan all rows +// filterCost = rowCount; +// } else { +// FilterByConstraint(fc, filterCost, rowCount); +// } +// ei.estimatedCost += filterCost; +// ei.estimatedRows = rowCount; +// ei.estimatedCost += rowCount * indexCost; + +// ei.isOrdered = true; +// auto orderbys = fc.GetOrderBys(); +// for (auto i = 0; i < orderbys.size(); i++) { +// switch (orderbys[i].iColumn) { +// case COUNTER_ID: +// break; +// default: // other columns can be sorted by SQLite +// ei.isOrdered = false; +// break; +// } +// } +// } + +// void GpuCounterObjectTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +// { +// auto fcConstraints = fc.GetConstraints(); +// for (int i = 0; i < static_cast(fcConstraints.size()); i++) { +// if (rowCount <= 1) { +// // only one row or nothing, needn't filter by constraint +// filterCost += rowCount; +// break; +// } +// const auto& c = fcConstraints[i]; +// switch (c.col) { +// case COUNTER_ID: { +// if (CanFilterId(c.op, rowCount)) { +// fc.UpdateConstraint(i, true); +// filterCost += 1; // binary search +// } else { +// filterCost += rowCount; +// } +// break; +// } +// default: // other column +// filterCost += rowCount; // scan all rows +// break; +// } +// } +// } + +// bool GpuCounterObjectTable::CanFilterId(const char op, size_t& rowCount) +// { +// switch (op) { +// case SQLITE_INDEX_CONSTRAINT_EQ: +// rowCount = 1; +// break; +// case SQLITE_INDEX_CONSTRAINT_GT: +// case SQLITE_INDEX_CONSTRAINT_GE: +// case SQLITE_INDEX_CONSTRAINT_LE: +// case SQLITE_INDEX_CONSTRAINT_LT: +// rowCount = (rowCount >> 1); +// break; +// default: +// return false; +// } +// return true; +// } + +std::unique_ptr GpuCounterObjectTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +GpuCounterObjectTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstGpuCounterObjectData().Size())), + gpuCounterObjectDataObj_(dataCache->GetConstGpuCounterObjectData()) +{ +} + +GpuCounterObjectTable::Cursor::~Cursor() {} + +// int GpuCounterObjectTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +// { +// // reset indexMap_ +// indexMap_ = std::make_unique(0, rowCount_); + +// if (rowCount_ <= 0) { +// return SQLITE_OK; +// } + +// auto& cs = fc.GetConstraints(); +// for (size_t i = 0; i < cs.size(); i++) { +// const auto& c = cs[i]; +// switch (c.col) { +// case COUNTER_ID: +// FilterId(c.op, argv[i]); +// break; +// default: +// break; +// } +// } + +// auto orderbys = fc.GetOrderBys(); +// for (auto i = orderbys.size(); i > 0;) { +// i--; +// switch (orderbys[i].iColumn) { +// case COUNTER_ID: +// indexMap_->SortBy(orderbys[i].desc); +// break; +// default: +// break; +// } +// } + +// return SQLITE_OK; +// } + +int GpuCounterObjectTable::Cursor::Column(int column) const +{ + switch (column) { + case COUNTER_ID: { + sqlite3_result_int64(context_, static_cast(gpuCounterObjectDataObj_.CounterId()[CurrentRow()])); + break; + } + case COUNTER_NAME: { + sqlite3_result_text(context_, gpuCounterObjectDataObj_.CounterName()[CurrentRow()].c_str(), STR_DEFAULT_LEN, + nullptr); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/table/gpu_counter_object_table.h b/host/trace_streamer/sdk/table/gpu_counter_object_table.h new file mode 100755 index 0000000000000000000000000000000000000000..b06b484cf51da8e0a82bbd73b65d364b05629ed3 --- /dev/null +++ b/host/trace_streamer/sdk/table/gpu_counter_object_table.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#ifndef GPU_COUNTER_OBJECT_TABLE_H +#define GPU_COUNTER_OBJECT_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class GpuCounterObjectTable : public TableBase { +public: + explicit GpuCounterObjectTable(const TraceDataCache* storage); + ~GpuCounterObjectTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {}; + // bool CanFilterId(const char op, size_t& rowCount); + // void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + }; + // void FilterSorted(int col, unsigned char op, sqlite3_value* argv){}; + int Column(int column) const override; + + private: + const GpuCounterObject& gpuCounterObjectDataObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // GPU_COUNTER_OBJECT_TABLE_H diff --git a/host/trace_streamer/sdk/table/gpu_counter_table.cpp b/host/trace_streamer/sdk/table/gpu_counter_table.cpp new file mode 100755 index 0000000000000000000000000000000000000000..c56708a93b7b67b247629ebaf428fad92d762ed5 --- /dev/null +++ b/host/trace_streamer/sdk/table/gpu_counter_table.cpp @@ -0,0 +1,188 @@ +/* + * 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. + */ + +#include "gpu_counter_table.h" +#include + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { TS = 0, COUNTER_ID = 1, VALUE = 2 }; +} +GpuCounterTable::GpuCounterTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("counter_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "REAL")); + tablePriKey_.push_back("ts"); + tablePriKey_.push_back("counter_id"); +} + +GpuCounterTable::~GpuCounterTable() {} + +// void GpuCounterTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +// { +// constexpr double filterBaseCost = 1000.0; // set-up and tear-down +// constexpr double indexCost = 2.0; +// ei.estimatedCost = filterBaseCost; + +// auto rowCount = dataCache_->GetConstGpuCounterData().Size(); +// if (rowCount == 0 || rowCount == 1) { +// ei.estimatedRows = rowCount; +// ei.estimatedCost += indexCost * rowCount; +// return; +// } + +// double filterCost = 0.0; +// auto constraints = fc.GetConstraints(); +// if (constraints.empty()) { // scan all rows +// filterCost = rowCount; +// } else { +// FilterByConstraint(fc, filterCost, rowCount); +// } +// ei.estimatedCost += filterCost; +// ei.estimatedRows = rowCount; +// ei.estimatedCost += rowCount * indexCost; + +// ei.isOrdered = true; +// auto orderbys = fc.GetOrderBys(); +// for (auto i = 0; i < orderbys.size(); i++) { +// switch (orderbys[i].iColumn) { +// case COUNTER_ID: +// break; +// default: // other columns can be sorted by SQLite +// ei.isOrdered = false; +// break; +// } +// } +// } + +// void GpuCounterTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +// { +// auto fcConstraints = fc.GetConstraints(); +// for (int i = 0; i < static_cast(fcConstraints.size()); i++) { +// if (rowCount <= 1) { +// // only one row or nothing, needn't filter by constraint +// filterCost += rowCount; +// break; +// } +// const auto& c = fcConstraints[i]; +// switch (c.col) { +// case COUNTER_ID: { +// if (CanFilterId(c.op, rowCount)) { +// fc.UpdateConstraint(i, true); +// filterCost += 1; // binary search +// } else { +// filterCost += rowCount; +// } +// break; +// } +// default: // other column +// filterCost += rowCount; // scan all rows +// break; +// } +// } +// } + +// bool GpuCounterTable::CanFilterId(const char op, size_t& rowCount) +// { +// switch (op) { +// case SQLITE_INDEX_CONSTRAINT_EQ: +// rowCount = 1; +// break; +// case SQLITE_INDEX_CONSTRAINT_GT: +// case SQLITE_INDEX_CONSTRAINT_GE: +// case SQLITE_INDEX_CONSTRAINT_LE: +// case SQLITE_INDEX_CONSTRAINT_LT: +// rowCount = (rowCount >> 1); +// break; +// default: +// return false; +// } +// return true; +// } + +std::unique_ptr GpuCounterTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +GpuCounterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstGpuCounterData().Size())), + gpuCounterDataObj_(dataCache->GetConstGpuCounterData()) +{ +} + +GpuCounterTable::Cursor::~Cursor() {} + +// int GpuCounterTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +// { +// // reset indexMap_ +// indexMap_ = std::make_unique(0, rowCount_); + +// if (rowCount_ <= 0) { +// return SQLITE_OK; +// } + +// auto& cs = fc.GetConstraints(); +// for (size_t i = 0; i < cs.size(); i++) { +// const auto& c = cs[i]; +// switch (c.col) { +// case COUNTER_ID: +// FilterId(c.op, argv[i]); +// break; +// default: +// break; +// } +// } + +// auto orderbys = fc.GetOrderBys(); +// for (auto i = orderbys.size(); i > 0;) { +// i--; +// switch (orderbys[i].iColumn) { +// case COUNTER_ID: +// indexMap_->SortBy(orderbys[i].desc); +// break; +// default: +// break; +// } +// } + +// return SQLITE_OK; +// } + +int GpuCounterTable::Cursor::Column(int column) const +{ + switch (column) { + case TS: { + sqlite3_result_int64(context_, static_cast(gpuCounterDataObj_.TimeStamp()[CurrentRow()])); + break; + } + case COUNTER_ID: { + sqlite3_result_int64(context_, static_cast(gpuCounterDataObj_.CounterId()[CurrentRow()])); + break; + } + case VALUE: { + sqlite3_result_int64(context_, static_cast(gpuCounterDataObj_.Value()[CurrentRow()])); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/table/gpu_counter_table.h b/host/trace_streamer/sdk/table/gpu_counter_table.h new file mode 100755 index 0000000000000000000000000000000000000000..72cecbd66ff156ff156c11489d5c6df311bf9f52 --- /dev/null +++ b/host/trace_streamer/sdk/table/gpu_counter_table.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#ifndef GPU_COUNTER_TABLE_H +#define GPU_COUNTER_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class GpuCounterTable : public TableBase { +public: + explicit GpuCounterTable(const TraceDataCache* storage); + ~GpuCounterTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override{}; + // bool CanFilterId(const char op, size_t& rowCount); + // void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + }; + int Column(int column) const override; + + private: + const GpuCounter& gpuCounterDataObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // GPU_COUNTER_TABLE_H diff --git a/host/trace_streamer/sdk/table/index_map.cpp b/host/trace_streamer/sdk/table/index_map.cpp new file mode 100755 index 0000000000000000000000000000000000000000..1864a664688cac78f1fc6d4ddfbc6b116d146762 --- /dev/null +++ b/host/trace_streamer/sdk/table/index_map.cpp @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#include "index_map.h" + +#include + +#include "log.h" + +namespace SysTuning { +namespace TraceStreamer { +IndexMap::IndexMap(TableRowId start, TableRowId end) + : current_(start), start_(start), end_(end), type_(COMPACT) {} + +void IndexMap::CovertToIndexMap() +{ + if (converted_) { + indexType_ = INDEX_TYPE_OUTER_INDEX; + return; + } + converted_ = true; + if (indexType_ == INDEX_TYPE_ID && HasData()) { + for (auto i = start_; i < end_; i++) { + rowIndex_.push_back(i); + } + current_ = start_ = 0; + end_ = rowIndex_.size(); + empty_ = !rowIndex_.size(); + } + indexType_ = INDEX_TYPE_OUTER_INDEX; +} +bool IndexMap::HasData() { + return (start_ != 0 || end_ != INVALID_UINT32) || !empty_; +} +void IndexMap::Intersect(TableRowId start, TableRowId end) +{ + if (indexType_ == INDEX_TYPE_OUTER_INDEX) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (*i >= start && *i < end) { + i++; + } else { + i = rowIndex_.erase(i); + } + } + start_ = current_ = 0; + end_ = rowIndex_.size(); + } else { + start_ = std::max(start_, start); + end_ = std::min(end_, end); + current_ = start_; + } + empty_ = false; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/table/index_map.h b/host/trace_streamer/sdk/table/index_map.h new file mode 100755 index 0000000000000000000000000000000000000000..c301486065559c0780a1dd962ebd55c367791e9c --- /dev/null +++ b/host/trace_streamer/sdk/table/index_map.h @@ -0,0 +1,420 @@ +/* + * 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. + */ + +#ifndef TABLE_INDEX_MAP_H +#define TABLE_INDEX_MAP_H + +#include +#include +#include +#include +#include +#include "log.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +class IndexMap { +public: + IndexMap() {} + ~IndexMap() {} + + IndexMap(TableRowId start, TableRowId end); + void CovertToIndexMap(); + template + void MixRange(unsigned char op, T value, const std::deque& dataQueue) + { + auto invalidValue = std::numeric_limits::max(); + bool remove = false; + if (HasData()) { + CovertToIndexMap(); + remove = true; + } + auto size = dataQueue.size(); + rowIndexBak_.clear(); + bool changed = false; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] != value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] == value) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_NE: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] == value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] != value) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNULL: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] != invalidValue) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] == invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] == invalidValue) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] != invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] <= value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] > value) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] < value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] >= invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] > value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] < invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] >= value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] < invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + + + default: + break; + } // end of switch (op) + empty_ = false; + } + void FixSize() + { + if (indexType_ == INDEX_TYPE_OUTER_INDEX) + { + end_ = rowIndex_.size(); + } + } + void Remove(TableRowId row) + { + (void)std::remove(rowIndex_.begin(), rowIndex_.end(), row); + } + void Set(TableRowId start, TableRowId end) + { + if (indexType_ == INDEX_TYPE_ID) { + end_ = std::min(end_, end); + current_ = start_ = std::max(start_, start); + } + } + + size_t Size() const + { + return end_ - start_; + } + + void Next() + { + if (desc_) { + if (current_ > start_) { + current_--; + } + } else { + if (current_ < end_) { + current_++; + } + } + } + + bool Eof() const + { + if (desc_) { + return current_ <= start_; + } else { + return current_ >= end_; + } + } + + TableRowId CurrentRow() const + { + auto current = current_; + // if (desc_) { + // current--; + // } + if (indexType_ == INDEX_TYPE_ID) { + return current; + } else { + return rowIndex_[current]; + } + } + + void SortBy(bool desc) + { + if (desc) { + current_ = end_; + } else { + current_ = start_; + } + desc_ = desc; + } + + // void Insert(TableRowId index); + + // void Intersect(const IndexMap& other); + void Intersect(TableRowId start, TableRowId end); + // void Intersect(const std::vector& iv); + + // the follow functions require that thecolData is sotred + template + void IntersectabcEqual(const std::deque& rows, Val v, GetV getValue) + { + auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v); + auto end = std::upper_bound(start, rows.begin() + end_, v); + auto newStart = std::distance(rows.begin(), start); + auto newEnd = std::distance(rows.begin(), end); + Intersect(newStart, newEnd); + return; + } + + template + void IntersectGreaterEqual(const std::deque& rows, Val v, GetV getValue) + { + uint32_t index = rows.size() - 1; + for (; index != -1; index--) { + if (v >= getValue(rows[index])) { + break; + } + } + if (index == -1) { + index = 0; + } + Intersect(index, INVALID_UINT32); + return; + } + + template + void IntersectLessEqual(const std::deque& rows, Val v, GetV getValue) + { + uint32_t index = 0; + for (; index < rows.size(); index++) { + if (v <= getValue(rows[index])) { + break; + } + } + Intersect(0, index); + return; + } + template + void RemoveNullElements(const std::deque& rows, T v) + { + auto invalidValue = std::numeric_limits::max(); + bool remove = false; + if (HasData()) { + CovertToIndexMap(); + remove = true; + } + + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (rows[*i] == invalidValue) { + i = rowIndex_.erase(i); + } else { + i++; + } + } + } else { + auto size = rows.size(); + for (auto i = 0; i < size; i++) { + if (rows[i] != invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + return; + } + bool HasData(); + std::vector rowIndex_; + std::vector rowIndexBak_; +private: + TableRowId end_ = INVALID_UINT32; + TableRowId current_ = 0; + TableRowId start_ = 0; + enum FindIndexType { + INDEX_TYPE_ID, + INDEX_TYPE_OUTER_INDEX, + }; + FindIndexType indexType_ = INDEX_TYPE_ID; + uint32_t indexSize_ = 0; + uint32_t index_ = 0; + + enum IndexType { + COMPACT, + SPARSE + }; + uint8_t type_ = COMPACT; + bool empty_ = true; + bool desc_ = false; + bool converted_ = false; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TABLE_INDEX_MAP_H diff --git a/host/trace_streamer/sdk/table/meta_table.cpp b/host/trace_streamer/sdk/table/meta_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9647d91b46fcb14204b973b286bc777d4953965 --- /dev/null +++ b/host/trace_streamer/sdk/table/meta_table.cpp @@ -0,0 +1,63 @@ +/* + * 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. + */ + +#include "meta_table.h" +#include "trace_stdtype.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { NAMEINDEX = 0, VALUE }; +} +MetaTable::MetaTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "TEXT")); + tablePriKey_.push_back("name"); +} + +MetaTable::~MetaTable() {} + +std::unique_ptr MetaTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +MetaTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, MetaDataItem::METADATA_ITEM_MAX) +{ +} + +MetaTable::Cursor::~Cursor() {} + +int MetaTable::Cursor::Column(int column) const +{ + switch (column) { + case NAMEINDEX: + sqlite3_result_text(context_, dataCache_->GetConstMetaData().Name(CurrentRow()).c_str(), STR_DEFAULT_LEN, + nullptr); + break; + case VALUE: + sqlite3_result_text(context_, dataCache_->GetConstMetaData().Value(CurrentRow()).c_str(), STR_DEFAULT_LEN, + nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/heap_table.h b/host/trace_streamer/sdk/table/meta_table.h similarity index 61% rename from host/trace_streamer/src/table/heap_table.h rename to host/trace_streamer/sdk/table/meta_table.h index 704f16d2f7781d337d0a8d0c997cc7f2c976d677..44caf03bcd73a817800ac7130178393d2a86d5a9 100644 --- a/host/trace_streamer/src/table/heap_table.h +++ b/host/trace_streamer/sdk/table/meta_table.h @@ -13,31 +13,37 @@ * limitations under the License. */ -#ifndef HEAP_TABLE_H -#define HEAP_TABLE_H +#ifndef META_TABLE_H +#define META_TABLE_H #include "table_base.h" #include "trace_data_cache.h" namespace SysTuning { namespace TraceStreamer { -class HeapTable : public TableBase { +class MetaTable : public TableBase { public: - explicit HeapTable(const TraceDataCache* dataCache); - ~HeapTable() override; - void CreateCursor() override; + explicit MetaTable(const TraceDataCache* dataCache); + ~MetaTable() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; - int Column(int column) const override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } - private: - const HeapInfo& heapInfoObj_; + int Column(int column) const override; }; }; } // namespace TraceStreamer } // namespace SysTuning -#endif // HEAP_TABLE_H +#endif // META_TABLE_H diff --git a/host/trace_streamer/sdk/table/slice_object_table.cpp b/host/trace_streamer/sdk/table/slice_object_table.cpp new file mode 100755 index 0000000000000000000000000000000000000000..cf2e310b5b56c72e0fff418669b01b52b4ee9a43 --- /dev/null +++ b/host/trace_streamer/sdk/table/slice_object_table.cpp @@ -0,0 +1,183 @@ +/* + * 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. + */ + +#include "slice_object_table.h" +#include + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { SLICE_ID = 0, SLICE_NAME = 1 }; +} +SliceObjectTable::SliceObjectTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("slice_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("slice_name", "REAL")); + tablePriKey_.push_back("slice_id"); +} + +SliceObjectTable::~SliceObjectTable() {} + +// void SliceObjectTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +// { +// constexpr double filterBaseCost = 1000.0; // set-up and tear-down +// constexpr double indexCost = 2.0; +// ei.estimatedCost = filterBaseCost; + +// auto rowCount = dataCache_->GetConstSliceObjectData().Size(); +// if (rowCount == 0 || rowCount == 1) { +// ei.estimatedRows = rowCount; +// ei.estimatedCost += indexCost * rowCount; +// return; +// } + +// double filterCost = 0.0; +// auto constraints = fc.GetConstraints(); +// if (constraints.empty()) { // scan all rows +// filterCost = rowCount; +// } else { +// FilterByConstraint(fc, filterCost, rowCount); +// } +// ei.estimatedCost += filterCost; +// ei.estimatedRows = rowCount; +// ei.estimatedCost += rowCount * indexCost; + +// ei.isOrdered = true; +// auto orderbys = fc.GetOrderBys(); +// for (auto i = 0; i < orderbys.size(); i++) { +// switch (orderbys[i].iColumn) { +// case SLICE_ID: +// break; +// default: // other columns can be sorted by SQLite +// ei.isOrdered = false; +// break; +// } +// } +// } + +// void SliceObjectTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +// { +// auto fcConstraints = fc.GetConstraints(); +// for (int i = 0; i < static_cast(fcConstraints.size()); i++) { +// if (rowCount <= 1) { +// // only one row or nothing, needn't filter by constraint +// filterCost += rowCount; +// break; +// } +// const auto& c = fcConstraints[i]; +// switch (c.col) { +// case SLICE_ID: { +// if (CanFilterId(c.op, rowCount)) { +// fc.UpdateConstraint(i, true); +// filterCost += 1; // binary search +// } else { +// filterCost += rowCount; +// } +// break; +// } +// default: // other column +// filterCost += rowCount; // scan all rows +// break; +// } +// } +// } + +// bool SliceObjectTable::CanFilterId(const char op, size_t& rowCount) +// { +// switch (op) { +// case SQLITE_INDEX_CONSTRAINT_EQ: +// rowCount = 1; +// break; +// case SQLITE_INDEX_CONSTRAINT_GT: +// case SQLITE_INDEX_CONSTRAINT_GE: +// case SQLITE_INDEX_CONSTRAINT_LE: +// case SQLITE_INDEX_CONSTRAINT_LT: +// rowCount = (rowCount >> 1); +// break; +// default: +// return false; +// } +// return true; +// } + +std::unique_ptr SliceObjectTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +SliceObjectTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstSliceObjectData().Size())), + sliceObjectDataObj_(dataCache->GetConstSliceObjectData()) +{ +} + +SliceObjectTable::Cursor::~Cursor() {} + +// int SliceObjectTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +// { +// // reset indexMap_ +// indexMap_ = std::make_unique(0, rowCount_); + +// if (rowCount_ <= 0) { +// return SQLITE_OK; +// } + +// auto& cs = fc.GetConstraints(); +// for (size_t i = 0; i < cs.size(); i++) { +// const auto& c = cs[i]; +// switch (c.col) { +// case SLICE_ID: +// FilterId(c.op, argv[i]); +// break; +// default: +// break; +// } +// } + +// auto orderbys = fc.GetOrderBys(); +// for (auto i = orderbys.size(); i > 0;) { +// i--; +// switch (orderbys[i].iColumn) { +// case SLICE_ID: +// indexMap_->SortBy(orderbys[i].desc); +// break; +// default: +// break; +// } +// } + +// return SQLITE_OK; +// } + +int SliceObjectTable::Cursor::Column(int column) const +{ + switch (column) { + case SLICE_ID: { + sqlite3_result_int64(context_, static_cast(sliceObjectDataObj_.SliceId()[CurrentRow()])); + break; + } + case SLICE_NAME: { + sqlite3_result_text(context_, sliceObjectDataObj_.SliceName()[CurrentRow()].c_str(), STR_DEFAULT_LEN, + nullptr); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/table/slice_object_table.h b/host/trace_streamer/sdk/table/slice_object_table.h new file mode 100755 index 0000000000000000000000000000000000000000..0e906dc7a55e15c88c703fa169b541c68d0a18bc --- /dev/null +++ b/host/trace_streamer/sdk/table/slice_object_table.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef SLICE_OBJECT_TABLE_H +#define SLICE_OBJECT_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class SliceObjectTable : public TableBase { +public: + explicit SliceObjectTable(const TraceDataCache* storage); + ~SliceObjectTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override{}; + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int Column(int column) const override; + + private: + const SliceObject& sliceObjectDataObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SLICE_OBJECT_TABLE_H diff --git a/host/trace_streamer/sdk/table/slice_table.cpp b/host/trace_streamer/sdk/table/slice_table.cpp new file mode 100755 index 0000000000000000000000000000000000000000..bc30e2dbbfe023b49f06ef3d75429a2904601355 --- /dev/null +++ b/host/trace_streamer/sdk/table/slice_table.cpp @@ -0,0 +1,194 @@ +/* + * 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. + */ + +#include "slice_table.h" +#include + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { TS = 0, ENDTS = 1, VALUE = 2, SLICE_ID = 3}; +} +SliceTable::SliceTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("slice_id", "INTEGER")); + tablePriKey_.push_back("start_ts"); + tablePriKey_.push_back("slice_id"); +} + +SliceTable::~SliceTable() {} + +// void SliceTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +// { +// constexpr double filterBaseCost = 1000.0; // set-up and tear-down +// constexpr double indexCost = 2.0; +// ei.estimatedCost = filterBaseCost; + +// auto rowCount = dataCache_->GetConstSliceData().Size(); +// if (rowCount == 0 || rowCount == 1) { +// ei.estimatedRows = rowCount; +// ei.estimatedCost += indexCost * rowCount; +// return; +// } + +// double filterCost = 0.0; +// auto constraints = fc.GetConstraints(); +// if (constraints.empty()) { // scan all rows +// filterCost = rowCount; +// } else { +// FilterByConstraint(fc, filterCost, rowCount); +// } +// ei.estimatedCost += filterCost; +// ei.estimatedRows = rowCount; +// ei.estimatedCost += rowCount * indexCost; + +// ei.isOrdered = true; +// auto orderbys = fc.GetOrderBys(); +// for (auto i = 0; i < orderbys.size(); i++) { +// switch (orderbys[i].iColumn) { +// case SLICE_ID: +// break; +// default: // other columns can be sorted by SQLite +// ei.isOrdered = false; +// break; +// } +// } +// } + +// void SliceTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +// { +// auto fcConstraints = fc.GetConstraints(); +// for (int i = 0; i < static_cast(fcConstraints.size()); i++) { +// if (rowCount <= 1) { +// // only one row or nothing, needn't filter by constraint +// filterCost += rowCount; +// break; +// } +// const auto& c = fcConstraints[i]; +// switch (c.col) { +// case SLICE_ID: { +// auto oldRowCount = rowCount; +// if (CanFilterSorted(c.op, rowCount)) { +// fc.UpdateConstraint(i, true); +// filterCost += log2(oldRowCount); // binary search +// } else { +// filterCost += oldRowCount; +// } +// break; +// } +// default: // other column +// filterCost += rowCount; // scan all rows +// break; +// } +// } +// } + +// bool SliceTable::CanFilterSorted(const char op, size_t& rowCount) +// { +// switch (op) { +// case SQLITE_INDEX_CONSTRAINT_EQ: +// rowCount = rowCount / log2(rowCount); +// break; +// case SQLITE_INDEX_CONSTRAINT_GT: +// case SQLITE_INDEX_CONSTRAINT_GE: +// case SQLITE_INDEX_CONSTRAINT_LE: +// case SQLITE_INDEX_CONSTRAINT_LT: +// rowCount = (rowCount >> 1); +// break; +// default: +// return false; +// } +// return true; +// } + +std::unique_ptr SliceTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +SliceTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstSliceData().Size())), + sliceDataObj_(dataCache->GetConstSliceData()) +{ +} + +SliceTable::Cursor::~Cursor() {} + +// int SliceTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +// { +// // reset indexMap_ +// indexMap_ = std::make_unique(0, rowCount_); + +// if (rowCount_ <= 0) { +// return SQLITE_OK; +// } + +// auto& cs = fc.GetConstraints(); +// for (size_t i = 0; i < cs.size(); i++) { +// const auto& c = cs[i]; +// switch (c.col) { +// case SLICE_ID: +// FilterSorted(c.col, c.op, argv[i]); +// break; +// default: +// break; +// } +// } + +// auto orderbys = fc.GetOrderBys(); +// for (auto i = orderbys.size(); i > 0;) { +// i--; +// switch (orderbys[i].iColumn) { +// case SLICE_ID: +// indexMap_->SortBy(orderbys[i].desc); +// break; +// default: +// break; +// } +// } + +// return SQLITE_OK; +// } + +int SliceTable::Cursor::Column(int column) const +{ + switch (column) { + case TS: { + sqlite3_result_int64(context_, static_cast(sliceDataObj_.TimeStamp()[CurrentRow()])); + break; + } + case ENDTS: { + sqlite3_result_int64(context_, static_cast(sliceDataObj_.EndTs()[CurrentRow()])); + break; + } + case VALUE: { + sqlite3_result_int64(context_, static_cast(sliceDataObj_.Value()[CurrentRow()])); + break; + } + case SLICE_ID: { + sqlite3_result_int64(context_, static_cast(sliceDataObj_.SliceId()[CurrentRow()])); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/table/slice_table.h b/host/trace_streamer/sdk/table/slice_table.h new file mode 100755 index 0000000000000000000000000000000000000000..80a5fe84edc758bc36b765ffdda5228c0b922c61 --- /dev/null +++ b/host/trace_streamer/sdk/table/slice_table.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef SLICE_TABLE_H +#define SLICE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class SliceTable : public TableBase { +public: + explicit SliceTable(const TraceDataCache* storage); + ~SliceTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override{}; + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int Column(int column) const override; + + private: + const SliceData& sliceDataObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // SLICE_TABLE_H diff --git a/host/trace_streamer/sdk/table/table_base.cpp b/host/trace_streamer/sdk/table/table_base.cpp new file mode 100755 index 0000000000000000000000000000000000000000..b053099e8f9f81ce74028094915894c4893eb9f2 --- /dev/null +++ b/host/trace_streamer/sdk/table/table_base.cpp @@ -0,0 +1,287 @@ +/* + * 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. + */ + +#include "table_base.h" + +#include +#include + +#include "log.h" + +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) + +namespace SysTuning { +namespace TraceStreamer { +namespace { +struct TableContext { + TabTemplate tmplate; + TraceDataCache* dataCache; + sqlite3_module module; + std::string tableName; +}; +} // namespace + +TableBase::~TableBase() +{ + dataCache_ = nullptr; + cursor_ = nullptr; +} + +void TableBase::TableRegister(sqlite3& db, TraceDataCache* cache, const std::string& tableName, TabTemplate tmplate) +{ + std::unique_ptr context(std::make_unique()); + context->dataCache = cache; + context->tmplate = tmplate; + context->tableName = tableName; + sqlite3_module& module = context->module; + module = {0}; + + auto createFn = [](sqlite3* xdb, void* pAux, int argc, const char* const* argv, sqlite3_vtab** ppVTab, + char** pzErr) { + UNUSED(argc); + UNUSED(argv); + UNUSED(pzErr); + auto xdesc = static_cast(pAux); + auto table = xdesc->tmplate(xdesc->dataCache); + table->name_ = xdesc->tableName; + if (table->name_ == "process" || table->name_ == "thread") { + table->wdataCache_ = xdesc->dataCache; + } + + table->Init(argc, argv); + std::string createStmt = table->CreateTableSql(); + TS_LOGD("xCreate table %s, statement: %s", table->name_.c_str(), createStmt.c_str()); + int ret = sqlite3_declare_vtab(xdb, createStmt.c_str()); + if (ret != SQLITE_OK) { + TS_LOGE("sqlite3_declare_vtab %s faild: %s", table->name_.c_str(), createStmt.c_str()); + return ret; + } + *ppVTab = table.release(); + return SQLITE_OK; + }; + + auto destroyFn = [](sqlite3_vtab* t) { + TS_LOGD("xDestroy table %s", static_cast(t)->name_.c_str()); + delete static_cast(t); + return SQLITE_OK; + }; + module.xCreate = createFn; + module.xConnect = createFn; + module.xDisconnect = destroyFn; + module.xDestroy = destroyFn; + + module.xOpen = [](sqlite3_vtab* pVTab, sqlite3_vtab_cursor** ppCursor) { + TS_LOGD("xOpen: %s", static_cast(pVTab)->name_.c_str()); + return static_cast(pVTab)->Open(ppCursor); + }; + + module.xClose = [](sqlite3_vtab_cursor* vc) { + TS_LOGD("xClose: %s", static_cast(vc)->table_->name_.c_str()); + delete static_cast(vc); + return SQLITE_OK; + }; + + module.xBestIndex = [](sqlite3_vtab* pVTab, sqlite3_index_info* idxInfo) { + TS_LOGD("xBestIndex: %s %d", static_cast(pVTab)->name_.c_str(), idxInfo->nConstraint); + return static_cast(pVTab)->BestIndex(idxInfo); + }; + + module.xFilter = [](sqlite3_vtab_cursor* vc, int idxNum, const char* idxStr, int argc, sqlite3_value** argv) { + auto* c = static_cast(vc); + c->Reset(); + TS_LOGD("xFilter %s: [%d]%s", static_cast(vc)->table_->name_.c_str(), idxNum, idxStr); + if (c->table_->cacheIdxNum_ != idxNum) { + c->table_->cacheConstraint_.Clear(); + c->table_->cacheConstraint_.FromString(idxStr); + c->table_->cacheIdxNum_ = idxNum; + } + return c->Filter(c->table_->cacheConstraint_, argv); + }; + + module.xNext = [](sqlite3_vtab_cursor* vc) { return static_cast(vc)->Next(); }; + module.xEof = [](sqlite3_vtab_cursor* vc) { return static_cast(vc)->Eof(); }; + module.xColumn = [](sqlite3_vtab_cursor* vc, sqlite3_context* ctx, int col) { + static_cast(vc)->context_ = ctx; + return static_cast(vc)->Column(col); + }; + if (tableName == "process" || tableName == "thread") { + module.xUpdate = [](sqlite3_vtab* pVTab, int argc, sqlite3_value** argv, sqlite3_int64* pRowid) { + TS_LOGD("xUpdate: %s", static_cast(pVTab)->name_.c_str()); + return static_cast(pVTab)->Update(argc, argv, pRowid); + }; + } + + sqlite3_create_module_v2(&db, tableName.c_str(), &module, context.release(), + [](void* arg) { delete static_cast(arg); }); +} + +std::string TableBase::CreateTableSql() const +{ + std::string stmt = "CREATE TABLE x("; + for (const auto& col : tableColumn_) { + stmt += " " + col.name_ + " " + col.type_; + stmt += ","; + } + stmt += " PRIMARY KEY("; + for (size_t i = 0; i < tablePriKey_.size(); i++) { + if (i != 0) + stmt += ", "; + stmt += tablePriKey_.at(i); + } + stmt += ")) WITHOUT ROWID;"; + return stmt; +} + +int TableBase::BestIndex(sqlite3_index_info* idxInfo) +{ + FilterConstraints filterConstraints; + for (int i = 0; i < idxInfo->nConstraint; i++) { + const auto& constraint = idxInfo->aConstraint[i]; + if (constraint.usable) { + filterConstraints.AddConstraint(i, constraint.iColumn, constraint.op); + } + } + for (int i = 0; i < idxInfo->nOrderBy; i++) { + filterConstraints.AddOrderBy(idxInfo->aOrderBy[i].iColumn, idxInfo->aOrderBy[i].desc); + } + + EstimatedIndexInfo estimate = {idxInfo->estimatedRows, idxInfo->estimatedCost, false}; + EstimateFilterCost(filterConstraints, estimate); + idxInfo->orderByConsumed = estimate.isOrdered; + idxInfo->estimatedCost = estimate.estimatedCost; + idxInfo->estimatedRows = estimate.estimatedRows; + + auto cs = filterConstraints.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + auto& c = cs[i]; + idxInfo->aConstraintUsage[c.idxInaConstraint].argvIndex = static_cast(i + 1); + idxInfo->aConstraintUsage[c.idxInaConstraint].omit = c.isSupport; + } + + std::string str; + filterConstraints.ToString(str); + char* pIdxStr = static_cast(sqlite3_malloc(str.size() + 1)); + std::copy(str.begin(), str.end(), pIdxStr); + pIdxStr[str.size()] = '\0'; + idxInfo->idxStr = pIdxStr; + idxInfo->needToFreeIdxStr = true; + idxInfo->idxNum = ++bestIndexNum_; + + TS_LOGD("%s BestIndex return: %d: %s", name_.c_str(), idxInfo->idxNum, str.c_str()); + TS_LOGD("%s, aConstraintUsage[%d]", idxInfo->idxStr, idxInfo->nConstraint); + for (int i = 0; i < idxInfo->nConstraint; i++) { + TS_LOGD("col: %d op: %d, argvindex: %d omit: %d", idxInfo->aConstraint[i].iColumn, idxInfo->aConstraint[i].op, + idxInfo->aConstraintUsage[i].argvIndex, idxInfo->aConstraintUsage[i].omit); + } + TS_LOGD("estimated: %lld cost:%.3f", idxInfo->estimatedRows, idxInfo->estimatedCost); + + return SQLITE_OK; +} + +int TableBase::Open(sqlite3_vtab_cursor** ppCursor) +{ + *ppCursor = static_cast(CreateCursor().release()); + return SQLITE_OK; +} + +TableBase::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table, uint32_t rowCount) + : context_(nullptr), + table_(table), + dataCache_(dataCache), + rowCount_(rowCount), + indexMap_(std::make_unique(0, rowCount)) +{ +} + +TableBase::Cursor::~Cursor() +{ + context_ = nullptr; + dataCache_ = nullptr; +} +void TableBase::Cursor::FilterTS(unsigned char op, sqlite3_value* argv, const std::deque& times) +{ + auto v = static_cast(sqlite3_value_int64(argv)); + auto getValue = [](const uint64_t& row) { return row; }; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->IntersectabcEqual(times, v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + case SQLITE_INDEX_CONSTRAINT_GE: { + indexMap_->IntersectGreaterEqual(times, v, getValue); + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + case SQLITE_INDEX_CONSTRAINT_LT: { + indexMap_->IntersectLessEqual(times, v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: { + indexMap_->RemoveNullElements(times, v); + break; + } + default: + break; + } // end of switch (op) + } +} + +int TableBase::Cursor::RowId(sqlite3_int64* id) +{ + if (dataCache_->Cancel() || indexMap_->Eof()) { + return SQLITE_ERROR; + } + *id = static_cast(indexMap_->CurrentRow()); + return SQLITE_OK; +} +void TableBase::Cursor::FilterId(unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL + indexMap_->Intersect(0, 0); + return; + } + + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + indexMap_->Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + indexMap_->Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/table/table_base.h b/host/trace_streamer/sdk/table/table_base.h new file mode 100755 index 0000000000000000000000000000000000000000..0c6c51b7619c9d0f77391d5443ad122fff633b46 --- /dev/null +++ b/host/trace_streamer/sdk/table/table_base.h @@ -0,0 +1,142 @@ +/* + * 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. + */ + +#ifndef TABLE_H +#define TABLE_H + +#include +#include +#include +#include +#include + +#include "filter_constraints.h" +#include "index_map.h" +#include "trace_data_cache.h" + +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) +namespace SysTuning { +namespace TraceStreamer { +class TableBase; +using TabTemplate = std::unique_ptr (*)(const TraceDataCache* dataCache); +class TableBase : public sqlite3_vtab { +public: + virtual ~TableBase(); + TableBase(const TableBase&) = delete; + TableBase& operator=(const TableBase&) = delete; + + template + static void TableDeclare(sqlite3& db, TraceDataCache* dataCache, const std::string& name) + { + TableRegister(db, dataCache, name, + [](const TraceDataCache* cache) { + return std::unique_ptr(std::make_unique(cache)); + }); + dataCache->AppendNewTable(name); + } + std::string CreateTableSql() const; + + class Cursor : public sqlite3_vtab_cursor { + public: + Cursor(const TraceDataCache* dataCache, TableBase* table, uint32_t rowCount); + virtual ~Cursor(); + virtual void Reset() + { + indexMap_ = std::make_unique(0, rowCount_); + } + + virtual int Next() + { + indexMap_->Next(); + return SQLITE_OK; + } + + virtual int Eof() + { + return dataCache_->Cancel() || indexMap_->Eof(); + } + + virtual uint32_t CurrentRow() const + { + return indexMap_->CurrentRow(); + } + virtual void FilterTS(unsigned char op, sqlite3_value* argv, const std::deque& times); + + virtual int RowId(sqlite3_int64* id); + virtual int Filter(const FilterConstraints& fc, sqlite3_value** argv) = 0; + virtual int Column(int n) const = 0; + virtual void FilterId(unsigned char op, sqlite3_value* argv); + public: + sqlite3_context* context_; + TableBase* table_ = nullptr; + + protected: + const TraceDataCache* dataCache_; + std::unique_ptr indexMap_; + uint32_t rowCount_; + }; + + struct ColumnInfo { + ColumnInfo(const std::string& name, const std::string& type) : name_(name), type_(type) {} + std::string name_; + std::string type_; + }; + +protected: + explicit TableBase(const TraceDataCache* dataCache) : dataCache_(dataCache), cursor_(nullptr) {} + + struct EstimatedIndexInfo { + int64_t estimatedRows = 0; + double estimatedCost = 0.0; + bool isOrdered = false; + }; + + static void TableRegister(sqlite3& db, TraceDataCache* cache, const std::string& name, TabTemplate tmplate); + virtual int Update(int argc, sqlite3_value** argv, sqlite3_int64* pRowid) + { + return SQLITE_READONLY; + } + int BestIndex(sqlite3_index_info* idxInfo); + // needs to correspond to Cursor::Filter() + virtual void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) = 0; + virtual std::unique_ptr CreateCursor() = 0; + int Open(sqlite3_vtab_cursor** ppCursor); + virtual void Init(int, const char* const*) + { + return; + }; + +public: + std::string name_; + +protected: + std::vector tableColumn_ = {}; + std::vector tablePriKey_ = {}; + const TraceDataCache* dataCache_; + TraceDataCache* wdataCache_ = nullptr; + std::unique_ptr cursor_; + +private: + uint16_t bestIndexNum_ = 0; + int cacheIdxNum_ = 0; + FilterConstraints cacheConstraint_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TABLE_H diff --git a/host/trace_streamer/sdk/test/BUILD.gn b/host/trace_streamer/sdk/test/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..4b84cf161ea209c830e14d1f99ef5045859cfe0c --- /dev/null +++ b/host/trace_streamer/sdk/test/BUILD.gn @@ -0,0 +1,90 @@ +# 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("//build/ohos.gni") +import("//build/test.gni") +import("../ts.gni") + +if (target == "sdkdemotest") { + ohos_unittest("trace_streamer_sdk_ut") { + sources = [ "unittest/sdk_api_test.cpp" ] + deps = [ + "../:trace_streamer_sdk", + "//prebuilts/protos:ts_proto_data_cpp", + "//third_party/googletest:gtest", + "//third_party/googletest:gtest_main", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + "//third_party/sqlite:sqlite", + ] + include_dirs = [ + "../base", + "../sdk", + "..", + "../trace_streamer", + "../filter", + "../table", + "../trace_data", + "../include", + "../plugin", + "../rpc", + "./", + "../parser", + "../cfg", + "//prebuilts/emsdk/emsdk/emscripten/system/include", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}", + "${OHOS_PROTO_GEN}/types/plugins/mock_data", + "//third_party/googletest/googletest/include/gtest", + "//third_party/protobuf/src", + "//third_party/json-master/include", + "//third_party/json-master/include/nlohmann", + ] + cflags = [ + "-Wno-inconsistent-missing-override", + "-Dprivate=public", #allow test code access private members + "-fprofile-arcs", + "-ftest-coverage", + "-Wno-unused-command-line-argument", + "-Wno-format", + "-Wno-unused-const-variable", + "-Wno-unused-variable", + "-Wno-used-but-marked-unused", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + cflags += [ + # clang coverage options: + "--coverage", + "-mllvm", + "-limited-coverage-experimental=true", + "-fno-use-cxa-atexit", + "-DIS_UT", + ] + if (is_macx) { + lib_dirs = [ "/usr/local/opt/llvm/lib" ] + } + libs = [ "LLVMCore" ] + } +} + +# this is the dest for ohos.build +if (target == "sdkdemotest") { + group("sdkunittest") { + testonly = true + deps = [ ":trace_streamer_sdk_ut" ] + } +} diff --git a/host/trace_streamer/sdk/test/unittest/sdk_api_test.cpp b/host/trace_streamer/sdk/test/unittest/sdk_api_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9db4a52b8ebbd4c90ec9e6c925e6d1cdbeb9db41 --- /dev/null +++ b/host/trace_streamer/sdk/test/unittest/sdk_api_test.cpp @@ -0,0 +1,647 @@ +/* + * 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. + */ + +#include +#include +#include "gpu_counter_object_table.h" +#include "gpu_counter_table.h" +#include "mock_plugin_result.pb.h" +#include "sdk_data_parser.h" +#include "slice_object_table.h" +#include "slice_table.h" +#include "ts_sdk_api.h" + +using namespace testing::ext; +namespace SysTuning ::TraceStreamer { +class SDKApiTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} + +public: + TraceStreamerSelector stream_ = {}; + RpcServer* rpcServer = new RpcServer(); +}; + +std::string g_resultTest; +void res(const std::string result, int finish, int isConfig) +{ + TS_LOGI("%s", result.c_str()); + g_resultTest = result; +} + +std::string g_reply; +void QueryResultCallback(const std::string& jsonResult, int finish, int isConfig) +{ + g_reply = jsonResult; +} + +/** + * @tc.name: SetTableName + * @tc.desc: Set the table name manually + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, SetTableName, TestSize.Level1) +{ + TS_LOGI("test1-1"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName("first_table", "second_table", "third_table", "fouth_table"); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from first_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_TRUE(ret); + EXPECT_EQ(g_resultTest.find("ok"), 0); + + std::string sqlQueryCounterObj("select * from second_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); + std::string sqlQuerySlice("select * from third_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); + std::string sqlQuerySliceObj("select * from fouth_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: DefaultTableName + * @tc.desc: Use the default table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, DefaultTableName, TestSize.Level1) +{ + TS_LOGI("test1-2"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from counter_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); + std::string sqlQueryCounterObj("select * from gpu_counter_object;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); + std::string sqlQuerySlice("select * from slice_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); + std::string sqlQuerySliceObj("select * from slice_object_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: NullTableName + * @tc.desc: Use the null table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, NullTableName, TestSize.Level1) +{ + TS_LOGI("test1-3"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", " ", " ", " "); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from counter_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); + std::string sqlQueryCounterObj("select * from gpu_counter_object;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); + std::string sqlQuerySlice("select * from slice_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); + std::string sqlQuerySliceObj("select * from slice_object_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); +} + +/** + * @tc.name: NullAndManuallyCounterTableName + * @tc.desc: Use the null and manually counter table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, NullAndManuallyCounterTableName, TestSize.Level1) +{ + TS_LOGI("test1-4"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName("first_table", "second_table", " ", " "); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from first_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); + std::string sqlQueryCounterObj("select * from second_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); + std::string sqlQuerySlice("select * from slice_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); + std::string sqlQuerySliceObj("select * from slice_object_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); +} + +/** + * @tc.name: NullAndManuallySliceTableName + * @tc.desc: Use the null and manually slice table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, NullAndManuallySliceTableName, TestSize.Level1) +{ + TS_LOGI("test1-5"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", " ", "first_table", "second_table"); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from counter_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); + std::string sqlQueryCounterObj("select * from gpu_counter_object;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); + std::string sqlQuerySlice("select * from first_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); + std::string sqlQuerySliceObj("select * from second_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: CurrentDataForCounterObjectWithDefaultTableName + * @tc.desc: Use CurrentData for CounterObject table with default table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, CurrentDataForCounterObjectWithDefaultTableName, TestSize.Level1) +{ + TS_LOGI("test1-6"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounterObject(1, "counter_1"); + EXPECT_EQ(0, ret); + std::string sqlQueryCounterObj("select * from gpu_counter_object;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: CurrentDataForCounterObjectWithManuallyTableName + * @tc.desc: Use CurrentData for CounterObject table with manually table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, CurrentDataForCounterObjectWithManuallyTableName, TestSize.Level1) +{ + TS_LOGI("test1-7"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", "second_table", " ", " "); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounterObject(1, "counter_1"); + EXPECT_EQ(0, ret); + std::string sqlQueryCounterObj("select * from second_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongDataForCounterObjectWithDefaultTableName + * @tc.desc: Use WrongData for CounterObject table with default table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForCounterObjectWithDefaultTableName, TestSize.Level1) +{ + TS_LOGI("test1-8"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounterObject(INVALID_INT32, "counter_1"); + EXPECT_EQ(0, ret); + std::string sqlQueryCounterObj("select * from gpu_counter_object;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongDataForCounterObjectWithManuallyTableName + * @tc.desc: Use WrongData for CounterObject table with manually table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForCounterObjectWithManuallyTableName, TestSize.Level1) +{ + TS_LOGI("test1-9"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", "second_table", " ", " "); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounterObject(INVALID_INT32, "counter_1"); + EXPECT_EQ(0, ret); + std::string sqlQueryCounterObj("select * from second_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongDataForCounterObject + * @tc.desc: Use WrongData for CounterObject table + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForCounterObject, TestSize.Level1) +{ + TS_LOGI("test1-10"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", "second_table", " ", " "); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounterObject(INVALID_INT32, " "); + EXPECT_EQ(0, ret); + std::string sqlQueryCounterObj("select * from gpu_counter_object;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounterObj.c_str(), sqlQueryCounterObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); +} + +/** + * @tc.name: CurrentDataForCounterWithDefaultTableName + * @tc.desc: Use CurrentData for Counter table with default table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, CurrentDataForCounterWithDefaultTableName, TestSize.Level1) +{ + TS_LOGI("test1-11"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounter(1, 100, 100); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from counter_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: CurrentDataForCounterWithManuallyTableName + * @tc.desc: Use CurrentData for Counter table with manually table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, CurrentDataForCounterWithManuallyTableName, TestSize.Level1) +{ + TS_LOGI("test1-12"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName("first_table", " ", " ", " "); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounter(1, 100, 100); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from first_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongDataForCounterWithDefaultTableName + * @tc.desc: Use WrongData for Counter table with default table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForCounterWithDefaultTableName, TestSize.Level1) +{ + TS_LOGI("test1-13"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounter(INVALID_INT32, 100, 100); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from counter_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongDataForCounterWithManuallyTableName + * @tc.desc: Use WrongData for Counter table with manually table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForCounterWithManuallyTableName, TestSize.Level1) +{ + TS_LOGI("test1-14"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName("first_table", " ", " ", " "); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounter(INVALID_INT32, 100, 100); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from first_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: CounterWithWrongData + * @tc.desc: Use wrongData for counter table + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, CounterWithWrongData, TestSize.Level1) +{ + TS_LOGI("test1-15"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendCounter(INVALID_INT32, INVALID_UINT64, INVALID_INT32); + EXPECT_EQ(0, ret); + std::string sqlQueryCounter("select * from counter_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQueryCounter.c_str(), sqlQueryCounter.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: CurrentDataForSliceObjectWithDefaultTableName + * @tc.desc: Use CurrentData for SliceObject table with default table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, CurrentDataForSliceObjectWithDefaultTableName, TestSize.Level1) +{ + TS_LOGI("test1-16"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSliceObject(1, "slice_1"); + EXPECT_EQ(0, ret); + std::string sqlQuerySliceObj("select * from slice_object_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: CurrentDataForSliceObjectWithManuallyTableName + * @tc.desc: Use CurrentData for SliceObject table with manually table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, CurrentDataForSliceObjectWithManuallyTableName, TestSize.Level1) +{ + TS_LOGI("test1-17"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", " ", " ", "fourth_table"); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSliceObject(1, "slice_1"); + EXPECT_EQ(0, ret); + std::string sqlQuerySliceObj("select * from fourth_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongDataForSliceObjectWithDefaultTableName + * @tc.desc: Use WrongData for SliceObject table with default table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForSliceObjectWithDefaultTableName, TestSize.Level1) +{ + TS_LOGI("test1-18"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSliceObject(1, "slice_1"); + EXPECT_EQ(0, ret); + std::string sqlQuerySliceObj("select * from slice_object_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongDataForSliceObjectWithManuallyTableName + * @tc.desc: Use WrongData for SliceObject table with manually table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForSliceObjectWithManuallyTableName, TestSize.Level1) +{ + TS_LOGI("test1-19"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", " ", " ", "fourth_table"); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSliceObject(INVALID_INT32, "slice_1"); + EXPECT_EQ(0, ret); + std::string sqlQuerySliceObj("select * from slice_object_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); +} + +/** + * @tc.name: WrongDataForSliceObject + * @tc.desc: Use WrongData for SliceObject table + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForSliceObject, TestSize.Level1) +{ + TS_LOGI("test1-20"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", " ", " ", "fourth_table"); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSliceObject(INVALID_INT32, " "); + EXPECT_EQ(0, ret); + std::string sqlQuerySliceObj("select * from slice_object_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySliceObj.c_str(), sqlQuerySliceObj.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), string::npos); + EXPECT_FALSE(ret); +} + +/** + * @tc.name: CurrentDataForSliceWithDefaultTableName + * @tc.desc: Use CurrentData for Slice table with default table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, CurrentDataForSliceWithDefaultTableName, TestSize.Level1) +{ + TS_LOGI("test1-21"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSlice(1, 100, 100, 100); + EXPECT_EQ(0, ret); + std::string sqlQuerySlice("select * from Slice_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: CurrentDataForSliceWithManuallyTableName + * @tc.desc: Use CurrentData for Slice table with manually table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, CurrentDataForSliceWithManuallyTableName, TestSize.Level1) +{ + TS_LOGI("test1-22"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", " ", "third_table", " "); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSlice(1, 100, 100, 100); + EXPECT_EQ(0, ret); + std::string sqlQuerySlice("select * from third_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongDataForSliceWithDefaultTableName + * @tc.desc: Use WrongData for Slice table with default table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForSliceWithDefaultTableName, TestSize.Level1) +{ + TS_LOGI("test1-23"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSlice(INVALID_INT32, 100, 100, 100); + EXPECT_EQ(0, ret); + std::string sqlQuerySlice("select * from Slice_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongDataForSliceWithManuallyTableName + * @tc.desc: Use WrongData for Slice table with manually table name + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, WrongDataForSliceWithManuallyTableName, TestSize.Level1) +{ + TS_LOGI("test1-24"); + SetRpcServer(rpcServer); + auto ret = SDK_SetTableName(" ", " ", "third_table", " "); + ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSlice(INVALID_INT32, 100, 100, 100); + EXPECT_EQ(0, ret); + std::string sqlQuerySlice("select * from third_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: SliceWithWrongData + * @tc.desc: Use wrongData for slice table + * @tc.type: FUNC + */ +HWTEST_F(SDKApiTest, SliceWithWrongData, TestSize.Level1) +{ + TS_LOGI("test1-25"); + SetRpcServer(rpcServer); + auto ret = rpcServer->ts_->sdkDataParser_->GetJsonConfig(QueryResultCallback); + EXPECT_EQ(0, ret); + ret = rpcServer->ts_->sdkDataParser_->CreateTableByJson(); + EXPECT_EQ(0, ret); + ret = SDK_AppendSlice(INVALID_INT32, INVALID_UINT64, INVALID_UINT64, INVALID_INT32); + EXPECT_EQ(0, ret); + std::string sqlQuerySlice("select * from slice_table;"); + ret = rpcServer->SqlQuery((const uint8_t*)sqlQuerySlice.c_str(), sqlQuerySlice.length(), res); + EXPECT_EQ(g_resultTest.find("ok"), 0); + EXPECT_TRUE(ret); +} +} // namespace SysTuning::TraceStreamer diff --git a/host/trace_streamer/sdk/trace_data/trace_data_cache.cpp b/host/trace_streamer/sdk/trace_data/trace_data_cache.cpp new file mode 100755 index 0000000000000000000000000000000000000000..799911df2e14ba73c6444dede7f541d23a98f1e8 --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_cache.cpp @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#include "trace_data_cache.h" +#include +#include "../table/gpu_counter_object_table.h" +#include "../table/gpu_counter_table.h" +#include "../table/slice_object_table.h" +#include "../table/slice_table.h" + +// #include "args_table.h" + +namespace SysTuning { +namespace TraceStreamer { +TraceDataCache::TraceDataCache() +{ + InitDB(); +} + +TraceDataCache::~TraceDataCache() {} + +void TraceDataCache::InitDB() +{ + if (dbInited) { + return; + } + dbInited = true; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/trace_data/trace_data_cache.h b/host/trace_streamer/sdk/trace_data/trace_data_cache.h new file mode 100755 index 0000000000000000000000000000000000000000..28defa3a0e9dc2efd44ec857655caa4a1fb8ef05 --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_cache.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#ifndef TRACE_DATA_CACHE_H +#define TRACE_DATA_CACHE_H + +#include "trace_data_cache_reader.h" +#include "trace_data_cache_writer.h" +#include "trace_data_db.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +class TraceDataCache : public TraceDataCacheReader, public TraceDataCacheWriter, public TraceDataDB { +public: + TraceDataCache(); + TraceDataCache(const TraceDataCache* dataCache) = delete; + TraceDataCache* operator=(const TraceDataCache* dataCache) = delete; + ~TraceDataCache() override; + void InitDB() override; + bool dbInited = false; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TRACE_DATA_CACHE_H diff --git a/host/trace_streamer/sdk/trace_data/trace_data_cache_base.cpp b/host/trace_streamer/sdk/trace_data/trace_data_cache_base.cpp new file mode 100755 index 0000000000000000000000000000000000000000..9da698ee3afe99fed20c4d3c75a075b78e9724bd --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_cache_base.cpp @@ -0,0 +1,24 @@ +/* + * 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. + */ + +#include "trace_data_cache_base.h" +#include + +namespace SysTuning { +namespace TraceStreamer { + + +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/trace_data/trace_data_cache_base.h b/host/trace_streamer/sdk/trace_data/trace_data_cache_base.h new file mode 100755 index 0000000000000000000000000000000000000000..da9156269218b388dc1cb0b53cb9b87a075a64d6 --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_cache_base.h @@ -0,0 +1,50 @@ +/* + * 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. + */ + +#ifndef TRACE_DATA_CACHE_BASE_H +#define TRACE_DATA_CACHE_BASE_H + + +#include +#include +#include +#include +#include +#include +#include "trace_stdtype.h" +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +class TraceDataCacheBase { +public: + TraceDataCacheBase() = default; + TraceDataCacheBase(const TraceDataCacheBase&) = delete; + TraceDataCacheBase& operator=(const TraceDataCacheBase&) = delete; + virtual ~TraceDataCacheBase() = default; + +public: + GpuCounter gpuCounter_; + GpuCounterObject gpuCounterObject_; + SliceObject sliceObject_; + SliceData sliceData_; + MetaData metaData_; + uint64_t traceStartTime_ = std::numeric_limits::max(); + uint64_t traceEndTime_ = 0; + +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TRACE_DATA_CACHE_BASE_H diff --git a/host/trace_streamer/sdk/trace_data/trace_data_cache_reader.cpp b/host/trace_streamer/sdk/trace_data/trace_data_cache_reader.cpp new file mode 100755 index 0000000000000000000000000000000000000000..ee224b06364a5054acbe43f7320505895c7dcd88 --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_cache_reader.cpp @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#include "trace_data_cache_reader.h" +#include "log.h" +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +TraceDataCacheReader::~TraceDataCacheReader() {} + +const GpuCounter& TraceDataCacheReader::GetConstGpuCounterData() const +{ + return gpuCounter_; +} +const GpuCounterObject& TraceDataCacheReader::GetConstGpuCounterObjectData() const +{ + return gpuCounterObject_; +} +const SliceObject& TraceDataCacheReader::GetConstSliceObjectData() const +{ + return sliceObject_; +} +const SliceData& TraceDataCacheReader::GetConstSliceData() const +{ + return sliceData_; +} +const MetaData& TraceDataCacheReader::GetConstMetaData() const +{ + return metaData_; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/trace_data/trace_data_cache_reader.h b/host/trace_streamer/sdk/trace_data/trace_data_cache_reader.h new file mode 100755 index 0000000000000000000000000000000000000000..916606ab21a49d01a6b848cc9d3e21c588c4a7e1 --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_cache_reader.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#ifndef TRACE_DATA_CACHE_READER_H +#define TRACE_DATA_CACHE_READER_H + +#include "log.h" +#include "trace_data_cache_base.h" +#include "trace_stdtype.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +class TraceDataCacheReader : virtual public TraceDataCacheBase { +public: + TraceDataCacheReader() = default; + TraceDataCacheReader(const TraceDataCacheReader&) = delete; + TraceDataCacheReader& operator=(const TraceDataCacheReader&) = delete; + ~TraceDataCacheReader() override; + +public: + const GpuCounter& GetConstGpuCounterData() const; + const GpuCounterObject& GetConstGpuCounterObjectData() const; + const SliceObject& GetConstSliceObjectData() const; + const SliceData& GetConstSliceData() const; + const MetaData& GetConstMetaData() const; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/sdk/trace_data/trace_data_cache_writer.cpp b/host/trace_streamer/sdk/trace_data/trace_data_cache_writer.cpp new file mode 100755 index 0000000000000000000000000000000000000000..a5a7920cfb2076c01e98308098d61c6cbb68297f --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_cache_writer.cpp @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#include "trace_data_cache_writer.h" +#include "log.h" +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +TraceDataCacheWriter::~TraceDataCacheWriter() {} + +GpuCounter* TraceDataCacheWriter::GetGpuCounterData() +{ + return &gpuCounter_; +} +GpuCounterObject* TraceDataCacheWriter::GetGpuCounterObjectData() +{ + return &gpuCounterObject_; +} +SliceObject* TraceDataCacheWriter::GetSliceObjectData() +{ + return &sliceObject_; +} +SliceData* TraceDataCacheWriter::GetSliceTableData() +{ + return &sliceData_; +} +MetaData* TraceDataCacheWriter::GetMetaData() +{ + return &metaData_; +} +void TraceDataCacheWriter::MixTraceTime(uint64_t timestampMin, uint64_t timestampMax) +{ + if (timestampMin == std::numeric_limits::max() || timestampMax == 0) { + return; + } + if (traceStartTime_ != std::numeric_limits::max()) { + traceStartTime_ = std::max(traceStartTime_, timestampMin); + } else { + traceStartTime_ = timestampMin; + } + if (traceEndTime_) { + traceEndTime_ = std::min(traceEndTime_, timestampMax); + } else { + traceEndTime_ = timestampMax; + } +} +void TraceDataCacheWriter::Clear() +{ + gpuCounter_.Clear(); + gpuCounterObject_.Clear(); + sliceObject_.Clear(); + sliceData_.Clear(); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/trace_data/trace_data_cache_writer.h b/host/trace_streamer/sdk/trace_data/trace_data_cache_writer.h new file mode 100755 index 0000000000000000000000000000000000000000..b97565b331520f414bb76a973a3ef1c7e4c26b60 --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_cache_writer.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef TRACE_DATA_CACHE_WRITER_H +#define TRACE_DATA_CACHE_WRITER_H + +#include "trace_data_cache_reader.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace TraceStdtype; +class TraceDataCacheWriter : virtual public TraceDataCacheBase { +public: + TraceDataCacheWriter() = default; + TraceDataCacheWriter(const TraceDataCacheWriter&) = delete; + TraceDataCacheWriter& operator=(const TraceDataCacheWriter&) = delete; + ~TraceDataCacheWriter() override; + void Clear(); + +public: + GpuCounter* GetGpuCounterData(); + GpuCounterObject* GetGpuCounterObjectData(); + SliceObject* GetSliceObjectData(); + SliceData* GetSliceTableData(); + MetaData* GetMetaData(); + void MixTraceTime(uint64_t timestampMin, uint64_t timestampMax); + // ThreadState* GetThreadStateData(); +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/sdk/trace_data/trace_data_db.cpp b/host/trace_streamer/sdk/trace_data/trace_data_db.cpp new file mode 100755 index 0000000000000000000000000000000000000000..9f84fe4bd63c9dd08b9703dc2b5e78d2750fef99 --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_db.cpp @@ -0,0 +1,422 @@ +/* + * 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. + */ + +#include "trace_data_db.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include "codec_cov.h" +#include "ext/sqlite_ext_funcs.h" +#include "file.h" +#include "log.h" +#include "string_help.h" + +const int ONCE_MAX_MB = 1024 * 1024 * 4; +namespace SysTuning { +namespace TraceStreamer { +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) +using namespace SysTuning::base; +TraceDataDB::TraceDataDB() : db_(nullptr) +{ + if (sqlite3_threadsafe() > 0) { + int retCode = sqlite3_config(SQLITE_CONFIG_SERIALIZED); + if (retCode == SQLITE_OK) { + TS_LOGI("Can now use sqlite on multiple threads, using the same connection"); + } else { + TS_LOGE("setting sqlite thread safe mode to serialized failed!!! return code: %d", retCode); + } + } else { + TS_LOGE("Your SQLite database is not compiled to be threadsafe."); + } + if (sqlite3_open(":memory:", &db_)) { + TS_LOGF("open :memory db failed"); + } + ts_create_extend_function(db_); +} + +TraceDataDB::~TraceDataDB() +{ + sqlite3_close(db_); +} + +void TraceDataDB::AppendNewTable(std::string tableName) +{ + internalTables_.push_back(tableName); +} +void TraceDataDB::EnableMetaTable(bool enabled) +{ + exportMetaTable_ = enabled; +} +int TraceDataDB::ExportDatabase(const std::string& outputName) +{ + { + int fd(base::OpenFile(outputName, O_CREAT | O_RDWR, 0600)); + if (!fd) { + fprintf(stdout, "Failed to create file: %s", outputName.c_str()); + return 1; + } + auto ret = ftruncate(fd, 0); + UNUSED(ret); + close(fd); + } + + std::string attachSql("ATTACH DATABASE '" + outputName + "' AS systuning_export"); +#ifdef _WIN32 + if (!base::GetCoding(reinterpret_cast(attachSql.c_str()), attachSql.length())) { + attachSql = base::GbkToUtf8(attachSql.c_str()); + } +#endif + ExecuteSql(attachSql); + + for (auto itor = internalTables_.begin(); itor != internalTables_.end(); itor++) { +#ifndef USE_VTABLE + if (*itor == "_meta" && !exportMetaTable_) { + continue; + } else { + std::string exportSql("CREATE TABLE systuning_export." + (*itor).substr(1, -1) + " AS SELECT * FROM " + + *itor); + ExecuteSql(exportSql); + } +#else + if (*itor == "meta" && !exportMetaTable_) { + continue; + } else { + std::string exportSql("CREATE TABLE systuning_export." + (*itor) + " AS SELECT * FROM " + *itor); + ExecuteSql(exportSql); + } +#endif + } + std::string createArgsView = + "create view systuning_export.args_view AS select A.argset, V2.data as keyName, A.id, D.desc, (case when " + "A.datatype==1 then V.data else A.value end) as strValue from args as A left join data_type as D on (D.typeId " + "= A.datatype) left join data_dict as V on V.id = A.value left join data_dict as V2 on V2.id = A.key"; + ExecuteSql(createArgsView); + std::string updateProcessName = + "update process set name = (select name from thread t where t.ipid = process.id and t.name is not null and " + "is_main_thread = 1)"; + ExecuteSql(updateProcessName); + std::string detachSql("DETACH DATABASE systuning_export"); + ExecuteSql(detachSql); + return 0; +} +void TraceDataDB::Prepare() +{ + if (pared_) { + return; + } + pared_ = true; +#ifndef USE_VTABLE + for (auto itor = internalTables_.begin(); itor != internalTables_.end(); itor++) { + std::string exportSql("CREATE TABLE " + (*itor).substr(1, -1) + " AS SELECT * FROM " + *itor); + ExecuteSql(exportSql); + } +#endif + std::string createArgsView = + "create view args_view AS select A.argset, V2.data as keyName, A.id, D.desc, (case when " + "A.datatype==1 then V.data else A.value end) as strValue from args as A left join data_type as D on " + "(D.typeId " + "= A.datatype) left join data_dict as V on V.id = A.value left join data_dict as V2 on V2.id = A.key"; + ExecuteSql(createArgsView); + + std::string updateProcessNewName = + "update process set name = (select name from thread t where t.ipid = process.id and t.name is not " + "null and " + "is_main_thread = 1)"; + ExecuteSql(updateProcessNewName); +} +void TraceDataDB::ExecuteSql(const std::string_view& sql) +{ + sqlite3_stmt* stmt = nullptr; + int ret = sqlite3_prepare_v2(db_, sql.data(), static_cast(sql.size()), &stmt, nullptr); + + while (!ret) { + int err = sqlite3_step(stmt); + if (err == SQLITE_ROW) { + continue; + } + if (err == SQLITE_DONE) { + break; + } + ret = err; + } + + sqlite3_finalize(stmt); +} +int TraceDataDB::SearchData() +{ + Prepare(); + std::string line; + bool printResult = false; + for (;;) { + std::cout << "> "; + getline(std::cin, line); + if (line.empty()) { + std::cout << "If you want to quit either type -q or press CTRL-Z" << std::endl; + continue; + } + if (!line.compare("-q") || !line.compare("-quit")) { + break; + } else if (!line.compare("-e")) { + TS_LOGI("the db file will be at current folder, the name is default.db"); + return ExportDatabase("default.db"); + } else if (!line.compare("-help") || !line.compare("-h")) { + std::cout << "use info" << std::endl; + continue; + } else if (!line.compare("-p")) { + std::cout << "will print result of query" << std::endl; + printResult = true; + continue; + } else if (!line.compare("-up")) { + std::cout << "will not print result of query" << std::endl; + printResult = false; + continue; + } else if (line.find("-c:") == 0) { + line = line.substr(strlen("-c:")); + if (OperateDatabase(line) == SQLITE_OK) { + printf("operate SQL success\n"); + } + continue; + } + + using namespace std::chrono; + const auto start = steady_clock::now(); + int rowCount = SearchDatabase(line, printResult); + std::chrono::nanoseconds searchDur = duration_cast(steady_clock::now() - start); + printf("\"%s\"\n\tused %.3fms row: %d\n", line.c_str(), searchDur.count() / 1E6, rowCount); + } + return 0; +} +int TraceDataDB::SearchDatabase(const std::string& sql, bool print) +{ + Prepare(); + int rowCount = 0; + sqlite3_stmt* stmt = nullptr; + int ret = sqlite3_prepare_v2(db_, sql.c_str(), static_cast(sql.size()), &stmt, nullptr); + if (ret != SQLITE_OK) { + TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:%s", sql.c_str(), ret, sqlite3_errmsg(db_)); + return 0; + } + + int colCount = sqlite3_column_count(stmt); + if (colCount == 0) { + TS_LOGI("sqlite3_column_count(%s) no column", sql.c_str()); + sqlite3_finalize(stmt); + return 0; + } + if (print) { + for (int i = 0; i < colCount; i++) { + printf("%s\t", sqlite3_column_name(stmt, i)); + } + printf("\n"); + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + rowCount++; + for (int i = 0; i < colCount; i++) { + const char* p = reinterpret_cast(sqlite3_column_text(stmt, i)); + int type = sqlite3_column_type(stmt, i); + if (!print) { + continue; + } + if (p == nullptr) { + printf("null\t"); + continue; + } + if (type == SQLITE_TEXT) { + printf("\"%s\"\t", p); + } else { + printf("%s\t", p); + } + } + if (print) { + printf("\n"); + } + } + sqlite3_finalize(stmt); + return rowCount; +} +int TraceDataDB::OperateDatabase(const std::string& sql) +{ + Prepare(); + char* errmsg = nullptr; + int ret = sqlite3_exec(db_, sql.c_str(), NULL, NULL, &errmsg); + if (ret != SQLITE_OK && errmsg) { + TS_LOGE("sqlite3_exec(%s) failed: %d:%s", sql.c_str(), ret, errmsg); + sqlite3_free(errmsg); + } + return ret; +} +int TraceDataDB::SearchDatabase(const std::string& sql, ResultCallBack resultCallBack) +{ + Prepare(); + sqlite3_stmt* stmt = nullptr; + int ret = sqlite3_prepare_v2(db_, sql.c_str(), static_cast(sql.size()), &stmt, nullptr); + if (ret != SQLITE_OK) { + resultCallBack("false\r\n", SEND_FINISH, 0); + TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:%s", sql.c_str(), ret, sqlite3_errmsg(db_)); + return ret; + } + if (!resultCallBack) { + return ret; + } + + std::string res = "ok\r\n"; + int colCount = sqlite3_column_count(stmt); + if (colCount == 0) { + resultCallBack(res, SEND_FINISH, 0); + return ret; + } + res += "{\"columns\":["; + for (int i = 0; i < colCount; i++) { + res += "\""; + res += sqlite3_column_name(stmt, i); + res += "\","; + } + res.pop_back(); // remove the last "," + res += "],\"values\":["; + bool hasRow = false; + constexpr int defaultLenRowString = 1024; + std::string row; + row.reserve(defaultLenRowString); + while (sqlite3_step(stmt) == SQLITE_ROW) { + hasRow = true; + GetRowString(stmt, colCount, row); + res += row + ","; + if (res.size() >= ONCE_MAX_MB) { + resultCallBack(res, SEND_CONTINUE, 0); + res = ""; + } + } + if (hasRow) { + res.pop_back(); // remove the last ',' + } + res += "]}\r\n"; + resultCallBack(res, SEND_FINISH, 0); + + sqlite3_finalize(stmt); + return ret; +} +int TraceDataDB::SearchDatabase(const std::string& sql, uint8_t* out, int outLen) +{ + Prepare(); + sqlite3_stmt* stmt = nullptr; + int ret = sqlite3_prepare_v2(db_, sql.c_str(), static_cast(sql.size()), &stmt, nullptr); + if (ret != SQLITE_OK) { + TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:%s", sql.c_str(), ret, sqlite3_errmsg(db_)); + return -1; + } + char* res = reinterpret_cast(out); + int retSnprintf = snprintf_s(res, outLen, 1, "ok\r\n"); + if (retSnprintf < 0) { + return -1; + } + int pos = retSnprintf; + int colCount = sqlite3_column_count(stmt); + if (colCount == 0) { + return pos; + } + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "%s", "{\"columns\":["); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + for (int i = 0; i < colCount; i++) { + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "%s%s%s", "\"", sqlite3_column_name(stmt, i), "\","); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + } + pos--; // rmove the last ',' + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "],\"values\":["); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + bool hasRow = false; + constexpr int defaultLenRowString = 1024; + std::string row; + row.reserve(defaultLenRowString); + while (sqlite3_step(stmt) == SQLITE_ROW) { + hasRow = true; + GetRowString(stmt, colCount, row); + if (pos + row.size() + strlen(",]}\r\n") >= size_t(outLen)) { + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "]}\r\n"); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + sqlite3_finalize(stmt); + return pos; + } + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "%s%s", row.c_str(), ","); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + } + if (hasRow) { + pos--; // remove the last ',' + } + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "]}\r\n"); + if (retSnprintf < 0) { + return -1; + } + pos += retSnprintf; + sqlite3_finalize(stmt); + return pos; +} +void TraceDataDB::SetCancel(bool cancel) +{ + cancelQuery_ = cancel; +} +void TraceDataDB::GetRowString(sqlite3_stmt* stmt, int colCount, std::string& rowStr) +{ + rowStr.clear(); + rowStr = "["; + for (int i = 0; i < colCount; i++) { + const char* p = reinterpret_cast(sqlite3_column_text(stmt, i)); + if (p == nullptr) { + rowStr += "null,"; + continue; + } + int type = sqlite3_column_type(stmt, i); + switch (type) { + case SQLITE_TEXT: + rowStr += "\""; + rowStr += p; + rowStr += "\""; + break; + default: + rowStr += p; + break; + } + rowStr += ","; + } + rowStr.pop_back(); // remove the last ',' + rowStr += "]"; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/trace_data/trace_data_db.h b/host/trace_streamer/sdk/trace_data/trace_data_db.h new file mode 100755 index 0000000000000000000000000000000000000000..995b695a31d84b3e18f2ae6b82f495cd3e7dc508 --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_data_db.h @@ -0,0 +1,69 @@ +/* + * 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. + */ + +#ifndef TRACE_DATA_DB_H +#define TRACE_DATA_DB_H + +#include +#include +#include + +extern "C" { +#include "sqlite3.h" +} + +namespace SysTuning { +namespace TraceStreamer { +const int SEND_CONTINUE = 0; +const int SEND_FINISH = 1; +class TraceDataDB { +public: + TraceDataDB(); + TraceDataDB(const TraceDataDB&) = delete; + TraceDataDB& operator=(const TraceDataDB&) = delete; + virtual ~TraceDataDB(); + virtual void InitDB() = 0; + void Prepare(); + +public: + int ExportDatabase(const std::string& outputName); + int SearchData(); + int OperateDatabase(const std::string& sql); + using ResultCallBack = std::function; + int SearchDatabase(const std::string& sql, ResultCallBack resultCallBack); + int SearchDatabase(const std::string& sql, uint8_t* out, int outLen); + void SetCancel(bool cancel); + void AppendNewTable(std::string tableName); + void EnableMetaTable(bool enabled); + bool Cancel() const + { + return cancelQuery_; + } + +public: + sqlite3* db_; + +private: + void ExecuteSql(const std::string_view& sql); + static void GetRowString(sqlite3_stmt* stmt, int colCount, std::string& rowStr); + int SearchDatabase(const std::string& sql, bool print); + std::list internalTables_ = {}; + bool exportMetaTable_ = true; + bool pared_ = false; + bool cancelQuery_ = false; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif diff --git a/host/trace_streamer/sdk/trace_data/trace_stdtype.cpp b/host/trace_streamer/sdk/trace_data/trace_stdtype.cpp new file mode 100755 index 0000000000000000000000000000000000000000..d468bc18a9dc649417af595d43c53fbac73f88ec --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_stdtype.cpp @@ -0,0 +1,120 @@ +/* + * 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. + */ + +#include "trace_stdtype.h" +#include +#include +namespace SysTuning { +namespace TraceStdtype { + +void GpuCounter::AppendNewData(uint64_t ts, int counterId, int value) +{ + ts_.emplace_back(ts); + counterId_.emplace_back(counterId); + value_.emplace_back(value); + ids_.push_back(counterId_.size() - 1); +} +const std::deque& GpuCounter::TimeStamp() const +{ + return ts_; +} +const std::deque& GpuCounter::CounterId() const +{ + return counterId_; +} +const std::deque& GpuCounter::Value() const +{ + return value_; +} + +void GpuCounterObject::AppendNewData(int counterId, const std::string counterName) +{ + counterId_.emplace_back(counterId); + counterName_.emplace_back(counterName); + ids_.push_back(counterId_.size() - 1); +} +const std::deque& GpuCounterObject::CounterId() const +{ + return counterId_; +} +const std::deque& GpuCounterObject::CounterName() const +{ + return counterName_; +} +void SliceObject::AppendNewData(int sliceId, std::string sliceName) +{ + sliceId_.emplace_back(sliceId); + sliceName_.emplace_back(sliceName); + ids_.push_back(sliceId_.size() - 1); +} +const std::deque& SliceObject::SliceId() const +{ + return sliceId_; +} +const std::deque& SliceObject::SliceName() const +{ + return sliceName_; +} +void SliceData::AppendNewData(int sliceId, uint64_t startTs, uint64_t endTs, int value) +{ + startTs_.emplace_back(startTs); + endTs_.emplace_back(endTs); + sliceId_.emplace_back(sliceId); + value_.emplace_back(value); + ids_.push_back(sliceId_.size() - 1); +} +const std::deque& SliceData::SliceId() const +{ + return sliceId_; +} +const std::deque& SliceData::TimeStamp() const +{ + return startTs_; +} +const std::deque& SliceData::EndTs() const +{ + return endTs_; +} +const std::deque& SliceData::Value() const +{ + return value_; +} +void MetaData::InitMetaData() +{ + columnNames_.resize(METADATA_ITEM_MAX); + values_.resize(METADATA_ITEM_MAX); + columnNames_[METADATA_ITEM_PARSERTOOL_VERSION] = METADATA_ITEM_PARSERTOOL_VERSION_COLNAME; + columnNames_[METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME] = METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME_COLNAME; +} +void MetaData::SetParserToolVersion(const std::string& version) +{ + values_[METADATA_ITEM_PARSERTOOL_VERSION] = version; + +} +void MetaData::SetParserToolPublishDateTime(const std::string& datetime) +{ + values_[METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME] = datetime; +} +const std::string& MetaData::Value(uint64_t row) const +{ + return values_[row]; +} +const std::string& MetaData::Name(uint64_t row) const +{ + return columnNames_[row]; +} + +} // namespace TraceStdtype +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/trace_data/trace_stdtype.h b/host/trace_streamer/sdk/trace_data/trace_stdtype.h new file mode 100755 index 0000000000000000000000000000000000000000..e28348dc4f2f71eb3f6162f9dd3efd4f1fee9e91 --- /dev/null +++ b/host/trace_streamer/sdk/trace_data/trace_stdtype.h @@ -0,0 +1,148 @@ +/* + * 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. + */ + +#ifndef TRACE_STDTYPE_H +#define TRACE_STDTYPE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "log.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStdtype { +using namespace SysTuning::TraceStreamer; +// the supported metadata +enum MetaDataItem { METADATA_ITEM_PARSERTOOL_VERSION, METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME, METADATA_ITEM_MAX }; +class CacheBase { +public: + size_t Size() const + { + return std::max(timeStamps_.size(), ids_.size()); + } + const std::deque& IdsData() const + { + return ids_; + } + const std::deque& TimeStamData() const + { + return timeStamps_; + } + const std::deque& InternalTidsData() const + { + return internalTids_; + } + virtual void Clear() + { + internalTids_.clear(); + timeStamps_.clear(); + ids_.clear(); + } + +public: + std::deque internalTids_ = {}; + std::deque timeStamps_ = {}; + std::deque ids_ = {}; +}; + +class GpuCounterObject : public CacheBase { +public: + GpuCounterObject() = default; + ~GpuCounterObject() = default; + void AppendNewData(int counterId, std::string counterName); + const std::deque& CounterId() const; + const std::deque& CounterName() const; + +private: + std::deque counterId_ = {}; + std::deque counterName_ = {}; +}; +class GpuCounter : public CacheBase { +public: + GpuCounter() = default; + ~GpuCounter() = default; + void AppendNewData(uint64_t ts, int counterId, int value); + const std::deque& TimeStamp() const; + const std::deque& CounterId() const; + const std::deque& Value() const; + +private: + std::deque ts_ = {}; + std::deque counterId_ = {}; + std::deque value_ = {}; +}; + +class SliceObject : public CacheBase { +public: + SliceObject() = default; + ~SliceObject() = default; + void AppendNewData(int sliceId, std::string sliceName); + const std::deque& SliceId() const; + const std::deque& SliceName() const; + +private: + std::deque sliceId_ = {}; + std::deque sliceName_ = {}; +}; +class SliceData : public CacheBase { +public: + SliceData() = default; + ~SliceData() = default; + void AppendNewData(int sliceId, uint64_t startTs, uint64_t endTs, int value); + const std::deque& SliceId() const; + const std::deque& TimeStamp() const; + const std::deque& EndTs() const; + const std::deque& Value() const; + +private: + std::deque startTs_ = {}; + std::deque sliceId_ = {}; + std::deque endTs_ = {}; + std::deque value_ = {}; +}; +class MetaData : public CacheBase { +public: + MetaData() = default; + ~MetaData() = default; + void InitMetaData(); + void SetParserToolVersion(const std::string& version); + void SetParserToolPublishDateTime(const std::string& datetime); + const std::string& Value(uint64_t row) const; + const std::string& Name(uint64_t row) const; + void Clear() + { + columnNames_.clear(); + values_.clear(); + } + +private: + const std::string METADATA_ITEM_PARSERTOOL_VERSION_COLNAME = "tool_version"; + const std::string METADATA_ITEM_PARSERTOOL_PUBLISH_DATETIME_COLNAME = "tool_publish_time"; + std::deque columnNames_ = {}; + std::deque values_ = {}; +}; +} // namespace TraceStdtype +} // namespace SysTuning + +#endif // TRACE_STDTYPE_H diff --git a/host/trace_streamer/sdk/trace_streamer/trace_streamer_filters.cpp b/host/trace_streamer/sdk/trace_streamer/trace_streamer_filters.cpp new file mode 100755 index 0000000000000000000000000000000000000000..1b831e4cea70d570902487a1267090ce0baf8a94 --- /dev/null +++ b/host/trace_streamer/sdk/trace_streamer/trace_streamer_filters.cpp @@ -0,0 +1,21 @@ +/* + * 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. + */ + +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/trace_streamer/trace_streamer_filters.h b/host/trace_streamer/sdk/trace_streamer/trace_streamer_filters.h new file mode 100755 index 0000000000000000000000000000000000000000..506a69e6d76c504df468965bdadfad17387db5c6 --- /dev/null +++ b/host/trace_streamer/sdk/trace_streamer/trace_streamer_filters.h @@ -0,0 +1,32 @@ +/* + * 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. + */ + +#ifndef TRACE_STREAMERTOKEN_H +#define TRACE_STREAMERTOKEN_H + +#include +#include "clock_filter.h" +namespace SysTuning { +namespace TraceStreamer { +class TraceStreamerFilters { +public: + TraceStreamerFilters(){}; + ~TraceStreamerFilters(){}; + std::unique_ptr clockFilter_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TRACE_STREAMERTOKEN_H diff --git a/host/trace_streamer/sdk/trace_streamer/trace_streamer_selector.cpp b/host/trace_streamer/sdk/trace_streamer/trace_streamer_selector.cpp new file mode 100755 index 0000000000000000000000000000000000000000..5387eef6938d5014c7afa746a9c5961c9954cb78 --- /dev/null +++ b/host/trace_streamer/sdk/trace_streamer/trace_streamer_selector.cpp @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#include "trace_streamer_selector.h" +#include +#include +#include +#include +#include "clock_filter.h" +#include "string_help.h" + +using namespace SysTuning::base; +namespace SysTuning { +namespace TraceStreamer { +namespace { +TraceFileType GuessFileType(const uint8_t* data, size_t size) +{ + return TRACE_FILETYPE_UN_KNOW; +} +} // namespace + +TraceStreamerSelector::TraceStreamerSelector() +{ + InitFilter(); + sdkDataParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); +} +TraceStreamerSelector::~TraceStreamerSelector() {} + +void TraceStreamerSelector::InitFilter() +{ + streamFilters_ = std::make_unique(); + traceDataCache_ = std::make_unique(); + streamFilters_->clockFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); +} + +MetaData* TraceStreamerSelector::GetMetaData() +{ + return traceDataCache_->GetMetaData(); +} + +void TraceStreamerSelector::WaitForParserEnd() +{ +} + +bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr data, size_t size) +{ + if (size == 0) { + return true; + } + return true; +} +void TraceStreamerSelector::EnableMetaTable(bool enabled) +{ + traceDataCache_->EnableMetaTable(enabled); +} + +void TraceStreamerSelector::SetCleanMode(bool cleanMode) {} +int TraceStreamerSelector::ExportDatabase(const std::string& outputName) const +{ + return traceDataCache_->ExportDatabase(outputName); +} +void TraceStreamerSelector::Clear() +{ + traceDataCache_->Prepare(); + traceDataCache_->Clear(); +} +int TraceStreamerSelector::SearchData() +{ + return traceDataCache_->SearchData(); +} +int TraceStreamerSelector::OperateDatabase(const std::string& sql) +{ + return traceDataCache_->OperateDatabase(sql); +} +int TraceStreamerSelector::SearchDatabase(const std::string& sql, + TraceDataDB::ResultCallBack resultCallBack) +{ + return traceDataCache_->SearchDatabase(sql, resultCallBack); +} +int TraceStreamerSelector::SearchDatabase(const std::string& sql, uint8_t* out, int outLen) +{ + return traceDataCache_->SearchDatabase(sql, out, outLen); +} +void TraceStreamerSelector::SetCancel(bool cancel) +{ + traceDataCache_->SetCancel(cancel); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/sdk/trace_streamer/trace_streamer_selector.h b/host/trace_streamer/sdk/trace_streamer/trace_streamer_selector.h new file mode 100755 index 0000000000000000000000000000000000000000..860b9a2e59679e3afb5379cde6f98a0be4cc1178 --- /dev/null +++ b/host/trace_streamer/sdk/trace_streamer/trace_streamer_selector.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +#ifndef TRACE_STREAMER_SELECTOR_H +#define TRACE_STREAMER_SELECTOR_H +#include +#include +#include "../sdk/sdk_data_parser.h" +#include "../trace_data/trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class SDKDataParser; +enum TraceFileType { /*TRACE_FILETYPE_BY_TRACE, TRACE_FILETYPE_H_TRACE,*/ TRACE_FILETYPE_UN_KNOW }; +class TraceStreamerSelector { +public: + TraceStreamerSelector(); + ~TraceStreamerSelector(); + bool ParseTraceDataSegment(std::unique_ptr data, size_t size); + void EnableMetaTable(bool enabled); + void SetCleanMode(bool cleanMode); + int ExportDatabase(const std::string& outputName) const; + int SearchData(); + int OperateDatabase(const std::string& sql); + int SearchDatabase(const std::string& sql, TraceDataDB::ResultCallBack resultCallBack); + int SearchDatabase(const std::string& sql, uint8_t* out, int outLen); + MetaData* GetMetaData(); + void WaitForParserEnd(); + void Clear(); + void SetDataType(TraceFileType type); + void SetCancel(bool cancel); + std::unique_ptr sdkDataParser_ = {}; + +private: + void InitFilter(); + std::unique_ptr streamFilters_ = {}; + std::unique_ptr traceDataCache_ = {}; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TRACE_STREAMER_SELECTOR_H diff --git a/host/trace_streamer/sdk/ts.gni b/host/trace_streamer/sdk/ts.gni new file mode 100755 index 0000000000000000000000000000000000000000..16279772850e6b180cc5c0b02a8945bfef54999b --- /dev/null +++ b/host/trace_streamer/sdk/ts.gni @@ -0,0 +1,61 @@ +# 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. +OHOS_PROTO_DIR = "" + +if (target_os == "linux" || target_os == "macx" || target_os == "windows") { + # OHOS_FTRACE_PROTO_DIR="//third_party/protogen" + OHOS_FTRACE_PROTO_DIR = "//src/multi_platform" + + # OHOS_MEMORY_PROTO_DIR="//third_party/protogen" + OHOS_MEMORY_PROTO_DIR = "//src/multi_platform" + + # OHOS_HILOG_PROTO_DIR="//third_party/protogen" + OHOS_HILOG_PROTO_DIR = "//src/multi_platform" + + # OHOS_NATIVE_HOOK_PROTO_DIR="//third_party/protogen" + OHOS_NATIVE_HOOK_PROTO_DIR = "//src/multi_platform" + + # OHOS_HIDUMP_PROTO_DIR="//third_party/protogen" + OHOS_HIDUMP_PROTO_DIR = "//src/multi_platform" + + # OHOS_SERVICE_PROTO_DIR = "//third_party/protogen" + OHOS_SERVICE_PROTO_DIR = "//src/multi_platform" + OHOS_PROTO_GEN = "//third_party/protogen" + + # kernel_version = "5.10.79_aarch64" + kernel_version = "." + if (target == "test") { + enable_ts_utest = true + } else { + enable_ts_utest = false + } + is_openharmony = false +} else { + enable_ts_utest = true + use_wasm = false + kernel_version = "." + is_fuzz = false + target = "trace_streamer" + is_openharmony = true + OHOS_FTRACE_PROTO_DIR = "//developtools/profiler/protos/types/plugins/ftrace_data/${kernel_version}" + OHOS_MEMORY_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/memory_data" + OHOS_HILOG_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/hilog_data" + OHOS_NATIVE_HOOK_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/native_hook" + OHOS_HIDUMP_PROTO_DIR = + "//developtools/profiler/protos/types/plugins/hidump_data" + OHOS_SERVICE_PROTO_DIR = "//developtools/profiler/protos/services" + OHOS_PROTO_GEN = "//out/ohos-arm-release/gen/cpp/developtools/profiler/protos" +} diff --git a/host/trace_streamer/src/rpc/rpc.pri b/host/trace_streamer/sdktest.sh old mode 100644 new mode 100755 similarity index 62% rename from host/trace_streamer/src/rpc/rpc.pri rename to host/trace_streamer/sdktest.sh index 0bee6706469c8d52d6c002d7615ccdd493cff44f..8efbf0fb61580b2d0e52aeecfc2845c87ac3fe3c --- a/host/trace_streamer/src/rpc/rpc.pri +++ b/host/trace_streamer/sdktest.sh @@ -1,4 +1,5 @@ -# Copyright (C) 2021 Huawei Device Co., Ltd. +#!/bin/bash +# 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 @@ -10,8 +11,11 @@ # 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. -INCLUDEPATH +=$$PWD \ - $$PWD/../cfg -SOURCES += $$PWD/rpc_server.cpp \ - $$PWD/http_socket.cpp \ - $$PWD/http_server.cpp +#./build.sh sdkdemotest clean +./build.sh sdkdemotest +rm out/sdkdemotest/*.xml +find out/sdkdemotest -name "*.gcda" -print0 | xargs -0 rm +mkdir -p out/sdkdemotest/data/resource +cp sdkdemotest/resource/* out/sdkdemotest/data/resource/ +cd out/sdkdemotest +./trace_streamer_sdk_ut diff --git a/host/trace_streamer/src/BUILD.gn b/host/trace_streamer/src/BUILD.gn index 3abb1454fb5c04175f128905a9c978899c3d58ef..a8b40f19f90efc06ba4761d4452c88697a0172c9 100644 --- a/host/trace_streamer/src/BUILD.gn +++ b/host/trace_streamer/src/BUILD.gn @@ -43,126 +43,38 @@ ohos_source_set("lib") { "parser/htrace_parser/htrace_event_parser", "parser/htrace_parser/htrace_cpu_parser", "//third_party/sqlite/include", + "//third_party/json-master/include", + "//third_party/json-master/include/nlohmann", "${OHOS_PROTO_GEN}/types/plugins/memory_data", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/${kernel_version}", "${OHOS_PROTO_GEN}/types/plugins/hilog_data", "${OHOS_PROTO_GEN}/types/plugins/native_hook", "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}/types/plugins/network_data", + "${OHOS_PROTO_GEN}/types/plugins/cpu_data", + "${OHOS_PROTO_GEN}/types/plugins/diskio_data", + "${OHOS_PROTO_GEN}/types/plugins/process_data", + "${OHOS_PROTO_GEN}/types/plugins/hisysevent_data", "${OHOS_PROTO_GEN}", "//third_party/protobuf/src", ] + if (with_perf) { + include_dirs += [ + "parser/hiperf_parser", + "parser/hiperf_parser/hiperf/include", + "parser/hiperf_parser/hiperf/include/linux", + "//third_party/perf_include", + ] + } public_deps = [] } ohos_source_set("trace_streamer_source") { sources = [ "cfg/trace_streamer_config.cpp", "cfg/trace_streamer_config.h", - "filter/args_filter.cpp", - "filter/args_filter.h", - "filter/binder_filter.cpp", - "filter/binder_filter.h", - "filter/clock_filter.cpp", - "filter/clock_filter.h", - "filter/cpu_filter.cpp", - "filter/filter_base.cpp", - "filter/filter_base.h", - "filter/filter_filter.cpp", - "filter/filter_filter.h", - "filter/irq_filter.cpp", - "filter/irq_filter.h", - "filter/measure_filter.cpp", - "filter/measure_filter.h", - "filter/process_filter.cpp", - "filter/process_filter.h", - "filter/slice_filter.cpp", - "filter/slice_filter.h", - "filter/stat_filter.cpp", - "filter/stat_filter.h", - "filter/symbols_filter.cpp", - "filter/symbols_filter.h", - "filter/system_event_measure_filter.cpp", - "filter/system_event_measure_filter.h", - "parser/bytrace_parser/bytrace_event_parser.cpp", - "parser/bytrace_parser/bytrace_event_parser.h", - "parser/bytrace_parser/bytrace_parser.cpp", - "parser/bytrace_parser/bytrace_parser.h", - "parser/common_types.h", - "parser/event_parser_base.cpp", - "parser/event_parser_base.h", - "parser/print_event_parser.cpp", - "parser/print_event_parser.h", - "parser/thread_state.cpp", - "parser/thread_state.h", "rpc/http_server.cpp", "rpc/http_socket.cpp", "rpc/rpc_server.cpp", - "table/args_table.cpp", - "table/args_table.h", - "table/callstack_table.cpp", - "table/callstack_table.h", - "table/clk_event_filter_table.cpp", - "table/clk_event_filter_table.h", - "table/clock_event_filter_table.cpp", - "table/clock_event_filter_table.h", - "table/cpu_measure_filter_table.cpp", - "table/cpu_measure_filter_table.h", - "table/data_dict_table.cpp", - "table/data_dict_table.h", - "table/data_type_table.cpp", - "table/data_type_table.h", - "table/filter_table.cpp", - "table/filter_table.h", - "table/heap_frame_table.cpp", - "table/heap_frame_table.h", - "table/heap_table.cpp", - "table/heap_table.h", - "table/hidump_table.cpp", - "table/hidump_table.h", - "table/instants_table.cpp", - "table/instants_table.h", - "table/irq_table.cpp", - "table/log_table.cpp", - "table/log_table.h", - "table/measure_filter_table.cpp", - "table/measure_filter_table.h", - "table/measure_table.cpp", - "table/measure_table.h", - "table/meta_table.cpp", - "table/meta_table.h", - "table/process_filter_table.cpp", - "table/process_filter_table.h", - "table/process_measure_filter_table.cpp", - "table/process_measure_filter_table.h", - "table/process_table.cpp", - "table/process_table.h", - "table/range_table.cpp", - "table/raw_table.cpp", - "table/raw_table.h", - "table/sched_slice_table.cpp", - "table/sched_slice_table.h", - "table/stat_table.cpp", - "table/stat_table.h", - "table/symbols_table.cpp", - "table/symbols_table.h", - "table/system_call_table.cpp", - "table/system_call_table.h", - "table/system_event_filter_table.cpp", - "table/table_base.cpp", - "table/thread_filter_table.cpp", - "table/thread_state_table.cpp", - "table/thread_table.cpp", - "trace_data/trace_data_cache.cpp", - "trace_data/trace_data_cache.h", - "trace_data/trace_data_cache_base.cpp", - "trace_data/trace_data_cache_base.h", - "trace_data/trace_data_cache_reader.cpp", - "trace_data/trace_data_cache_reader.h", - "trace_data/trace_data_cache_writer.cpp", - "trace_data/trace_data_cache_writer.h", - "trace_data/trace_data_db.cpp", - "trace_data/trace_data_db.h", - "trace_data/trace_stdtype.cpp", - "trace_data/trace_stdtype.h", "trace_streamer/trace_streamer_filters.cpp", "trace_streamer/trace_streamer_filters.h", "trace_streamer/trace_streamer_selector.cpp", @@ -183,25 +95,78 @@ ohos_source_set("trace_streamer_source") { "parser/htrace_parser", "parser/htrace_parser/htrace_event_parser", "parser/htrace_parser/htrace_cpu_parser", + "parser/ebpf_parser", "//third_party/sqlite/include", "${OHOS_PROTO_GEN}/types/plugins/memory_data", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/${kernel_version}", "${OHOS_PROTO_GEN}/types/plugins/hilog_data", "${OHOS_PROTO_GEN}/types/plugins/native_hook", "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}/types/plugins/network_data", + "${OHOS_PROTO_GEN}/types/plugins/cpu_data", + "${OHOS_PROTO_GEN}/types/plugins/diskio_data", + "${OHOS_PROTO_GEN}/types/plugins/process_data", + "${OHOS_PROTO_GEN}/types/plugins/hisysevent_data", "${OHOS_PROTO_GEN}", "//third_party/protobuf/src", ] + if (use_wasm) { + include_dirs += + [ "../prebuilts/emsdk/emsdk/emscripten/cache/sysroot/include" ] + } + if (is_macx && !is_test) { + cflags = [ "-D_XOPEN_SOURCE=600" ] + } + if (is_test) { + include_dirs += [ "../prebuilts/emsdk/emsdk/emscripten/system/include" ] + } + include_dirs += [ + "//third_party/libunwind/include", + "//third_party/libunwind/src", + "//third_party/json-master/include", + "//third_party/json-master/include/nlohmann", + ] + if (with_ebpf_help_table) { + sources += [ + "table/ebpf_elf_symbol_table.cpp", + "table/ebpf_elf_symbol_table.h", + "table/ebpf_elf_table.cpp", + "table/ebpf_elf_table.h", + "table/ebpf_process_maps_table.cpp", + "table/ebpf_process_maps_table.h", + ] + } + + if (with_perf) { + include_dirs += [ + "parser/hiperf_parser", + "parser/hiperf_parser/hiperf/linux", + "parser/hiperf_parser/hiperf/kernel", + "parser/hiperf_parser/hiperf/include", + "parser/hiperf_parser/hiperf/include/linux", + "//third_party/perf_include/libbpf", + "//third_party/perf_include/musl", + ] + } deps = [ "base:base", "ext:sqliteext", + "filter:filter", "include:ibase", - "parser/htrace_parser:htrace_parser", + "parser:parser", + "table:table", + "trace_data:trace_data", "//third_party/sqlite:sqlite", ] + if (with_perf) { + deps += [ "parser/hiperf_parser:hiperf_parser" ] + } - if (use_wasm) { - sources += [ "rpc/wasm_func.cpp" ] + if (use_wasm || enable_ts_utest) { + sources += [ + "rpc/wasm_func.cpp", + "rpc/wasm_func.h", + ] } if (enable_ts_utest && !use_wasm) { cflags = [ @@ -213,6 +178,9 @@ ohos_source_set("trace_streamer_source") { "-ftest-coverage", "--coverage", ] + if (is_test) { + cflags += [ "-D IS_UT" ] + } } public_deps = [] } @@ -222,7 +190,9 @@ if (use_wasm) { deps = [ ":lib" ] } } else { - executable("trace_streamer") { - deps = [ ":lib" ] + if (!is_test && !is_fuzz) { + executable("trace_streamer") { + deps = [ ":lib" ] + } } } diff --git a/host/trace_streamer/src/base/BUILD.gn b/host/trace_streamer/src/base/BUILD.gn index 110bed46b652bdc52ea836da59bd8c2dc114baf7..3c151a7add7517a154c9c0e691e8b69eaa979429 100644 --- a/host/trace_streamer/src/base/BUILD.gn +++ b/host/trace_streamer/src/base/BUILD.gn @@ -21,7 +21,9 @@ ohos_source_set("base") { "codec_cov.cpp", "file.cpp", "log.cpp", + "meta.cpp", "parting_string.cpp", + "string_help.cpp", ] if (enable_ts_utest && !use_wasm) { cflags = [ diff --git a/host/trace_streamer/src/base/args_set.h b/host/trace_streamer/src/base/args_set.h index 9a506be0534bbff7af525d1c498001c95ac5f640..6148fd25be100805820643594e7a5a9bfc27174b 100644 --- a/host/trace_streamer/src/base/args_set.h +++ b/host/trace_streamer/src/base/args_set.h @@ -28,6 +28,9 @@ public: ArgsSet& operator=(const ArgsSet& other) { this->valuesMap_ = other.valuesMap_; + this->argSetId_ = other.argSetId_; + this->sliceId_ = other.sliceId_; + this->inserted_ = other.inserted_; return *this; } void AppendArg(DataIndex dataIndex, BaseDataType datatype, uint64_t value) @@ -38,6 +41,9 @@ public: valuesMap_.emplace(dataIndex, data); } std::map valuesMap_; + uint32_t argSetId_ = 0; + uint32_t sliceId_ = 0; + bool inserted_ = false; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/base/codec_cov.cpp b/host/trace_streamer/src/base/codec_cov.cpp old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/base/double_map.h b/host/trace_streamer/src/base/double_map.h index 921a10c484e645b1ca5c79488aeeb27268b4afca..70a8a2252422a620cf540dbe0b66ebee6af247b2 100644 --- a/host/trace_streamer/src/base/double_map.h +++ b/host/trace_streamer/src/base/double_map.h @@ -60,6 +60,14 @@ public: return invalidValue_; } } + const std::map* Find(T1 t1) const + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + return &streamIdHookidMap->second; + } + return nullptr; + } void Erase(T1 t1) { auto streamIdHookidMap = internalMap_.find(t1); @@ -77,6 +85,14 @@ public: } } } + bool Empty() + { + return internalMap_.size() == 0 ? true : false; + } + void Clear() + { + internalMap_.clear(); + } private: std::map> internalMap_; diff --git a/host/trace_streamer/src/base/file.cpp b/host/trace_streamer/src/base/file.cpp index 1d8bd187e7ce47d97caee6f59db4956cd8c9c3b3..4c6b3e65f59d0feb5a7890128c5f844a27a52f26 100644 --- a/host/trace_streamer/src/base/file.cpp +++ b/host/trace_streamer/src/base/file.cpp @@ -73,8 +73,7 @@ std::string GetExecutionDirectoryPath() readlink("/proc/self/exe", currPath, sizeof(currPath) - 1); #endif std::string str(currPath); - str = str.substr(0, str.find_last_of('/')); - return str; + return str.substr(0, str.find_last_of('/')); } } // namespace base } // namespace SysTuning diff --git a/host/trace_streamer/src/base/log.cpp b/host/trace_streamer/src/base/log.cpp index 7a751c899f3153b7fa520bd4e1e89eaec591a078..7d167a90cb4f5f1678b59e23518ddce9873b89d1 100644 --- a/host/trace_streamer/src/base/log.cpp +++ b/host/trace_streamer/src/base/log.cpp @@ -14,9 +14,4 @@ */ #include "log.h" - -// namespace SysTuning { -// namespace base { bool g_cleanMode = false; -// } // namespace base -// } // namespace SysTuning diff --git a/host/trace_streamer/src/base/meta.cpp b/host/trace_streamer/src/base/meta.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aecc2191ea3e801d38152cd714f11ca2c3b08cbf --- /dev/null +++ b/host/trace_streamer/src/base/meta.cpp @@ -0,0 +1,18 @@ +/* + * 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. + */ +#include "meta.h" +size_t g_loadSize = 0; +std::string TRACE_STREAM_VERSION = "2.6.141"; // version +std::string TRACE_STREAM_PUBLISHVERSION = "2023/2/1"; // publish datetime diff --git a/host/trace_streamer/src/base/meta.h b/host/trace_streamer/src/base/meta.h new file mode 100644 index 0000000000000000000000000000000000000000..a7558554ea8e55a4363f08dc195aa1aaa1da745b --- /dev/null +++ b/host/trace_streamer/src/base/meta.h @@ -0,0 +1,23 @@ +/* + * 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. + */ + +#ifndef META_H +#define META_H +#include +#include +extern size_t g_loadSize; +extern std::string TRACE_STREAM_VERSION; // version +extern std::string TRACE_STREAM_PUBLISHVERSION; // publish datetime +#endif diff --git a/host/trace_streamer/src/base/parting_string.cpp b/host/trace_streamer/src/base/parting_string.cpp old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/base/quatra_map.h b/host/trace_streamer/src/base/quatra_map.h new file mode 100644 index 0000000000000000000000000000000000000000..df344bd08bf91b71c2d5be8f86921b0c058068a4 --- /dev/null +++ b/host/trace_streamer/src/base/quatra_map.h @@ -0,0 +1,90 @@ +/* + * 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. + */ + +#ifndef SRC_TRACE_BASE_QUATRAMAP_H +#define SRC_TRACE_BASE_QUATRAMAP_H + +#include "triple_map.h" + +template +class QuatraMap { +public: + QuatraMap(T5 invalidValue) + { + invalidValue_ = invalidValue; + } + void SetInvalidRet(T5 invalidValue) + { + invalidValue_ = invalidValue; + } + void Insert(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Insert(t2, t3, t4, t5); + } else { + TripleMap mm(invalidValue_); + mm.Insert(t2, t3, t4, t5); + internalMap_.insert(std::make_pair(t1, mm)); + } + } + T5 Find(T1 t1, T2 t2, T3 t3, T4 t4) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + return (*streamIdHookidMap).second.Find(t2, t3, t4); + } else { + return invalidValue_; + } + } + void Erase(T1 t1) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + internalMap_.erase(streamIdHookidMap); + } + } + void Erase(T1 t1, T2 t2) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2); + } + } + void Erase(T1 t1, T2 t2, T3 t3) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2, t3); + } + } + void Erase(T1 t1, T2 t2, T3 t3, T4 t4) + { + auto streamIdHookidMap = internalMap_.find(t1); + if (streamIdHookidMap != internalMap_.end()) { + (*streamIdHookidMap).second.Erase(t2, t3, t4); + } + } + void Clear() + { + internalMap_.clear(); + } + +private: + std::map> internalMap_; + T5 invalidValue_; +}; + +#endif // SRC_TRACE_BASE_QUATRAMAP_H diff --git a/host/trace_streamer/src/base/string_help.cpp b/host/trace_streamer/src/base/string_help.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce13b6461c7246e845700b2e01dc5654b0e8ce80 --- /dev/null +++ b/host/trace_streamer/src/base/string_help.cpp @@ -0,0 +1,81 @@ +/* + * 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. + */ +#include "string_help.h" +#include +#include +#include +#include +namespace SysTuning { +namespace base { +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) +int memcpy_s(void* dest, uint32_t destSize, const void* src, size_t srcSize) +{ + if (srcSize > destSize || src == nullptr || dest == nullptr) { + return -1; + } else { + if (!memcpy(dest, src, srcSize)) { + printf("memcpy fail\n"); + return -1; + } + } + return 0; +} +#if !is_mingw +int sscanf_s(const char* buffer, const char* format, ...) +{ + va_list ap; + __builtin_va_start(ap, format); + int ret = scanf(buffer, format, ap); + __builtin_va_end(ap); + return ret; +} + +int strncpy_s(char* strDest, size_t destMax, const char* strSrc, size_t count) +{ + return memcpy_s(strDest, destMax, strSrc, count); +} +#endif +void* memset_s(void* dest, size_t destSize, int ch, size_t n) +{ + UNUSED(destSize); + UNUSED(ch); + return memset(dest, 0, n); +} + +int snprintf_s(char* strDest, size_t destMax, size_t count, const char* format, ...) +{ + UNUSED(count); + int ret; + va_list ap; + __builtin_va_start(ap, format); + ret = vsnprintf(strDest, destMax, format, ap); + __builtin_va_end(ap); + return ret; +} + +int sprintf_s(char* strDest, size_t destMax, const char* format, ...) +{ + UNUSED(destMax); + va_list ap; + __builtin_va_start(ap, format); + int ret = sprintf(strDest, format, ap); + __builtin_va_end(ap); + return ret; +} +} // namespace base +} // namespace SysTuning diff --git a/host/trace_streamer/src/base/string_help.h b/host/trace_streamer/src/base/string_help.h new file mode 100644 index 0000000000000000000000000000000000000000..09323834a7d6d092860e1012e5c1ddbc892b147f --- /dev/null +++ b/host/trace_streamer/src/base/string_help.h @@ -0,0 +1,32 @@ +/* + * 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. + */ +#ifndef SRC_TRACE_BASE_STRINGHELP_H +#define SRC_TRACE_BASE_STRINGHELP_H + +#include +#include +namespace SysTuning { +namespace base { +#if !is_mingw +int memcpy_s(void* dest, uint32_t destSize, const void* src, size_t srcSize); +int sscanf_s(const char* buffer, const char* format, ...); +int strncpy_s(char* strDest, size_t destMax, const char* strSrc, size_t count); +#endif +void* memset_s(void* dest, size_t destSize, int ch, size_t n); +int snprintf_s(char* strDest, size_t destMax, size_t count, const char* format, ...); +int sprintf_s(char* strDest, size_t destMax, const char* format, ...); +} // namespace base +} // namespace SysTuning +#endif // SRC_TRACE_BASE_STRINGHELP_H diff --git a/host/trace_streamer/src/base/triple_map.h b/host/trace_streamer/src/base/triple_map.h index c856d73223a0cccd8c622c9a300368107f3c35fe..b9c30f8402fa067e3ae1f3bb9644c2f622a5ae06 100644 --- a/host/trace_streamer/src/base/triple_map.h +++ b/host/trace_streamer/src/base/triple_map.h @@ -70,6 +70,10 @@ public: (*streamIdHookidMap).second.Erase(t2, t3); } } + void Clear() + { + internalMap_.clear(); + } private: std::map> internalMap_; diff --git a/host/trace_streamer/src/base/ts_common.h b/host/trace_streamer/src/base/ts_common.h index 57ada7286e98a2074d96da60135f7a432e62426c..434088c78d21b48391fd3cc5bca160c0523ce1a7 100644 --- a/host/trace_streamer/src/base/ts_common.h +++ b/host/trace_streamer/src/base/ts_common.h @@ -25,13 +25,17 @@ const uint64_t INVALID_UTID = std::numeric_limits::max(); const uint64_t INVALID_UINT64 = std::numeric_limits::max(); const uint64_t MAX_UINT32 = std::numeric_limits::max(); const uint64_t MAX_UINT64 = std::numeric_limits::max(); +const uint32_t INVALID_UINT16 = std::numeric_limits::max(); const uint32_t INVALID_UINT32 = std::numeric_limits::max(); const uint32_t INVALID_INT32 = std::numeric_limits::max(); +const int64_t INVALID_INT64 = std::numeric_limits::max(); const uint64_t INVALID_DATAINDEX = std::numeric_limits::max(); const size_t MAX_SIZE_T = std::numeric_limits::max(); const uint32_t INVALID_ID = std::numeric_limits::max(); const uint64_t SEC_TO_NS = 1000 * 1000 * 1000; const int STR_DEFAULT_LEN = -1; +const auto INVALID_CPU = INVALID_UINT32; +const auto INVALID_TIME = INVALID_UINT64; enum BuiltinClocks { TS_CLOCK_UNKNOW = 0, TS_CLOCK_BOOTTIME = 1, @@ -98,12 +102,26 @@ enum SchedWakeType { SCHED_WAKING = 0, // sched_waking SCHED_WAKEUP = 1, // sched_wakeup }; +enum DataSourceType { + DATA_SOURCE_TYPE_TRACE, + DATA_SOURCE_TYPE_MEM, + DATA_SOURCE_TYPE_HILOG, + DATA_SOURCE_TYPE_ALLOCATION, + DATA_SOURCE_TYPE_FPS, + DATA_SOURCE_TYPE_NETWORK, + DATA_SOURCE_TYPE_DISKIO, + DATA_SOURCE_TYPE_CPU, + DATA_SOURCE_TYPE_PROCESS, + DATA_SOURCE_TYPE_HISYSEVENT, + DATA_SOURCE_TYPE_HISYSEVENT_CONFIG +}; using DataIndex = uint64_t; -using TableRowId = uint64_t; +using TableRowId = int32_t; using InternalPid = uint32_t; using InternalTid = uint32_t; using InternalTime = uint64_t; using FilterId = uint32_t; +using InternalCpu = uint32_t; // how many cpus? could change to int8_t? enum BaseDataType { BASE_DATA_TYPE_INT, diff --git a/host/trace_streamer/src/cfg/trace_streamer_config.cpp b/host/trace_streamer/src/cfg/trace_streamer_config.cpp old mode 100644 new mode 100755 index e72cf60d218d31458c62c45f2f6dea8548cccd6b..80e9689fc3c8be2ad78fd8855f23341ef395823f --- a/host/trace_streamer/src/cfg/trace_streamer_config.cpp +++ b/host/trace_streamer/src/cfg/trace_streamer_config.cpp @@ -89,6 +89,12 @@ void TraceStreamerConfig::PrintInfo() const } printf("\n"); } + +uint32_t TraceStreamerConfig::GetStateValue(uint32_t state) const +{ + return (state > CPU_IDEL_INVALID_VALUE ? 0 : (state + 1)); +} + void TraceStreamerConfig::InitEventNameMap() { eventNameMap_ = {{TRACE_EVENT_BINDER_TRANSACTION, TRACE_ACTION_BINDER_TRANSACTION}, @@ -106,6 +112,7 @@ void TraceStreamerConfig::InitEventNameMap() {TRACE_EVENT_SCHED_WAKING, TRACE_ACTION_SCHED_WAKING}, {TRACE_EVENT_CPU_IDLE, TRACE_ACTION_CPU_IDLE}, {TRACE_EVENT_CPU_FREQUENCY, TRACE_ACTION_CPU_FREQUENCY}, + {TRACE_EVENT_CPU_FREQUENCY_LIMITS, TRACE_ACTION_CPU_FREQUENCY_LIMITS}, {TRACE_EVENT_SUSPEND_RESUME, TRACE_ACTION_SUSPEND_RESUME}, {TRACE_EVENT_WORKQUEUE_EXECUTE_START, TRACE_ACTION_WORKQUEUE_EXECUTE_START}, {TRACE_EVENT_WORKQUEUE_EXECUTE_END, TRACE_ACTION_WORKQUEUE_EXECUTE_END}, @@ -133,9 +140,6 @@ void TraceStreamerConfig::InitEventNameMap() {TRACE_EVENT_PROCESS_EXIT, TRACE_ACTION_PROCESS_EXIT}, {TRACE_EVENT_PROCESS_FREE, TRACE_ACTION_PROCESS_FREE}, {TRACE_EVENT_CLOCK_SYNC, TRACE_ACTION_CLOCK_SYNC}, - {TRACE_MEMORY, TRACE_ACTION_MEMORY}, - {TRACE_SYS_MEMORY, TRACE_ACTION_SYS_MEMORY}, - {TRACE_SYS_VIRTUAL_MEMORY, TRACE_ACTION_SYS_VIRTUAL_MEMORY}, {TRACE_EVENT_SIGNAL_GENERATE, TRACE_ACTION_SIGNAL_GENERATE}, {TRACE_EVENT_SIGNAL_DELIVER, TRACE_ACTION_SIGNAL_DELIVER}, {TRACE_EVENT_BLOCK_BIO_BACKMERGE, TRACE_ACTION_BLOCK_BIO_BACKMERGE}, @@ -152,49 +156,64 @@ void TraceStreamerConfig::InitEventNameMap() {TRACE_EVENT_BLOCK_RQ_REMAP, TRACE_ACTION_BLOCK_RQ_REMAP}, {TRACE_EVENT_BLOCK_RQ_ISSUE, TRACE_ACTION_BLOCK_RQ_ISSUE}, {TRACE_EVENT_OTHER, TRACE_ACTION_OTHER}, + {TRACE_MEMORY, TRACE_ACTION_MEMORY}, + {TRACE_SYS_MEMORY, TRACE_ACTION_SYS_MEMORY}, + {TRACE_SYS_VIRTUAL_MEMORY, TRACE_ACTION_SYS_VIRTUAL_MEMORY}, + {TRACE_DISKIO, TRACE_ACTION_DISKIO}, + {TRACE_PROCESS, TRACE_ACTION_PROCESS}, + {TRACE_CPU_USAGE, TRACE_ACTION_CPU_USAGE}, + {TRACE_NETWORK, TRACE_ACTION_NETWORK}, + {TRACE_PERF, TRACE_ACTION_PERF}, {TRACE_HILOG, TRACE_ACTION_HILOG}, {TRACE_HIDUMP_FPS, TRACE_ACTION_HIDUMP_FPS}, {TRACE_NATIVE_HOOK_MALLOC, TRACE_ACTION_NATIVE_HOOK_MALLOC}, - {TRACE_NATIVE_HOOK_FREE, TRACE_ACTION_NATIVE_HOOK_FREE}}; + {TRACE_NATIVE_HOOK_FREE, TRACE_ACTION_NATIVE_HOOK_FREE}, + {TRACE_NATIVE_HOOK_MMAP, TRACE_ACTION_NATIVE_HOOK_MMAP}, + {TRACE_HISYSEVENT, TRACE_ACTION_HISYS_EVENT}, + {TRACE_SMAPS, TRACE_ACTION_SMAPS}, + {TRACE_NATIVE_HOOK_MUNMAP, TRACE_ACTION_NATIVE_HOOK_MUNMAP}, + {TRACE_EVENT_EBPF, TRACE_ACTION_EBPF}, + {TRACE_EVENT_EBPF_FILE_SYSTEM, TRACE_ACTION_EBPF_FILE_SYSTEM}, + {TRACE_EVENT_EBPF_PAGED_MEMORY, TRACE_ACTION_EBPF_PAGED_MEMORY}, + {TRACE_EVENT_EBPF_BIO_LATENCY, TRACE_ACTION_EBPF_BIO_LATENCY}}; } void TraceStreamerConfig::InitSysMemMap() { - sysMemNameMap_ = { - {SysMeminfoType::PMEM_UNSPECIFIED, SYS_MEMINFO_UNSPECIFIED_DESC}, - {SysMeminfoType::PMEM_MEM_TOTAL, SYS_MEMINFO_MEM_TOTAL_DESC}, - {SysMeminfoType::PMEM_MEM_FREE, SYS_MEMINFO_MEM_FREE_DESC}, - {SysMeminfoType::PMEM_MEM_AVAILABLE, SYS_MEMINFO_MEM_AVAILABLE_DESC}, - {SysMeminfoType::PMEM_BUFFERS, SYS_MEMINFO_BUFFERS_DESC}, - {SysMeminfoType::PMEM_CACHED, SYS_MEMINFO_CACHED_DESC}, - {SysMeminfoType::PMEM_SWAP_CACHED, SYS_MEMINFO_SWAP_CACHED_DESC}, - {SysMeminfoType::PMEM_ACTIVE, SYS_MEMINFO_ACTIVE_DESC}, - {SysMeminfoType::PMEM_INACTIVE, SYS_MEMINFO_INACTIVE_DESC}, - {SysMeminfoType::PMEM_ACTIVE_ANON, SYS_MEMINFO_ACTIVE_ANON_DESC}, - {SysMeminfoType::PMEM_INACTIVE_ANON, SYS_MEMINFO_INACTIVE_ANON_DESC}, - {SysMeminfoType::PMEM_ACTIVE_FILE, SYS_MEMINFO_ACTIVE_FILE_DESC}, - {SysMeminfoType::PMEM_INACTIVE_FILE, SYS_MEMINFO_INACTIVE_FILE_DESC}, - {SysMeminfoType::PMEM_UNEVICTABLE, SYS_MEMINFO_UNEVICTABLE_DESC}, - {SysMeminfoType::PMEM_MLOCKED, SYS_MEMINFO_MLOCKED_DESC}, - {SysMeminfoType::PMEM_SWAP_TOTAL, SYS_MEMINFO_SWAP_TOTAL_DESC}, - {SysMeminfoType::PMEM_SWAP_FREE, SYS_MEMINFO_SWAP_FREE_DESC}, - {SysMeminfoType::PMEM_DIRTY, SYS_MEMINFO_DIRTY_DESC}, - {SysMeminfoType::PMEM_WRITEBACK, SYS_MEMINFO_WRITEBACK_DESC}, - {SysMeminfoType::PMEM_ANON_PAGES, SYS_MEMINFO_ANON_PAGES_DESC}, - {SysMeminfoType::PMEM_MAPPED, SYS_MEMINFO_MAPPED_DESC}, - {SysMeminfoType::PMEM_SHMEM, SYS_MEMINFO_SHMEM_DESC}, - {SysMeminfoType::PMEM_SLAB, SYS_MEMINFO_SLAB_DESC}, - {SysMeminfoType::PMEM_SLAB_RECLAIMABLE, SYS_MEMINFO_SLAB_RECLAIMABLE_DESC}, - {SysMeminfoType::PMEM_SLAB_UNRECLAIMABLE, SYS_MEMINFO_SLAB_UNRECLAIMABLE_DESC}, - {SysMeminfoType::PMEM_KERNEL_STACK, SYS_MEMINFO_KERNEL_STACK_DESC}, - {SysMeminfoType::PMEM_PAGE_TABLES, SYS_MEMINFO_PAGE_TABLES_DESC}, - {SysMeminfoType::PMEM_COMMIT_LIMIT, SYS_MEMINFO_COMMIT_LIMIT_DESC}, - {SysMeminfoType::PMEM_COMMITED_AS, SYS_MEMINFO_COMMITED_AS_DESC}, - {SysMeminfoType::PMEM_VMALLOC_TOTAL, SYS_MEMINFO_VMALLOC_TOTAL_DESC}, - {SysMeminfoType::PMEM_VMALLOC_USED, SYS_MEMINFO_VMALLOC_USED_DESC}, - {SysMeminfoType::PMEM_VMALLOC_CHUNK, SYS_MEMINFO_VMALLOC_CHUNK_DESC}, - {SysMeminfoType::PMEM_CMA_TOTAL, SYS_MEMINFO_CMA_TOTAL_DESC}, - {SysMeminfoType::PMEM_CMA_FREE, SYS_MEMINFO_CMA_FREE_DESC}, - }; + sysMemNameMap_ = {{SysMeminfoType::PMEM_UNSPECIFIED, SYS_MEMINFO_UNSPECIFIED_DESC}, + {SysMeminfoType::PMEM_MEM_TOTAL, SYS_MEMINFO_MEM_TOTAL_DESC}, + {SysMeminfoType::PMEM_MEM_FREE, SYS_MEMINFO_MEM_FREE_DESC}, + {SysMeminfoType::PMEM_MEM_AVAILABLE, SYS_MEMINFO_MEM_AVAILABLE_DESC}, + {SysMeminfoType::PMEM_BUFFERS, SYS_MEMINFO_BUFFERS_DESC}, + {SysMeminfoType::PMEM_CACHED, SYS_MEMINFO_CACHED_DESC}, + {SysMeminfoType::PMEM_SWAP_CACHED, SYS_MEMINFO_SWAP_CACHED_DESC}, + {SysMeminfoType::PMEM_ACTIVE, SYS_MEMINFO_ACTIVE_DESC}, + {SysMeminfoType::PMEM_INACTIVE, SYS_MEMINFO_INACTIVE_DESC}, + {SysMeminfoType::PMEM_ACTIVE_ANON, SYS_MEMINFO_ACTIVE_ANON_DESC}, + {SysMeminfoType::PMEM_INACTIVE_ANON, SYS_MEMINFO_INACTIVE_ANON_DESC}, + {SysMeminfoType::PMEM_ACTIVE_FILE, SYS_MEMINFO_ACTIVE_FILE_DESC}, + {SysMeminfoType::PMEM_INACTIVE_FILE, SYS_MEMINFO_INACTIVE_FILE_DESC}, + {SysMeminfoType::PMEM_UNEVICTABLE, SYS_MEMINFO_UNEVICTABLE_DESC}, + {SysMeminfoType::PMEM_MLOCKED, SYS_MEMINFO_MLOCKED_DESC}, + {SysMeminfoType::PMEM_SWAP_TOTAL, SYS_MEMINFO_SWAP_TOTAL_DESC}, + {SysMeminfoType::PMEM_SWAP_FREE, SYS_MEMINFO_SWAP_FREE_DESC}, + {SysMeminfoType::PMEM_DIRTY, SYS_MEMINFO_DIRTY_DESC}, + {SysMeminfoType::PMEM_WRITEBACK, SYS_MEMINFO_WRITEBACK_DESC}, + {SysMeminfoType::PMEM_ANON_PAGES, SYS_MEMINFO_ANON_PAGES_DESC}, + {SysMeminfoType::PMEM_MAPPED, SYS_MEMINFO_MAPPED_DESC}, + {SysMeminfoType::PMEM_SHMEM, SYS_MEMINFO_SHMEM_DESC}, + {SysMeminfoType::PMEM_SLAB, SYS_MEMINFO_SLAB_DESC}, + {SysMeminfoType::PMEM_SLAB_RECLAIMABLE, SYS_MEMINFO_SLAB_RECLAIMABLE_DESC}, + {SysMeminfoType::PMEM_SLAB_UNRECLAIMABLE, SYS_MEMINFO_SLAB_UNRECLAIMABLE_DESC}, + {SysMeminfoType::PMEM_KERNEL_STACK, SYS_MEMINFO_KERNEL_STACK_DESC}, + {SysMeminfoType::PMEM_PAGE_TABLES, SYS_MEMINFO_PAGE_TABLES_DESC}, + {SysMeminfoType::PMEM_COMMIT_LIMIT, SYS_MEMINFO_COMMIT_LIMIT_DESC}, + {SysMeminfoType::PMEM_COMMITED_AS, SYS_MEMINFO_COMMITED_AS_DESC}, + {SysMeminfoType::PMEM_VMALLOC_TOTAL, SYS_MEMINFO_VMALLOC_TOTAL_DESC}, + {SysMeminfoType::PMEM_VMALLOC_USED, SYS_MEMINFO_VMALLOC_USED_DESC}, + {SysMeminfoType::PMEM_VMALLOC_CHUNK, SYS_MEMINFO_VMALLOC_CHUNK_DESC}, + {SysMeminfoType::PMEM_CMA_TOTAL, SYS_MEMINFO_CMA_TOTAL_DESC}, + {SysMeminfoType::PMEM_CMA_FREE, SYS_MEMINFO_CMA_FREE_DESC}, + {SysMeminfoType::PMEM_KERNEL_RECLAIMABLE, SYS_MEMINFO_KERNEL_RECLAIMABLE_DESC}}; } void TraceStreamerConfig::InitSysVmemMap() @@ -483,6 +502,16 @@ void TraceStreamerConfig::InitSecurityMap() {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, }, }, + { + TRACE_EVENT_CPU_FREQUENCY_LIMITS, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, { TRACE_EVENT_SUSPEND_RESUME, { @@ -803,6 +832,26 @@ void TraceStreamerConfig::InitSecurityMap() {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, }, }, + { + TRACE_NATIVE_HOOK_MMAP, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_NATIVE_HOOK_MUNMAP, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, { TRACE_SYS_MEMORY, { @@ -823,6 +872,56 @@ void TraceStreamerConfig::InitSecurityMap() {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, }, }, + { + TRACE_DISKIO, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_PROCESS, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_CPU_USAGE, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_NETWORK, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_PERF, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, { TRACE_EVENT_SIGNAL_GENERATE, { @@ -973,6 +1072,66 @@ void TraceStreamerConfig::InitSecurityMap() {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, }, }, + { + TRACE_EVENT_EBPF, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_EBPF_FILE_SYSTEM, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_EBPF_PAGED_MEMORY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_EVENT_EBPF_BIO_LATENCY, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_HISYSEVENT, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, + { + TRACE_SMAPS, + { + {STAT_EVENT_RECEIVED, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_DATA_LOST, STAT_SEVERITY_LEVEL_ERROR}, + {STAT_EVENT_NOTMATCH, STAT_SEVERITY_LEVEL_INFO}, + {STAT_EVENT_NOTSUPPORTED, STAT_SEVERITY_LEVEL_WARN}, + {STAT_EVENT_DATA_INVALID, STAT_SEVERITY_LEVEL_ERROR}, + }, + }, { TRACE_EVENT_OTHER, { diff --git a/host/trace_streamer/src/cfg/trace_streamer_config.h b/host/trace_streamer/src/cfg/trace_streamer_config.h old mode 100644 new mode 100755 index 3e71a1a1f669c5ad8910b2867bf04c0e54df2fbf..0bc7bc05551810acda47a56ca1cbbfb0f8b7d2e4 --- a/host/trace_streamer/src/cfg/trace_streamer_config.h +++ b/host/trace_streamer/src/cfg/trace_streamer_config.h @@ -18,9 +18,12 @@ #include #include #include "memory_plugin_common.pb.h" +#include "ts_common.h" namespace SysTuning { namespace TraceCfg { // all supported events should be defined here +#define CPU_IDEL_INVALID_KEY 4294967295 +#define CPU_IDEL_INVALID_VALUE 4 enum SupportedTraceEventType { TRACE_EVENT_START = 0, TRACE_EVENT_BINDER_TRANSACTION = TRACE_EVENT_START, @@ -38,6 +41,7 @@ enum SupportedTraceEventType { TRACE_EVENT_SCHED_WAKING, TRACE_EVENT_CPU_IDLE, TRACE_EVENT_CPU_FREQUENCY, + TRACE_EVENT_CPU_FREQUENCY_LIMITS, TRACE_EVENT_SUSPEND_RESUME, TRACE_EVENT_WORKQUEUE_EXECUTE_START, TRACE_EVENT_WORKQUEUE_EXECUTE_END, @@ -65,13 +69,6 @@ enum SupportedTraceEventType { TRACE_EVENT_PROCESS_EXIT, TRACE_EVENT_PROCESS_FREE, TRACE_EVENT_CLOCK_SYNC, - TRACE_MEMORY, - TRACE_HILOG, - TRACE_HIDUMP_FPS, - TRACE_NATIVE_HOOK_MALLOC, - TRACE_NATIVE_HOOK_FREE, - TRACE_SYS_MEMORY, - TRACE_SYS_VIRTUAL_MEMORY, TRACE_EVENT_SIGNAL_GENERATE, TRACE_EVENT_SIGNAL_DELIVER, TRACE_EVENT_BLOCK_BIO_BACKMERGE, @@ -87,6 +84,26 @@ enum SupportedTraceEventType { TRACE_EVENT_BLOCK_RQ_INSERT, TRACE_EVENT_BLOCK_RQ_REMAP, TRACE_EVENT_BLOCK_RQ_ISSUE, + TRACE_MEMORY, + TRACE_HILOG, + TRACE_HIDUMP_FPS, + TRACE_NATIVE_HOOK_MALLOC, + TRACE_NATIVE_HOOK_FREE, + TRACE_NATIVE_HOOK_MMAP, + TRACE_NATIVE_HOOK_MUNMAP, + TRACE_SYS_MEMORY, + TRACE_SYS_VIRTUAL_MEMORY, + TRACE_DISKIO, + TRACE_PROCESS, + TRACE_CPU_USAGE, + TRACE_NETWORK, + TRACE_PERF, + TRACE_EVENT_EBPF, + TRACE_EVENT_EBPF_FILE_SYSTEM, + TRACE_EVENT_EBPF_PAGED_MEMORY, + TRACE_EVENT_EBPF_BIO_LATENCY, + TRACE_HISYSEVENT, + TRACE_SMAPS, TRACE_EVENT_OTHER, TRACE_EVENT_MAX }; @@ -142,7 +159,7 @@ public: TraceStreamerConfig(); ~TraceStreamerConfig() = default; void PrintInfo() const; - + uint32_t GetStateValue(uint32_t state) const; public: std::map eventNameMap_ = {}; std::map eventErrorDescMap_ = {}; @@ -156,7 +173,6 @@ public: std::map sysMemNameMap_ = {}; // sys virtual memorty info desc std::map sysVirtualMemNameMap_ = {}; - private: void InitEventNameMap(); void InitSysMemMap(); @@ -174,6 +190,7 @@ private: const std::string TRACE_ACTION_SCHED_WAKING = "sched_waking"; const std::string TRACE_ACTION_CPU_IDLE = "cpu_idle"; const std::string TRACE_ACTION_CPU_FREQUENCY = "cpu_frequency"; + const std::string TRACE_ACTION_CPU_FREQUENCY_LIMITS = "cpu_frequency_limits"; const std::string TRACE_ACTION_SUSPEND_RESUME = "suspend_resume"; const std::string TRACE_ACTION_WORKQUEUE_EXECUTE_START = "workqueue_execute_start"; const std::string TRACE_ACTION_WORKQUEUE_EXECUTE_END = "workqueue_execute_end"; @@ -211,6 +228,8 @@ private: const std::string TRACE_ACTION_HIDUMP_FPS = "hidump_fps"; const std::string TRACE_ACTION_NATIVE_HOOK_MALLOC = "native_hook_malloc"; const std::string TRACE_ACTION_NATIVE_HOOK_FREE = "native_hook_free"; + const std::string TRACE_ACTION_NATIVE_HOOK_MMAP = "native_hook_mmap"; + const std::string TRACE_ACTION_NATIVE_HOOK_MUNMAP = "native_hook_munmap"; const std::string TRACE_ACTION_SIGNAL_GENERATE = "signal_generate"; const std::string TRACE_ACTION_SIGNAL_DELIVER = "signal_deliver"; const std::string TRACE_ACTION_BLOCK_BIO_BACKMERGE = "trace_block_bio_backmerge"; @@ -229,6 +248,17 @@ private: const std::string TRACE_ACTION_SYS_MEMORY = "sys_memory"; const std::string TRACE_ACTION_SYS_VIRTUAL_MEMORY = "sys_virtual_memory"; + const std::string TRACE_ACTION_DISKIO = "trace_diskio"; + const std::string TRACE_ACTION_PROCESS = "trace_process"; + const std::string TRACE_ACTION_CPU_USAGE = "trace_cpu_usage"; + const std::string TRACE_ACTION_NETWORK = "trace_network"; + const std::string TRACE_ACTION_PERF = "trace_perf"; + const std::string TRACE_ACTION_EBPF = "trace_ebpf"; + const std::string TRACE_ACTION_EBPF_FILE_SYSTEM = "trace_ebpf_file_system"; + const std::string TRACE_ACTION_EBPF_PAGED_MEMORY = "trace_ebpf_paged_memory"; + const std::string TRACE_ACTION_EBPF_BIO_LATENCY = "trace_ebpf_bio_latency"; + const std::string TRACE_ACTION_HISYS_EVENT = "trace_hisys_event"; + const std::string TRACE_ACTION_SMAPS = "trace_smaps"; const std::string TRACE_ACTION_OTHER = "other"; const std::string MEM_INFO_VM_SIZE_DESC = "mem.vm.size"; @@ -276,6 +306,7 @@ private: const std::string SYS_MEMINFO_VMALLOC_CHUNK_DESC = "sys.mem.vmalloc.chunk"; const std::string SYS_MEMINFO_CMA_TOTAL_DESC = "sys.mem.cma.total"; const std::string SYS_MEMINFO_CMA_FREE_DESC = "sys.mem.cma.free"; + const std::string SYS_MEMINFO_KERNEL_RECLAIMABLE_DESC = "sys.mem.kernel.reclaimable"; const std::string SYS_VMEMINFO_UNSPECIFIED_DESC = "sys.virtual.mem.unspecified"; const std::string SYS_VMEMINFO_NR_FREE_PAGES_DESC = "sys.virtual.mem.nr.free.pages"; const std::string SYS_VMEMINFO_NR_ALLOC_BATCH_DESC = "sys.virtual.mem.nr.alloc.batch"; diff --git a/host/trace_streamer/src/ext/BUILD.gn b/host/trace_streamer/src/ext/BUILD.gn index 09643024743e6ad5e9a3aa9cb7d33317d975534d..0099b5d862f83ed29c1503173721c389b019af94 100644 --- a/host/trace_streamer/src/ext/BUILD.gn +++ b/host/trace_streamer/src/ext/BUILD.gn @@ -17,7 +17,10 @@ config("sqlite_config") { "../../third_party/sqlite/include", "../include", ] - cflags = [ "-Wno-writable-strings" ] + cflags = [ + "-Wno-writable-strings", + "-std=c++17", + ] } source_set("sqliteext") { sources = [ "sqlite_ext_funcs.cpp" ] diff --git a/host/trace_streamer/src/ext/sqlite_ext_funcs.cpp b/host/trace_streamer/src/ext/sqlite_ext_funcs.cpp index 680e61e625ebd95022bf552d6a88a255f345e76d..c23e78c20cb96210f19d4c168aa189e58501b56b 100644 --- a/host/trace_streamer/src/ext/sqlite_ext_funcs.cpp +++ b/host/trace_streamer/src/ext/sqlite_ext_funcs.cpp @@ -14,8 +14,13 @@ */ #include "sqlite_ext_funcs.h" #include +#include +#include #include "log.h" #include "sqlite3.h" +#include "../base/string_help.h" +namespace SysTuning { +namespace base { /* ** Return a stdev value */ @@ -47,8 +52,312 @@ static void sqliteExtStdevNextStep(sqlite3_context* context, int argc, sqlite3_v } } -void CreateExtendFunction(sqlite3* db) +enum Type { + TS_NULL = 0, + TS_LONG, + TS_DOUBLE, + TS_STRING, + TS_BYTES, +}; + +struct TSSqlValue { + TSSqlValue() = default; + + static TSSqlValue Long(int64_t v) + { + TSSqlValue value; + value.longValue = v; + value.type = Type::TS_LONG; + return value; + } + + static TSSqlValue Double(double v) + { + TSSqlValue value; + value.doubleValue = v; + value.type = Type::TS_DOUBLE; + return value; + } + + static TSSqlValue String(const char* v) + { + TSSqlValue value; + value.stringValue = v; + value.type = Type::TS_STRING; + return value; + } + + static TSSqlValue Bytes(const char* v, size_t size) + { + TSSqlValue value; + value.bytesValue = v; + value.bytesCount = size; + value.type = Type::TS_BYTES; + return value; + } + + double GetDouble() const + { + return doubleValue; + } + int64_t GetLong() const + { + return longValue; + } + const char* GetString() const + { + return stringValue; + } + const void* GetBytes() const + { + return bytesValue; + } + + bool IsNull() const + { + return type == Type::TS_NULL; + } + + union { + const char* stringValue; + int64_t longValue; + double doubleValue; + const void* bytesValue; + }; + size_t bytesCount = 0; + Type type = TS_NULL; +}; + +TSSqlValue SqliteValueToTSSqlValue(sqlite3_value* value) { - sqlite3_create_function(db, "stdev", 1, SQLITE_UTF8, nullptr, 0, sqliteExtStdevNextStep, - sqliteExtStdevFinalize); -} \ No newline at end of file + TSSqlValue sqlValue; + switch (sqlite3_value_type(value)) { + case SQLITE_INTEGER: + sqlValue.type = Type::TS_LONG; + sqlValue.longValue = sqlite3_value_int64(value); + break; + case SQLITE_FLOAT: + sqlValue.type = Type::TS_DOUBLE; + sqlValue.doubleValue = sqlite3_value_double(value); + break; + case SQLITE_TEXT: + sqlValue.type = Type::TS_STRING; + sqlValue.stringValue = reinterpret_cast(sqlite3_value_text(value)); + break; + case SQLITE_BLOB: + sqlValue.type = Type::TS_BYTES; + sqlValue.bytesValue = sqlite3_value_blob(value); + sqlValue.bytesCount = static_cast(sqlite3_value_bytes(value)); + break; + } + return sqlValue; +} +class JsonBuild { +public: + JsonBuild() = default; + void AppendHead() + { + body_ += "{"; + } + void AppendTail() + { + body_ += "}"; + } + void AppendCommon() + { + body_ += ","; + } + bool AppendSqlValue(const std::string& field_name, const TSSqlValue& value) + { + body_ += "\"" + field_name + "\":"; + return AppendSqlValue(value); + } + bool AppendSqlValue(const TSSqlValue& value) + { + switch (value.type) { + case TS_LONG: + body_ += std::to_string(value.longValue) + ","; + break; + case TS_DOUBLE: + body_ += std::to_string(value.doubleValue) + ","; + break; + case TS_STRING: + body_ += "\"" + std::string(value.stringValue) + "\"" + ","; + break; + case TS_BYTES: + body_ += "\"" + std::string(static_cast(value.bytesValue), value.bytesCount) + "\"" + ","; + break; + case TS_NULL: + body_ += std::to_string(0) + ","; + break; + } + return true; + } + std::string body_; + bool poped_ = false; + void PopLast() + { + body_.pop_back(); + } + const std::string& Body() + { + return body_; + } +}; + +void BuildJson(sqlite3_context* ctx, int argc, sqlite3_value** argv) +{ + const int PAIR_ARGS_SIZE = 2; + if (argc % PAIR_ARGS_SIZE != 0) { + TS_LOGI("BuildJson arg number error"); + sqlite3_result_error(ctx, "BuildJson arg number error", -1); + return; + } + + JsonBuild builder; + builder.AppendHead(); + for (int i = 0; i < argc; i += PAIR_ARGS_SIZE) { + if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) { + TS_LOGI("BuildJson: Invalid args argc:%d, %d", argc, sqlite3_value_type(argv[i])); + sqlite3_result_error(ctx, "BuildJson: Invalid args", -1); + return; + } + + auto* key = reinterpret_cast(sqlite3_value_text(argv[i])); + auto value = SqliteValueToTSSqlValue(argv[i + 1]); + auto status = builder.AppendSqlValue(key, value); + if (!status) { + TS_LOGI("AppendSqlValueError"); + sqlite3_result_error(ctx, "AppendSqlValueError", -1); + return; + } + } + builder.PopLast(); + builder.AppendTail(); + std::string raw = builder.Body(); + if (raw.empty()) { + sqlite3_result_blob(ctx, "", 0, nullptr); + return; + } + std::unique_ptr data = std::make_unique(raw.size()); + memcpy_s(data.get(), raw.size(), raw.data(), raw.size()); + sqlite3_result_blob(ctx, data.release(), static_cast(raw.size()), free); +} + +void RepeatedJsonStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) +{ + const int PAIR_ARGS_SIZE = 2; + auto** jsonBuild = static_cast(sqlite3_aggregate_context(ctx, sizeof(JsonBuild*))); + + if (*jsonBuild == nullptr) { + *jsonBuild = new JsonBuild(); + } + JsonBuild* builder = *jsonBuild; + builder->AppendHead(); + for (int i = 0; i < argc; i += PAIR_ARGS_SIZE) { + if (sqlite3_value_type(argv[i]) != SQLITE_TEXT) { + TS_LOGI("BuildJson: Invalid args argc:%d, %d", argc, sqlite3_value_type(argv[i])); + sqlite3_result_error(ctx, "BuildJson: Invalid args", -1); + return; + } + + auto* key = reinterpret_cast(sqlite3_value_text(argv[i])); + auto value = SqliteValueToTSSqlValue(argv[i + 1]); + auto status = builder->AppendSqlValue(key, value); + if (!status) { + TS_LOGI("AppendSqlValueError"); + sqlite3_result_error(ctx, "AppendSqlValueError", -1); + return; + } + } + builder->PopLast(); + builder->AppendTail(); + builder->AppendCommon(); +} +void RepeatedFieldStep(sqlite3_context* ctx, int argc, sqlite3_value** argv) +{ + if (argc != 1) { + TS_LOGE( + "RepeatedField only support one arg, you can use BuildJson or BuildRepeatedJson function for multi args"); + return; + } + auto** jsonBuild = static_cast(sqlite3_aggregate_context(ctx, sizeof(JsonBuild*))); + + if (*jsonBuild == nullptr) { + *jsonBuild = new JsonBuild(); + } + JsonBuild* builder = *jsonBuild; + for (int i = 0; i < argc; i++) { + auto value = SqliteValueToTSSqlValue(argv[i]); + auto status = builder->AppendSqlValue(value); + if (!status) { + sqlite3_result_error(ctx, "error", -1); + } + } +} + +void RepeatedFieldFinal(sqlite3_context* ctx) +{ + auto** jsonBuilder = static_cast(sqlite3_aggregate_context(ctx, 0)); + + if (jsonBuilder == nullptr) { + sqlite3_result_null(ctx); + return; + } + + std::unique_ptr builder(*jsonBuilder); + std::string raw = builder->Body(); + raw.pop_back(); + if (raw.empty()) { + sqlite3_result_null(ctx); + return; + } + + std::unique_ptr data = std::make_unique(raw.size()); + memcpy_s(data.get(), raw.size(), raw.data(), raw.size()); + sqlite3_result_blob(ctx, data.release(), static_cast(raw.size()), free); +} + +void RepeatedJsonFinal(sqlite3_context* ctx) +{ + auto** jsonBuilder = static_cast(sqlite3_aggregate_context(ctx, 0)); + + if (jsonBuilder == nullptr) { + sqlite3_result_null(ctx); + return; + } + + std::unique_ptr builder(*jsonBuilder); + builder->PopLast(); + std::string raw = builder->Body(); + if (raw.empty()) { + sqlite3_result_null(ctx); + return; + } + + std::unique_ptr data = std::make_unique(raw.size()); + memcpy_s(data.get(), raw.size(),raw.data(), raw.size()); + sqlite3_result_blob(ctx, data.release(), static_cast(raw.size()), free); +} +void ts_create_extend_function(sqlite3* db) +{ + sqlite3_create_function(db, "stdev", -1, SQLITE_UTF8, nullptr, 0, sqliteExtStdevNextStep, sqliteExtStdevFinalize); + auto ret = sqlite3_create_function_v2(db, "RepeatedField", 1, SQLITE_UTF8, nullptr, nullptr, RepeatedFieldStep, + RepeatedFieldFinal, nullptr); + if (ret) { + TS_LOGF("Error while initializing RepeatedField"); + } + ret = sqlite3_create_function_v2(db, "BuildRepeatedJson", -1, SQLITE_UTF8, nullptr, nullptr, RepeatedJsonStep, + RepeatedJsonFinal, nullptr); + if (ret) { + TS_LOGF("Error while initializing BuildRepeatedJson"); + } + std::unique_ptr ctx = std::make_unique(); + ret = sqlite3_create_function_v2(db, "BuildJson", -1, SQLITE_UTF8, ctx.release(), BuildJson, nullptr, nullptr, + [](void* ptr) { delete static_cast(ptr); }); + if (ret != SQLITE_OK) { + TS_LOGF("Error while initializing BuildJson"); + } +} +} // namespace base +} // namespace SysTuning \ No newline at end of file diff --git a/host/trace_streamer/src/ext/sqlite_ext_funcs.h b/host/trace_streamer/src/ext/sqlite_ext_funcs.h index b75925f45b8234e7a7c6c5770e202196e0ce5ca2..e1ce74a727d69a10d177682f38f54ac943c0687c 100644 --- a/host/trace_streamer/src/ext/sqlite_ext_funcs.h +++ b/host/trace_streamer/src/ext/sqlite_ext_funcs.h @@ -16,12 +16,15 @@ #define SQLITE_EXT_FUNCS_H 1 #include #include "sqlite3.h" - +namespace SysTuning { +namespace base { typedef struct StdevCtx StdevCtx; struct StdevCtx { double rMValue; double rSValue; int64_t cntValue; }; -void CreateExtendFunction(sqlite3* db); +void ts_create_extend_function(sqlite3* db); +} // namespace base +} // namespace SysTuning #endif diff --git a/host/trace_streamer/src/filter/BUILD.gn b/host/trace_streamer/src/filter/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..7360facae3f50a6264fc81ca1ea038f205c18c54 --- /dev/null +++ b/host/trace_streamer/src/filter/BUILD.gn @@ -0,0 +1,81 @@ +# 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("//build/ohos.gni") +import("//src/ts.gni") + +ohos_source_set("filter") { + sources = [ + "args_filter.cpp", + "args_filter.h", + "binder_filter.cpp", + "binder_filter.h", + "clock_filter.cpp", + "clock_filter.h", + "cpu_filter.cpp", + "filter_base.cpp", + "filter_base.h", + "filter_filter.cpp", + "filter_filter.h", + "hi_sysevent_measure_filter.cpp", + "hi_sysevent_measure_filter.h", + "irq_filter.cpp", + "irq_filter.h", + "measure_filter.cpp", + "measure_filter.h", + "process_filter.cpp", + "process_filter.h", + "slice_filter.cpp", + "slice_filter.h", + "stat_filter.cpp", + "stat_filter.h", + "symbols_filter.cpp", + "symbols_filter.h", + "system_event_measure_filter.cpp", + "system_event_measure_filter.h", + ] + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + if (is_test) { + cflags += [ "-D IS_UT" ] + } + } + deps = [] + include_dirs = [ + "//src/base", + "//src/trace_streamer", + "//src/trace_data", + "//src/include", + "//src/filter", + "//src/cfg", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "//src", + "//third_party/protobuf/src", + "//third_party/sqlite/include", + ".", + ] + if (with_perf) { + sources += [ + "perf_data_filter.cpp", + "perf_data_filter.h", + ] + } +} diff --git a/host/trace_streamer/src/filter/binder_filter.cpp b/host/trace_streamer/src/filter/binder_filter.cpp index b13ad8edea336e800a48b66de7adfefd88222d7a..dd4250dbf440c14d113abd269925e09219d1d10d 100644 --- a/host/trace_streamer/src/filter/binder_filter.cpp +++ b/host/trace_streamer/src/filter/binder_filter.cpp @@ -51,22 +51,6 @@ std::string BinderFilter::GetBinderFlagsDesc(uint32_t flag) } return str; } -void BinderFilter::MaybeDealEvent() -{ - if (tsBinderEventQueue_.size() > MAX_CACHE_SIZE) { - DealEvent(tsBinderEventQueue_.begin()->second.get()); - tsBinderEventQueue_.erase(tsBinderEventQueue_.begin()); - } -} - -void BinderFilter::FinishBinderEvent() -{ - for (auto it = tsBinderEventQueue_.begin(); it != tsBinderEventQueue_.end(); it++) { - DealEvent(it->second.get()); - } - tsBinderEventQueue_.clear(); -} - void BinderFilter::SendTraction(int64_t ts, uint32_t tid, uint64_t transactionId, @@ -76,108 +60,6 @@ void BinderFilter::SendTraction(int64_t ts, bool isReply, int32_t flags, int32_t code) -{ - auto sendTractionEvent = std::make_unique(ts, tid, transactionId, destNode, - destTgid, destTid, isReply, flags, code); - auto binderEvent = std::make_unique(); - binderEvent->type_ = TS_EVENT_BINDER_SEND; - binderEvent->senderBinderEvent_ = std::move(sendTractionEvent); - tsBinderEventQueue_.insert(std::make_pair(ts, std::move(binderEvent))); - MaybeDealEvent(); -} -void BinderFilter::ReceiveTraction(int64_t ts, uint32_t pid, uint64_t transactionId) -{ - auto receiveTractionEvent = std::make_unique(ts, pid, transactionId); - auto binderEvent = std::make_unique(); - binderEvent->type_ = TS_EVENT_BINDER_RECIVED; - binderEvent->receivedBinderEvent_ = std::move(receiveTractionEvent); - tsBinderEventQueue_.insert(std::make_pair(ts, - std::move(binderEvent))); - MaybeDealEvent(); -} -void BinderFilter::TransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize) -{ - auto tractionAllocBufEvent = std::make_unique(ts, pid, dataSize, offsetsSize); - auto binderEvent = std::make_unique(); - binderEvent->type_ = TS_EVENT_BINDER_ALLOC_BUF; - binderEvent->binderAllocBufEvent_ = std::move(tractionAllocBufEvent); - tsBinderEventQueue_.insert(std::make_pair(ts, - std::move(binderEvent))); - MaybeDealEvent(); -} -void BinderFilter::TractionLock(int64_t ts, uint32_t pid, const std::string& tag) -{ - auto tractionLockEvent = std::make_unique(ts, pid, tag); - auto binderEvent = std::make_unique(); - binderEvent->type_ = TS_EVENT_BINDER_LOCK; - binderEvent->binderLockEvent_ = std::move(tractionLockEvent); - tsBinderEventQueue_.insert(std::make_pair(ts, - std::move(binderEvent))); - MaybeDealEvent(); -} -void BinderFilter::TractionLocked(int64_t ts, uint32_t pid, const std::string& tag) -{ - auto tractionLockedEvent = std::make_unique(ts, pid, tag); - auto binderEvent = std::make_unique(); - binderEvent->type_ = TS_EVENT_BINDER_LOCKED; - binderEvent->binderLockedEvent_ = std::move(tractionLockedEvent); - tsBinderEventQueue_.insert(std::make_pair(ts, - std::move(binderEvent))); - MaybeDealEvent(); -} -void BinderFilter::TractionUnlock(int64_t ts, uint32_t pid, const std::string& tag) -{ - auto tractionUnlockEvent = std::make_unique(ts, pid, tag); - auto binderEvent = std::make_unique(); - binderEvent->type_ = TS_EVENT_BINDER_UNLOCK; - binderEvent->binderUnlockEvent_ = std::move(tractionUnlockEvent); - tsBinderEventQueue_.insert(std::make_pair(ts, - std::move(binderEvent))); - MaybeDealEvent(); -} -void BinderFilter::DealEvent(const TSBinderEvent* event) -{ - switch (static_cast(event->type_)) { - case TS_EVENT_BINDER_SEND: - ExecSendTraction(event->senderBinderEvent_->ts_, event->senderBinderEvent_->tid_, - event->senderBinderEvent_->transactionId_, event->senderBinderEvent_->destNode_, - event->senderBinderEvent_->destTgid_, event->senderBinderEvent_->destTid_, - event->senderBinderEvent_->isReply_, event->senderBinderEvent_->flags_, - event->senderBinderEvent_->code_); - break; - case TS_EVENT_BINDER_RECIVED: - ExecReceiveTraction(event->receivedBinderEvent_->ts_, event->receivedBinderEvent_->pid_, - event->receivedBinderEvent_->transactionId_); - break; - case TS_EVENT_BINDER_ALLOC_BUF: - ExecTransactionAllocBuf(event->binderAllocBufEvent_->ts_, event->binderAllocBufEvent_->pid_, - event->binderAllocBufEvent_->dataSize_, event->binderAllocBufEvent_->offsetsSize_); - break; - case TS_EVENT_BINDER_LOCK: - ExecTractionLock(event->binderLockEvent_->ts_, event->binderLockEvent_->pid_, - event->binderLockEvent_->tag_); - break; - case TS_EVENT_BINDER_LOCKED: - ExecTractionLocked(event->binderLockedEvent_->ts_, event->binderLockedEvent_->pid_, - event->binderLockedEvent_->tag_); - break; - case TS_EVENT_BINDER_UNLOCK: - ExecTractionUnlock(event->binderUnlockEvent_->ts_, event->binderUnlockEvent_->pid_, - event->binderUnlockEvent_->tag_); - break; - default: - break; - } -} -void BinderFilter::ExecSendTraction(int64_t ts, - uint32_t tid, - uint64_t transactionId, - int32_t destNode, - int32_t destTgid, - int32_t destTid, - bool isReply, - int32_t flags, - int32_t code) { auto flagsStr = traceDataCache_->GetDataIndex("0x" + base::number(flags, base::INTEGER_RADIX_TYPE_HEX) + GetBinderFlagsDesc(flags)); @@ -193,12 +75,19 @@ void BinderFilter::ExecSendTraction(int64_t ts, argsSend.AppendArg(callingTid_, BASE_DATA_TYPE_INT, tid); if (isReply) { - // Add dest information to Reply slices, the Begin msg is from TAG-2 - InternalTid dstItid = streamFilters_->processFilter_->UpdateOrCreateThread(ts, destTid); - const auto destThreadName = traceDataCache_->GetConstThreadData(dstItid).nameIndex_; - argsSend.AppendArg(destThreadId_, BASE_DATA_TYPE_INT, destTid); - argsSend.AppendArg(destThreadNameId_, BASE_DATA_TYPE_STRING, destThreadName); - streamFilters_->sliceFilter_->EndBinder(ts, tid, nullStringId_, nullStringId_, argsSend); + // sometime a reply-binder from a tid appear repeated to different dest, we only chose the right one + if (transReplyFilter_.count(tid) && transReplyFilter_[tid] == destTid) { + // Add dest information to Reply slices, the Begin msg is from TAG-2 + InternalTid dstItid = streamFilters_->processFilter_->UpdateOrCreateThread(ts, destTid); + const auto destThreadName = traceDataCache_->GetConstThreadData(dstItid).nameIndex_; + ArgsSet destArgs; + destArgs.AppendArg(destThreadId_, BASE_DATA_TYPE_INT, destTid); + destArgs.AppendArg(destThreadNameId_, BASE_DATA_TYPE_STRING, destThreadName); + streamFilters_->sliceFilter_->AddArgs(tid, binderCatalogId_, replyId_, destArgs); + transReplyFilter_.erase(tid); + } + // the flowing code should be under the ubove conditions, but this will bring a big impact to the UI-SHOW + streamFilters_->sliceFilter_->EndBinder(ts, tid, INVALID_UINT64, INVALID_UINT64, argsSend); transReplyWaitingReply_.insert(transactionId); return; } else { @@ -206,15 +95,17 @@ void BinderFilter::ExecSendTraction(int64_t ts, if (needReply) { // transaction needs reply TAG-1 streamFilters_->sliceFilter_->BeginBinder(ts, tid, binderCatalogId_, transSliceId_, argsSend); - transWaitingRcv_[transactionId] = tid; + transNeedReply_[transactionId] = tid; } else { - // transaction not need reply - streamFilters_->sliceFilter_->BeginAsyncBinder(ts, tid, binderCatalogId_, transAsyncId_, argsSend); - transNoNeedReply_[transactionId] = argsSend; + // transaction do not need reply + // tid calling id + // a binder event only care the transactionId and the callint tid + streamFilters_->sliceFilter_->AsyncBinder(ts, tid, binderCatalogId_, transAsyncId_, argsSend); + asyncBinderEvents_[transactionId] = argsSend; } } } -void BinderFilter::ExecReceiveTraction(int64_t ts, uint32_t pid, uint64_t transactionId) +void BinderFilter::ReceiveTraction(int64_t ts, uint32_t pid, uint64_t transactionId) { InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(ts, pid); const auto threadName = traceDataCache_->GetConstThreadData(internalTid).nameIndex_; @@ -224,9 +115,10 @@ void BinderFilter::ExecReceiveTraction(int64_t ts, uint32_t pid, uint64_t transa return; } - if (transWaitingRcv_.count(transactionId)) { + if (transNeedReply_.count(transactionId)) { // First, begin the reply, the reply will be end in "SendTraction" func, and the isReply will be true, TAG-2 auto replySliceid = streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, replyId_); + transReplyFilter_[pid] = transNeedReply_[transactionId]; // Add dest info to the reply ArgsSet args; args.AppendArg(destThreadId_, BASE_DATA_TYPE_INT, pid); @@ -235,28 +127,32 @@ void BinderFilter::ExecReceiveTraction(int64_t ts, uint32_t pid, uint64_t transa args.AppendArg(destSliceId_, BASE_DATA_TYPE_INT, replySliceid); } // Add dest args - auto transSliceId = streamFilters_->sliceFilter_->AddArgs(transWaitingRcv_[transactionId], binderCatalogId_, + uint64_t transSliceId = INVALID_UINT64; + uint32_t argSetId = INVALID_UINT32; + std::tie(transSliceId, argSetId) = streamFilters_->sliceFilter_->AddArgs(transNeedReply_[transactionId], binderCatalogId_, transSliceId_, args); - // remeber dest slice-id to the argset form "SendTraction" TAG-1 + // remeber dest slice-id to the argset from "SendTraction" TAG-1 ArgsSet replyDestInserter; if (IsValidUint32(transSliceId)) { replyDestInserter.AppendArg(destSliceId_, BASE_DATA_TYPE_INT, transSliceId); } - streamFilters_->sliceFilter_->AddArgs(pid, binderCatalogId_, replyId_, replyDestInserter); - transWaitingRcv_.erase(transactionId); + std::tie(transSliceId, argSetId) = streamFilters_->sliceFilter_->AddArgs(pid, binderCatalogId_, replyId_, replyDestInserter); + traceDataCache_->GetInternalSlicesData()->SetArgSetId(transSliceId, argSetId); + transNeedReply_.erase(transactionId); return; } // the code below can be hard to understand, may be a EndBinder will be better - // this problem cna be test after the IDE is finished - if (transNoNeedReply_.count(transactionId)) { - auto args = transNoNeedReply_[transactionId]; - streamFilters_->sliceFilter_->BeginAsyncBinder(ts, pid, binderCatalogId_, asyncRcvId_, args); - transNoNeedReply_.erase(transactionId); + // this problem can be test after the IDE is finished + if (asyncBinderEvents_.count(transactionId)) { + auto args = asyncBinderEvents_[transactionId]; + streamFilters_->sliceFilter_->AsyncBinder(ts, pid, binderCatalogId_, asyncRcvId_, args); + // maybe you can use the flowing code: streamFilters_->sliceFilter_->EndBinder(ts, pid); + asyncBinderEvents_.erase(transactionId); return; } } -void BinderFilter::ExecTransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize) +void BinderFilter::TransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize) { ArgsSet args; args.AppendArg(dataSizeId_, BASE_DATA_TYPE_INT, dataSize); @@ -264,13 +160,15 @@ void BinderFilter::ExecTransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t da streamFilters_->sliceFilter_->AddArgs(pid, binderCatalogId_, transSliceId_, args); UNUSED(ts); } -void BinderFilter::ExecTractionLock(int64_t ts, uint32_t pid, const std::string& tag) +void BinderFilter::TractionLock(int64_t ts, uint32_t pid, const std::string& tag) { + UNUSED(tag); lastEventTs_[pid] = ts; streamFilters_->sliceFilter_->BeginBinder(ts, pid, binderCatalogId_, lockTryId_); } -void BinderFilter::ExecTractionLocked(int64_t ts, uint32_t pid, const std::string& tag) +void BinderFilter::TractionLocked(int64_t ts, uint32_t pid, const std::string& tag) { + UNUSED(tag); if (!lastEventTs_.count(pid)) { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_LOCKED, STAT_EVENT_NOTMATCH); return; @@ -280,15 +178,24 @@ void BinderFilter::ExecTractionLocked(int64_t ts, uint32_t pid, const std::strin lastEventTs_.erase(pid); lastEventTs_[pid] = ts; } -void BinderFilter::ExecTractionUnlock(int64_t ts, uint32_t pid, const std::string& tag) +void BinderFilter::TractionUnlock(int64_t ts, uint32_t pid, const std::string& tag) { + UNUSED(tag); if (!lastEventTs_.count(pid)) { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, STAT_EVENT_NOTMATCH); return; } - streamFilters_->sliceFilter_->EndBinder(ts, pid); + streamFilters_->sliceFilter_->EndBinder(ts, pid, binderCatalogId_, lockHoldId_); lastEventTs_.erase(pid); lastEventTs_[pid] = ts; } +void BinderFilter::Clear() +{ + lastEventTs_.clear(); + transReplyWaitingReply_.clear(); + transNeedReply_.clear(); + asyncBinderEvents_.clear(); + binderFlagDescs_.clear(); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/binder_filter.h b/host/trace_streamer/src/filter/binder_filter.h index 183338494d511467e6d7cd10076746af57ae281d..59e2d6e399302cada36757ceaa6e1fda23c9938f 100644 --- a/host/trace_streamer/src/filter/binder_filter.h +++ b/host/trace_streamer/src/filter/binder_filter.h @@ -45,113 +45,8 @@ public: void TractionLock(int64_t ts, uint32_t pid, const std::string& tag); void TractionLocked(int64_t ts, uint32_t pid, const std::string& tag); void TractionUnlock(int64_t ts, uint32_t pid, const std::string& tag); - void FinishBinderEvent(); - + void Clear(); private: - void MaybeDealEvent(); - - class TSSendTractionEvent { - public: - TSSendTractionEvent(int64_t ts, - uint32_t tid, - uint64_t transactionId, - int32_t destNode, - int32_t destTgid, - int32_t destTid, - bool isReply, - int32_t flags, - int32_t code) - : ts_(ts), - tid_(tid), - transactionId_(transactionId), - destNode_(destNode), - destTgid_(destTgid), - destTid_(destTid), - isReply_(isReply), - flags_(flags), - code_(code) - { - } - ~TSSendTractionEvent() {} - int64_t ts_; - uint32_t tid_; - uint64_t transactionId_; - int32_t destNode_; - int32_t destTgid_; - int32_t destTid_; - bool isReply_; - int32_t flags_; - int32_t code_; - }; - class TSReceiveTractionEvent { - public: - TSReceiveTractionEvent(int64_t ts, uint32_t pid, uint64_t transactionId) - : ts_(ts), pid_(pid), transactionId_(transactionId) - { - } - ~TSReceiveTractionEvent() {} - uint64_t ts_; - uint32_t pid_; - uint64_t transactionId_; - }; - class TSTractionLockEvent { - public: - TSTractionLockEvent(int64_t ts, uint32_t pid, const std::string& tag) : ts_(ts), pid_(pid), tag_(tag) {} - ~TSTractionLockEvent() {} - uint64_t ts_; - uint32_t pid_; - const std::string tag_; - }; - class TSTransactionAllocBufEvent { - public: - TSTransactionAllocBufEvent(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize) - : ts_(ts), pid_(pid), dataSize_(dataSize), offsetsSize_(offsetsSize) - { - } - ~TSTransactionAllocBufEvent() {} - uint64_t ts_; - uint32_t pid_; - uint64_t dataSize_; - uint64_t offsetsSize_; - }; - enum TSBinderEventType { - TS_EVENT_BINDER_SEND, - TS_EVENT_BINDER_RECIVED, - TS_EVENT_BINDER_ALLOC_BUF, - TS_EVENT_BINDER_LOCK, - TS_EVENT_BINDER_LOCKED, - TS_EVENT_BINDER_UNLOCK - }; - class TSBinderEvent { - public: - TSBinderEvent() {} - ~TSBinderEvent() {} - TSBinderEventType type_; - // us union below will be a good choice - // but union with unique_ptr can bring about runtime error on windows and mac,only work well on linux - std::unique_ptr senderBinderEvent_ = {}; - std::unique_ptr receivedBinderEvent_ = {}; - std::unique_ptr binderAllocBufEvent_ = {}; - std::unique_ptr binderLockEvent_ = {}; - std::unique_ptr binderLockedEvent_ = {}; - std::unique_ptr binderUnlockEvent_ = {}; - }; - void DealEvent(const TSBinderEvent* event); - - void ExecSendTraction(int64_t ts, - uint32_t tid, - uint64_t transactionId, - int32_t destNode, - int32_t destTgid, - int32_t destTid, - bool isReply, - int32_t flags, - int32_t code); - void ExecReceiveTraction(int64_t ts, uint32_t pid, uint64_t transactionId); - void ExecTransactionAllocBuf(int64_t ts, uint32_t pid, uint64_t dataSize, uint64_t offsetsSize); - void ExecTractionLock(int64_t ts, uint32_t pid, const std::string& tag); - void ExecTractionLocked(int64_t ts, uint32_t pid, const std::string& tag); - void ExecTractionUnlock(int64_t ts, uint32_t pid, const std::string& tag); std::string GetBinderFlagsDesc(uint32_t flag); bool IsValidUint32(uint32_t value) const { @@ -162,36 +57,32 @@ private: uint32_t statusCodeMsgFlag_ = 0x08; uint32_t acceptFdsMsgFlag_ = 0x10; uint32_t noFlagsMsgFlag_ = 0; - DataIndex binderCatalogId_ = traceDataCache_->GetDataIndex("binder"); - DataIndex replyId_ = traceDataCache_->GetDataIndex("binder reply"); - DataIndex isReplayId_ = traceDataCache_->GetDataIndex("reply transaction?"); - DataIndex flagsId_ = traceDataCache_->GetDataIndex("flags"); - DataIndex transSliceId_ = traceDataCache_->GetDataIndex("binder transaction"); - DataIndex transId_ = traceDataCache_->GetDataIndex("transaction id"); - DataIndex asyncRcvId_ = traceDataCache_->GetDataIndex("binder async rcv"); - DataIndex codeId_ = traceDataCache_->GetDataIndex("code"); - DataIndex callingTid_ = traceDataCache_->GetDataIndex("calling tid"); - DataIndex destNodeId_ = traceDataCache_->GetDataIndex("destination node"); - DataIndex destThreadId_ = traceDataCache_->GetDataIndex("destination thread"); - DataIndex destThreadNameId_ = traceDataCache_->GetDataIndex("destination name"); - DataIndex destSliceId_ = traceDataCache_->GetDataIndex("destination slice id"); - DataIndex destProcessId_ = traceDataCache_->GetDataIndex("destination process"); - DataIndex transAsyncId_ = traceDataCache_->GetDataIndex("binder transaction async"); - DataIndex lockTryId_ = traceDataCache_->GetDataIndex("binder lock waiting"); - DataIndex lockHoldId_ = traceDataCache_->GetDataIndex("binder lock held"); - DataIndex dataSizeId_ = traceDataCache_->GetDataIndex("data size"); - DataIndex dataOffsetSizeId_ = traceDataCache_->GetDataIndex("offsets size"); - DataIndex nullStringId_ = traceDataCache_->GetDataIndex("null"); + const DataIndex binderCatalogId_ = traceDataCache_->GetDataIndex("binder"); + const DataIndex replyId_ = traceDataCache_->GetDataIndex("binder reply"); + const DataIndex isReplayId_ = traceDataCache_->GetDataIndex("reply transaction?"); + const DataIndex flagsId_ = traceDataCache_->GetDataIndex("flags"); + const DataIndex transSliceId_ = traceDataCache_->GetDataIndex("binder transaction"); + const DataIndex transId_ = traceDataCache_->GetDataIndex("transaction id"); + const DataIndex asyncRcvId_ = traceDataCache_->GetDataIndex("binder async rcv"); + const DataIndex codeId_ = traceDataCache_->GetDataIndex("code"); + const DataIndex callingTid_ = traceDataCache_->GetDataIndex("calling tid"); + const DataIndex destNodeId_ = traceDataCache_->GetDataIndex("destination node"); + const DataIndex destThreadId_ = traceDataCache_->GetDataIndex("destination thread"); + const DataIndex destThreadNameId_ = traceDataCache_->GetDataIndex("destination name"); + const DataIndex destSliceId_ = traceDataCache_->GetDataIndex("destination slice id"); + const DataIndex destProcessId_ = traceDataCache_->GetDataIndex("destination process"); + const DataIndex transAsyncId_ = traceDataCache_->GetDataIndex("binder transaction async"); + const DataIndex lockTryId_ = traceDataCache_->GetDataIndex("binder lock waiting"); + const DataIndex lockHoldId_ = traceDataCache_->GetDataIndex("binder lock held"); + const DataIndex dataSizeId_ = traceDataCache_->GetDataIndex("data size"); + const DataIndex dataOffsetSizeId_ = traceDataCache_->GetDataIndex("offsets size"); + const DataIndex nullStringId_ = traceDataCache_->GetDataIndex("null"); std::unordered_map lastEventTs_ = {}; std::unordered_set transReplyWaitingReply_ = {}; - std::unordered_map transWaitingRcv_ = {}; - std::unordered_map transNoNeedReply_ = {}; + std::unordered_map transNeedReply_ = {}; + std::unordered_map transReplyFilter_ = {}; + std::unordered_map asyncBinderEvents_ = {}; std::unordered_map binderFlagDescs_ = {}; - std::multimap> tsBinderEventQueue_; - // timestamp of ftrace events from different cpu can be outof order - // keep a cache of ftrace events in memory and keep msg in order - // the value below is the count of msg, maybe you can change it - const size_t MAX_CACHE_SIZE = 10000; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/clock_filter.cpp b/host/trace_streamer/src/filter/clock_filter.cpp index 392bae50f27a479286229b3d1459d67d879d6127..1bffae39b59cc3facda88fcdbf3a3d5ef7e80e4f 100644 --- a/host/trace_streamer/src/filter/clock_filter.cpp +++ b/host/trace_streamer/src/filter/clock_filter.cpp @@ -20,13 +20,13 @@ namespace SysTuning { namespace TraceStreamer { ClockFilter::ClockFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) - : FilterBase(dataCache, filter), primaryClock_(BuiltinClocks::TS_CLOCK_BOOTTIME) + : FilterBase(dataCache, filter), primaryClock_(BuiltinClocks::TS_CLOCK_BOOTTIME), dataCache_(dataCache) { } ClockFilter::~ClockFilter() {} -std::string ClockFilter::GenClockKey(ClockId srcClockId, ClockId desClockId) const +std::string ClockFilter::GenClockKey(ClockId srcClockId, ClockId desClockId) { std::string ret; ret += std::to_string(srcClockId); @@ -78,17 +78,26 @@ void ClockFilter::AddConvertClockMap(ClockId srcClockId, ClockId dstClockId, uin void ClockFilter::AddClockSnapshot(const std::vector& snapShot) { ClockId srcId, desId; - for (srcId = 0; srcId < snapShot.size() - 1; srcId++) { - for (desId = srcId + 1; desId < snapShot.size(); desId++) { - ClockId srcClockId = snapShot[srcId].clockId; + const int theDataBeforeLast = 2; + for (srcId = 0; srcId < snapShot.size() - 1; ++srcId) { + ClockId srcClockId = snapShot[srcId].clockId; + uint64_t srcTs = snapShot[srcId].ts; + traceDataCache_->GetClockSnapshotData()->AppendNewSnapshot( + srcClockId, srcTs, + dataCache_->GetConstStatAndInfo().clockid2ClockNameMap_.at(static_cast(srcClockId))); + for (desId = srcId + 1; desId < snapShot.size(); ++desId) { ClockId desClockId = snapShot[desId].clockId; - uint64_t srcTs = snapShot[srcId].ts; uint64_t desTs = snapShot[desId].ts; - + if ((srcId == snapShot.size() - theDataBeforeLast) and (desId == snapShot.size() - 1)) { + traceDataCache_->GetClockSnapshotData()->AppendNewSnapshot( + desClockId, desTs, + dataCache_->GetConstStatAndInfo().clockid2ClockNameMap_.at(static_cast(desClockId))); + } AddConvertClockMap(srcClockId, desClockId, srcTs, desTs); AddConvertClockMap(desClockId, srcClockId, desTs, srcTs); } } + hasInitSnapShot_ = true; } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/clock_filter.h b/host/trace_streamer/src/filter/clock_filter.h old mode 100644 new mode 100755 index 6d8e29db686a76fc0d45e8e75048c224da7851a3..69a743afc0a7c7dec537bf624f2fa919f1bf87e9 --- a/host/trace_streamer/src/filter/clock_filter.h +++ b/host/trace_streamer/src/filter/clock_filter.h @@ -58,18 +58,28 @@ public: { primaryClock_ = primary; } + ClockId GetPrimaryClock() const + { + return primaryClock_; + } uint64_t ToPrimaryTraceTime(ClockId srcClockId, uint64_t srcTs) const; uint64_t Convert(ClockId srcClockId, uint64_t srcTs, ClockId desClockId) const; void AddClockSnapshot(const std::vector& snapShot); + bool HasInitSnapShot() const + { + return hasInitSnapShot_; + } private: - std::string GenClockKey(ClockId srcClockId, ClockId desClockId) const; + static std::string GenClockKey(ClockId srcClockId, ClockId desClockId); void AddConvertClockMap(ClockId srcClockId, ClockId dstClockId, uint64_t srcTs, uint64_t dstTs); private: std::unordered_map clockMaps_ = {}; ClockId primaryClock_; + bool hasInitSnapShot_ = false; + TraceDataCache* dataCache_; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/cpu_filter.cpp b/host/trace_streamer/src/filter/cpu_filter.cpp old mode 100644 new mode 100755 index 8ce228345836a20d9669d0721a9aac8695de6d62..e2b1e5a988819191a22ce11cdfe5c06741640c26 --- a/host/trace_streamer/src/filter/cpu_filter.cpp +++ b/host/trace_streamer/src/filter/cpu_filter.cpp @@ -14,6 +14,7 @@ */ #include "cpu_filter.h" +#include "process_filter.h" namespace SysTuning { namespace TraceStreamer { @@ -26,99 +27,6 @@ void CpuFilter::InsertSwitchEvent(uint64_t ts, uint64_t prevState, uint64_t nextPid, uint64_t nextPior) -{ - auto switchEvent = std::make_unique(ts, cpu, prevPid, prevPior, prevState, nextPid, nextPior); - auto cpuEvent = std::make_unique(); - cpuEvent->type_ = TS_EVENT_THREAD_SWITCH; - cpuEvent->switchEvent_ = std::move(switchEvent); - tsCpuEventQueue_.insert(std::make_pair(ts, std::move(cpuEvent))); - MaybeDealEvent(); -} -bool CpuFilter::InsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid) -{ - auto processExitEvent = std::make_unique(ts, cpu, pid); - auto cpuEvent = std::make_unique(); - cpuEvent->type_ = TS_EVENT_PROCESS_EXIT; - cpuEvent->processExitEvent_ = std::move(processExitEvent); - tsCpuEventQueue_.insert(std::make_pair(ts, - std::move(cpuEvent))); - MaybeDealEvent(); - return true; -} - -bool CpuFilter::InsertProcessFreeEvent(uint64_t ts, uint64_t pid) -{ - auto processExitEvent = std::make_unique(ts, 0, pid); - auto cpuEvent = std::make_unique(); - cpuEvent->type_ = TS_EVENT_PROCESS_FREE; - cpuEvent->processExitEvent_ = std::move(processExitEvent); - tsCpuEventQueue_.insert(std::make_pair(ts, - std::move(cpuEvent))); - MaybeDealEvent(); - return true; -} -void CpuFilter::InsertWakeupEvent(uint64_t ts, uint64_t internalTid) -{ - auto wakeupEvent = std::make_unique(TSWakeupEvent(ts, internalTid)); - auto cpuEvent = std::make_unique(); - cpuEvent->type_ = TS_EVENT_THREAD_WAKING; - cpuEvent->wakeupEvent_ = std::move(wakeupEvent); - tsCpuEventQueue_.insert(std::make_pair(ts, - std::move(cpuEvent))); - MaybeDealEvent(); -} -uint64_t CpuFilter::RemberInternalTidInStateTable(uint64_t uid, uint64_t row, uint64_t state) -{ - if (internalTidToRowThreadState_.find(uid) != internalTidToRowThreadState_.end()) { - internalTidToRowThreadState_.at(uid) = TPthread{row, state}; - } else { - internalTidToRowThreadState_.insert(std::make_pair(uid, TPthread{row, state})); - } - return 0; -} - -void CpuFilter::MaybeDealEvent() -{ - if (tsCpuEventQueue_.size() > MAX_CACHE_SIZE) { - DealEvent(tsCpuEventQueue_.begin()->second.get()); - tsCpuEventQueue_.erase(tsCpuEventQueue_.begin()); - } -} - -void CpuFilter::DealEvent(const TSCpuEvent* event) -{ - switch (static_cast(event->type_)) { - case TS_EVENT_THREAD_SWITCH: - ExecInsertSwitchEvent(event->switchEvent_->ts_, event->switchEvent_->cpu_, event->switchEvent_->prevPid_, - event->switchEvent_->prevPior_, event->switchEvent_->prevState_, - event->switchEvent_->nextPid_, event->switchEvent_->nextPior_); - break; - case TS_EVENT_THREAD_WAKING: - ExecInsertWakeupEvent(event->wakeupEvent_->ts_, event->wakeupEvent_->pid_); - break; - case TS_EVENT_PROCESS_EXIT: - case TS_EVENT_PROCESS_FREE: - ExecInsertProcessExitEvent(event->processExitEvent_->ts_, event->processExitEvent_->cpu_, - event->processExitEvent_->pid_); - break; - default: - break; - } -} -void CpuFilter::FinishCpuEvent() -{ - for (auto it = tsCpuEventQueue_.begin(); it != tsCpuEventQueue_.end(); it++) { - DealEvent(it->second.get()); - } - tsCpuEventQueue_.clear(); -} -void CpuFilter::ExecInsertSwitchEvent(uint64_t ts, - uint64_t cpu, - uint64_t prevPid, - uint64_t prevPior, - uint64_t prevState, - uint64_t nextPid, - uint64_t nextPior) { auto index = traceDataCache_->GetSchedSliceData()->AppendSchedSlice(ts, 0, cpu, nextPid, 0, nextPior); @@ -134,10 +42,10 @@ void CpuFilter::ExecInsertSwitchEvent(uint64_t ts, CheckWakeupEvent(nextPid); auto lastRow = RowOfInternalTidInStateTable(nextPid); if (lastRow != INVALID_UINT64) { - traceDataCache_->GetThreadStateData()->UpdateDuration(lastRow, ts); + traceDataCache_->GetThreadStateData()->UpdateDuration(static_cast(lastRow), ts); } index = - traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_UINT64, cpu, nextPid, TASK_RUNNING); + traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_TIME, cpu, nextPid, TASK_RUNNING); RemberInternalTidInStateTable(nextPid, index, TASK_RUNNING); if (cpuToRowThreadState_.find(cpu) == cpuToRowThreadState_.end()) { cpuToRowThreadState_.insert(std::make_pair(cpu, index)); @@ -150,27 +58,31 @@ void CpuFilter::ExecInsertSwitchEvent(uint64_t ts, CheckWakeupEvent(prevPid); auto lastRow = RowOfInternalTidInStateTable(prevPid); if (lastRow != INVALID_UINT64) { - traceDataCache_->GetThreadStateData()->UpdateDuration(lastRow, ts); + traceDataCache_->GetThreadStateData()->UpdateDuration(static_cast(lastRow), ts); + streamFilters_->processFilter_->AddCpuStateCount(prevPid); + auto thread = traceDataCache_->GetThreadData(prevPid); + if (thread){ + thread->switchCount_ = 1; + } } - auto temp = traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_UINT64, INVALID_UINT64, + auto temp = traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_TIME, INVALID_CPU, prevPid, prevState); RemberInternalTidInStateTable(prevPid, temp, prevState); } } -void CpuFilter::ExecInsertWakeupEvent(uint64_t ts, uint64_t internalTid) +bool CpuFilter::InsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid) { - /* repeated wakeup msg may come, we only record last wakeupmsg, and - the wakeup will only insert to DataCache when a sched_switch comes - */ - if (lastWakeUpMsg.find(internalTid) != lastWakeUpMsg.end()) { - lastWakeUpMsg.at(internalTid) = ts; - } else { - lastWakeUpMsg.insert(std::make_pair(internalTid, ts)); + UNUSED(cpu); + auto thread = traceDataCache_->GetThreadData(static_cast(pid)); + if (thread) { + thread->endT_ = ts; + return true; } + return false; } -bool CpuFilter::ExecInsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid) + +bool CpuFilter::InsertProcessFreeEvent(uint64_t ts, uint64_t pid) { - UNUSED(cpu); auto thread = traceDataCache_->GetThreadData(static_cast(pid)); if (thread) { thread->endT_ = ts; @@ -178,6 +90,75 @@ bool CpuFilter::ExecInsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t p } return false; } + +void CpuFilter::Finish() const +{ + auto size = traceDataCache_->ThreadSize(); + for (auto i = 0; i < size; i++) { + auto thread = traceDataCache_->GetThreadData(i); + if (thread->internalPid_ != INVALID_UINT32) { + traceDataCache_->GetProcessData(thread->internalPid_)->threadCount_++; + traceDataCache_->GetProcessData(thread->internalPid_)->cpuStatesCount_ += thread->cpuStatesCount_; + traceDataCache_->GetProcessData(thread->internalPid_)->sliceSize_ += thread->sliceSize_; + traceDataCache_->GetProcessData(thread->internalPid_)->switchCount_ += thread->switchCount_; + continue; + } + auto ipid = traceDataCache_->AppendNewProcessData( + thread->tid_, traceDataCache_->GetDataFromDict(thread->nameIndex_), thread->startT_); + thread->internalPid_ = ipid; + traceDataCache_->GetProcessData(thread->internalPid_)->threadCount_++; + traceDataCache_->GetProcessData(thread->internalPid_)->cpuStatesCount_ += thread->cpuStatesCount_; + traceDataCache_->GetProcessData(thread->internalPid_)->sliceSize_ += thread->sliceSize_; + traceDataCache_->GetProcessData(thread->internalPid_)->switchCount_ += thread->switchCount_; + } + auto threadState = traceDataCache_->GetConstThreadStateData(); + size = threadState.Size(); + auto rowData = threadState.ItidsData(); + for (auto i = 0; i < size; i++) { + auto thread = traceDataCache_->GetThreadData(rowData[i]); + if (thread->internalPid_ == INVALID_UINT32) { + continue; + } + auto process = traceDataCache_->GetProcessData(thread->internalPid_); + traceDataCache_->GetThreadStateData()->UpdateTidAndPid(i, thread->tid_, process->pid_); + } + auto slice = traceDataCache_->GetConstSchedSliceData(); + size = slice.Size(); + for (auto i = 0; i < size; i++) { + traceDataCache_->GetSchedSliceData()->AppendInternalPid( + traceDataCache_->GetThreadData(slice.InternalTidsData()[i])->internalPid_); + } +} +void CpuFilter::Clear() +{ + cpuToRowThreadState_.clear(); + cpuToRowSched_.clear(); + lastWakeUpMsg_.clear(); + internalTidToRowThreadState_.clear(); +} +void CpuFilter::InsertWakeupEvent(uint64_t ts, uint64_t internalTid) +{ + uint64_t lastrow = RowOfInternalTidInStateTable(internalTid); + auto lastState = StateOfInternalTidInStateTable(internalTid); + if (lastState == TASK_RUNNING) { + return; + } + if (lastrow != INVALID_UINT64) { + traceDataCache_->GetThreadStateData()->UpdateDuration(static_cast(lastrow), ts); + } + auto index = traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_TIME, INVALID_CPU, + internalTid, TASK_RUNNABLE); + RemberInternalTidInStateTable(internalTid, index, TASK_RUNNABLE); +} +uint64_t CpuFilter::RemberInternalTidInStateTable(uint64_t uid, uint64_t row, uint64_t state) +{ + if (internalTidToRowThreadState_.find(uid) != internalTidToRowThreadState_.end()) { + internalTidToRowThreadState_.at(uid) = TPthread{row, state}; + } else { + internalTidToRowThreadState_.insert(std::make_pair(uid, TPthread{row, state})); + } + return 0; +} uint64_t CpuFilter::RowOfInternalTidInStateTable(uint64_t uid) const { auto row = internalTidToRowThreadState_.find(uid); @@ -198,22 +179,7 @@ uint64_t CpuFilter::StateOfInternalTidInStateTable(uint64_t uid) const void CpuFilter::CheckWakeupEvent(uint64_t internalTid) { - if (lastWakeUpMsg.find(internalTid) == lastWakeUpMsg.end()) { - return; - } - auto ts = lastWakeUpMsg.at(internalTid); - lastWakeUpMsg.erase(internalTid); - uint64_t lastrow = RowOfInternalTidInStateTable(internalTid); - auto lastState = StateOfInternalTidInStateTable(internalTid); - if (lastState == TASK_RUNNING) { - return; - } - if (lastrow != INVALID_UINT64) { - traceDataCache_->GetThreadStateData()->UpdateDuration(lastrow, ts); - } - auto index = traceDataCache_->GetThreadStateData()->AppendThreadState(ts, INVALID_UINT64, INVALID_UINT64, - internalTid, TASK_RUNNABLE); - RemberInternalTidInStateTable(internalTid, index, TASK_RUNNABLE); + return; } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/cpu_filter.h b/host/trace_streamer/src/filter/cpu_filter.h old mode 100644 new mode 100755 index a798a11664ec875ab258bb85f40e24752d228a05..7b98b10d9284efa31333cdd4115644c8e6a8e76b --- a/host/trace_streamer/src/filter/cpu_filter.h +++ b/host/trace_streamer/src/filter/cpu_filter.h @@ -48,99 +48,21 @@ public: void InsertWakeupEvent(uint64_t ts, uint64_t internalTid); bool InsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid); bool InsertProcessFreeEvent(uint64_t ts, uint64_t pid); - void FinishCpuEvent(); - + void Finish() const; + void Clear(); private: - void MaybeDealEvent(); - - class TSSwitchEvent { - public: - TSSwitchEvent(uint64_t ts, - uint64_t cpu, - uint64_t prevPid, - uint64_t prevPior, - uint64_t prevState, - uint64_t nextPid, - uint64_t nextPior) - : ts_(ts), - cpu_(cpu), - prevPid_(prevPid), - prevPior_(prevPior), - prevState_(prevState), - nextPid_(nextPid), - nextPior_(nextPior) - - { - } - ~TSSwitchEvent() {} - uint64_t ts_; - uint64_t cpu_; - uint64_t prevPid_; - uint64_t prevPior_; - uint64_t prevState_; - uint64_t nextPid_; - uint64_t nextPior_; - }; - class TSWakeupEvent { - public: - TSWakeupEvent(uint64_t ts, uint64_t pid) : ts_(ts), pid_(pid) {} - ~TSWakeupEvent() {} - uint64_t ts_; - uint64_t pid_; - }; - class TSProcessExitEvent { - public: - TSProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid) : ts_(ts), cpu_(cpu), pid_(pid) {} - ~TSProcessExitEvent() {} - uint64_t ts_; - uint64_t cpu_; - uint64_t pid_; - }; - enum TSCpuEventType { - TS_EVENT_THREAD_SWITCH, - TS_EVENT_THREAD_WAKING, - TS_EVENT_PROCESS_EXIT, - TS_EVENT_PROCESS_FREE - }; - class TSCpuEvent { - public: - TSCpuEvent() {} - ~TSCpuEvent() {} - TSCpuEventType type_; - // us union below will be a good choice - // but union with unique_ptr can bring about runtime error on windows and mac,only work well on linux - std::unique_ptr switchEvent_ = {}; - std::unique_ptr wakeupEvent_ = {}; - std::unique_ptr processExitEvent_ = {}; - }; - void DealEvent(const TSCpuEvent* event); - void ExecInsertSwitchEvent(uint64_t ts, - uint64_t cpu, - uint64_t prevPid, - uint64_t prevPior, - uint64_t prevState, - uint64_t nextPid, - uint64_t nextPior); - void ExecInsertWakeupEvent(uint64_t ts, uint64_t internalTid); - bool ExecInsertProcessExitEvent(uint64_t ts, uint64_t cpu, uint64_t pid); void CheckWakeupEvent(uint64_t internalTid); uint64_t RemberInternalTidInStateTable(uint64_t uid, uint64_t row, uint64_t state = TASK_INVALID); uint64_t RowOfInternalTidInStateTable(uint64_t uid) const; uint64_t StateOfInternalTidInStateTable(uint64_t uid) const; - std::multimap> tsCpuEventQueue_; std::map cpuToRowThreadState_ = {}; std::map cpuToRowSched_ = {}; - std::map lastWakeUpMsg = {}; - + std::map lastWakeUpMsg_ = {}; struct TPthread { uint64_t row_; uint64_t state_; }; std::map internalTidToRowThreadState_ = {}; - // timestamp of ftrace events from different cpu can be outof order - // keep a cache of ftrace events in memory and keep msg in order - // the value below is the count of msg, maybe you can change it - const size_t MAX_CACHE_SIZE = 10000; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/filter.pri b/host/trace_streamer/src/filter/filter.pri deleted file mode 100644 index 1de2180993eaf1e2197e3f0ae56f0d02a212d70f..0000000000000000000000000000000000000000 --- a/host/trace_streamer/src/filter/filter.pri +++ /dev/null @@ -1,43 +0,0 @@ -# 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. - -INCLUDEPATH +=$$PWD \ - $$PWD/../cfg -HEADERS += \ - $$PWD/clock_filter.h \ - $$PWD/cpu_filter.h \ - $$PWD/filter_base.h \ - $$PWD/filter_filter.h \ - $$PWD/measure_filter.h \ - $$PWD/process_filter.h \ - $$PWD/slice_filter.h \ - $$PWD/symbols_filter.h \ - $$PWD/stat_filter.h \ - $$PWD/binder_filter.h \ - $$PWD/args_filter.h \ - $$PWD/irq_filter.h \ - $$PWD/system_event_measure_filter.h -SOURCES += \ - $$PWD/clock_filter.cpp \ - $$PWD/cpu_filter.cpp \ - $$PWD/filter_base.cpp \ - $$PWD/filter_filter.cpp \ - $$PWD/measure_filter.cpp \ - $$PWD/process_filter.cpp \ - $$PWD/slice_filter.cpp \ - $$PWD/symbols_filter.cpp \ - $$PWD/stat_filter.cpp \ - $$PWD/binder_filter.cpp \ - $$PWD/args_filter.cpp \ - $$PWD/irq_filter.cpp \ - $$PWD/system_event_measure_filter.cpp diff --git a/host/trace_streamer/src/filter/filter_base.h b/host/trace_streamer/src/filter/filter_base.h old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/filter/filter_filter.h b/host/trace_streamer/src/filter/filter_filter.h old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/filter/hi_sysevent_measure_filter.cpp b/host/trace_streamer/src/filter/hi_sysevent_measure_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e91d33756b8745b0becb534cb578fecb4ce8af68 --- /dev/null +++ b/host/trace_streamer/src/filter/hi_sysevent_measure_filter.cpp @@ -0,0 +1,144 @@ +/* + * 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. + */ + +#include "hi_sysevent_measure_filter.h" +#include "filter_filter.h" +#include "log.h" +#include "system_event_measure_filter.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +HiSysEventMeasureFilter::HiSysEventMeasureFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter), appKey_(INVALID_UINT64), appName_(INVALID_UINT64) +{ +} + +HiSysEventMeasureFilter::~HiSysEventMeasureFilter() {} + +DataIndex HiSysEventMeasureFilter::AppendNewValue(uint64_t serial, + uint64_t timestamp, + DataIndex appNameId, + DataIndex key, + int32_t type, + double numericValue, + DataIndex strValue) +{ + uint64_t appKeyId = GetOrCreateFilterIdInternal(appNameId, key); + traceDataCache_->GetSyseventMeasureData()->AppendData(serial, timestamp, appNameId, appKeyId, type, numericValue, strValue); + return appNameId; +} +void HiSysEventMeasureFilter::AppendNewValue(std::string msg, std::string processName) +{ + traceDataCache_->GetTraceConfigData()->AppendNewData("hisys_event", msg, processName); + return; +} +void HiSysEventMeasureFilter::AppendNewValue(int32_t brightnessState, + int32_t btState, + int32_t locationState, + int32_t wifiState, + int32_t streamDefault, + int32_t voiceCall, + int32_t music, + int32_t streamRing, + int32_t media, + int32_t voiceAssistant, + int32_t system, + int32_t alarm, + int32_t notification, + int32_t bluetoolthSco, + int32_t enforcedAudible, + int32_t streamDtmf, + int32_t streamTts, + int32_t accessibility, + int32_t recording, + int32_t streamAll) +{ + traceDataCache_->GetDeviceStateData()->AppendNewData( + brightnessState, btState, locationState, wifiState, streamDefault, voiceCall, music, streamRing, media, + voiceAssistant, system, alarm, notification, bluetoolthSco, enforcedAudible, streamDtmf, streamTts, + accessibility, recording, streamAll); + return; +} +DataIndex HiSysEventMeasureFilter::GetOrCreateFilterIdInternal(DataIndex appNameId, DataIndex key) +{ + uint64_t appKeyId = appKey_.Find(appNameId, key); + if (appKeyId == INVALID_DATAINDEX) { + appKeyId = traceDataCache_->GetAppNamesData()->AppendAppName(1, appNameId, key); + appKey_.Insert(appNameId, key, appKeyId); + } + return appKeyId; +} + +DataIndex HiSysEventMeasureFilter::GetOrCreateFilterId(DataIndex eventSource) +{ + DataIndex eventSourceFilterId = INVALID_DATAINDEX; + if (eventSource_.find(eventSource) == eventSource_.end()) { + eventSourceFilterId = streamFilters_->sysEventSourceFilter_->AppendNewMeasureFilter(eventSource); + eventSource_.insert(std::make_pair(eventSource, eventSourceFilterId)); + } else { + eventSourceFilterId = eventSource_.at(eventSource); + } + return eventSourceFilterId; +} +DataIndex HiSysEventMeasureFilter::GetOrCreateFilterId(DataIndex eventSource, DataIndex appName) +{ + DataIndex eventSourceFilterId = INVALID_DATAINDEX; + DataIndex appNameId = INVALID_DATAINDEX; + if (eventSource_.find(eventSource) == eventSource_.end()) { + eventSourceFilterId = streamFilters_->sysEventSourceFilter_->AppendNewMeasureFilter(eventSource); + eventSource_.insert(std::make_pair(eventSource, eventSourceFilterId)); + } else { + eventSourceFilterId = eventSource_.at(eventSource); + } + appNameId = appName_.Find(eventSourceFilterId, appName); + if (appNameId == INVALID_DATAINDEX) { + appNameId = traceDataCache_->GetAppNamesData()->AppendAppName(0, eventSourceFilterId, appName); + appName_.Insert(eventSourceFilterId, appName, appNameId); + } + return appNameId; +} +std::tuple + HiSysEventMeasureFilter::GetOrCreateFilterId(DataIndex eventSource, DataIndex appName, DataIndex key) +{ + DataIndex eventSourceFilterId = INVALID_DATAINDEX; + DataIndex appNameId = INVALID_DATAINDEX; + if (eventSource_.find(eventSource) == eventSource_.end()) { + eventSourceFilterId = streamFilters_->sysEventSourceFilter_->AppendNewMeasureFilter(eventSource); + eventSource_.insert(std::make_pair(eventSource, eventSourceFilterId)); + } else { + eventSourceFilterId = eventSource_.at(eventSource); + } + appNameId = appName_.Find(eventSourceFilterId, appName); + if (appNameId == INVALID_DATAINDEX) { + appNameId = traceDataCache_->GetAppNamesData()->AppendAppName(0, eventSourceFilterId, appName); + appName_.Insert(eventSourceFilterId, appName, appNameId); + } + uint64_t appKeyId = appKey_.Find(appNameId, key); + if (appKeyId == INVALID_DATAINDEX) { + appKeyId = traceDataCache_->GetAppNamesData()->AppendAppName(1, appNameId, key); + appKey_.Insert(appNameId, key, appKeyId); + } + return std::make_tuple(appNameId, appKeyId); +} + +void HiSysEventMeasureFilter::Clear() +{ + appKey_.Clear(); + appName_.Clear(); + eventSource_.clear(); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/hi_sysevent_measure_filter.h b/host/trace_streamer/src/filter/hi_sysevent_measure_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..54ea07a81eaeaf3722090dc1f900e871da64c27c --- /dev/null +++ b/host/trace_streamer/src/filter/hi_sysevent_measure_filter.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + +#ifndef HI_SYS_EVENT_MEASURE_FILTER_H +#define HI_SYS_EVENT_MEASURE_FILTER_H + +#include +#include +#include + +#include "double_map.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" +#include "triple_map.h" + +namespace SysTuning { +namespace TraceStreamer { +class HiSysEventMeasureFilter : private FilterBase { +public: + HiSysEventMeasureFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + HiSysEventMeasureFilter(const HiSysEventMeasureFilter&) = delete; + HiSysEventMeasureFilter& operator=(const HiSysEventMeasureFilter&) = delete; + ~HiSysEventMeasureFilter() override; + DataIndex GetOrCreateFilterId(DataIndex eventSource); + DataIndex GetOrCreateFilterId(DataIndex eventSource, DataIndex appName); + std::tuple GetOrCreateFilterId(DataIndex eventSource, DataIndex appName, DataIndex key); + DataIndex AppendNewValue(uint64_t serial, + uint64_t timestamp, + DataIndex appNameId, + DataIndex key, + int32_t type, + double numericValue, + DataIndex strValue); + void AppendNewValue(std::string msg, std::string processName); + void AppendNewValue(int32_t brightnessState, + int32_t btState, + int32_t locationState, + int32_t wifiState, + int32_t streamDefault, + int32_t voiceCall, + int32_t music, + int32_t streamRing, + int32_t media, + int32_t voiceAssistant, + int32_t system, + int32_t alarm, + int32_t notification, + int32_t bluetoolthSco, + int32_t enforcedAudible, + int32_t streamDtmf, + int32_t streamTts, + int32_t accessibility, + int32_t recording, + int32_t streamAll); + void Clear(); + +private: + DataIndex GetOrCreateFilterIdInternal(DataIndex appNameId, DataIndex key); + DoubleMap appKey_; + DoubleMap appName_; + std::map eventSource_; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // HI_SYS_EVENT_MEASURE_FILTER_H diff --git a/host/trace_streamer/src/filter/irq_filter.cpp b/host/trace_streamer/src/filter/irq_filter.cpp index aef7b3cdbf6064334f8baa6eadabcf751788106d..199c10c16914a6b18f7456fe752bdc45386c66a1 100644 --- a/host/trace_streamer/src/filter/irq_filter.cpp +++ b/host/trace_streamer/src/filter/irq_filter.cpp @@ -61,5 +61,13 @@ void IrqFilter::SoftIrqExit(int64_t ts, uint32_t cpu, uint32_t vec) streamFilters_->sliceFilter_->SoftIrqExit(ts, cpu, args); return; } +void IrqFilter::Clear() +{ + lastEventTs_.clear(); + transReplyWaitingReply_.clear(); + transWaitingRcv_.clear(); + transNoNeedReply_.clear(); + binderFlagDescs_.clear(); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/irq_filter.h b/host/trace_streamer/src/filter/irq_filter.h index d13c9b34216721c3f7529b97e58eb2c8402fe239..f6281a9af4a452db5b17f4d8f756b14ac3a68ac6 100644 --- a/host/trace_streamer/src/filter/irq_filter.h +++ b/host/trace_streamer/src/filter/irq_filter.h @@ -35,14 +35,14 @@ public: void IrqHandlerExit(int64_t ts, uint32_t cpu, uint32_t ret); void SoftIrqEntry(int64_t ts, uint32_t cpu, uint32_t vec); void SoftIrqExit(int64_t ts, uint32_t cpu, uint32_t vec); - + void Clear(); private: - DataIndex irqId_ = traceDataCache_->GetDataIndex("irq_id"); - DataIndex irqRet_ = traceDataCache_->GetDataIndex("irq_ret"); - DataIndex irqHandled_ = traceDataCache_->GetDataIndex("handled"); - DataIndex irqUnHandled_ = traceDataCache_->GetDataIndex("unhandled"); - DataIndex irqCatalog_ = traceDataCache_->GetDataIndex("irq"); - DataIndex softIrqCatalog_ = traceDataCache_->GetDataIndex("softirq"); + const DataIndex irqId_ = traceDataCache_->GetDataIndex("irq_id"); + const DataIndex irqRet_ = traceDataCache_->GetDataIndex("irq_ret"); + const DataIndex irqHandled_ = traceDataCache_->GetDataIndex("handled"); + const DataIndex irqUnHandled_ = traceDataCache_->GetDataIndex("unhandled"); + const DataIndex irqCatalog_ = traceDataCache_->GetDataIndex("irq"); + const DataIndex softIrqCatalog_ = traceDataCache_->GetDataIndex("softirq"); std::unordered_map lastEventTs_ = {}; std::unordered_set transReplyWaitingReply_ = {}; std::unordered_map transWaitingRcv_ = {}; diff --git a/host/trace_streamer/src/filter/measure_filter.cpp b/host/trace_streamer/src/filter/measure_filter.cpp old mode 100644 new mode 100755 index ad723fa3c6221a91aa8aaba3407b649d7cb43bb1..a9386c8b0cf126d4f279ad9465e4b6942e853e30 --- a/host/trace_streamer/src/filter/measure_filter.cpp +++ b/host/trace_streamer/src/filter/measure_filter.cpp @@ -29,10 +29,15 @@ MeasureFilter::MeasureFilter(TraceDataCache* dataCache, const TraceStreamerFilte MeasureFilter::~MeasureFilter() {} -void MeasureFilter::AppendNewMeasureData(uint64_t internalTid, DataIndex nameIndex, uint64_t timestamp, int64_t value) +bool MeasureFilter::AppendNewMeasureData(uint64_t internalTid, DataIndex nameIndex, uint64_t timestamp, int64_t value) { auto filterId = GetOrCreateFilterId(internalTid, nameIndex); - traceDataCache_->GetMeasureData()->AppendMeasureData(0, timestamp, value, filterId); + if (filterType_ == E_PROCESS_MEASURE_FILTER) { + traceDataCache_->GetProcessMeasureData()->AppendMeasureData(0, timestamp, value, filterId); + } else { + traceDataCache_->GetMeasureData()->AppendMeasureData(0, timestamp, value, filterId); + } + return value != 0; } uint32_t MeasureFilter::GetOrCreateFilterId(uint64_t internalTid, DataIndex nameIndex) { @@ -85,5 +90,9 @@ void MeasureFilter::AddCertainFilterId(uint64_t internalTid, DataIndex nameIndex static_cast(nameIndex), internalTid); } } +void MeasureFilter::Clear() +{ + tidStreamIdFilterIdMap_.Clear(); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/measure_filter.h b/host/trace_streamer/src/filter/measure_filter.h old mode 100644 new mode 100755 index ef8efeb43c229171506b0ef7250786241c2714dc..af4e2eb0ed8f4c23c8b07c0f5c27658caa7f229e --- a/host/trace_streamer/src/filter/measure_filter.h +++ b/host/trace_streamer/src/filter/measure_filter.h @@ -47,8 +47,9 @@ public: MeasureFilter(const MeasureFilter&) = delete; MeasureFilter& operator=(const MeasureFilter&) = delete; ~MeasureFilter() override; - void AppendNewMeasureData(uint64_t internalTid, DataIndex nameIndex, uint64_t timestamp, int64_t value); + bool AppendNewMeasureData(uint64_t internalTid, DataIndex nameIndex, uint64_t timestamp, int64_t value); uint32_t GetOrCreateFilterId(uint64_t internalTid, DataIndex nameIndex); + void Clear(); private: void AddCertainFilterId(uint64_t internalTid, DataIndex nameIndex, uint64_t filterId); DoubleMap tidStreamIdFilterIdMap_; @@ -67,12 +68,12 @@ private: { E_CLK_ENABLE_FILTER, "clk_enable_filter" }, { E_CLK_DISABLE_FILTER, "clk_disable_filter" } }; - DataIndex clockSetRateDataIndex_ = traceDataCache_->GetDataIndex("clock_set_rate"); - DataIndex clockEnableDataIndex_ = traceDataCache_->GetDataIndex("clock_enable"); - DataIndex clockDisableDataIndex_ = traceDataCache_->GetDataIndex("clock_disable"); - DataIndex clkSetRateDataIndex_ = traceDataCache_->GetDataIndex("clk_set_rate"); - DataIndex clkEnableDataIndex_ = traceDataCache_->GetDataIndex("clk_enable"); - DataIndex clkDisableDataIndex_ = traceDataCache_->GetDataIndex("clk_disable"); + const DataIndex clockSetRateDataIndex_ = traceDataCache_->GetDataIndex("clock_set_rate"); + const DataIndex clockEnableDataIndex_ = traceDataCache_->GetDataIndex("clock_enable"); + const DataIndex clockDisableDataIndex_ = traceDataCache_->GetDataIndex("clock_disable"); + const DataIndex clkSetRateDataIndex_ = traceDataCache_->GetDataIndex("clk_set_rate"); + const DataIndex clkEnableDataIndex_ = traceDataCache_->GetDataIndex("clk_enable"); + const DataIndex clkDisableDataIndex_ = traceDataCache_->GetDataIndex("clk_disable"); }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/perf_data_filter.cpp b/host/trace_streamer/src/filter/perf_data_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..83a632206d4be66b08aabef6d8ffb633fec9bcf9 --- /dev/null +++ b/host/trace_streamer/src/filter/perf_data_filter.cpp @@ -0,0 +1,96 @@ +/* + * 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. + */ +#include "perf_data_filter.h" +#include "measure_filter.h" +#include "process_filter.h" +#include "slice_filter.h" +#include "string_to_numerical.h" +namespace SysTuning { +namespace TraceStreamer { +PerfDataFilter::PerfDataFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : FilterBase(dataCache, filter), fileIdToRowInFileTable_(INVALID_UINT64), fileIdToRowInChainTable_(INVALID_UINT64) +{ +} +PerfDataFilter::~PerfDataFilter() = default; + +size_t PerfDataFilter::AppendPerfFiles(uint64_t fileId, uint32_t serial, DataIndex symbols, DataIndex filePath) +{ + fileIds_.emplace(fileId); + auto size = traceDataCache_->GetPerfFilesData()->AppendNewPerfFiles(fileId, serial, symbols, filePath); + fileIdToRowInFileTable_.Insert(fileId, serial, size); + if (!serial) { + fileIdToRow_.insert(std::make_pair(fileId, size)); + } + return size; +} + +size_t PerfDataFilter::AppendPerfCallChain(uint64_t sampleId, + uint64_t callChainId, + uint64_t vaddrInFile, + uint64_t fileId, + uint64_t symbolId) +{ + auto size = traceDataCache_->GetPerfCallChainData()->AppendNewPerfCallChain(sampleId, callChainId, vaddrInFile, + fileId, symbolId); + fileIdToRowInChainTable_.Insert(fileId, symbolId, size); + return size; +} +void PerfDataFilter::Finish() +{ + auto fileIds = traceDataCache_->GetPerfCallChainData()->FileIds(); + auto symbolsIds = traceDataCache_->GetPerfCallChainData()->SymbolIds(); + auto size = traceDataCache_->GetPerfCallChainData()->Size(); + auto filePath = traceDataCache_->GetPerfFilesData()->FilePaths(); + auto sambols = traceDataCache_->GetPerfFilesData()->Symbols(); + uint64_t flag = 1; + flag = ~(flag << 63); + for (auto i = 0; i < size; i++) { + if (fileIds_.find(fileIds[i]) == fileIds_.end()) { + // When the function name is empty and there is no file information to which the function belongs, + // set the function name to the virtual address of the function in the file + traceDataCache_->GetPerfCallChainData()->SetName( + i, "+0x" + base::number(traceDataCache_->GetPerfCallChainData()->VaddrInFiles()[i] & flag)); + continue; + } + if (symbolsIds[i] == -1) { + // When the function name is empty, if there has the file Id to which the function belongs,but the symboleid + // is -1. Set the function name as "the file name of the function at the top of the callstack + the virtual + // address of this function" + auto pathIndex = filePath[fileIdToRow_.at(fileIds[i])]; + auto fullPath = traceDataCache_->GetDataFromDict(pathIndex); + auto iPos = fullPath.find_last_of('/'); + fullPath = fullPath.substr(iPos + 1, -1); + traceDataCache_->GetPerfCallChainData()->SetName( + i, fullPath + "+0x" + base::number(traceDataCache_->GetPerfCallChainData()->VaddrInFiles()[i] & flag)); + continue; + } + // When the function name is empty, if there has the file Id to which the function belongs,and the symboleid + // is not -1. Set the function name as the virtual address of this function + auto value = fileIdToRowInFileTable_.Find(fileIds[i], symbolsIds[i]); + if (value == INVALID_UINT64) { + traceDataCache_->GetPerfCallChainData()->SetName( + i, "+0x" + base::number(traceDataCache_->GetPerfCallChainData()->VaddrInFiles()[i] & flag)); + continue; + } + // The function name is not empty + traceDataCache_->GetPerfCallChainData()->SetName(i, traceDataCache_->GetDataFromDict(sambols[value])); + } + fileIdToRowInFileTable_.Clear(); + fileIdToRowInChainTable_.Clear(); + fileIds_.clear(); + fileIdToRow_.clear(); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/filter/perf_data_filter.h b/host/trace_streamer/src/filter/perf_data_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..b0569d4e0cf2f16e03f61e07b7bdfaa8315529b0 --- /dev/null +++ b/host/trace_streamer/src/filter/perf_data_filter.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef PERF_DATA_FILTER_H +#define PERF_DATA_FILTER_H +#include +#include +#include +#include "double_map.h" +#include "filter_base.h" +#include "trace_data_cache.h" +#include "trace_streamer_filters.h" +namespace SysTuning { +namespace TraceStreamer { +class PerfDataFilter : private FilterBase { +public: + PerfDataFilter(TraceDataCache*, const TraceStreamerFilters*); + PerfDataFilter(const PerfDataFilter&) = delete; + PerfDataFilter& operator=(const PerfDataFilter&) = delete; + ~PerfDataFilter() override; + +public: + size_t AppendPerfFiles(uint64_t fileId, uint32_t serial, DataIndex symbols, DataIndex filePath); + size_t AppendPerfCallChain(uint64_t sampleId, + uint64_t callChainId, + uint64_t vaddrInFile, + uint64_t fileId, + uint64_t symbolId); + void Finish(); + +private: + DoubleMap fileIdToRowInFileTable_; + DoubleMap fileIdToRowInChainTable_; + std::set fileIds_; + std::map fileIdToRow_{}; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // PERF_DATA_FILTER_H diff --git a/host/trace_streamer/src/filter/process_filter.cpp b/host/trace_streamer/src/filter/process_filter.cpp old mode 100644 new mode 100755 index 0c941f317f02255d214a2b70b272060d08ce64a9..5021febb1445563d0e55fc76346401e47e6aa0f4 --- a/host/trace_streamer/src/filter/process_filter.cpp +++ b/host/trace_streamer/src/filter/process_filter.cpp @@ -40,11 +40,32 @@ uint32_t ProcessFilter::UpdateOrCreateThreadWithName(uint64_t timeStamp, uint32_ return UpdateOrCreateThreadWithNameIndex(timeStamp, tid, nameIndex); } -uint32_t ProcessFilter::UpdateOrCreateThread(uint64_t timestamp, uint32_t tid) +void ProcessFilter::AddProcessMemory(uint32_t ipid) { - return UpdateOrCreateThreadWithNameIndex(timestamp, tid, 0); + traceDataCache_->GetProcessData(ipid)->memSize_ = 1; } -void ProcessFilter::UpdateOrCreateThreadWithPidAndName(uint32_t tid, uint32_t pid, std::string_view name) + +void ProcessFilter::AddThreadSliceNum(uint32_t itid) +{ + traceDataCache_->GetThreadData(itid)->sliceSize_ = 1; +} +void ProcessFilter::AddProcessSliceNum(uint32_t ipid) +{ + traceDataCache_->GetProcessData(ipid)->sliceSize_ = 1; +} + +void ProcessFilter::AddCpuStateCount(uint32_t itid) +{ + auto thread = traceDataCache_->GetThreadData(itid); + if (thread) { + thread->cpuStatesCount_++; + } +} +uint32_t ProcessFilter::UpdateOrCreateThread(uint64_t timeStamp, uint32_t tid) +{ + return UpdateOrCreateThreadWithNameIndex(timeStamp, tid, 0); +} +uint32_t ProcessFilter::UpdateOrCreateThreadWithPidAndName(uint32_t tid, uint32_t pid, std::string_view name) { uint32_t internalTid = GetOrCreateThreadWithPid(tid, pid); auto thread = traceDataCache_->GetThreadData(internalTid); @@ -54,6 +75,7 @@ void ProcessFilter::UpdateOrCreateThreadWithPidAndName(uint32_t tid, uint32_t pi if (tid == pid) { UpdateOrCreateProcessWithName(pid, name); } + return internalTid; } uint32_t ProcessFilter::GetOrCreateThreadWithPid(uint32_t tid, uint32_t pid) @@ -71,7 +93,7 @@ uint32_t ProcessFilter::GetOrCreateThreadWithPid(uint32_t tid, uint32_t pid) std::tie(internalTid, thread) = NewThread(tid); } - if (!thread->internalPid_ && pid != 0) { + if (thread->internalPid_ == INVALID_UINT32 && pid != 0) { std::tie(thread->internalPid_, std::ignore) = CreateProcessMaybe(pid, thread->startT_); } @@ -120,7 +142,7 @@ uint32_t ProcessFilter::GetInternalTid(uint32_t tid, uint32_t pid) const for (auto it = tidsPair.first; it != tidsPair.second; it++) { uint32_t iterItid = it->second; auto iterThread = traceDataCache_->GetThreadData(iterItid); - if (!iterThread->internalPid_) { + if (iterThread->internalPid_ == INVALID_UINT32) { internalTid = iterItid; continue; } @@ -166,7 +188,7 @@ InternalPid ProcessFilter::GetInternalPid(uint32_t pid) const return INVALID_ID; } -InternalTid ProcessFilter::GetOrCreateInternalPid(uint64_t timestamp, uint32_t pid) +InternalPid ProcessFilter::GetOrCreateInternalPid(uint64_t timeStamp, uint32_t pid) { auto ipid = GetInternalPid(pid); if (ipid != INVALID_ID) { @@ -175,7 +197,7 @@ InternalTid ProcessFilter::GetOrCreateInternalPid(uint64_t timestamp, uint32_t p uint32_t internalPid = 0; TraceStdtype::Process* process = nullptr; - std::tie(internalPid, process) = CreateProcessMaybe(pid, timestamp); + std::tie(internalPid, process) = CreateProcessMaybe(pid, timeStamp); return internalPid; } std::tuple ProcessFilter::NewThread(uint32_t tid) @@ -215,5 +237,10 @@ std::tuple ProcessFilter::CreateProcessMaybe(u return std::make_tuple(internalPid, process); } +void ProcessFilter::Clear() +{ + tidMappingSet_.clear(); + pidToInternalPidMap_.clear(); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/process_filter.h b/host/trace_streamer/src/filter/process_filter.h old mode 100644 new mode 100755 index a3e04e7ef3a65682fc38d3fb7a3dc4d5c5db38e3..4c9293ef69cb3def8baec871ab1ba17b8b41187f --- a/host/trace_streamer/src/filter/process_filter.h +++ b/host/trace_streamer/src/filter/process_filter.h @@ -30,21 +30,28 @@ public: ~ProcessFilter() override; uint32_t UpdateOrCreateProcessWithName(uint32_t pid, std::string_view name); - uint32_t UpdateOrCreateThreadWithName(uint64_t timestamp, uint32_t tid, std::string_view name); - void UpdateOrCreateThreadWithPidAndName(uint32_t tid, uint32_t pid, std::string_view name); + uint32_t UpdateOrCreateThreadWithName(uint64_t timeStamp, uint32_t tid, std::string_view name); + uint32_t UpdateOrCreateThreadWithPidAndName(uint32_t tid, uint32_t pid, std::string_view name); uint32_t GetOrCreateThreadWithPid(uint32_t tid, uint32_t pid); - uint32_t UpdateOrCreateThread(uint64_t timestamp, uint32_t tid); + uint32_t UpdateOrCreateThread(uint64_t timeStamp, uint32_t tid); InternalPid GetInternalPid(uint32_t pid) const; - InternalTid GetOrCreateInternalPid(uint64_t timestamp, uint32_t pid); + InternalPid GetOrCreateInternalPid(uint64_t timeStamp, uint32_t pid); bool isThreadNameEmpty(uint32_t tid) const; - uint32_t UpdateOrCreateThreadWithNameIndex(uint64_t timestamp, uint32_t tid, DataIndex threadNameIndex); + InternalTid GetInternalTid(uint32_t tid) const; + uint32_t UpdateOrCreateThreadWithNameIndex(uint64_t timeStamp, uint32_t tid, DataIndex threadNameIndex); + void AddProcessMemory(uint32_t ipid); + void AddThreadSliceNum(uint32_t itid); + void AddCpuStateCount(uint32_t itid); + void AddProcessSliceNum(uint32_t ipid); + void Clear(); + private: - std::tuple CreateProcessMaybe(uint32_t pid, uint64_t start_ns); + std::tuple CreateProcessMaybe(uint32_t pid, uint64_t startT); std::tuple NewThread(uint32_t tid); std::tuple NewProcess(uint32_t pid); - InternalTid GetInternalTid(uint32_t tid) const; InternalTid GetInternalTid(uint32_t tid, uint32_t pid) const; + private: std::multimap tidMappingSet_ = {}; std::map pidToInternalPidMap_ = {}; diff --git a/host/trace_streamer/src/filter/slice_filter.cpp b/host/trace_streamer/src/filter/slice_filter.cpp old mode 100644 new mode 100755 index 5ae3854fea33cd9ae923fdedea937a2179e806e7..b091988ddd9e3409cbcf1436741be75481d6efb0 --- a/host/trace_streamer/src/filter/slice_filter.cpp +++ b/host/trace_streamer/src/filter/slice_filter.cpp @@ -23,10 +23,12 @@ #include "measure_filter.h" #include "process_filter.h" #include "stat_filter.h" +#include "string_to_numerical.h" #include "ts_common.h" namespace SysTuning { namespace TraceStreamer { +using namespace SysTuning::base; SliceFilter::SliceFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : FilterBase(dataCache, filter), asyncEventMap_(INVALID_UINT64) { @@ -34,30 +36,33 @@ SliceFilter::SliceFilter(TraceDataCache* dataCache, const TraceStreamerFilters* SliceFilter::~SliceFilter() = default; -bool SliceFilter::BeginSlice(uint64_t timestamp, - uint32_t pid, - uint32_t threadGroupId, - DataIndex cat, - DataIndex nameIndex) +size_t SliceFilter::BeginSlice(const std::string& comm, + uint64_t timestamp, + uint32_t pid, + uint32_t threadGroupId, + DataIndex cat, + DataIndex nameIndex) { InternalTid internalTid = INVALID_UTID; if (threadGroupId > 0) { - internalTid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(pid, threadGroupId); + internalTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithPidAndName(pid, threadGroupId, comm); pidTothreadGroupId_[pid] = threadGroupId; } else { - internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); + internalTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithName(timestamp, pid, comm); } // make a SliceData DataItem, {timestamp, dur, internalTid, cat, nameIndex} - struct SliceData sliceData = {timestamp, 0, internalTid, cat, nameIndex}; - return BeginSliceInternal(sliceData); + struct SliceData sliceData = {timestamp, -1, internalTid, cat, nameIndex}; + ArgsSet args; + return StartSlice(timestamp, pid, cat, nameIndex, args, sliceData); } void SliceFilter::IrqHandlerEntry(uint64_t timestamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex) { struct SliceData sliceData = {timestamp, 0, cpu, catalog, nameIndex}; auto slices = traceDataCache_->GetIrqData(); - size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, - sliceData.cat, sliceData.name, 0, std::nullopt); + size_t index = slices->AppendInternalSlice( + sliceData.timestamp, sliceData.duration, sliceData.internalTid, sliceData.cat, + GetNameASCIISumNoNum(traceDataCache_->GetDataFromDict(sliceData.name)), sliceData.name, 0, std::nullopt); if (irqEventMap_.count(cpu)) { // not match streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_DATA_LOST); @@ -65,7 +70,6 @@ void SliceFilter::IrqHandlerEntry(uint64_t timestamp, uint32_t cpu, DataIndex ca } else { irqEventMap_[cpu] = {timestamp, index}; } - slices->AppendDistributeInfo(); return; } @@ -79,7 +83,7 @@ void SliceFilter::IrqHandlerExit(uint64_t timestamp, uint32_t cpu, ArgsSet args) uint32_t argSetId = INVALID_UINT32; auto slices = traceDataCache_->GetIrqData(); argSetId = streamFilters_->argsFilter_->NewArgs(args); - slices->SetDurationAndArg(irqEventMap_.at(cpu).row, timestamp, argSetId); + slices->SetIrqDurAndArg(irqEventMap_.at(cpu).row, timestamp, argSetId); irqEventMap_.erase(cpu); return; } @@ -88,8 +92,9 @@ void SliceFilter::SoftIrqEntry(uint64_t timestamp, uint32_t cpu, DataIndex catal { struct SliceData sliceData = {timestamp, 0, cpu, catalog, nameIndex}; auto slices = traceDataCache_->GetIrqData(); - size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, - sliceData.cat, sliceData.name, 0, std::nullopt); + size_t index = slices->AppendInternalSlice( + sliceData.timestamp, sliceData.duration, sliceData.internalTid, sliceData.cat, + GetNameASCIISumNoNum(traceDataCache_->GetDataFromDict(sliceData.name)), sliceData.name, 0, std::nullopt); if (softIrqEventMap_.count(cpu)) { // not match streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_DATA_LOST); @@ -97,7 +102,6 @@ void SliceFilter::SoftIrqEntry(uint64_t timestamp, uint32_t cpu, DataIndex catal } else { softIrqEventMap_[cpu] = {timestamp, index}; } - slices->AppendDistributeInfo(); return; } @@ -111,141 +115,307 @@ void SliceFilter::SoftIrqExit(uint64_t timestamp, uint32_t cpu, ArgsSet args) uint32_t argSetId = INVALID_UINT32; auto slices = traceDataCache_->GetIrqData(); argSetId = streamFilters_->argsFilter_->NewArgs(args); - slices->SetDurationAndArg(softIrqEventMap_.at(cpu).row, timestamp, argSetId); + slices->SetIrqDurAndArg(softIrqEventMap_.at(cpu).row, timestamp, argSetId); softIrqEventMap_.erase(cpu); return; } -size_t SliceFilter::BeginAsyncBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet args) +void SliceFilter::RememberSliceData(InternalTid internalTid, + std::unordered_map& stackMap, + SliceData& slice, + uint32_t depth, + uint64_t index) { - InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); - struct SliceData sliceData = {timestamp, 0, internalTid, cat, nameIndex}; - auto slices = traceDataCache_->GetInternalSlicesData(); - - auto sliceStack = &sliceStackMap_[sliceData.internalTid]; - if (sliceStack->size() >= std::numeric_limits::max()) { - TS_LOGW("stack depth out of range."); - } - const uint8_t depth = static_cast(sliceStack->size()); - size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, - sliceData.cat, sliceData.name, depth, std::nullopt); - - uint32_t argSetId = INVALID_INT32; - if (args.valuesMap_.size()) { - argSetId = streamFilters_->argsFilter_->NewArgs(args); - slices->AppendArgSet(argSetId); - binderQueue_[pid] = argSetId; + if (stackMap.find(internalTid) == stackMap.end()) { + auto& sliceStack = stackMap[internalTid].sliceStack; // this can be a empty call, but it does not matter + slice.depth = depth; + slice.index = index; + sliceStack.push_back(slice); } else { - argSetId = streamFilters_->argsFilter_->NewArgs(args); - slices->AppendArgSet(argSetId); - binderQueue_[pid] = argSetId; + auto& sliceStack = stackMap.at(internalTid).sliceStack; // this can be a empty call, but it does not matter + slice.depth = depth; + slice.index = index; + sliceStack.push_back(slice); } - argsToSliceQueue_[argSetId] = static_cast(index); - return index; } -size_t SliceFilter::BeginBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, - ArgsSet args) +size_t SliceFilter::AsyncBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet& args) { InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); struct SliceData sliceData = {timestamp, 0, internalTid, cat, nameIndex}; - auto slices = traceDataCache_->GetInternalSlicesData(); - - auto sliceStack = &sliceStackMap_[sliceData.internalTid]; - if (sliceStack->size() >= std::numeric_limits::max()) { - TS_LOGW("stack depth out of range."); + return StartSlice(timestamp, pid, cat, nameIndex, args, std::move(sliceData)); +} +uint8_t SliceFilter::CurrentDepth(InternalTid internalTid) +{ + if (depthHolder_.find(internalTid) == depthHolder_.end()) { + return 0; } - const uint8_t depth = static_cast(sliceStack->size()); - size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, - sliceData.cat, sliceData.name, depth, std::nullopt); - - sliceStack->push_back(index); + auto& depthMap = depthHolder_.at(internalTid); + auto depthSize = depthMap.size(); + for (int32_t i = depthSize - 1; i >= 0; i--) { + if (depthMap.at(i)) { + return i; + } + } + return 0; +} +uint8_t SliceFilter::UpdateDepth(bool increase, InternalTid internalTid, int32_t depth) +{ + if (increase) { + if (depthHolder_.find(internalTid) == depthHolder_.end()) { + StackOnDepth tmp; + tmp.insert(std::make_pair(0, true)); + depthHolder_.insert(std::make_pair(internalTid, tmp)); + return 0; + } + auto& depthMap = depthHolder_.at(internalTid); + auto depthSize = depthMap.size(); + auto lastIndex = 0; + for (int32_t i = depthSize - 1; i >= 0; i--) { + if (depthMap.at(i) && (i == depthSize - 1)) { + depthMap.insert(std::make_pair(depthSize, true)); + return depthSize; + } + if (depthMap.at(i)) { + break; + } + lastIndex = i; + } - uint32_t argSetId = INVALID_INT32; - if (args.valuesMap_.size()) { - argSetId = streamFilters_->argsFilter_->NewArgs(args); - slices->AppendArgSet(argSetId); - binderQueue_[pid] = argSetId; + if (!depthMap.at(lastIndex)) { + depthMap.at(lastIndex) = true; + return lastIndex; + } } else { - argSetId = streamFilters_->argsFilter_->NewArgs(args); - slices->AppendArgSet(argSetId); - binderQueue_[pid] = argSetId; + if (depthHolder_.find(internalTid) == depthHolder_.end()) { + TS_LOGE("internalTid not found"); + return 0; + } + auto& depthMap = depthHolder_.at(internalTid); + if (depthMap.find(depth) == depthMap.end()) { + return 0; + } + depthMap.at(depth) = false; } - argsToSliceQueue_[argSetId] = static_cast(index); - return index; + return depth; } -uint32_t SliceFilter::AddArgs(uint32_t tid, DataIndex key1, DataIndex key2, ArgsSet &args) +void SliceFilter::CloseUnMatchedSlice(int64_t ts, SlicesStack& stack, InternalTid itid) { - if (!binderQueue_.count(tid)) { - return INVALID_UINT32; + auto slices = traceDataCache_->GetInternalSlicesData(); + bool incomplete = false; + for (int i = stack.size() - 1; i >= 0; i--) { + uint32_t sliceIdx = stack[i].index; + int64_t startTs = slices->TimeStamData()[sliceIdx]; + int64_t dur = slices->DursData()[sliceIdx]; + int64_t endTs = startTs + dur; + if (dur == -1) { + incomplete = true; + continue; + } + if (incomplete) { + if (ts <= endTs) { + continue; + } + for (int j = stack.size() - 1; j > i; --j) { + uint32_t childIdx = stack[i].index; + slices->SetDur(childIdx, endTs - slices->TimeStamData()[childIdx]); + stack.pop_back(); + } + stack.pop_back(); + incomplete = false; + continue; + } + if (endTs <= ts) { + stack.pop_back(); + } } - streamFilters_->argsFilter_->AppendArgs(args, binderQueue_[tid]); - return argsToSliceQueue_[binderQueue_[tid]]; } -bool SliceFilter::EndBinder(uint64_t timestamp, uint32_t pid, DataIndex category, DataIndex name, ArgsSet args) + +int32_t SliceFilter::MatchingIncompleteSliceIndex(const SlicesStack& stack, DataIndex category, DataIndex name) { - if (!binderQueue_.count(pid)) { - return false; + auto slices = traceDataCache_->GetInternalSlicesData(); + for (int i = stack.size() - 1; i >= 0; i--) { + uint32_t sliceIdx = stack[i].index; + if (slices->DursData()[sliceIdx] != -1) { + continue; + } + const DataIndex& categoryLast = slices->CatsData()[sliceIdx]; + if (category != INVALID_UINT64 && (categoryLast != INVALID_UINT64 && category != categoryLast)) { + continue; + } + const DataIndex& nameLast = slices->NamesData()[sliceIdx]; + if (name != INVALID_UINT64 && nameLast != INVALID_UINT64 && name != nameLast) { + continue; + } + return static_cast(i); } - auto lastRow = argsToSliceQueue_[binderQueue_[pid]]; + return -1; +} +size_t SliceFilter::StartSlice(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet& args, SliceData sliceData) +{ + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); + auto& sliceStack = binderStackMap_[internalTid]; + auto& stack = sliceStack.sliceStack; + if (sliceStack.isAsyncEvent) { + sliceStack.asyncEventCount++; + sliceStack.asyncEventLastBeginTs = timestamp; + if (!stack.empty()) { + return INVALID_UINT32; + } + } + // keep slice of thread + CloseUnMatchedSlice(timestamp, stack, internalTid); + uint32_t depth = stack.size(); auto slices = traceDataCache_->GetInternalSlicesData(); - slices->SetDuration(lastRow, timestamp); - streamFilters_->argsFilter_->AppendArgs(args, binderQueue_[pid]); - argsToSliceQueue_.erase(binderQueue_[pid]); + uint32_t parentId = depth == 0 ? INVALID_UINT32 : slices->IdsData()[stack.back().index]; + + size_t index = slices->AppendInternalSlice( + sliceData.timestamp, sliceData.duration, sliceData.internalTid, sliceData.cat, + GetNameASCIISumNoNum(traceDataCache_->GetDataFromDict(sliceData.name)), sliceData.name, 0, parentId); + if (depth >= std::numeric_limits::max()) { + return INVALID_UINT32; + } + slices->SetDepth(index, depth); - binderQueue_.erase(pid); + uint32_t argSetId = INVALID_UINT32; + if (args.valuesMap_.size()) { + if (args.inserted_) { + argSetId = args.argSetId_; + } else { + argSetId = streamFilters_->argsFilter_->NewArgs(args); + sliceRowToArgsSetId_[index] = argSetId; + argsSetIdToSliceRow_[argSetId] = static_cast(index); + args.argSetId_ = argSetId; + args.inserted_ = true; + } + // set ArgSetId here + slices->SetArgSetId(index, argSetId); + } + sliceData.argSetId = argSetId; + RememberSliceData(sliceData.internalTid, binderStackMap_, sliceData, depth, index); + return index; +} +size_t SliceFilter::BeginBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet args) +{ InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); + struct SliceData sliceData = {timestamp, -1, internalTid, cat, nameIndex}; + return StartSlice(timestamp, pid, cat, nameIndex, args, std::move(sliceData)); +} - const auto& stack = sliceStackMap_[internalTid]; +size_t SliceFilter::CompleteSlice(uint64_t timestamp, uint32_t pid, DataIndex category, DataIndex name, ArgsSet args) +{ + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, pid); + if (binderStackMap_.find(internalTid) == binderStackMap_.end()) { + return INVALID_INT32; + } + auto& stackInfo = binderStackMap_[internalTid]; + SlicesStack& stack = stackInfo.sliceStack; + CloseUnMatchedSlice(timestamp, stack, internalTid); if (stack.empty()) { TS_LOGE("a slice end do not match a slice start event"); callEventDisMatchCount++; - return false; + return INVALID_INT32; } - sliceStackMap_[internalTid].pop_back(); - return true; -} + auto stackIdx = MatchingIncompleteSliceIndex(stack, category, name); + if (stackIdx < 0) { + TS_LOGE("MatchingIncompleteSliceIndex failed"); + return INVALID_INT32; + } + auto lastRow = stack[stackIdx].index; + auto slices = traceDataCache_->GetInternalSlicesData(); + slices->SetDuration(lastRow, timestamp); + auto argSize = sliceRowToArgsSetId_.count(lastRow); + size_t argSetId = 0; + if (args.valuesMap_.size()) { + if (!argSize) { + argSetId = streamFilters_->argsFilter_->NewArgs(args); + sliceRowToArgsSetId_[lastRow] = argSetId; + slices->SetArgSetId(lastRow, argSetId); + } else { + argSetId = sliceRowToArgsSetId_.at(lastRow); + } + streamFilters_->argsFilter_->AppendArgs(args, argSetId); + } + if (stackInfo.isAsyncEvent) { + ArgsSet args; + args.AppendArg(asyncBeginCountId_, BASE_DATA_TYPE_INT, stackInfo.asyncEventCount); + args.AppendArg(asyncBeginTsId_, BASE_DATA_TYPE_INT, stackInfo.asyncEventLastBeginTs); + if (!argSetId) { + argSetId = streamFilters_->argsFilter_->NewArgs(args); + sliceRowToArgsSetId_[lastRow] = argSetId; + slices->SetArgSetId(lastRow, argSetId); + } else { + streamFilters_->argsFilter_->AppendArgs(args, argSetId); + } + } + if (stackIdx == stack.size() - 1) { + stack.pop_back(); + } + streamFilters_->processFilter_->AddThreadSliceNum(internalTid); + return lastRow; +} +size_t SliceFilter::EndBinder(uint64_t timestamp, uint32_t pid, DataIndex category, DataIndex name, ArgsSet args) +{ + return CompleteSlice(timestamp, pid, category, name, args); +} +std::tuple SliceFilter::AddArgs(uint32_t tid, DataIndex key1, DataIndex key2, ArgsSet& args) +{ + InternalTid internalTid = streamFilters_->processFilter_->GetInternalTid(tid); + if (binderStackMap_.find(internalTid) == binderStackMap_.end()) { + return std::make_tuple(INVALID_UINT32, INVALID_UINT32); + } + auto& stack = binderStackMap_[internalTid]; + auto idx = MatchingIncompleteSliceIndex(stack.sliceStack, key1, key2); + if (idx < 0) { + return std::make_tuple(INVALID_UINT32, INVALID_UINT32); + } + uint32_t argSetId = stack.sliceStack[idx].argSetId; + if (argSetId == INVALID_UINT32) { + argSetId = streamFilters_->argsFilter_->NewArgs(args); + sliceRowToArgsSetId_[stack.sliceStack[idx].index] = argSetId; + stack.sliceStack[idx].argSetId = argSetId; + } else { + streamFilters_->argsFilter_->AppendArgs(args, argSetId); + } + return std::make_tuple(stack.sliceStack[idx].index, argSetId); +} void SliceFilter::StartAsyncSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, - int64_t cookie, + uint64_t cookie, DataIndex nameIndex) { - InternalPid internalPid = streamFilters_->processFilter_->GetOrCreateInternalPid(timestamp, threadGroupId); - auto lastFilterId = asyncEventMap_.Find(internalPid, cookie, nameIndex); + UNUSED(pid); + InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, threadGroupId); + + auto lastFilterId = asyncEventMap_.Find(internalTid, cookie, nameIndex); auto slices = traceDataCache_->GetInternalSlicesData(); if (lastFilterId != INVALID_UINT64) { asyncEventDisMatchCount++; - FinishAsyncSlice(timestamp, pid, threadGroupId, cookie, nameIndex); + return; } asyncEventSize_++; // a pid, cookie and function name determain a callstack - asyncEventMap_.Insert(internalPid, cookie, nameIndex, asyncEventSize_); + asyncEventMap_.Insert(internalTid, cookie, nameIndex, asyncEventSize_); // 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; - if (asyncNoEndingEventMap_.find(internalPid) == asyncNoEndingEventMap_.end()) { - depth = 0; - asyncNoEndingEventMap_.insert(std::make_pair(internalPid, 1)); - } else { - depth = asyncNoEndingEventMap_.at(internalPid); - asyncNoEndingEventMap_.at(internalPid)++; - } - size_t index = slices->AppendInternalAsyncSlice(timestamp, 0, internalPid, INVALID_UINT64, nameIndex, depth, cookie, - std::nullopt); + size_t index = slices->AppendInternalAsyncSlice(timestamp, -1, internalTid, INVALID_UINT64, + GetNameASCIISumNoNum(traceDataCache_->GetDataFromDict(nameIndex)), + nameIndex, depth, cookie, std::nullopt); asyncEventFilterMap_.insert(std::make_pair(asyncEventSize_, AsyncEvent{timestamp, index})); } void SliceFilter::FinishAsyncSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, - int64_t cookie, + uint64_t cookie, DataIndex nameIndex) { UNUSED(pid); - InternalPid internalPid = streamFilters_->processFilter_->GetOrCreateInternalPid(timestamp, threadGroupId); - auto lastFilterId = asyncEventMap_.Find(internalPid, cookie, nameIndex); + InternalPid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(timestamp, threadGroupId); + auto lastFilterId = asyncEventMap_.Find(internalTid, cookie, nameIndex); auto slices = traceDataCache_->GetInternalSlicesData(); if (lastFilterId == INVALID_UINT64) { // if failed asyncEventDisMatchCount++; @@ -260,90 +430,29 @@ void SliceFilter::FinishAsyncSlice(uint64_t timestamp, asyncEventFilterMap_.at(lastFilterId).timestamp = timestamp; slices->SetDuration(asyncEventFilterMap_.at(lastFilterId).row, timestamp); asyncEventFilterMap_.erase(lastFilterId); - asyncEventMap_.Erase(internalPid, cookie, nameIndex); - - if (asyncNoEndingEventMap_.find(internalPid) == asyncNoEndingEventMap_.end()) { - asyncNoEndingEventMap_.insert(std::make_pair(internalPid, 1)); - } else { - asyncNoEndingEventMap_.at(internalPid)--; - if (!asyncNoEndingEventMap_.at(internalPid)) { - asyncNoEndingEventMap_.erase(internalPid); - } - } + asyncEventMap_.Erase(internalTid, cookie, nameIndex); + streamFilters_->processFilter_->AddThreadSliceNum(internalTid); } -bool SliceFilter::BeginSliceInternal(const SliceData& sliceData) -{ - // the call stack belongs to thread, so we keep a call-tree for the thread - auto sliceStack = &sliceStackMap_[sliceData.internalTid]; // this can be a empty call, but it does not matter - auto slices = traceDataCache_->GetInternalSlicesData(); - if (sliceStack->size() >= std::numeric_limits::max()) { - TS_LOGW("stack depth out of range."); - } - const uint8_t depth = static_cast(sliceStack->size()); - std::optional parentId = std::nullopt; - if (depth != 0) { - size_t lastDepth = sliceStack->back(); - parentId = std::make_optional(slices->IdsData()[lastDepth]); // get the depth here - } - size_t index = slices->AppendInternalSlice(sliceData.timestamp, sliceData.duration, sliceData.internalTid, - sliceData.cat, sliceData.name, depth, parentId); - sliceStack->push_back(index); - return true; -} - -bool SliceFilter::EndSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId) +size_t SliceFilter::EndSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, DataIndex category, DataIndex name) { - InternalTid internalTid = INVALID_UTID; - if (threadGroupId) { - auto actThreadGroupIdIter = pidTothreadGroupId_.find(pid); - if (actThreadGroupIdIter == pidTothreadGroupId_.end()) { - callEventDisMatchCount++; - return false; - } - uint32_t actThreadGroupId = actThreadGroupIdIter->second; - if (threadGroupId != actThreadGroupId) { - TS_LOGD("pid %u mismatched thread group id %u", pid, actThreadGroupId); - } - internalTid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(pid, actThreadGroupId); - } else { - internalTid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(pid, 0); - } - - const auto& stack = sliceStackMap_[internalTid]; - if (stack.empty()) { - TS_LOGW("a slice end do not match a slice start event"); - callEventDisMatchCount++; - return false; - } - - auto slices = traceDataCache_->GetInternalSlicesData(); - size_t index = stack.back(); - slices->SetDuration(index, timestamp); - sliceStackMap_[internalTid].pop_back(); - // update dur of parent slice maybe - auto parentId = slices->ParentIdData()[index]; - if (parentId.has_value()) { - slices->SetDuration(parentId.value(), timestamp); - } - return true; + return CompleteSlice(timestamp, pid, category, name); } -uint64_t SliceFilter::GenHashByStack(const StackOfSlices& sliceStack) const +void SliceFilter::Clear() { - std::string hashStr; - const auto& sliceSet = traceDataCache_->GetConstInternalSlicesData(); - for (size_t i = 0; i < sliceStack.size(); i++) { - size_t index = sliceStack[i]; - hashStr += "cat"; - hashStr += std::to_string(sliceSet.CatsData()[index]); - hashStr += "name"; - hashStr += std::to_string(sliceSet.NamesData()[index]); - } - - const uint64_t stackHashMask = uint64_t(-1) >> 1; - return (std::hash{}(hashStr)) & stackHashMask; + asyncEventMap_.Clear(); + asyncNoEndingEventMap_.clear(); + irqEventMap_.clear(); + softIrqEventMap_.clear(); + asyncEventFilterMap_.clear(); + sliceStackMap_.clear(); + depthHolder_.clear(); + sliceRowToArgsSetId_.clear(); + argsSetIdToSliceRow_.clear(); + argsSetIdToSliceRow_.clear(); + argsSet_.clear(); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/slice_filter.h b/host/trace_streamer/src/filter/slice_filter.h old mode 100644 new mode 100755 index c2cb7ad83412c26916311ad332e13ed654a0d6bb..1fab2f54e82d3ef472ac8f22492f60af91d11a31 --- a/host/trace_streamer/src/filter/slice_filter.h +++ b/host/trace_streamer/src/filter/slice_filter.h @@ -29,10 +29,13 @@ namespace SysTuning { namespace TraceStreamer { struct SliceData { uint64_t timestamp; - uint64_t duration; + int32_t duration; InternalTid internalTid; DataIndex cat; DataIndex name; + uint32_t depth; + uint64_t index; + uint32_t argSetId; }; struct AsyncEvent { uint64_t timestamp; @@ -43,29 +46,72 @@ public: SliceFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter); ~SliceFilter() override; - bool BeginSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, DataIndex cat, DataIndex nameIndex); + size_t BeginSlice(const std::string& comm, + uint64_t timestamp, + uint32_t pid, + uint32_t threadGroupId, + DataIndex cat, + DataIndex nameIndex); size_t BeginBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet args = ArgsSet()); - size_t BeginAsyncBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, - ArgsSet args = ArgsSet()); - bool EndBinder(uint64_t timestamp, uint32_t pid, DataIndex category = {}, DataIndex name = {}, ArgsSet args = {}); - bool EndSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId); - void StartAsyncSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, int64_t cookie, DataIndex nameIndex); + size_t StartSlice(uint64_t timestamp, + uint32_t pid, + DataIndex cat, + DataIndex nameIndex, + ArgsSet& args, + SliceData sliceData = SliceData()); + size_t AsyncBinder(uint64_t timestamp, uint32_t pid, DataIndex cat, DataIndex nameIndex, ArgsSet& args); + size_t EndBinder(uint64_t timestamp, + uint32_t pid, + DataIndex category = INVALID_UINT64, + DataIndex name = INVALID_UINT64, + ArgsSet args = {}); + size_t CompleteSlice(uint64_t timestamp, + uint32_t pid, + DataIndex category = INVALID_UINT64, + DataIndex name = INVALID_UINT64, + ArgsSet args = {}); + size_t EndSlice(uint64_t timestamp, + uint32_t pid, + uint32_t threadGroupId, + DataIndex category = INVALID_UINT64, + DataIndex name = INVALID_UINT64); + void StartAsyncSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, uint64_t cookie, DataIndex nameIndex); void - FinishAsyncSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, int64_t cookie, DataIndex nameIndex); - uint32_t AddArgs(FilterId, DataIndex key1, DataIndex key2, ArgsSet& args); + FinishAsyncSlice(uint64_t timestamp, uint32_t pid, uint32_t threadGroupId, uint64_t cookie, DataIndex nameIndex); void IrqHandlerEntry(uint64_t timestamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex); + std::tuple AddArgs(uint32_t tid, DataIndex key1, DataIndex key2, ArgsSet& args); void IrqHandlerExit(uint64_t timestamp, uint32_t cpu, ArgsSet args); void SoftIrqEntry(uint64_t timestamp, uint32_t cpu, DataIndex catalog, DataIndex nameIndex); void SoftIrqExit(uint64_t timestamp, uint32_t cpu, ArgsSet args); + void Clear(); + private: - using StackOfSlices = std::vector; - uint64_t GenHashByStack(const StackOfSlices& sliceStack) const; - bool BeginSliceInternal(const SliceData& sliceData); + struct StackInfo { + bool isAsyncEvent = false; + uint32_t asyncEventCount = 0; + uint32_t asyncEventLastBeginTs = 0; + std::vector sliceStack; + }; + using SlicesStack = std::vector; + using StackOfSlices = StackInfo; + using StackOnDepth = std::map; + // uint64_t GenHashByStack(const StackOfSlices& sliceStack) const; + // bool BeginSliceInternal(const SliceData& sliceData); + void RememberSliceData(InternalTid internalTid, + std::unordered_map& stackMap, + SliceData& slice, + uint32_t depth, + uint64_t index); + uint8_t UpdateDepth(bool increase, InternalTid internalTid, int32_t depth = -1); + void CloseUnMatchedSlice(int64_t ts, SlicesStack& stack, InternalTid itid); + int32_t MatchingIncompleteSliceIndex(const SlicesStack& stack, DataIndex category, DataIndex name); + uint8_t CurrentDepth(InternalTid internalTid); + private: // The parameter list is tid, cookid, functionName, asyncCallId. TripleMap asyncEventMap_; // this is only used to calc the layer of the async event in same time range - std::map asyncNoEndingEventMap_ = {}; + std::map asyncNoEndingEventMap_ = {}; // irq map, key1 is cpu, key2 struct IrqRecords { uint64_t ts; @@ -76,18 +122,22 @@ private: std::unordered_map softIrqEventMap_ = {}; std::map asyncEventFilterMap_ = {}; std::unordered_map sliceStackMap_ = {}; - std::unordered_map binderStackMap_ = {}; + std::unordered_map& binderStackMap_ = sliceStackMap_; + std::unordered_map depthHolder_ = {}; std::unordered_map pidTothreadGroupId_ = {}; uint64_t asyncEventSize_ = 0; uint64_t asyncEventDisMatchCount = 0; uint64_t callEventDisMatchCount = 0; - std::unordered_map binderQueue_ = {}; - std::unordered_map argsToSliceQueue_ = {}; + std::unordered_map sliceRowToArgsSetId_ = {}; + std::unordered_map argsSetIdToSliceRow_ = {}; + std::unordered_map tidToArgsSetId_ = {}; struct SliceInfo { uint32_t row; ArgsSet args_tracker; }; std::unordered_map> argsSet_ = {}; + DataIndex asyncBeginCountId_ = traceDataCache_->GetDataIndex("legacy_unnestable_begin_count"); + DataIndex asyncBeginTsId_ = traceDataCache_->GetDataIndex("legacy_unnestable_last_begin_ts"); }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/stat_filter.cpp b/host/trace_streamer/src/filter/stat_filter.cpp old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/filter/stat_filter.h b/host/trace_streamer/src/filter/stat_filter.h old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/filter/symbols_filter.cpp b/host/trace_streamer/src/filter/symbols_filter.cpp old mode 100644 new mode 100755 index 277272595945140881a65b699fff7e33a67f0797..ba9497b4d5d3dc1b7ea562478832db1cdf73d0a7 --- a/host/trace_streamer/src/filter/symbols_filter.cpp +++ b/host/trace_streamer/src/filter/symbols_filter.cpp @@ -53,5 +53,9 @@ const DataIndex& SymbolsFilter::GetFunc(uint64_t addr) const return symbolsMap_.at(addr); } } +void SymbolsFilter::Clear() +{ + symbolsMap_.clear(); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/symbols_filter.h b/host/trace_streamer/src/filter/symbols_filter.h old mode 100644 new mode 100755 index 4814c86c47e83e855734142a9af11741d7968b1e..ede9c3726c69bd63ea3d0ea29a498d33eaa8f380 --- a/host/trace_streamer/src/filter/symbols_filter.h +++ b/host/trace_streamer/src/filter/symbols_filter.h @@ -31,6 +31,7 @@ public: void RegisterFunc(uint64_t addr, DataIndex funcNameDictIndex); const DataIndex& GetFunc(uint64_t addr) const; + void Clear(); private: std::map symbolsMap_ = {}; }; diff --git a/host/trace_streamer/src/filter/system_event_measure_filter.cpp b/host/trace_streamer/src/filter/system_event_measure_filter.cpp index 7f79deac42dc2feaddf40ec86cf3454ae6be01e9..37b98f1b2374eec52ece8c1e0195dafabcd69727 100644 --- a/host/trace_streamer/src/filter/system_event_measure_filter.cpp +++ b/host/trace_streamer/src/filter/system_event_measure_filter.cpp @@ -32,7 +32,11 @@ SystemEventMeasureFilter::~SystemEventMeasureFilter() {} void SystemEventMeasureFilter::AppendNewMeasureData(DataIndex nameIndex, uint64_t timestamp, int64_t value) { auto filterId = GetOrCreateFilterId(nameIndex); - traceDataCache_->GetMeasureData()->AppendMeasureData(0, timestamp, value, filterId); + traceDataCache_->GetSysMemMeasureData()->AppendMeasureData(0, timestamp, value, filterId); +} +uint32_t SystemEventMeasureFilter::AppendNewMeasureFilter(DataIndex nameIndex) +{ + return GetOrCreateFilterId(nameIndex); } uint32_t SystemEventMeasureFilter::GetOrCreateFilterId(DataIndex nameIndex) { @@ -57,7 +61,15 @@ void SystemEventMeasureFilter::AddCertainFilterId(DataIndex nameIndex, uint64_t } else if (filterType_ == E_SYS_VIRTUAL_MEMORY_FILTER) { traceDataCache_->GetSysMeasureFilterData()->AppendNewFilter(filterId, sysVMemoryFilterId_, static_cast(nameIndex)); + } else if (filterType_ == E_SYS_EVENT_SOURCE_FILTER) { + traceDataCache_->GetSysMeasureFilterData()->AppendNewFilter(filterId, sysEventSourceFilterId_, + static_cast(nameIndex)); } } + +void SystemEventMeasureFilter::Clear() +{ + tidStreamIdFilterIdMap_.clear(); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/filter/system_event_measure_filter.h b/host/trace_streamer/src/filter/system_event_measure_filter.h index 8baf4a62e347794b193d9dd721ae7d47738b4749..2eec14a67ca49c1fcfee29e496d0a01c1b151a46 100644 --- a/host/trace_streamer/src/filter/system_event_measure_filter.h +++ b/host/trace_streamer/src/filter/system_event_measure_filter.h @@ -27,7 +27,7 @@ namespace SysTuning { namespace TraceStreamer { -enum SysEventType { E_SYS_MEMORY_FILTER, E_SYS_VIRTUAL_MEMORY_FILTER }; +enum SysEventType { E_SYS_MEMORY_FILTER, E_SYS_VIRTUAL_MEMORY_FILTER, E_SYS_EVENT_SOURCE_FILTER }; class SystemEventMeasureFilter : private FilterBase { public: @@ -36,7 +36,8 @@ public: SystemEventMeasureFilter& operator=(const SystemEventMeasureFilter&) = delete; ~SystemEventMeasureFilter() override; void AppendNewMeasureData(DataIndex nameIndex, uint64_t timestamp, int64_t value); - + uint32_t AppendNewMeasureFilter(DataIndex nameIndex); + void Clear(); private: uint32_t GetOrCreateFilterId(DataIndex nameIndex); void AddCertainFilterId(DataIndex nameIndex, uint64_t filterId); @@ -45,9 +46,11 @@ private: const std::map filterTypeValue = { {E_SYS_MEMORY_FILTER, "sys_memory_filter"}, - {E_SYS_VIRTUAL_MEMORY_FILTER, "sys_virtual_memory_filter"}}; + {E_SYS_VIRTUAL_MEMORY_FILTER, "sys_virtual_memory_filter"}, + {E_SYS_EVENT_SOURCE_FILTER, "sys_event_source_filter"}}; const DataIndex sysMemoryFilterId_ = traceDataCache_->GetDataIndex("sys_memory_filter"); const DataIndex sysVMemoryFilterId_ = traceDataCache_->GetDataIndex("sys_virtual_memory_filter"); + const DataIndex sysEventSourceFilterId_ = traceDataCache_->GetDataIndex("sys_event_source_filter"); }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/include/BUILD.gn b/host/trace_streamer/src/include/BUILD.gn old mode 100644 new mode 100755 index e0f6aa748092c12737d8357c20351724f4c3a677..e9ede7f9c4cae8ab3aeb8b9db4982b44effb3711 --- a/host/trace_streamer/src/include/BUILD.gn +++ b/host/trace_streamer/src/include/BUILD.gn @@ -16,6 +16,7 @@ ohos_source_set("ibase") { "codec_cov.h", "file.h", "log.h", + "numerical_to_string.h", "parting_string.h", "string_to_numerical.h", ] diff --git a/host/trace_streamer/src/include/codec_cov.h b/host/trace_streamer/src/include/codec_cov.h old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/include/file.h b/host/trace_streamer/src/include/file.h old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/include/log.h b/host/trace_streamer/src/include/log.h old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/include/numerical_to_string.h b/host/trace_streamer/src/include/numerical_to_string.h new file mode 100644 index 0000000000000000000000000000000000000000..e019d789b27e8a9e4c10ecf6b84ccc2625723b53 --- /dev/null +++ b/host/trace_streamer/src/include/numerical_to_string.h @@ -0,0 +1,35 @@ +/* + * 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. + */ +#ifndef INCLUDE_BASE_NUMERICAL_TO_STRING_H_ +#define INCLUDE_BASE_NUMERICAL_TO_STRING_H_ +#include +#include "string_to_numerical.h" +#include "ts_common.h" + +namespace SysTuning { +namespace base { +// Put uint_ 64 type numbers are converted to hexadecimal numbers and expressed as strings. +inline std::string Uint64ToHexText(uint64_t inputNumber) +{ + if (inputNumber == INVALID_UINT64) { + return ""; + } + std::string str = "0x" + base::number(inputNumber, base::INTEGER_RADIX_TYPE_HEX); + return str; +} +} // namespace base +} // namespace SysTuning + +#endif // INCLUDE_BASE_NUMERICAL_TO_STRING_H_ diff --git a/host/trace_streamer/src/include/parting_string.h b/host/trace_streamer/src/include/parting_string.h old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/include/string_to_numerical.h b/host/trace_streamer/src/include/string_to_numerical.h old mode 100644 new mode 100755 index 3340f5009fabbb38351458ddf3710da1e735399a..ccfce4bc33612fde68c1a7b8a8a1c4a75bac6de9 --- a/host/trace_streamer/src/include/string_to_numerical.h +++ b/host/trace_streamer/src/include/string_to_numerical.h @@ -26,21 +26,34 @@ enum IntegerRadixType { INTEGER_RADIX_TYPE_DEC = 10, INTEGER_RADIX_TYPE_HEX = 16 }; +inline uint16_t GetNameASCIISumNoNum(const std::string& str) +{ + uint32_t sum = 0; + int len = str.length() - 1; + while (len >= 0) { + sum += std::isdigit(str.at(len)) ? 0 : str.at(len); + len--; + } + return sum % INTEGER_RADIX_TYPE_HEX; +} inline std::optional StrToUInt32(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) { if (!str.empty()) { - uint32_t value = static_cast(std::stoul(str, nullptr, base)); - return std::make_optional(value); + char* endPtr = nullptr; + auto value = static_cast(std::strtoul(str.c_str(), &endPtr, base)); + if (!*endPtr) { + return std::make_optional(value); + } } return std::nullopt; } -inline std::string number(int value, int base = INTEGER_RADIX_TYPE_DEC) +inline std::string number(uint64_t value, int base = INTEGER_RADIX_TYPE_DEC) { std::stringstream ss; if (base == INTEGER_RADIX_TYPE_DEC) { - ss << std::oct << value; + ss << std::dec << value; } else if (base == INTEGER_RADIX_TYPE_HEX) { ss << std::hex << value; } @@ -50,8 +63,11 @@ inline std::string number(int value, int base = INTEGER_RADIX_TYPE_DEC) inline std::optional StrToInt32(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) { if (!str.empty()) { - int32_t value = static_cast(std::stol(str, nullptr, base)); - return std::make_optional(value); + char* endPtr = nullptr; + auto value = static_cast(std::strtol(str.c_str(), &endPtr, base)); + if (!*endPtr) { + return std::make_optional(value); + } } return std::nullopt; @@ -60,8 +76,11 @@ inline std::optional StrToInt32(const std::string& str, int base = INTE inline std::optional StrToUInt64(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) { if (!str.empty()) { - uint64_t value = static_cast(std::stoull(str, nullptr, base)); - return std::make_optional(value); + char* endPtr = nullptr; + auto value = static_cast(std::strtoull(str.c_str(), &endPtr, base)); + if (!*endPtr) { + return std::make_optional(value); + } } return std::nullopt; @@ -70,8 +89,11 @@ inline std::optional StrToUInt64(const std::string& str, int base = IN inline std::optional StrToInt64(const std::string& str, int base = INTEGER_RADIX_TYPE_DEC) { if (!str.empty()) { - int64_t value = static_cast(std::stoll(str, nullptr, base)); - return std::make_optional(value); + char* endPtr = nullptr; + int64_t value = static_cast(std::strtoll(str.c_str(), &endPtr, base)); + if (!*endPtr) { + return std::make_optional(value); + } } return std::nullopt; } diff --git a/host/trace_streamer/src/main.cpp b/host/trace_streamer/src/main.cpp old mode 100644 new mode 100755 index 8b16b5a49261b986e9e698e39ed993ad0b42a5c8..3028fde0856fa96ea759c81e233737338271f342 --- a/host/trace_streamer/src/main.cpp +++ b/host/trace_streamer/src/main.cpp @@ -28,6 +28,7 @@ #include "filter/slice_filter.h" #include "http_server.h" #include "log.h" +#include "meta.h" #include "parser/bytrace_parser/bytrace_event_parser.h" #include "parser/bytrace_parser/bytrace_parser.h" #include "parting_string.h" @@ -45,9 +46,7 @@ using namespace SysTuning::base; constexpr size_t G_CHUNK_SIZE = 1024 * 1024; constexpr int G_MIN_PARAM_NUM = 2; constexpr size_t G_FILE_PERMISSION = 664; -size_t g_loadSize = 0; -const char* TRACE_STREAM_VERSION = "2.3.118"; // version -const char* TRACE_STREAM_PUBLISHVERSION = "2022/3/29"; // publish datetime +// set version info in meta.cpp please void ExportStatusToLog(const std::string& dbPath, TraceParserStatus status) { std::string path = dbPath + ".ohos.ts"; @@ -87,7 +86,7 @@ void PrintInformation() } void PrintVersion() { - fprintf(stderr, "version %s\n", TRACE_STREAM_VERSION); + fprintf(stderr, "version %s\n", TRACE_STREAM_VERSION.c_str()); } bool ReadAndParser(SysTuning::TraceStreamer::TraceStreamerSelector& ta, int fd) @@ -182,34 +181,35 @@ int ExportDatabase(TraceStreamerSelector& ts, const std::string& sqliteFilePath) return 0; } +struct TraceExportOption { + std::string traceFilePath; + std::string sqliteFilePath; + bool interactiveState = false; + bool exportMetaTable = true; +}; struct HttpOption { bool enable = false; int port = 9001; }; -int CheckArgs(int argc, - char** argv, - bool& interactiveState, - bool& exportMetaTable, - std::string& traceFilePath, - std::string& sqliteFilePath, - HttpOption& httpOption) +int CheckArgs(int argc, char** argv, TraceExportOption& traceExportOption, HttpOption& httpOption) { for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-e")) { - if (++i == argc) { + i++; + if (i == argc) { ShowHelpInfo(argv[0]); return 1; } - sqliteFilePath = std::string(argv[i]); + traceExportOption.sqliteFilePath = std::string(argv[i]); continue; } else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--command")) { - interactiveState = true; + traceExportOption.interactiveState = true; continue; } else if (!strcmp(argv[i], "-i") || !strcmp(argv[i], "--info")) { PrintInformation(); } else if (!strcmp(argv[i], "-nm") || !strcmp(argv[i], "--nometa")) { - exportMetaTable = false; + traceExportOption.exportMetaTable = false; continue; } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--v") || !strcmp(argv[i], "-version") || !strcmp(argv[i], "--version")) { @@ -226,10 +226,11 @@ int CheckArgs(int argc, httpOption.port = std::stoi(argv[i]); continue; } - traceFilePath = std::string(argv[i]); + traceExportOption.traceFilePath = std::string(argv[i]); } - if ((traceFilePath.empty() || (!interactiveState && sqliteFilePath.empty())) - && !httpOption.enable) { + if ((traceExportOption.traceFilePath.empty() || + (!traceExportOption.interactiveState && traceExportOption.sqliteFilePath.empty())) && + !httpOption.enable) { ShowHelpInfo(argv[0]); return 1; } @@ -237,22 +238,18 @@ int CheckArgs(int argc, } } // namespace TraceStreamer } // namespace SysTuning - int main(int argc, char** argv) { if (argc < G_MIN_PARAM_NUM) { ShowHelpInfo(argv[0]); return 1; } - std::string traceFilePath; - std::string sqliteFilePath; - bool interactiveState = false; - bool exportMetaTable = true; + TraceExportOption tsOption; HttpOption httpOption; - int ret = CheckArgs(argc, argv, interactiveState, exportMetaTable, traceFilePath, sqliteFilePath, httpOption); + int ret = CheckArgs(argc, argv, tsOption, httpOption); if (ret) { - if (!sqliteFilePath.empty()) { - ExportStatusToLog(sqliteFilePath, GetAnalysisResult()); + if (!tsOption.sqliteFilePath.empty()) { + ExportStatusToLog(tsOption.sqliteFilePath, GetAnalysisResult()); } return 0; } @@ -265,23 +262,28 @@ int main(int argc, char** argv) return 0; } TraceStreamerSelector ts; - ts.EnableMetaTable(exportMetaTable); - if (OpenAndParserFile(ts, traceFilePath)) { - if (!sqliteFilePath.empty()) { - ExportStatusToLog(sqliteFilePath, GetAnalysisResult()); + ts.EnableMetaTable(tsOption.exportMetaTable); + if (OpenAndParserFile(ts, tsOption.traceFilePath)) { + if (!tsOption.sqliteFilePath.empty()) { + ExportStatusToLog(tsOption.sqliteFilePath, GetAnalysisResult()); } return 1; } - if (interactiveState) { + if (tsOption.interactiveState) { + MetaData* metaData = ts.GetMetaData(); + metaData->SetOutputFileName("command line mode"); + metaData->SetParserToolVersion(TRACE_STREAM_VERSION.c_str()); + metaData->SetParserToolPublishDateTime(TRACE_STREAM_PUBLISHVERSION.c_str()); + metaData->SetTraceDataSize(g_loadSize); ts.SearchData(); return 0; } - if (ExportDatabase(ts, sqliteFilePath)) { - ExportStatusToLog(sqliteFilePath, GetAnalysisResult()); + if (ExportDatabase(ts, tsOption.sqliteFilePath)) { + ExportStatusToLog(tsOption.sqliteFilePath, GetAnalysisResult()); return 1; } - if (!sqliteFilePath.empty()) { - ExportStatusToLog(sqliteFilePath, GetAnalysisResult()); + if (!tsOption.sqliteFilePath.empty()) { + ExportStatusToLog(tsOption.sqliteFilePath, GetAnalysisResult()); } return 0; } diff --git a/host/trace_streamer/src/multi_platform/BUILD.gn b/host/trace_streamer/src/multi_platform/BUILD.gn deleted file mode 100644 index 35da1afb016d016c274e973b3089cff451e5daa3..0000000000000000000000000000000000000000 --- a/host/trace_streamer/src/multi_platform/BUILD.gn +++ /dev/null @@ -1,305 +0,0 @@ -# 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("//build/ohos.gni") -import("../ts.gni") -if (use_wasm) { -} else { -} -if (use_wasm) { - source_set("proto_services_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/compaction.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/compaction.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} else { - shared_library("proto_services_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/compaction.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/compaction.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} -if (use_wasm) { - source_set("ftrace_data_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/services/common_types.pb.cc", - "${OHOS_PROTO_GEN}/services/common_types.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/binder.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/binder.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/block.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/block.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cgroup.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cgroup.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/clk.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/clk.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cpuhp.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cpuhp.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/dma_fence.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/dma_fence.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ext4.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ext4.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filelock.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filelock.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filemap.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filemap.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace_event.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace_event.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/gpio.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/gpio.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/i2c.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/i2c.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ipi.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ipi.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/irq.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/irq.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/kmem.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/kmem.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/net.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/net.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/oom.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/oom.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/pagemap.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/pagemap.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/power.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/power.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/printk.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/printk.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/raw_syscalls.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/raw_syscalls.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/rcu.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/rcu.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sched.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sched.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/signal.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/signal.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sunrpc.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sunrpc.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/task.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/task.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/timer.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/timer.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/trace_plugin_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/trace_plugin_result.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/v4l2.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/v4l2.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/vmscan.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/vmscan.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/workqueue.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/workqueue.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/writeback.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/writeback.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} else { - shared_library("ftrace_data_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/services/common_types.pb.cc", - "${OHOS_PROTO_GEN}/services/common_types.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/binder.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/binder.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/block.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/block.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cgroup.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cgroup.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/clk.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/clk.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cpuhp.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/cpuhp.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/dma_fence.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/dma_fence.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ext4.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ext4.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filelock.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filelock.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filemap.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/filemap.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace_event.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ftrace_event.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/gpio.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/gpio.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/i2c.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/i2c.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ipi.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/ipi.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/irq.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/irq.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/kmem.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/kmem.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/net.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/net.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/oom.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/oom.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/pagemap.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/pagemap.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/power.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/power.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/printk.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/printk.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/raw_syscalls.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/raw_syscalls.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/rcu.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/rcu.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sched.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sched.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/signal.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/signal.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sunrpc.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/sunrpc.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/task.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/task.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/timer.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/timer.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/trace_plugin_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/trace_plugin_result.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/v4l2.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/v4l2.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/vmscan.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/vmscan.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/workqueue.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/workqueue.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/writeback.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/writeback.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} -if (use_wasm) { - source_set("memory_data_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_common.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_common.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_config.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_config.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_result.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} else { - shared_library("memory_data_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_common.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_common.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_config.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_config.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/memory_data/memory_plugin_result.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} -if (use_wasm) { - source_set("hilog_data_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/hilog_data/hilog_plugin_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/hilog_data/hilog_plugin_result.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} else { - shared_library("hilog_data_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/hilog_data/hilog_plugin_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/hilog_data/hilog_plugin_result.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} - -if (use_wasm) { - source_set("native_hook_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_config.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_config.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_result.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} else { - shared_library("native_hook_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_config.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_config.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/native_hook/native_hook_result.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} - -if (use_wasm) { - source_set("hidump_data_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_config.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_config.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_result.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} else { - shared_library("hidump_data_cpp") { - sources = [ - "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_config.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_config.pb.h", - "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_result.pb.cc", - "${OHOS_PROTO_GEN}/types/plugins/hidump_data/hidump_plugin_result.pb.h", - ] - include_dirs = [ - "//third_party/protobuf/src", - "//src/include", - ] - } -} diff --git a/host/trace_streamer/src/multi_platform/global.pri b/host/trace_streamer/src/multi_platform/global.pri deleted file mode 100644 index a1dab5b59f50c843ae3cc438c38b50bcd8f23ae8..0000000000000000000000000000000000000000 --- a/host/trace_streamer/src/multi_platform/global.pri +++ /dev/null @@ -1,75 +0,0 @@ -# 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. - -#DEFINES +=_AIX -#DEFINES +=_GLIBCXX_BITS_STD_ABS_H -#DEFINES +=__CORRECT_ISO_CPP_STDLIB_H_PROTO -#DEFINES += __CORRECT_ISO_CPP11_MATH_H_PROTO_FP -#DEFINES +=__CORRECT_ISO_CPP_MATH_H_PROTO -#DEFINES +=_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC - -INCLUDEPATH +=$${ROOTSRCDIR}/include -INCLUDEPATH +=$${ROOTSRCDIR}/ -CONFIG(debug, debug|release){ - BUILDVERSION = _debug - message("debug") -}else{ - message("release") - BUILDVERSION = - DEFINES += NDEBUG -} -contains(QT_ARCH, i386) { - message("qmake" $$TARGET "32-bit") - BIT = x32 -} else { - message("qmake" $$TARGET "64-bit") - BIT = -} -macx{ - PLATFORM = macx - TOOL = - BIT = -} -unix:!macx { - PLATFORM = linux - TOOL = - BIT = -} -win32 { - PLATFORM = windows - TOOL = -} -DESTFOLDER =$${PLATFORM}$${BIT}$${TOOL}$${BUILDVERSION} -islib{ -message("this is for lib") -DESTDIR = $${ROOTSRCDIR}/lib/$${DESTFOLDER} -} else { -message("this is for app") -DESTDIR = $${ROOTSRCDIR}/out/$${DESTFOLDER} -} -unix{ -QMAKE_CXXFLAGS += -BigObj -INCLUDEPATH += $$DESTDIR/gen/build_config -INCLUDEPATH += $$DESTDIR/gen -INCLUDEPATH +=/usr/include/c++/7 -INCLUDEPATH +=/usr/include/x86_64-linux-gnu/ -} else { -INCLUDEPATH += $${GENDIR}/gen/build_config -INCLUDEPATH += $${GENDIR}/gen -DEFINES += WIN32 -QMAKE_CXXFLAGS += -BigObj -staticlib{ -QMAKE_CXXFLAGS += -Ofast -flto -} -} -OBJECTS_DIR = $${ROOTSRCDIR}/tmp_$${TARGET}_$${DESTFOLDER} diff --git a/host/trace_streamer/src/multi_platform/protogen.pri b/host/trace_streamer/src/multi_platform/protogen.pri deleted file mode 100644 index 72da7fded06058c7c2aeef807a04ab35f2d50fdc..0000000000000000000000000000000000000000 --- a/host/trace_streamer/src/multi_platform/protogen.pri +++ /dev/null @@ -1,107 +0,0 @@ -# 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. -PROTOGEN = $$PWD/../../third_party/protogen -INCLUDEPATH += $${PROTOGEN}/types/plugins/ftrace_data \ - $${PROTOGEN}/types/plugins/memory_data \ - $${PROTOGEN}/types/plugins/hilog_data \ - $${PROTOGEN}/types/plugins/native_hook \ - $${PROTOGEN}/types/plugins/hidump_data \ - $${PROTOGEN} -SOURCES +=$${PROTOGEN}/services/common_types.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/trace_plugin_result.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/ftrace_event.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/irq.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/vmscan.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/workqueue.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/task.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/power.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/sched.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/filemap.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/i2c.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/kmem.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/block.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/ipi.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/ftrace.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/ext4.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/oom.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/compaction.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/clk.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/cgroup.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/binder.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/signal.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/sunrpc.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/net.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/cpuhp.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/writeback.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/v4l2.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/pagemap.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/dma_fence.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/printk.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/filelock.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/gpio.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/timer.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/raw_syscalls.pb.cc \ - $${PROTOGEN}/types/plugins/ftrace_data/rcu.pb.cc \ - \ - $${PROTOGEN}/types/plugins/memory_data/memory_plugin_common.pb.cc \ - $${PROTOGEN}/types/plugins/memory_data/memory_plugin_config.pb.cc \ - $${PROTOGEN}/types/plugins/memory_data/memory_plugin_result.pb.cc \ - $${PROTOGEN}/types/plugins/hilog_data/hilog_plugin_result.pb.cc \ - $${PROTOGEN}/types/plugins/native_hook/native_hook_result.pb.cc \ - $${PROTOGEN}/types/plugins/native_hook/native_hook_config.pb.cc \ - $${PROTOGEN}/types/plugins/hidump_data/hidump_plugin_result.pb.cc \ - $${PROTOGEN}/types/plugins/hidump_data/hidump_plugin_config.pb.cc - -HEADERS += $${PROTOGEN}/services/common_types.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/trace_plugin_result.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/ftrace_event.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/irq.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/vmscan.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/workqueue.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/task.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/power.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/sched.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/filemap.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/i2c.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/kmem.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/block.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/ipi.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/ftrace.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/ext4.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/oom.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/compaction.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/clk.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/cgroup.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/signal.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/binder.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/net.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/v4l2.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/writeback.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/cpuhp.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/pagemap.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/dma_fence.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/printk.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/filelock.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/gpio.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/timer.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/raw_syscalls.pb.h \ - $${PROTOGEN}/types/plugins/ftrace_data/rcu.pb.h \ - \ - $${PROTOGEN}/types/plugins/memory_data/memory_plugin_common.pb.h \ - $${PROTOGEN}/types/plugins/memory_data/memory_plugin_config.pb.h \ - $${PROTOGEN}/types/plugins/memory_data/memory_plugin_result.pb.h \ - $${PROTOGEN}/types/plugins/hilog_data/hilog_plugin_result.pb.h \ - $${PROTOGEN}/types/plugins/native_hook/native_hook_result.pb.h \ - $${PROTOGEN}/types/plugins/native_hook/native_hook_config.pb.h \ - $${PROTOGEN}/types/plugins/hidump_data/hidump_plugin_result.pb.h \ - $${PROTOGEN}/types/plugins/hidump_data/hidump_plugin_config.pb.h diff --git a/host/trace_streamer/src/parser/BUILD.gn b/host/trace_streamer/src/parser/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..72d9fa4b98135a623379ba13e19bdfc8534047e2 --- /dev/null +++ b/host/trace_streamer/src/parser/BUILD.gn @@ -0,0 +1,76 @@ +# 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("//build/ohos.gni") +import("//src/ts.gni") + +ohos_source_set("parser") { + sources = [ + "bytrace_parser/bytrace_event_parser.cpp", + "bytrace_parser/bytrace_event_parser.h", + "bytrace_parser/bytrace_parser.cpp", + "bytrace_parser/bytrace_parser.h", + "common_types.h", + "event_parser_base.cpp", + "event_parser_base.h", + "print_event_parser.cpp", + "print_event_parser.h", + "thread_state.cpp", + "thread_state.h", + ] + deps = [ + "ebpf_parser:ebpf_parser", + "htrace_parser:htrace_parser", + ] + include_dirs = [ + "//third_party/protobuf/src", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/${kernel_version}", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data", + "${OHOS_PROTO_GEN}/types/plugins/native_hook", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}/types/plugins/network_data", + "${OHOS_PROTO_GEN}/types/plugins/cpu_data", + "${OHOS_PROTO_GEN}/types/plugins/diskio_data", + "${OHOS_PROTO_GEN}/types/plugins/hisysevent_data", + "${OHOS_PROTO_GEN}/types/plugins/process_data", + "${OHOS_PROTO_GEN}/types/plugins/", + "${OHOS_PROTO_GEN}", + "//third_party/sqlite/include", + "//src/base", + "//src/cfg", + "//src/trace_streamer", + "//src/trace_data", + "//src/include", + "//src/filter", + "//src", + ".", + "//third_party/json-master/include", + "//third_party/json-master/include/nlohmann", + ] + + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + if (is_test) { + cflags += [ "-D IS_UT" ] + } + } +} diff --git a/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp b/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp old mode 100644 new mode 100755 index 8ab3d13df46530c63811a7380019de3f8045de94..bba5ddbe38f164a19bb58be41eb8d41722c1d017 --- a/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp +++ b/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.cpp @@ -47,10 +47,6 @@ std::string GetFunctionName(const std::string_view& text, const std::string_view BytraceEventParser::BytraceEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter) : EventParserBase(dataCache, filter), - ioWaitId_(const_cast(dataCache)->GetDataIndex("io_wait")), - workQueueId_(const_cast(dataCache)->GetDataIndex("workqueue")), - schedWakeupId_(const_cast(dataCache)->GetDataIndex("sched_wakeup")), - schedBlockedReasonId_(const_cast(dataCache)->GetDataIndex("sched_blocked_reason")), printEventParser_(traceDataCache_, streamFilters_) { eventToFunctionMap_ = { @@ -61,7 +57,9 @@ BytraceEventParser::BytraceEventParser(TraceDataCache* dataCache, const TraceStr {config_.eventNameMap_.at(TRACE_EVENT_TASK_NEWTASK), bind(&BytraceEventParser::TaskNewtaskEvent, this, std::placeholders::_1, std::placeholders::_2)}, {config_.eventNameMap_.at(TRACE_EVENT_TRACING_MARK_WRITE), - bind(&BytraceEventParser::TracingMarkWriteEvent, this, std::placeholders::_1, std::placeholders::_2)}, + bind(&BytraceEventParser::TracingMarkWriteOrPrintEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_PRINT), + bind(&BytraceEventParser::TracingMarkWriteOrPrintEvent, this, std::placeholders::_1, std::placeholders::_2)}, {config_.eventNameMap_.at(TRACE_EVENT_SCHED_WAKEUP), bind(&BytraceEventParser::SchedWakeupEvent, this, std::placeholders::_1, std::placeholders::_2)}, {config_.eventNameMap_.at(TRACE_EVENT_SCHED_WAKING), @@ -70,6 +68,8 @@ BytraceEventParser::BytraceEventParser(TraceDataCache* dataCache, const TraceStr bind(&BytraceEventParser::CpuIdleEvent, this, std::placeholders::_1, std::placeholders::_2)}, {config_.eventNameMap_.at(TRACE_EVENT_CPU_FREQUENCY), bind(&BytraceEventParser::CpuFrequencyEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_CPU_FREQUENCY_LIMITS), + bind(&BytraceEventParser::CpuFrequencyLimitsEvent, this, std::placeholders::_1, std::placeholders::_2)}, {config_.eventNameMap_.at(TRACE_EVENT_WORKQUEUE_EXECUTE_START), bind(&BytraceEventParser::WorkqueueExecuteStartEvent, this, std::placeholders::_1, std::placeholders::_2)}, {config_.eventNameMap_.at(TRACE_EVENT_WORKQUEUE_EXECUTE_END), @@ -117,7 +117,7 @@ BytraceEventParser::BytraceEventParser(TraceDataCache* dataCache, const TraceStr bool BytraceEventParser::SchedSwitchEvent(const ArgsMap& args, const BytraceLine& line) const { - if (args.empty() || args.size() < MIN_SCHED_ARGS_COUNT) { + if (args.empty() || args.size() < MIN_SCHED_SWITCH_ARGS_COUNT) { TS_LOGD("Failed to parse sched_switch event, no args or args size < 6"); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_DATA_INVALID); return false; @@ -128,7 +128,7 @@ bool BytraceEventParser::SchedSwitchEvent(const ArgsMap& args, const BytraceLine auto nextPrioValue = base::StrToInt32(args.at("next_prio")); auto prevPidValue = base::StrToUInt32(args.at("prev_pid")); auto nextPidValue = base::StrToUInt32(args.at("next_pid")); - if (!(!prevCommStr.empty() && prevPidValue.has_value() && prevPrioValue.has_value() && nextPidValue.has_value() && + if (!(prevPidValue.has_value() && prevPrioValue.has_value() && nextPidValue.has_value() && nextPrioValue.has_value())) { TS_LOGD("Failed to parse sched_switch event"); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_DATA_INVALID); @@ -149,8 +149,12 @@ bool BytraceEventParser::SchedSwitchEvent(const ArgsMap& args, const BytraceLine nextInternalTid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, nextPidValue.value()); } if (streamFilters_->processFilter_->isThreadNameEmpty(prevPidValue.value())) { - uprevtid = - streamFilters_->processFilter_->UpdateOrCreateThreadWithName(line.ts, prevPidValue.value(), prevCommStr); + if (!prevCommStr.empty()) { + uprevtid = streamFilters_->processFilter_->UpdateOrCreateThreadWithName(line.ts, prevPidValue.value(), + prevCommStr); + } else { + uprevtid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, prevPidValue.value()); + } } else { uprevtid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, prevPidValue.value()); } @@ -163,6 +167,11 @@ bool BytraceEventParser::SchedSwitchEvent(const ArgsMap& args, const BytraceLine bool BytraceEventParser::TaskRenameEvent(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_TASK_RENAME_ARGS_COUNT) { + TS_LOGD("Failed to parse task_rename event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TASK_RENAME, STAT_EVENT_DATA_INVALID); + return false; + } auto prevCommStr = std::string_view(args.at("newcomm")); auto pidValue = base::StrToUInt32(args.at("pid")); streamFilters_->processFilter_->UpdateOrCreateThreadWithName(line.ts, pidValue.value(), prevCommStr); @@ -178,13 +187,12 @@ bool BytraceEventParser::TaskNewtaskEvent(const ArgsMap& args, const BytraceLine return true; } -bool BytraceEventParser::TracingMarkWriteEvent(const ArgsMap& args, const BytraceLine& line) const +bool BytraceEventParser::TracingMarkWriteOrPrintEvent(const ArgsMap& args, const BytraceLine& line) { UNUSED(args); - printEventParser_.ParsePrintEvent(line.ts, line.pid, line.argsStr.c_str()); - return true; + return printEventParser_.ParsePrintEvent(line.task, line.ts, line.pid, line.argsStr.c_str()); } - +// prefer to use waking, unless no waking, can use wakeup bool BytraceEventParser::SchedWakeupEvent(const ArgsMap& args, const BytraceLine& line) const { if (args.size() < MIN_SCHED_WAKEUP_ARGS_COUNT) { @@ -198,10 +206,12 @@ bool BytraceEventParser::SchedWakeupEvent(const ArgsMap& args, const BytraceLine streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_DATA_INVALID); return false; } - DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_wakeup")); auto instants = traceDataCache_->GetInstantsData(); - InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, wakePidValue.value()); - instants->AppendInstantEventData(line.ts, name, internalTid); + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, wakePidValue.value_or(0)); + + InternalTid wakeupFromPid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, line.pid); + + instants->AppendInstantEventData(line.ts, schedWakeupName_, internalTid, wakeupFromPid); std::optional targetCpu = base::StrToUInt32(args.at("target_cpu")); if (targetCpu.has_value()) { traceDataCache_->GetRawData()->AppendRawData(0, line.ts, RAW_SCHED_WAKEUP, targetCpu.value(), internalTid); @@ -212,6 +222,11 @@ bool BytraceEventParser::SchedWakeupEvent(const ArgsMap& args, const BytraceLine bool BytraceEventParser::SchedWakingEvent(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_SCHED_WAKING_ARGS_COUNT) { + TS_LOGD("Failed to parse sched_waking event, no args or args size < 4"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_DATA_INVALID); + return false; + } std::optional wakePidValue = base::StrToUInt32(args.at("pid")); auto wakePidStr = std::string_view(args.at("comm")); if (!wakePidValue.has_value()) { @@ -219,17 +234,21 @@ bool BytraceEventParser::SchedWakingEvent(const ArgsMap& args, const BytraceLine streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_DATA_INVALID); return false; } - DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_waking")); auto instants = traceDataCache_->GetInstantsData(); DataIndex wakePidStrIndex = traceDataCache_->GetDataIndex(wakePidStr); - InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithNameIndex(line.ts, - wakePidValue.value(), - wakePidStrIndex); + InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithNameIndex( + line.ts, wakePidValue.value(), wakePidStrIndex); + + DataIndex wakeByPidStrIndex = traceDataCache_->GetDataIndex(line.task); + InternalTid internalTidWakeup = + streamFilters_->processFilter_->UpdateOrCreateThreadWithNameIndex(line.ts, line.pid, wakeByPidStrIndex); streamFilters_->cpuFilter_->InsertWakeupEvent(line.ts, internalTid); - instants->AppendInstantEventData(line.ts, name, internalTid); + InternalTid wakeupFromPid = streamFilters_->processFilter_->UpdateOrCreateThread(line.ts, line.pid); + instants->AppendInstantEventData(line.ts, schedWakingName_, internalTid, wakeupFromPid); std::optional targetCpu = base::StrToUInt32(args.at("target_cpu")); if (targetCpu.has_value()) { - traceDataCache_->GetRawData()->AppendRawData(0, line.ts, RAW_SCHED_WAKING, targetCpu.value(), internalTid); + traceDataCache_->GetRawData()->AppendRawData(0, line.ts, RAW_SCHED_WAKING, targetCpu.value(), + internalTidWakeup); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_RECEIVED); } @@ -238,6 +257,11 @@ bool BytraceEventParser::SchedWakingEvent(const ArgsMap& args, const BytraceLine bool BytraceEventParser::CpuIdleEvent(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_CPU_IDLE_ARGS_COUNT) { + TS_LOGD("Failed to parse cpu_idle event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_DATA_INVALID); + return false; + } std::optional eventCpuValue = base::StrToUInt32(args.at("cpu_id")); std::optional newStateValue = base::StrToInt64(args.at("state")); if (!eventCpuValue.has_value()) { @@ -250,17 +274,22 @@ bool BytraceEventParser::CpuIdleEvent(const ArgsMap& args, const BytraceLine& li streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_DATA_INVALID); return false; } - auto cpuIdleNameIndex = traceDataCache_->GetDataIndex(line.eventName.c_str()); - streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuIdleNameIndex, line.ts, - newStateValue.value()); // Add cpu_idle event to raw_data_table - traceDataCache_->GetRawData()->AppendRawData(0, line.ts, RAW_CPU_IDLE, eventCpuValue.value(), 0); + auto cpuidleNameIndex = traceDataCache_->GetDataIndex(line.eventName.c_str()); + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuidleNameIndex, line.ts, + config_.GetStateValue(newStateValue.value())); streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_RECEIVED); return true; } bool BytraceEventParser::CpuFrequencyEvent(const ArgsMap& args, const BytraceLine& line) const { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_RECEIVED); + if (args.empty() || args.size() < MIN_CPU_FREQUENCY_ARGS_COUNT) { + TS_LOGD("Failed to parse cpu_frequency event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_DATA_INVALID); + return false; + } std::optional eventCpuValue = base::StrToUInt32(args.at("cpu_id")); std::optional newStateValue = base::StrToInt64(args.at("state")); @@ -280,15 +309,50 @@ bool BytraceEventParser::CpuFrequencyEvent(const ArgsMap& args, const BytraceLin newStateValue.value()); return true; } +bool BytraceEventParser::CpuFrequencyLimitsEvent(const ArgsMap& args, const BytraceLine& line) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY_LIMITS, STAT_EVENT_RECEIVED); + if (args.empty() || args.size() < MIN_CPU_FREQUENCY_ARGS_COUNT) { + TS_LOGD("Failed to parse cpu_frequency event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY_LIMITS, STAT_EVENT_DATA_INVALID); + return false; + } + std::optional eventCpuValue = base::StrToUInt32(args.at("cpu_id")); + std::optional minValue = base::StrToInt64(args.at("min")); + std::optional maxValue = base::StrToInt64(args.at("max")); + + if (!minValue.has_value()) { + TS_LOGD("Failed to get frequency minValue"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY_LIMITS, STAT_EVENT_DATA_INVALID); + return false; + } + if (!maxValue.has_value()) { + TS_LOGD("Failed to get frequency maxValue"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY_LIMITS, STAT_EVENT_DATA_INVALID); + return false; + } + if (!eventCpuValue.has_value()) { + TS_LOGD("Failed to get frequency cpu"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY_LIMITS, STAT_EVENT_DATA_INVALID); + return false; + } + + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuFrequencyLimitMaxNameId, line.ts, + maxValue.value()); + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuFrequencyLimitMinNameId, line.ts, + minValue.value()); + return true; +} bool BytraceEventParser::WorkqueueExecuteStartEvent(const ArgsMap& args, const BytraceLine& line) const { UNUSED(args); auto splitStr = GetFunctionName(line.argsStr, "function "); auto splitStrIndex = traceDataCache_->GetDataIndex(splitStr); - bool result = streamFilters_->sliceFilter_->BeginSlice(line.ts, line.pid, 0, workQueueId_, splitStrIndex); + size_t result = + streamFilters_->sliceFilter_->BeginSlice(line.task, line.ts, line.pid, 0, workQueueId_, splitStrIndex); traceDataCache_->GetInternalSlicesData()->AppendDistributeInfo(); - if (result) { + if (result != INVALID_UINT32) { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_START, STAT_EVENT_RECEIVED); return true; } else { @@ -300,7 +364,7 @@ bool BytraceEventParser::WorkqueueExecuteStartEvent(const ArgsMap& args, const B bool BytraceEventParser::WorkqueueExecuteEndEvent(const ArgsMap& args, const BytraceLine& line) const { UNUSED(args); - if (streamFilters_->sliceFilter_->EndSlice(line.ts, line.pid, 0)) { + if (streamFilters_->sliceFilter_->EndSlice(line.ts, line.pid, 0, workQueueId_)) { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_END, STAT_EVENT_RECEIVED); return true; } else { @@ -311,6 +375,11 @@ bool BytraceEventParser::WorkqueueExecuteEndEvent(const ArgsMap& args, const Byt bool BytraceEventParser::ProcessExitEvent(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_PROCESS_EXIT_ARGS_COUNT) { + TS_LOGD("Failed to parse process_exit event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PROCESS_EXIT, STAT_EVENT_DATA_INVALID); + return false; + } auto comm = std::string_view(args.at("comm")); auto pid = base::StrToUInt32(args.at("pid")); if (!pid.has_value()) { @@ -329,6 +398,11 @@ bool BytraceEventParser::ProcessExitEvent(const ArgsMap& args, const BytraceLine bool BytraceEventParser::SetRateEvent(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_CLOCK_SET_RATE_ARGS_COUNT) { + TS_LOGD("Failed to parse clock_set_rate event, no args or args size < 3"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_SET_RATE, STAT_EVENT_DATA_INVALID); + return false; + } auto name = std::string_view(args.at("name")); auto state = base::StrToInt64(args.at("state")); auto cpu = base::StrToUInt64(args.at("cpu_id")); @@ -340,6 +414,11 @@ bool BytraceEventParser::SetRateEvent(const ArgsMap& args, const BytraceLine& li bool BytraceEventParser::ClockEnableEvent(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_CLOCK_ENABLE_ARGS_COUNT) { + TS_LOGD("Failed to parse clock_enable event, no args or args size < 3"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_ENABLE, STAT_EVENT_DATA_INVALID); + return false; + } auto name = std::string_view(args.at("name")); auto state = base::StrToInt64(args.at("state")); auto cpuId = base::StrToUInt64(args.at("cpu_id")); @@ -350,6 +429,11 @@ bool BytraceEventParser::ClockEnableEvent(const ArgsMap& args, const BytraceLine } bool BytraceEventParser::ClockDisableEvent(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_CLOCK_DISABLE_ARGS_COUNT) { + TS_LOGD("Failed to parse clock_disable event, no args or args size < 3"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_DISABLE, STAT_EVENT_DATA_INVALID); + return false; + } auto name = std::string_view(args.at("name")); auto state = base::StrToInt64(args.at("state")); auto cpuId = base::StrToUInt64(args.at("cpu_id")); @@ -411,8 +495,11 @@ bool BytraceEventParser::IpiExitEvent(const ArgsMap& args, const BytraceLine& li } bool BytraceEventParser::IrqHandlerEntryEvent(const ArgsMap& args, const BytraceLine& line) const { - UNUSED(args); - UNUSED(line); + if (args.empty() || args.size() < MIN_IRQ_HANDLER_ENTRY_ARGS_COUNT) { + TS_LOGD("Failed to parse irq_handler_entry event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_DATA_INVALID); + return false; + } traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_RECEIVED); auto name = std::string_view(args.at("name")); streamFilters_->irqFilter_->IrqHandlerEntry(line.ts, line.cpu, traceDataCache_->GetDataIndex(name)); @@ -420,8 +507,11 @@ bool BytraceEventParser::IrqHandlerEntryEvent(const ArgsMap& args, const Bytrace } bool BytraceEventParser::IrqHandlerExitEvent(const ArgsMap& args, const BytraceLine& line) const { - UNUSED(args); - UNUSED(line); + if (args.empty() || args.size() < MIN_IRQ_HANDLER_EXIT_ARGS_COUNT) { + TS_LOGD("Failed to parse irq_handler_exit event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_DATA_INVALID); + return false; + } traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_RECEIVED); uint32_t ret = (args.at("ret") == "handled") ? 1 : 0; streamFilters_->irqFilter_->IrqHandlerExit(line.ts, line.cpu, ret); @@ -437,6 +527,11 @@ bool BytraceEventParser::SoftIrqRaiseEvent(const ArgsMap& args, const BytraceLin } bool BytraceEventParser::SoftIrqEntryEvent(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_SOFTIRQ_ENTRY_ARGS_COUNT) { + TS_LOGD("Failed to parse softirq_entry event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_DATA_INVALID); + return false; + } traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_RECEIVED); auto vec = base::StrToUInt32(args.at("vec")); streamFilters_->irqFilter_->SoftIrqEntry(line.ts, line.cpu, vec.value()); @@ -444,6 +539,11 @@ bool BytraceEventParser::SoftIrqEntryEvent(const ArgsMap& args, const BytraceLin } bool BytraceEventParser::SoftIrqExitEvent(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_SOFTIRQ_EXIT_ARGS_COUNT) { + TS_LOGD("Failed to parse softirq_exit event, no args or args size < 2"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_INVALID); + return false; + } traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_RECEIVED); auto vec = base::StrToUInt32(args.at("vec")); streamFilters_->irqFilter_->SoftIrqExit(line.ts, line.cpu, vec.value()); @@ -452,6 +552,11 @@ bool BytraceEventParser::SoftIrqExitEvent(const ArgsMap& args, const BytraceLine bool BytraceEventParser::BinderTransaction(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_BINDER_TRANSACTION_ARGS_COUNT) { + TS_LOGD("Failed to parse binder_transaction event, no args or args size < 7"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION, STAT_EVENT_DATA_INVALID); + return false; + } streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION, STAT_EVENT_RECEIVED); auto transactionId = base::StrToInt64(args.at("transaction")); auto destNode = base::StrToUInt32(args.at("dest_node")); @@ -470,6 +575,11 @@ bool BytraceEventParser::BinderTransaction(const ArgsMap& args, const BytraceLin } bool BytraceEventParser::BinderTransactionReceived(const ArgsMap& args, const BytraceLine& line) const { + if (args.empty() || args.size() < MIN_BINDER_TRANSACTION_RECEIVED_ARGS_COUNT) { + TS_LOGD("Failed to parse binder_transaction_received event, no args or args size < 1"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, STAT_EVENT_DATA_INVALID); + return false; + } streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, STAT_EVENT_RECEIVED); auto transactionId = base::StrToInt64(args.at("transaction")); streamFilters_->binderFilter_->ReceiveTraction(line.ts, line.pid, transactionId.value()); @@ -478,8 +588,11 @@ bool BytraceEventParser::BinderTransactionReceived(const ArgsMap& args, const By } bool BytraceEventParser::BinderTransactionAllocBufEvent(const ArgsMap& args, const BytraceLine& line) const { - UNUSED(args); - UNUSED(line); + if (args.empty() || args.size() < MIN_BINDER_TRANSACTION_ALLOC_BUF_ARGS_COUNT) { + TS_LOGD("Failed to parse binder_transaction_alloc_buf event, no args or args size < 3"); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, STAT_EVENT_DATA_INVALID); + return false; + } streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, STAT_EVENT_RECEIVED); auto dataSize = base::StrToUInt64(args.at("data_size")); auto offsetsSize = base::StrToUInt64(args.at("offsets_size")); @@ -487,23 +600,137 @@ bool BytraceEventParser::BinderTransactionAllocBufEvent(const ArgsMap& args, con TS_LOGD("dataSize:%lu, offsetSize:%lu", dataSize.value(), offsetsSize.value()); return true; } -bool BytraceEventParser::ParseDataItem(const BytraceLine& line, const ArgsMap& args, uint32_t tgid) const +void BytraceEventParser::ParseDataItem(const BytraceLine& line) { - traceDataCache_->UpdateTraceTime(line.ts); - if (tgid) { - streamFilters_->processFilter_->UpdateOrCreateThreadWithPidAndName(line.pid, tgid, line.task); + eventList_.push_back(std::move(std::make_unique(line.ts, std::move(line)))); + return; +} +void BytraceEventParser::GetDataSegArgs(BytraceLine& bufLine, ArgsMap& args, uint32_t& tgid) const +{ + if (bufLine.tGidStr.at(0) != '-') { + tgid = base::StrToUInt32(bufLine.tGidStr).value_or(0); } else { - // When tgid is zero, only use tid create thread - streamFilters_->processFilter_->GetOrCreateThreadWithPid(line.pid, tgid); + tgid = 0; + } + + for (base::PartingString ss(bufLine.argsStr, ' '); ss.Next();) { + std::string key; + std::string value; + if (!(std::string(ss.GetCur()).find("=") != std::string::npos)) { + key = "name"; + value = ss.GetCur(); + args.emplace(std::move(key), std::move(value)); + continue; + } + for (base::PartingString inner(ss.GetCur(), '='); inner.Next();) { + if (key.empty()) { + key = inner.GetCur(); + } else { + value = inner.GetCur(); + } + } + args.emplace(std::move(key), std::move(value)); + } +} +void BytraceEventParser::FilterAllEventsTemp() +{ + size_t maxBuffSize = 1000 * 1000; + size_t maxQueue = 2; + if (eventList_.size() < maxBuffSize * maxQueue) { + return; + } + auto cmp = [](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->eventTimestamp < b->eventTimestamp; + }; + std::sort(eventList_.begin(), eventList_.end(), cmp); + auto endOfList = eventList_.begin() + maxBuffSize; + for (auto itor = eventList_.begin(); itor != endOfList; itor++) { + EventInfo* event = itor->get(); + auto it = eventToFunctionMap_.find(event->line.eventName); + if (it != eventToFunctionMap_.end()) { + uint32_t tgid; + ArgsMap args; + GetDataSegArgs(event->line, args, tgid); + if (tgid) { + streamFilters_->processFilter_->UpdateOrCreateThreadWithPidAndName(event->line.pid, tgid, + event->line.task); + } else { + // When tgid is zero, only use tid create thread + streamFilters_->processFilter_->GetOrCreateThreadWithPid(event->line.pid, tgid); + } + if (it->second(args, event->line)) { + traceDataCache_->UpdateTraceTime(event->line.ts); + } + } else { + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_NOTSUPPORTED); + TS_LOGW("UnRecognizable event name:%s", event->line.eventName.c_str()); + } + itor->reset(); } + eventList_.erase(eventList_.begin(), endOfList); +} + +void BytraceEventParser::FilterAllEvents() +{ + auto cmp = [](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->eventTimestamp < b->eventTimestamp; + }; + std::sort(eventList_.begin(), eventList_.end(), cmp); + size_t maxBuffSize = 1000 * 1000; + while (eventList_.size()) { + int size = std::min(maxBuffSize, eventList_.size()); + auto endOfList = eventList_.begin() + size; + for (auto itor = eventList_.begin(); itor != endOfList; itor++) { + EventInfo* event = itor->get(); + BeginFilterEvents(event); + itor->reset(); + } + eventList_.erase(eventList_.begin(), endOfList); + } + eventList_.clear(); + streamFilters_->cpuFilter_->Finish(); + traceDataCache_->dataDict_.Finish(); + traceDataCache_->UpdataZeroThreadInfo(); +} - auto it = eventToFunctionMap_.find(line.eventName); +void BytraceEventParser::BeginFilterEvents(EventInfo* event) +{ + auto it = eventToFunctionMap_.find(event->line.eventName); if (it != eventToFunctionMap_.end()) { - return it->second(args, line); + uint32_t tgid; + ArgsMap args; + GetDataSegArgs(event->line, args, tgid); + if (tgid) { + streamFilters_->processFilter_->UpdateOrCreateThreadWithPidAndName(event->line.pid, tgid, event->line.task); + } else { + // When tgid is zero, only use tid create thread + streamFilters_->processFilter_->GetOrCreateThreadWithPid(event->line.pid, tgid); + } + if (it->second(args, event->line)) { + traceDataCache_->UpdateTraceTime(event->line.ts); + } + } else { + traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_NOTSUPPORTED); + TS_LOGW("UnRecognizable event name:%s", event->line.eventName.c_str()); } - TS_LOGW("UnRecognizable event name:%s", line.eventName.c_str()); - traceDataCache_->GetStatAndInfo()->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_NOTSUPPORTED); - return false; +} + +void BytraceEventParser::Clear() const +{ + streamFilters_->binderFilter_->Clear(); + streamFilters_->sliceFilter_->Clear(); + streamFilters_->cpuFilter_->Clear(); + streamFilters_->irqFilter_->Clear(); + streamFilters_->cpuMeasureFilter_->Clear(); + streamFilters_->threadMeasureFilter_->Clear(); + streamFilters_->threadFilter_->Clear(); + streamFilters_->processMeasureFilter_->Clear(); + streamFilters_->processFilterFilter_->Clear(); + streamFilters_->clockEnableFilter_->Clear(); + streamFilters_->clockDisableFilter_->Clear(); + streamFilters_->clkRateFilter_->Clear(); + streamFilters_->clkDisableFilter_->Clear(); + streamFilters_->binderFilter_->Clear(); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.h b/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.h old mode 100644 new mode 100755 index 6f3aee89862234506890581037458f4f38b5d244..c9f922b0f11f1a324533bc81014831dc9bc10330 --- a/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.h +++ b/host/trace_streamer/src/parser/bytrace_parser/bytrace_event_parser.h @@ -17,6 +17,7 @@ #define SRC_BYTRACE_EVENT_PARSER_H #include +#include #include "common_types.h" #include "event_parser_base.h" @@ -28,21 +29,33 @@ namespace SysTuning { namespace TraceStreamer { using ArgsMap = std::unordered_map; -class BytraceEventParser : private EventParserBase { +class BytraceEventParser : public EventParserBase { +private: + class EventInfo { + public: + EventInfo(uint64_t ts, BytraceLine li) : eventTimestamp(ts), line(li) {} + uint64_t eventTimestamp; + BytraceLine line; + }; + public: BytraceEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter); - bool ParseDataItem(const BytraceLine& line, const ArgsMap& args, uint32_t tgid) const; - + void ParseDataItem(const BytraceLine& line); + void FilterAllEventsTemp(); + void FilterAllEvents(); + void BeginFilterEvents(EventInfo* event); + void Clear() const; private: using FuncCall = std::function; bool SchedSwitchEvent(const ArgsMap& args, const BytraceLine& line) const; bool TaskRenameEvent(const ArgsMap& args, const BytraceLine& line) const; bool TaskNewtaskEvent(const ArgsMap& args, const BytraceLine& line) const; - bool TracingMarkWriteEvent(const ArgsMap& args, const BytraceLine& line) const; + bool TracingMarkWriteOrPrintEvent(const ArgsMap& args, const BytraceLine& line); bool SchedWakeupEvent(const ArgsMap& args, const BytraceLine& line) const; bool SchedWakingEvent(const ArgsMap& args, const BytraceLine& line) const; bool CpuIdleEvent(const ArgsMap& args, const BytraceLine& line) const; bool CpuFrequencyEvent(const ArgsMap& args, const BytraceLine& line) const; + bool CpuFrequencyLimitsEvent(const ArgsMap& args, const BytraceLine& line) const; bool WorkqueueExecuteStartEvent(const ArgsMap& args, const BytraceLine& line) const; bool WorkqueueExecuteEndEvent(const ArgsMap& args, const BytraceLine& line) const; bool ProcessExitEvent(const ArgsMap& args, const BytraceLine& line) const; @@ -63,15 +76,38 @@ 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; -private: - const DataIndex ioWaitId_; - const DataIndex workQueueId_; - const DataIndex schedWakeupId_; - const DataIndex schedBlockedReasonId_; + void GetDataSegArgs(BytraceLine& bufLine, ArgsMap& args, uint32_t& tgid) const; + std::map eventToFunctionMap_ = {}; - const unsigned int MIN_SCHED_ARGS_COUNT = 6; + const unsigned int MIN_SCHED_SWITCH_ARGS_COUNT = 6; const unsigned int MIN_SCHED_WAKEUP_ARGS_COUNT = 2; + const unsigned int MIN_TASK_RENAME_ARGS_COUNT = 2; + const unsigned int MIN_SCHED_WAKING_ARGS_COUNT = 4; + const unsigned int MIN_CPU_IDLE_ARGS_COUNT = 2; + const unsigned int MIN_CPU_FREQUENCY_ARGS_COUNT = 2; + const unsigned int MIN_PROCESS_EXIT_ARGS_COUNT = 2; + const unsigned int MIN_CLOCK_SET_RATE_ARGS_COUNT = 3; + const unsigned int MIN_CLOCK_ENABLE_ARGS_COUNT = 3; + const unsigned int MIN_CLOCK_DISABLE_ARGS_COUNT = 3; + const unsigned int MIN_IRQ_HANDLER_ENTRY_ARGS_COUNT = 2; + const unsigned int MIN_IRQ_HANDLER_EXIT_ARGS_COUNT = 2; + const unsigned int MIN_SOFTIRQ_ENTRY_ARGS_COUNT = 2; + const unsigned int MIN_SOFTIRQ_EXIT_ARGS_COUNT = 2; + const unsigned int MIN_BINDER_TRANSACTION_ARGS_COUNT = 7; + const unsigned int MIN_BINDER_TRANSACTION_RECEIVED_ARGS_COUNT = 1; + const unsigned int MIN_BINDER_TRANSACTION_ALLOC_BUF_ARGS_COUNT = 3; + std::vector> eventList_ = {}; PrintEventParser printEventParser_; + const DataIndex schedWakeupName_ = traceDataCache_->GetDataIndex("sched_wakeup"); + const DataIndex schedWakingName_ = traceDataCache_->GetDataIndex("sched_waking"); + const DataIndex ioWaitId_ = traceDataCache_->GetDataIndex("io_wait"); + const DataIndex workQueueId_ = traceDataCache_->GetDataIndex("workqueue"); + const DataIndex schedWakeupId_ = traceDataCache_->GetDataIndex("sched_wakeup"); + const DataIndex schedBlockedReasonId_ = traceDataCache_->GetDataIndex("sched_blocked_reason"); + const DataIndex cpuFrequencyLimitMaxNameId = traceDataCache_->GetDataIndex("cpu_frequency_limits_max"); + const DataIndex cpuFrequencyLimitMinNameId = traceDataCache_->GetDataIndex("cpu_frequency_limits_min"); +protected: + TraceStreamerConfig config_{}; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.cpp b/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.cpp old mode 100644 new mode 100755 index cdf20e3f9f6ed331b57e73d40fe715be32665c6f..731457b87e7b43f026f79a7111ca42a43418bac3 --- a/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.cpp +++ b/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.cpp @@ -14,21 +14,27 @@ */ #include "bytrace_parser.h" +#include +#include #include #include "binder_filter.h" #include "cpu_filter.h" +#include "hi_sysevent_measure_filter.h" #include "parting_string.h" #include "stat_filter.h" +#include "system_event_measure_filter.h" namespace SysTuning { namespace TraceStreamer { BytraceParser::BytraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters) : ParserBase(filters), eventParser_(std::make_unique(dataCache, filters)), - dataSegArray(new DataSegment[MAX_SEG_ARRAY_SIZE]) -{ #ifdef SUPPORTTHREAD - noThread_ = false; + supportThread_(true), + dataSegArray_(std::make_unique(MAX_SEG_ARRAY_SIZE)) +#else + dataSegArray_(std::make_unique(1)) #endif +{ } BytraceParser::~BytraceParser() = default; @@ -41,8 +47,9 @@ void BytraceParser::WaitForParserEnd() usleep(sleepDur_ * sleepDur_); } } - streamFilters_->cpuFilter_->FinishCpuEvent(); - streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser_->FilterAllEvents(); + eventParser_->Clear(); + dataSegArray_.reset(); } void BytraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, size_t size) { @@ -51,14 +58,19 @@ void BytraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, } packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]); auto packagesBegin = packagesBuffer_.begin(); - while (1) { auto packagesLine = std::find(packagesBegin, packagesBuffer_.end(), '\n'); if (packagesLine == packagesBuffer_.end()) { break; } - - std::string bufferLine(packagesBegin, packagesLine); + if (packagesLine == packagesBuffer_.begin()) { + packagesLine++; + packagesBegin = packagesLine; + continue; + } + // Support parsing windows file format(ff=dos) + auto extra = *(packagesLine - 1) == '\r' ? 1 : 0; + std::string bufferLine(packagesBegin, packagesLine - extra); if (IsTraceComment(bufferLine)) { traceCommentLines_++; @@ -73,7 +85,11 @@ void BytraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, isParsingOver_ = true; break; } - ParseTraceDataItem(bufferLine); + if (isBytrace_) { + ParseTraceDataItem(bufferLine); + } else { + ParseJsonData(bufferLine); + } NEXT_LINE: packagesBegin = packagesLine + 1; @@ -87,24 +103,150 @@ void BytraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, } return; } +int32_t BytraceParser::JGetData(json& jMessage, + JsonData& jData, + size_t& maxArraySize, + std::vector& noArrayIndex, + std::vector& arrayIndex) +{ + for (auto i = jMessage.begin(); i != jMessage.end(); i++) { + if (i.key() == "name_") { + jData.eventSource = i.value(); + if (find(eventsAccordingAppNames.begin(), eventsAccordingAppNames.end(), jData.eventSource) == + eventsAccordingAppNames.end()) { + TS_LOGW("event source:%s not supported for hisysevent", jData.eventSource.c_str()); + return -1; + } + continue; + } + if (i.key() == "time_") { + jData.timestamp = i.value(); + continue; + } + if (i.key() == "tag_" && i.value() != "PowerStats") { + TS_LOGW("energy data without PowerStats tag_ would be invalid"); + return -1; + } + if (i.key() == "APPNAME") { + jData.appName.assign(i.value().begin(), i.value().end()); + } + if (i.value().is_array()) { + maxArraySize = std::max(maxArraySize, i.value().size()); + arrayIndex.push_back(jData.key.size()); + } else { + noArrayIndex.push_back(jData.key.size()); + } + jData.key.push_back(i.key()); + jData.value.push_back(i.value()); + } + return 0; +} +void BytraceParser::NoArrayDataParse(JsonData jData, std::vector noArrayIndex, DataIndex eventSourceIndex) +{ + for (auto itor = noArrayIndex.begin(); itor != noArrayIndex.end(); itor++) { + auto value = jData.value[*itor]; + std::string key = jData.key[*itor]; + streamFilters_->hiSysEventMeasureFilter_->GetOrCreateFilterId(eventSourceIndex); + DataIndex keyIndex = eventParser_->traceDataCache_->GetDataIndex(key); + if (value.is_string()) { + std::string strValue = value; + DataIndex valueIndex = eventParser_->traceDataCache_->GetDataIndex(strValue); + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp, eventSourceIndex, keyIndex, 1, 0, + valueIndex); + } else { + DataIndex valueIndex = value; + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp, eventSourceIndex, keyIndex, 0, + valueIndex, 0); + } + } +} +void BytraceParser::ArrayDataParse(JsonData jData, + std::vector arrayIndex, + DataIndex eventSourceIndex, + size_t maxArraySize) +{ + for (int j = 0; j < maxArraySize; j++) { + for (auto itor = arrayIndex.begin(); itor != arrayIndex.end(); itor++) { + auto value = jData.value[*itor][j]; + std::string key = jData.key[*itor]; + DataIndex keyIndex = eventParser_->traceDataCache_->GetDataIndex(key); + streamFilters_->hiSysEventMeasureFilter_->GetOrCreateFilterId(eventSourceIndex); + if (value.is_number()) { + DataIndex valueIndex = value; + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp, eventSourceIndex, keyIndex, 0, + valueIndex, 0); + } else if (value.is_string()) { + std::string strValue = value; + DataIndex valueIndex = eventParser_->traceDataCache_->GetDataIndex(strValue); + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp, eventSourceIndex, keyIndex, 1, + 0, valueIndex); + } + } + } +} +void BytraceParser::CommonDataParser(JsonData jData, DataIndex eventSourceIndex) +{ + for (int j = 0; j < jData.key.size(); j++) { + std::string key = jData.key[j]; + auto value = jData.value[j]; + DataIndex keyIndex = eventParser_->traceDataCache_->GetDataIndex(key); + streamFilters_->hiSysEventMeasureFilter_->GetOrCreateFilterId(eventSourceIndex); + if (value.is_string()) { + std::string strValue = value; + DataIndex valueIndex = eventParser_->traceDataCache_->GetDataIndex(strValue); + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp, eventSourceIndex, keyIndex, 1, 0, + valueIndex); + } else { + DataIndex valueIndex = value; + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(0, jData.timestamp, eventSourceIndex, keyIndex, 0, + valueIndex, 0); + } + } +} +void BytraceParser::ParseJsonData(const std::string& buffer) +{ + std::stringstream ss; + json jMessage; + ss << buffer; + ss >> jMessage; + JsonData jData; + size_t maxArraySize = 0; + std::vector noArrayIndex = {}; + std::vector arrayIndex = {}; + if (JGetData(jMessage, jData, maxArraySize, noArrayIndex, arrayIndex) < 0) { + return; + } + DataIndex eventSourceIndex = eventParser_->traceDataCache_->GetDataIndex(jData.eventSource); + if (maxArraySize) { + NoArrayDataParse(jData, noArrayIndex, eventSourceIndex); + ArrayDataParse(jData, arrayIndex, eventSourceIndex, maxArraySize); + } else { + CommonDataParser(jData, eventSourceIndex); + } + return; +} void BytraceParser::ParseTraceDataItem(const std::string& buffer) { + if (!supportThread_) { + dataSegArray_[rawDataHead_].seg = std::move(buffer); + ParserData(dataSegArray_[rawDataHead_]); + return; + } int head = rawDataHead_; while (!toExit_) { - if (dataSegArray[head].status.load() != TS_PARSE_STATUS_INIT) { - TS_LOGD("rawDataHead_:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_); + if (dataSegArray_[head].status.load() != TS_PARSE_STATUS_INIT) { + TS_LOGD("rawDataHead_:\t%d, parseHead_:\t%d, filterHead_:\t%d status:\t%d\n", rawDataHead_, parseHead_, + filterHead_, dataSegArray_[head].status.load()); usleep(sleepDur_); continue; } - dataSegArray[head].seg = std::move(buffer); - dataSegArray[head].status = TS_PARSE_STATUS_SEPRATED; - if (!noThread_) { - rawDataHead_ = (rawDataHead_ + 1) % MAX_SEG_ARRAY_SIZE; - } + dataSegArray_[head].seg = std::move(buffer); + dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED; + rawDataHead_ = (rawDataHead_ + 1) % MAX_SEG_ARRAY_SIZE; break; } - if (!parseThreadStarted_ && !noThread_) { + if (!parseThreadStarted_) { parseThreadStarted_ = true; int tmp = maxThread_; while (tmp--) { @@ -114,9 +256,6 @@ void BytraceParser::ParseTraceDataItem(const std::string& buffer) TS_LOGI("parser Thread:%d/%d start working ...\n", maxThread_ - tmp, maxThread_); } } - if (noThread_) { - ParserData(dataSegArray[head]); - } return; } int BytraceParser::GetNextSegment() @@ -124,7 +263,7 @@ int BytraceParser::GetNextSegment() int head; dataSegMux_.lock(); head = parseHead_; - DataSegment& seg = dataSegArray[head]; + DataSegment& seg = dataSegArray_[head]; if (seg.status.load() != TS_PARSE_STATUS_SEPRATED) { if (toExit_) { parserThreadCount_--; @@ -135,13 +274,14 @@ int BytraceParser::GetNextSegment() } return ERROR_CODE_EXIT; } - if (seg.status == TS_PARSE_STATUS_PARSING) { + if (seg.status.load() == TS_PARSE_STATUS_PARSING) { dataSegMux_.unlock(); usleep(sleepDur_); return ERROR_CODE_NODATA; } dataSegMux_.unlock(); - TS_LOGD("ParseThread watting:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_); + TS_LOGD("ParseThread watting:\t%d, parseHead_:\t%d, filterHead_:\t%d status:\t%d\n", rawDataHead_, parseHead_, + filterHead_, seg.status.load()); usleep(sleepDur_); return ERROR_CODE_NODATA; } @@ -153,6 +293,7 @@ int BytraceParser::GetNextSegment() void BytraceParser::GetDataSegAttr(DataSegment& seg, const std::smatch& matcheLine) const { + const uint64_t US_TO_NS = 1000; size_t index = 0; std::string pidStr = matcheLine[++index].str(); std::optional optionalPid = base::StrToUInt32(pidStr); @@ -185,41 +326,12 @@ void BytraceParser::GetDataSegAttr(DataSegment& seg, const std::smatch& matcheLi seg.bufLine.argsStr = StrTrim(matcheLine.suffix()); seg.bufLine.pid = optionalPid.value(); seg.bufLine.cpu = optionalCpu.value(); - seg.bufLine.ts = static_cast(optionalTime.value() * 1e9); + seg.bufLine.ts = round(static_cast(optionalTime.value() * 1e6)); + seg.bufLine.ts *= US_TO_NS; seg.bufLine.tGidStr = tGidStr; seg.bufLine.eventName = eventName; - GetDataSegArgs(seg); seg.status = TS_PARSE_STATUS_PARSED; } - -void BytraceParser::GetDataSegArgs(DataSegment& seg) const -{ - seg.args.clear(); - if (seg.bufLine.tGidStr != "-----") { - seg.tgid = base::StrToUInt32(seg.bufLine.tGidStr).value_or(0); - } else { - seg.tgid = 0; - } - - for (base::PartingString ss(seg.bufLine.argsStr, ' '); ss.Next();) { - std::string key; - std::string value; - if (!(std::string(ss.GetCur()).find("=") != std::string::npos)) { - key = "name"; - value = ss.GetCur(); - seg.args.emplace(std::move(key), std::move(value)); - continue; - } - for (base::PartingString inner(ss.GetCur(), '='); inner.Next();) { - if (key.empty()) { - key = inner.GetCur(); - } else { - value = inner.GetCur(); - } - } - seg.args.emplace(std::move(key), std::move(value)); - } -} void BytraceParser::ParseThread() { while (1) { @@ -233,7 +345,7 @@ void BytraceParser::ParseThread() } return; } - DataSegment& seg = dataSegArray[head]; + DataSegment& seg = dataSegArray_[head]; ParserData(seg); } } @@ -243,27 +355,28 @@ void BytraceParser::ParserData(DataSegment& seg) std::smatch matcheLine; if (!std::regex_search(seg.seg, matcheLine, bytraceMatcher_)) { TS_LOGD("Not support this event (line: %s)", seg.seg.c_str()); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); seg.status = TS_PARSE_STATUS_INVALID; parsedTraceInvalidLines_++; - FilterData(seg); return; } else { parsedTraceValidLines_++; } GetDataSegAttr(seg, matcheLine); - if (!filterThreadStarted_ && !noThread_) { + if (!supportThread_) { + FilterData(seg); + return; + } + if (!filterThreadStarted_) { filterThreadStarted_ = true; std::thread ParserThread(&BytraceParser::FilterThread, this); ParserThread.detach(); } - if (noThread_) { - FilterData(seg); - } } void BytraceParser::FilterThread() { while (1) { - DataSegment& seg = dataSegArray[filterHead_]; + DataSegment& seg = dataSegArray_[filterHead_]; if (!FilterData(seg)) { return; } @@ -271,12 +384,19 @@ void BytraceParser::FilterThread() } bool BytraceParser::FilterData(DataSegment& seg) { - if (seg.status.load() == TS_PARSE_STATUS_INVALID) { - seg.status = TS_PARSE_STATUS_INIT; - if (!noThread_) { - filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; + if (!supportThread_) { + if (seg.status.load() != TS_PARSE_STATUS_INVALID) { + eventParser_->ParseDataItem(seg.bufLine); + seg.status = TS_PARSE_STATUS_INIT; + return true; } streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); + return false; + } + if (seg.status.load() == TS_PARSE_STATUS_INVALID) { + filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); + seg.status = TS_PARSE_STATUS_INIT; return true; } if (seg.status.load() != TS_PARSE_STATUS_PARSED) { @@ -286,17 +406,11 @@ bool BytraceParser::FilterData(DataSegment& seg) filterThreadStarted_ = false; return false; } - if (!noThread_) { // wasm do not allow thread - usleep(sleepDur_); - } + usleep(sleepDur_); return true; } - BytraceLine line = seg.bufLine; - uint32_t tgid = seg.tgid; - eventParser_->ParseDataItem(line, seg.args, tgid); - if (!noThread_) { - filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; - } + eventParser_->ParseDataItem(seg.bufLine); + filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; seg.status = TS_PARSE_STATUS_INIT; return true; } @@ -304,12 +418,11 @@ bool BytraceParser::FilterData(DataSegment& seg) std::string BytraceParser::StrTrim(const std::string& input) const { std::string str = input; - auto posBegin = std::find_if(str.begin(), str.end(), IsNotSpace); - str.erase(str.begin(), posBegin); - - auto posEnd = std::find_if(str.rbegin(), str.rend(), IsNotSpace); - str.erase(posEnd.base(), str.end()); - + if (str.empty()) { + return str; + } + str.erase(0, str.find_first_not_of(" ")); + str.erase(str.find_last_not_of(" ") + 1); return str; } } // namespace TraceStreamer diff --git a/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.h b/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.h old mode 100644 new mode 100755 index 95c552efed3e2370db24ac3847c9b2cbfab451d8..e6b798a7be646871b5e4e23912edd9c339b1dc81 --- a/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.h +++ b/host/trace_streamer/src/parser/bytrace_parser/bytrace_parser.h @@ -22,6 +22,7 @@ #include #include "bytrace_event_parser.h" +#include "json.hpp" #include "log.h" #include "parser_base.h" #include "string_to_numerical.h" @@ -48,13 +49,18 @@ public: { return traceCommentLines_; } + void EnableBytrace(bool enable) { + isBytrace_ = enable; + } + + void WaitForParserEnd(); private: enum ErrorCode { ERROR_CODE_EXIT = -2, ERROR_CODE_NODATA = -1 }; int GetNextSegment(); void GetDataSegAttr(DataSegment& seg, const std::smatch& matcheLine) const; - void GetDataSegArgs(DataSegment& seg) const; + void FilterThread(); inline static bool IsNotSpace(char c) { @@ -70,7 +76,26 @@ private: void ParseThread(); void ParserData(DataSegment& seg); bool FilterData(DataSegment& seg); - +private: + using json = nlohmann::json; + typedef struct { + std::string eventSource; + uint64_t timestamp; + std::vector appName; + std::vector appVersions; + std::vector key; + std::vector value; + } JsonData; + void NoArrayDataParse(JsonData jData, std::vector noArrayIndex, DataIndex eventSourceIndex); + void + ArrayDataParse(JsonData jData, std::vector arrayIndex, DataIndex eventSourceIndex, size_t maxArraySize); + void CommonDataParser(JsonData jData, DataIndex eventSourceIndex); + int32_t JGetData(json& jMessage, + JsonData& jData, + size_t& maxArraySize, + std::vector& noArrayIndex, + std::vector& arrayIndex); + void ParseJsonData(const std::string& buffer); private: using ArgsMap = std::unordered_map; bool isParsingOver_ = false; @@ -80,6 +105,42 @@ private: const std::string script_ = R"()"; + std::vector eventsAccordingAppNames = {"POWER_IDE_BATTERY", + "POWER_IDE_CPU", + "POWER_IDE_LOCATION", + "POWER_IDE_GPU", + "POWER_IDE_DISPLAY", + "POWER_IDE_CAMERA", + "POWER_IDE_BLUETOOTH", + "POWER_IDE_FLASHLIGHT", + "POWER_IDE_AUDIO", + "POWER_IDE_WIFISCAN", + "BRIGHTNESS_NIT", + "SIGNAL_LEVEL", + "WIFI_EVENT_RECEIVED", + "AUDIO_STREAM_CHANGE", + "AUDIO_VOLUME_CHANGE", + "WIFI_STATE", + "BLUETOOTH_BR_SWITCH_STATE", + "LOCATION_SWITCH_STATE", + "ENABLE_SENSOR", + "DISABLE_SENSOR", + "WORK_REMOVE", + "WORK_START", + "WORK_STOP", + "WORK_ADD", + "POWER_RUNNINGLOCK", + "GNSS_STATE", + "ANOMALY_SCREEN_OFF_ENERGY", + "ANOMALY_ALARM_WAKEUP", + "ANOMALY_KERNEL_WAKELOCK", + "ANOMALY_RUNNINGLOCK", + "ANORMALY_APP_ENERGY", + "ANOMALY_GNSS_ENERGY", + "ANOMALY_CPU_HIGH_FREQUENCY", + "ANOMALY_CPU_ENERGY", + "ANOMALY_WAKEUP"}; + size_t parsedTraceValidLines_ = 0; size_t parsedTraceInvalidLines_ = 0; size_t traceCommentLines_ = 0; @@ -92,11 +153,12 @@ private: int parserThreadCount_ = 0; bool toExit_ = false; bool exited_ = false; - std::unique_ptr dataSegArray; + std::unique_ptr dataSegArray_; int rawDataHead_ = 0; int filterHead_ = 0; const int sleepDur_ = 100; - bool noThread_ = true; + bool supportThread_ = false; + bool isBytrace_ = true; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/common_types.h b/host/trace_streamer/src/parser/common_types.h old mode 100644 new mode 100755 index 5d7c0a416ad3c77523cc5b4a16cadd8842947ae7..67a059907a475af27c3a5ad8fd23609cac88720b --- a/host/trace_streamer/src/parser/common_types.h +++ b/host/trace_streamer/src/parser/common_types.h @@ -19,10 +19,16 @@ #include #include #include +#include "cpu_plugin_result.pb.h" +#include "diskio_plugin_result.pb.h" #include "hidump_plugin_result.pb.h" #include "hilog_plugin_result.pb.h" +#include "hisysevent_plugin_config.pb.h" +#include "hisysevent_plugin_result.pb.h" #include "memory_plugin_result.pb.h" #include "native_hook_result.pb.h" +#include "network_plugin_result.pb.h" +#include "process_plugin_result.pb.h" #include "services/common_types.pb.h" #include "trace_plugin_result.pb.h" #include "ts_common.h" @@ -31,7 +37,6 @@ namespace SysTuning { namespace TraceStreamer { enum ParseResult { ERROR = 0, SUCCESS }; enum RawType { RAW_CPU_IDLE = 1, RAW_SCHED_WAKEUP = 2, RAW_SCHED_WAKING = 3 }; - enum Stat : uint32_t { RUNNABLE = 0, INTERRUPTABLESLEEP = 1, @@ -70,17 +75,8 @@ enum ParseStatus { struct DataSegment { std::string seg; BytraceLine bufLine; - std::unordered_map args; - uint32_t tgid; std::atomic status{TS_PARSE_STATUS_INIT}; }; -enum DataSourceType { - DATA_SOURCE_TYPE_TRACE, - DATA_SOURCE_TYPE_MEM, - DATA_SOURCE_TYPE_HILOG, - DATA_SOURCE_TYPE_HEAP, - DATA_SOURCE_TYPE_FPS -}; // 注意使用完之后恢复初始化状态,保证下次使用不会出现数据混乱。 struct HtraceDataSegment { std::string seg; @@ -88,14 +84,48 @@ struct HtraceDataSegment { HilogInfo logData; BatchNativeHookData batchNativeHookData; HidumpInfo hidumpInfo; + CpuData cpuInfo; + NetworkDatas networkInfo; + DiskioData diskIOInfo; + ProcessData processInfo; + HisyseventInfo hisyseventInfo; + HisyseventConfig hisyseventConfig; uint64_t timeStamp; - TracePluginResult traceData; + std::unique_ptr traceData; BuiltinClocks clockId; DataSourceType dataType; std::atomic status{TS_PARSE_STATUS_INIT}; }; -struct TracePoint { +class TracePoint { +public: + TracePoint() {} + TracePoint(const TracePoint& point) + : phase_(point.phase_), + tgid_(point.tgid_), + name_(point.name_), + value_(point.value_), + categoryGroup_(point.categoryGroup_), + chainId_(point.chainId_), + spanId_(point.spanId_), + parentSpanId_(point.parentSpanId_), + flag_(point.flag_), + args_(point.args_) + { + } + void operator=(const TracePoint& point) + { + phase_ = point.phase_; + tgid_ = point.tgid_; + name_ = point.name_; + value_ = point.value_; + categoryGroup_ = point.categoryGroup_; + chainId_ = point.chainId_; + spanId_ = point.spanId_; + parentSpanId_ = point.parentSpanId_; + flag_ = point.flag_; + args_ = point.args_; + } char phase_ = '\0'; uint32_t tgid_ = 0; std::string name_ = ""; diff --git a/host/trace_streamer/src/parser/ebpf_parser/BUILD.gn b/host/trace_streamer/src/parser/ebpf_parser/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..56e00489368b1954a955a7b73765eba5cbafd138 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/BUILD.gn @@ -0,0 +1,86 @@ +# 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("//build/ohos.gni") +import("../../ts.gni") +ohos_source_set("ebpf_parser_src") { + sources = [ + "bio_latency_data_parser.cpp", + "bio_latency_data_parser.h", + "ebpf_base.cpp", + "ebpf_base.h", + "ebpf_data_parser.cpp", + "ebpf_data_parser.h", + "ebpf_data_reader.cpp", + "ebpf_data_reader.h", + "ebpf_stdtype.h", + "file_system_data_parser.cpp", + "file_system_data_parser.h", + "paged_memory_data_parser.cpp", + "paged_memory_data_parser.h", + ] + include_dirs = [ + ".", + "../", + "../htrace_parser", + "../..", + "../../trace_data", + "../../base", + "../../include", + "../../filter", + "../../cfg", + "../../trace_streamer", + "${OHOS_PROTO_GEN}", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/${kernel_version}", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data", + "${OHOS_PROTO_GEN}/types/plugins/native_hook", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}/types/plugins/network_data", + "${OHOS_PROTO_GEN}/types/plugins/cpu_data", + "${OHOS_PROTO_GEN}/types/plugins/diskio_data", + "${OHOS_PROTO_GEN}/types/plugins/process_data", + "${OHOS_PROTO_GEN}/types/plugins/hisysevent_data", + "//third_party/protobuf/src", + "//third_party/sqlite/include", + ] + if (is_win || is_macx) { + include_dirs += [ + "//third_party/perf_include/linux", + "//third_party/perf_include/musl", + ] + } + + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + if (is_test) { + cflags += [ "-D IS_UT" ] + } + } +} + +group("ebpf_parser") { + deps = [ + ":ebpf_parser_src", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + ] +} diff --git a/host/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp b/host/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..efcd8eaf822ab8cb1caf9e84143bc7e784494e94 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.cpp @@ -0,0 +1,102 @@ +/* + * 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. + */ +#include "bio_latency_data_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +#include "string_to_numerical.h" + +namespace SysTuning { +namespace TraceStreamer { +BioLatencyDataParser::BioLatencyDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : EventParserBase(dataCache, ctx), + EbpfBase(dataCache, ctx), + timeParser_(std::make_unique(dataCache, ctx)) +{ +} +BioLatencyDataParser::~BioLatencyDataParser() +{ + TS_LOGI("EBPF Bio data ts MIN:%llu, MAX:%llu", static_cast(timeParser_->GetPluginStartTime()), + static_cast(timeParser_->GetPluginEndTime())); +} +void BioLatencyDataParser::ParseBioLatencyEvent() +{ + if (!reader_->GetBIOSampleMap().size()) { + return; + } + for (auto mapItor = reader_->GetBIOSampleMap().begin(); mapItor != reader_->GetBIOSampleMap().end(); mapItor++) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_BIO_LATENCY, STAT_EVENT_RECEIVED); + auto bioFixedHeadrAddr = mapItor->second; + bool callIdExistFlag = false; + + auto userIpsAddr = reinterpret_cast(bioFixedHeadrAddr + 1); + if (bioFixedHeadrAddr->nips) { + std::string ipsToStr(reinterpret_cast(userIpsAddr), bioFixedHeadrAddr->nips * SINGLE_IP_SIZE); + auto ipsHashValue = hashFun_(ipsToStr); + auto value = pidAndipsToCallId_.Find(bioFixedHeadrAddr->pid, ipsHashValue); + if (value != INVALID_UINT64) { + callIdExistFlag = true; + currentCallId_ = value; + } else { + pidAndipsToCallId_.Insert(bioFixedHeadrAddr->pid, ipsHashValue, callChainId_); + currentCallId_ = callChainId_++; + } + } else { + currentCallId_ = INVALID_UINT64; + } + + uint32_t type = bioFixedHeadrAddr->type; + // Init process name data + const char* processName = reinterpret_cast(bioFixedHeadrAddr->processName); + uint32_t ipid = + streamFilters_->processFilter_->UpdateOrCreateProcessWithName(bioFixedHeadrAddr->pid, processName); + uint32_t itid = + streamFilters_->processFilter_->GetOrCreateThreadWithPid(bioFixedHeadrAddr->tid, bioFixedHeadrAddr->pid); + uint64_t startTs = bioFixedHeadrAddr->startTime; + uint64_t endTs = bioFixedHeadrAddr->endTime; + auto newStartTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, startTs); + timeParser_->UpdatePluginTimeRange(clockId_, startTs, newStartTs); + auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, endTs); + timeParser_->UpdatePluginTimeRange(clockId_, endTs, newEndTs); + if (newStartTs > newEndTs) { + TS_LOGE("File system event origin startTs = %lu, endTs = %lu, newStartTs = %lu, newEndTs = %lu", startTs, + endTs, newStartTs, newEndTs); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_PAGED_MEMORY, STAT_EVENT_DATA_INVALID); + return; + } + uint64_t duration = newEndTs - newStartTs; + auto prio = bioFixedHeadrAddr->prio; + auto size = bioFixedHeadrAddr->size; + const int FOUR_KB = 1024 * 4; + uint32_t durPer4K = INVALID_UINT32; + if (size > 0) { + durPer4K = duration / (size / FOUR_KB); + } + + auto blkCount = ConvertToHexTextIndex(bioFixedHeadrAddr->blkcnt); + + auto tracerEventToStrIndexMap = reader_->GetTracerEventToStrIndexMap(); + auto pathId = tracerEventToStrIndexMap.Find(ITEM_EVENT_BIO, type, itid, startTs); + if (pathId != INVALID_UINT64) { + tracerEventToStrIndexMap.Erase(ITEM_EVENT_FS, type, itid, startTs); + } + traceDataCache_->GetBioLatencySampleData()->AppendNewData(currentCallId_, type, ipid, itid, newStartTs, newEndTs, duration, + prio, size, blkCount, pathId, durPer4K); + if (!callIdExistFlag) { + ParseCallStackData(userIpsAddr, bioFixedHeadrAddr->nips, bioFixedHeadrAddr->pid, currentCallId_); + } + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.h b/host/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..68b215105a45414ab9adfd561fc0185b24f63be1 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/bio_latency_data_parser.h @@ -0,0 +1,37 @@ +/* + * 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. + */ +#ifndef BIO_LATENCY_DATA_PARSER_H +#define BIO_LATENCY_DATA_PARSER_H +#include "clock_filter.h" +#include "double_map.h" +#include "ebpf_base.h" +#include "htrace_plugin_time_parser.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::EbpfStdtype; +class BioLatencyDataParser : virtual public EbpfBase { +public: + BioLatencyDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~BioLatencyDataParser(); + void ParseBioLatencyEvent(); +protected: + std::unique_ptr timeParser_; +private: + uint64_t currentCallId_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // BIO_LATENCY_DATA_PARSER_H diff --git a/host/trace_streamer/src/parser/ebpf_parser/ebpf_base.cpp b/host/trace_streamer/src/parser/ebpf_parser/ebpf_base.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04dfe5fa7445492787f6f7a971b41a4e384239ab --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/ebpf_base.cpp @@ -0,0 +1,166 @@ +/* + * 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. + */ +#include "ebpf_base.h" + +namespace SysTuning { +namespace TraceStreamer { +EbpfBase::EbpfBase(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : EventParserBase(dataCache, ctx), + pidAndIpToSymbolAndFilePathIndex_(SymbolAndFilePathIndex(false)), + pidAndipsToCallId_(INVALID_UINT64) +{ +} +EbpfBase::~EbpfBase() +{ + pidAndipsToCallId_.Clear(); + pidAndIpToSymbolAndFilePathIndex_.Clear(); +} +bool EbpfBase::InitEbpfDataParser(EbpfDataReader* reader) +{ + auto clockId = reader->GetEbpfDataHeader()->header.clock; + auto itor = ebpfToTSClockType_.find(clockId); + if (itor == ebpfToTSClockType_.end()) { + return false; + } + clockId_ = ebpfToTSClockType_.at(clockId); + reader_ = std::move(reader); + return true; +} + +void EbpfBase::ParseCallStackData(const uint64_t* userIpsAddr, uint16_t count, uint32_t pid, uint64_t callId) +{ + uint64_t depth = 0; + for (auto i = count - 1; i >= 0; i--) { + if (userIpsAddr[i] > MIN_USER_IP) { + auto symbolAndFilePathIndex = GetSymbolAndFilePathIndex(pid, userIpsAddr[i]); + auto ipIndex = ConvertToHexTextIndex(userIpsAddr[i]); + traceDataCache_->GetEbpfCallStack()->AppendNewData(callId, depth, ipIndex, + symbolAndFilePathIndex.symbolIndex, + symbolAndFilePathIndex.filePathIndex); + depth++; + } + } +} + +SymbolAndFilePathIndex EbpfBase::GetSymbolAndFilePathIndex(uint32_t pid, uint64_t ip) +{ + auto value = pidAndIpToSymbolAndFilePathIndex_.Find(pid, ip); + if (value.flag) { + return value; + } + return GetSymbolNameIndexFromElfSym(pid, ip); +} + +DataIndex EbpfBase::GetSymbolNameIndexFromSymVaddr(const ElfEventFixedHeader* elfHeaderAddr, uint64_t symVaddr) +{ + uint32_t symbolStart = INVALID_UINT32; + auto startValueToSymAddr = reader_->GetElfAddrAndStartValueToSymAddr().Find(elfHeaderAddr); + if (!startValueToSymAddr) { + return INVALID_UINT64; + } + auto end = startValueToSymAddr->upper_bound(symVaddr); + auto symEntLen = elfHeaderAddr->symEntLen; + auto length = std::distance(startValueToSymAddr->begin(), end); + if (length > 0) { + end--; + if (symEntLen == ELF32_SYM) { + auto symbolAddr = reinterpret_cast(end->second); + if (end->first <= symVaddr && end->first + symbolAddr->st_size >= symVaddr) { + symbolStart = symbolAddr->st_name; + } + } else { + auto symbolAddr = reinterpret_cast(end->second); + if (end->first <= symVaddr && end->first + symbolAddr->st_size >= symVaddr) { + symbolStart = symbolAddr->st_name; + } + } + } + + if (symbolStart == INVALID_UINT32) { + return INVALID_UINT64; + } + + // Take out the string according to the subscript + auto strTabAddr = reinterpret_cast(elfHeaderAddr + 1); + + if (symbolStart > elfHeaderAddr->strTabLen) { + TS_LOGE("symbolStart = %u, elfHeaderAddr->strTabLen = %u", symbolStart, elfHeaderAddr->strTabLen); + return INVALID_UINT64; + } + + auto symbolName = reinterpret_cast(strTabAddr) + symbolStart; + return traceDataCache_->GetDataIndex(symbolName); +} + +SymbolAndFilePathIndex EbpfBase::GetSymbolNameIndexFromElfSym(uint32_t pid, uint64_t ip) +{ + SymbolAndFilePathIndex symbolAndFilePathIndex(false); + if (ip <= reader_->maxKernelAddr_ && ip >= reader_->minKernelAddr_) { + symbolAndFilePathIndex = reader_->GetSymbolNameIndexFromElfSym(ip); + pidAndIpToSymbolAndFilePathIndex_.Insert(pid, ip, symbolAndFilePathIndex); + return symbolAndFilePathIndex; + } + + auto& pidAndStartAddrToMapsAddr = reader_->GetPidAndStartAddrToMapsAddr(); + auto startToMapsAddr = pidAndStartAddrToMapsAddr.Find(pid); + if (!startToMapsAddr) { + symbolAndFilePathIndex.flag = true; + pidAndIpToSymbolAndFilePathIndex_.Insert(pid, ip, symbolAndFilePathIndex); + return symbolAndFilePathIndex; + } + + uint64_t vmStart = INVALID_UINT64; + uint64_t vmOffset = INVALID_UINT64; + auto end = startToMapsAddr->upper_bound(ip); + auto length = std::distance(startToMapsAddr->begin(), end); + if (length > 0) { + end--; + if (ip <= end->second->end) { + vmStart = end->first; + vmOffset = end->second->offset; + symbolAndFilePathIndex.filePathIndex = + traceDataCache_->GetDataIndex(reinterpret_cast((end->second) + 1)); + } + } + symbolAndFilePathIndex.flag = true; + if (symbolAndFilePathIndex.filePathIndex == INVALID_INT64) { + pidAndIpToSymbolAndFilePathIndex_.Insert(pid, ip, symbolAndFilePathIndex); + return symbolAndFilePathIndex; + } + + auto itor = reader_->GetElfPathIndexToElfAddr().find(symbolAndFilePathIndex.filePathIndex); + if (itor == reader_->GetElfPathIndexToElfAddr().end()) { + pidAndIpToSymbolAndFilePathIndex_.Insert(pid, ip, symbolAndFilePathIndex); + return symbolAndFilePathIndex; + } + uint64_t symVaddr = ip - vmStart + vmOffset + itor->second->textVaddr - itor->second->textOffset; + auto symbolIndex = GetSymbolNameIndexFromSymVaddr(itor->second, symVaddr); + if (symbolIndex != INVALID_UINT64) { + symbolAndFilePathIndex.symbolIndex = symbolIndex; + } + pidAndIpToSymbolAndFilePathIndex_.Insert(pid, ip, symbolAndFilePathIndex); + return symbolAndFilePathIndex; +} + +DataIndex EbpfBase::ConvertToHexTextIndex(uint64_t number) +{ + if (number == INVALID_UINT64) { + return number; + } + std::string str = "0x" + base::number(number, base::INTEGER_RADIX_TYPE_HEX); + return traceDataCache_->GetDataIndex(str.c_str()); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/ebpf_parser/ebpf_base.h b/host/trace_streamer/src/parser/ebpf_parser/ebpf_base.h new file mode 100644 index 0000000000000000000000000000000000000000..e3871ad19a053a52ecabdc1b9312bfaf72c1fd89 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/ebpf_base.h @@ -0,0 +1,53 @@ +/* + * 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. + */ +#ifndef EBPF_BASE_H +#define EBPF_BASE_H +#include +#include "double_map.h" +#include "ebpf_data_reader.h" +#include "ebpf_stdtype.h" +#include "event_parser_base.h" +#include "string_to_numerical.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::base; +using namespace SysTuning::EbpfStdtype; + +class EbpfBase : virtual public EventParserBase +{ +public: + EbpfBase(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~EbpfBase(); + bool InitEbpfDataParser(EbpfDataReader* reader); + +protected: + void ParseCallStackData(const uint64_t* userIpsAddr, uint16_t count, uint32_t pid, uint64_t callId); + DataIndex GetSymbolNameIndexFromSymVaddr(const ElfEventFixedHeader* elfHeaderAddr, uint64_t symVaddr); + SymbolAndFilePathIndex GetSymbolAndFilePathIndex(uint32_t pid, uint64_t ip); + SymbolAndFilePathIndex GetSymbolNameIndexFromElfSym(uint32_t pid, uint64_t ip); + DataIndex ConvertToHexTextIndex(uint64_t number); + + ClockId clockId_ = INVALID_UINT32; + std::hash hashFun_; + EbpfDataReader* reader_ = nullptr; + DoubleMap pidAndIpToSymbolAndFilePathIndex_; + DoubleMap pidAndipsToCallId_; + uint64_t callChainId_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // EBPF_BASE_H diff --git a/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_parser.cpp b/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..04af66e85e8aae3207d00a9fa85aa3108b1b96a4 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_parser.cpp @@ -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. + */ +#include "ebpf_data_parser.h" +#include "stat_filter.h" + +namespace SysTuning { +namespace TraceStreamer { +EbpfDataParser::EbpfDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : EventParserBase(dataCache, ctx), + EbpfBase(dataCache, ctx), + FileSystemDataParser(dataCache, ctx), + PagedMemoryDataParser(dataCache, ctx), + BioLatencyDataParser(dataCache, ctx), + reader_(std::make_unique(dataCache, ctx)) +{ +} +EbpfDataParser::~EbpfDataParser() +{ + TS_LOGI("EBPF all event data ts MIN:%llu, MAX:%llu", static_cast(ebpfAllEventStartTime_), + static_cast(ebpfAllEventEndTime_)); +} + +bool EbpfDataParser::Init(const std::deque& dequeBuffer, uint64_t size) +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF, STAT_EVENT_RECEIVED); + if (!reader_->InitEbpfData(dequeBuffer, size)) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF, STAT_EVENT_NOTSUPPORTED); + TS_LOGE("InitEbpfData failed!"); + return false; + } + if (!InitEbpfDataParser(reader_.get())) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF, STAT_EVENT_NOTSUPPORTED); + return false; + } + return true; +} + +void EbpfDataParser::InitAndParseEbpfData(const std::deque& dequeBuffer, uint64_t size) +{ + if (!Init(dequeBuffer, size)) { + return; + } + if (reader_->GetFileSystemEventMap().size()) { + ParseFileSystemEvent(); + } + if (reader_->GetPagedMemoryMap().size()) { + ParsePagedMemoryEvent(); + } + if (reader_->GetBIOSampleMap().size()) { + ParseBioLatencyEvent(); + } +} + +void EbpfDataParser::Finish() +{ + ebpfAllEventStartTime_ = std::min(FileSystemDataParser::timeParser_->GetPluginStartTime(), ebpfAllEventStartTime_); + ebpfAllEventStartTime_ = std::min(PagedMemoryDataParser::timeParser_->GetPluginStartTime(), ebpfAllEventStartTime_); + ebpfAllEventStartTime_ = std::min(BioLatencyDataParser::timeParser_->GetPluginStartTime(), ebpfAllEventStartTime_); + ebpfAllEventEndTime_ = std::max(FileSystemDataParser::timeParser_->GetPluginEndTime(), ebpfAllEventEndTime_); + ebpfAllEventEndTime_ = std::max(PagedMemoryDataParser::timeParser_->GetPluginEndTime(), ebpfAllEventEndTime_); + ebpfAllEventEndTime_ = std::max(BioLatencyDataParser::timeParser_->GetPluginEndTime(), ebpfAllEventEndTime_); + // Update trace_range when there is only ebpf data in the trace file + if (traceDataCache_->traceStartTime_ == INVALID_UINT64 || traceDataCache_->traceEndTime_ == 0) { + traceDataCache_->MixTraceTime(ebpfAllEventStartTime_, ebpfAllEventEndTime_); + } else { + TS_LOGI("EBPF data time is not updated, maybe this trace file has other data"); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_parser.h b/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..29d0112e396f937da8c4ba602673b3388383a390 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_parser.h @@ -0,0 +1,42 @@ +/* + * 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. + */ +#ifndef EBPF_DATA_PARSER_H +#define EBPF_DATA_PARSER_H +#include "bio_latency_data_parser.h" +#include "ebpf_data_reader.h" +#include "ebpf_stdtype.h" +#include "file_system_data_parser.h" +#include "paged_memory_data_parser.h" +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class EbpfDataParser : public FileSystemDataParser, public PagedMemoryDataParser, public BioLatencyDataParser { +public: + EbpfDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~EbpfDataParser(); + void InitAndParseEbpfData(const std::deque& dequeBuffer, uint64_t size); + void Finish(); + +private: + bool Init(const std::deque& dequeBuffer, uint64_t size); + std::unique_ptr reader_; + uint64_t ebpfAllEventStartTime_ = std::numeric_limits::max(); + uint64_t ebpfAllEventEndTime_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // EBPF_DATA_PARSER_H diff --git a/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp b/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eeb852f4673e2eb3dc100384f1183cefe3c752a3 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.cpp @@ -0,0 +1,401 @@ +/* + * 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. + */ + +#include "ebpf_data_reader.h" +#include "file_system_data_parser.h" +#include "string_help.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::base; +using namespace SysTuning::EbpfStdtype; +EbpfDataReader::EbpfDataReader(TraceDataCache* dataCache, const TraceStreamerFilters* filter) + : EventParserBase(dataCache, filter), + pidAndStartAddrToMapsAddr_(nullptr), + elfAddrAndStValueToSymAddr_(nullptr), + tracerEventToStrIndex_(INVALID_UINT64), + kernelFilePath_(traceDataCache_->GetDataIndex("/proc/kallsyms")), + ebpfDataHeader_(reinterpret_cast(startAddr_)) +{ +} +bool EbpfDataReader::InitEbpfData(const std::deque& dequeBuffer, uint64_t size) +{ + buffer_ = std::make_unique(size); + std::copy(dequeBuffer.begin(), dequeBuffer.begin() + size, buffer_.get()); + + startAddr_ = buffer_.get(); + bufferSize_ = size; + unresolvedLen_ = size; + if (!InitEbpfHeader() || !ReadEbpfData()) { + return false; + } + return true; +} + +bool EbpfDataReader::InitEbpfHeader() +{ + if (bufferSize_ < EbpfDataHeader::EBPF_DATA_HEADER_SIZE) { + TS_LOGE("buffer size less than ebpf data header!!!, bufferSize_ = %lu ", bufferSize_); + return false; + } + ebpfDataHeader_ = reinterpret_cast(startAddr_); + + if (ebpfDataHeader_->header.magic != EbpfDataHeader::HEADER_MAGIC) { + TS_LOGE("Get EBPF file header failed! magic = %lx", ebpfDataHeader_->header.magic); + return false; + } + if (ebpfDataHeader_->header.headSize != EbpfDataHeader::EBPF_DATA_HEADER_SIZE) { + TS_LOGE("Get ebpf file header failed! headSize = %u", ebpfDataHeader_->header.headSize); + return false; + } + TS_LOGI("EBPF data header : magic = %llx, headSize = %llu, clock = %llu, cmdline = %s", + ebpfDataHeader_->header.magic, ebpfDataHeader_->header.headSize, ebpfDataHeader_->header.clock, + ebpfDataHeader_->cmdline); + startAddr_ += EbpfDataHeader::EBPF_DATA_HEADER_SIZE; + unresolvedLen_ -= EbpfDataHeader::EBPF_DATA_HEADER_SIZE; + return true; +} + +bool EbpfDataReader::ReadEbpfData() +{ + while (unresolvedLen_ > EBPF_TITLE_SIZE) { + EbpfTypeAndLength* dataTitle = reinterpret_cast(startAddr_); + startAddr_ += EBPF_TITLE_SIZE; + unresolvedLen_ -= EBPF_TITLE_SIZE; + if (dataTitle->length > unresolvedLen_) { + TS_LOGE("Get EBPF data Title failed!"); + TS_LOGE("type = %lx, length = %lx", dataTitle->type, dataTitle->length); + return false; + } + if (dataTitle->length == 0) { + continue; + } + + bool ret = true; + switch (dataTitle->type) { + case ITEM_EVENT_MAPS: { + ret = ReadItemEventMaps(startAddr_, dataTitle->length); + break; + } + case ITEM_SYMBOL_INFO: { + ret = ReadItemSymbolInfo(startAddr_, dataTitle->length); + break; + } + case ITEM_EVENT_FS: { + ret = ReadItemEventFs(startAddr_, dataTitle->length); + break; + } + case ITEM_EVENT_VM: { + ret = ReadItemEventPagedMemory(startAddr_, dataTitle->length); + break; + } + case ITEM_EVENT_BIO: { + ret = ReadItemEventBIO(startAddr_, dataTitle->length); + break; + } + case ITEM_EVENT_STR: { + ret = ReadItemEventStr(startAddr_, dataTitle->length); + break; + } + case ITEM_EVENT_KENEL_SYMBOL_INFO: { + ret = ReaItemKernelSymbolInfo(startAddr_, dataTitle->length); + break; + } + default: + TS_LOGI("Do not support EBPF type: %d, length: %d", dataTitle->type, dataTitle->length); + } + if (!ret) { + return false; + } + startAddr_ += dataTitle->length; + unresolvedLen_ -= dataTitle->length; + } + return true; +} + +bool EbpfDataReader::ReadItemEventMaps(const uint8_t* buffer, uint32_t size) +{ + if (size < sizeof(MapsFixedHeader)) { + TS_LOGE("get maps addr Failed!!!"); + return false; + } + auto procMapsAddr = reinterpret_cast(buffer); + pidAndStartAddrToMapsAddr_.Insert(procMapsAddr->pid, procMapsAddr->start, procMapsAddr); +#if WITH_EBPF_HELP + if ((procMapsAddr->fileNameLen > size - sizeof(MapsFixedHeader)) || !procMapsAddr->fileNameLen) { + TS_LOGE("maps fileNameLen error!!!"); + return false; + } + auto fileNameAddr = const_cast(reinterpret_cast(procMapsAddr + 1)); + fileNameAddr[procMapsAddr->fileNameLen - 1] = '\0'; + auto fileNameIndex = traceDataCache_->GetDataIndex(fileNameAddr); + + // add proc Maps Data + traceDataCache_->GetEbpfProcessMaps()->AppendNewData(procMapsAddr->start, procMapsAddr->end, procMapsAddr->offset, + procMapsAddr->pid, procMapsAddr->fileNameLen, fileNameIndex); +#endif + return true; +} +void EbpfDataReader::UpdateElfAddrAndStValueToSymAddrMap(const ElfEventFixedHeader* elfAddr, uint32_t size) +{ + if (size < sizeof(ElfEventFixedHeader) + elfAddr->strTabLen + elfAddr->symTabLen + elfAddr->fileNameLen) { + TS_LOGE("elf addr size error!!!"); + return; + } + auto symEntLen = elfAddr->symEntLen; + auto symTabHeadAddr = reinterpret_cast(elfAddr + 1) + elfAddr->strTabLen; + if (symEntLen == ELF32_SYM) { + auto firstSymbolAddr = reinterpret_cast(symTabHeadAddr); + for (auto i = 0; i < elfAddr->symTabLen / symEntLen; i++) { + auto symAddr = firstSymbolAddr + i; + if ((symAddr->st_info & STT_FUNC) && symAddr->st_value) { + elfAddrAndStValueToSymAddr_.Insert(elfAddr, symAddr->st_value, + reinterpret_cast(symAddr)); + } + } + } else { + auto firstSymbolAddr = reinterpret_cast(symTabHeadAddr); + for (auto i = 0; i < elfAddr->symTabLen / symEntLen; i++) { + auto symAddr = firstSymbolAddr + i; + if ((symAddr->st_info & STT_FUNC) && symAddr->st_value) { + elfAddrAndStValueToSymAddr_.Insert(elfAddr, symAddr->st_value, + reinterpret_cast(symAddr)); + } + } + } +} +void EbpfDataReader::ReadKernelSymAddrMap(const KernelSymbolInfoHeader* elfAddr, uint32_t size) +{ + if (size < sizeof(KernelSymbolInfoHeader) + elfAddr->symTabLen + elfAddr->strTabLen) { + TS_LOGE("elf addr size error!!!, size is:%u and the symTabLen is:%u, strTabLen is:%u", size, elfAddr->symTabLen, + elfAddr->strTabLen); + return; + } + auto symTabLen = elfAddr->symTabLen; + auto sysItemSize = symTabLen / sizeof(KernelSymItem); + auto start = reinterpret_cast(elfAddr + 1); + auto strTab = reinterpret_cast(start + sysItemSize); + maxKernelAddr_ = elfAddr->vaddrEnd; + minKernelAddr_ = elfAddr->vaddrStart; + char strName[MAX_SYMBOL_LENGTH]; + for (auto i = 0; i < sysItemSize; i++) { + memset_s(strName, MAX_SYMBOL_LENGTH, 0, MAX_SYMBOL_LENGTH); + auto item = start + i; + if (strncpy_s(strName, MAX_SYMBOL_LENGTH, strTab + item->nameOffset, MAX_SYMBOL_LENGTH) < 0) { + TS_LOGE("get kernel symbol name error"); + } + AddrDesc desc{item->size, traceDataCache_->dataDict_.GetStringIndex(std::string(strName))}; + kernelSymbolMap_.insert(std::make_pair(item->value, desc)); + } +} + +void EbpfDataReader::UpdateElfPathIndexToElfAddrMap(const ElfEventFixedHeader* elfAddr, uint32_t size) +{ + if ((elfAddr->fileNameLen > size - sizeof(ElfEventFixedHeader) - elfAddr->strTabLen - elfAddr->symTabLen) || + !elfAddr->fileNameLen) { + TS_LOGE("elf filename len is error!!!"); + return; + } + + uint64_t fileNameIndex = INVALID_UINT64; + auto fileNameAddr = const_cast(reinterpret_cast( + reinterpret_cast(elfAddr + 1) + elfAddr->strTabLen + elfAddr->symTabLen)); + fileNameAddr[elfAddr->fileNameLen - 1] = '\0'; + fileNameIndex = traceDataCache_->GetDataIndex(fileNameAddr); + elfPathIndexToElfFixedHeaderAddr_.insert(std::make_pair(fileNameIndex, elfAddr)); + +#if WITH_EBPF_HELP + // add Elf symbol Data + traceDataCache_->GetEbpfElf()->AppendNewData(elfId_, elfAddr->textVaddr, elfAddr->textOffset, elfAddr->strTabLen, + elfAddr->symTabLen, elfAddr->fileNameLen, elfAddr->symEntLen, + fileNameIndex); +#endif +} + +#if WITH_EBPF_HELP +void EbpfDataReader::UpdateEbpfElfSymbolTable(const ElfEventFixedHeader* elfAddr, uint32_t size) +{ + if (size < sizeof(ElfEventFixedHeader) + elfAddr->strTabLen + elfAddr->symTabLen + elfAddr->fileNameLen) { + TS_LOGE("elf addr size error!!!"); + return; + } + auto symEntLen = elfAddr->symEntLen; + if (symEntLen == ELF32_SYM) { + auto firstSymbolAddr = + reinterpret_cast(reinterpret_cast(elfAddr + 1) + elfAddr->strTabLen); + for (auto i = 0; i < elfAddr->symTabLen / symEntLen; i++) { + auto symAddr = firstSymbolAddr + i; + if ((symAddr->st_info & STT_FUNC) && symAddr->st_value) { + traceDataCache_->GetEbpfElfSymbol()->AppendNewData(elfId_, symAddr->st_name, symAddr->st_value, + symAddr->st_size); + } + } + } else { + auto firstSymbolAddr = + reinterpret_cast(reinterpret_cast(elfAddr + 1) + elfAddr->strTabLen); + for (auto i = 0; i < elfAddr->symTabLen / symEntLen; i++) { + auto symAddr = firstSymbolAddr + i; + if ((symAddr->st_info & STT_FUNC) && symAddr->st_value) { + traceDataCache_->GetEbpfElfSymbol()->AppendNewData(elfId_, symAddr->st_name, symAddr->st_value, + symAddr->st_size); + } + } + } +} +#endif + +bool EbpfDataReader::ReadItemSymbolInfo(const uint8_t* buffer, uint32_t size) +{ + if (size < sizeof(ElfEventFixedHeader)) { + TS_LOGE("get symbol addr failed!!!"); + return false; + } + auto elfAddr = reinterpret_cast(buffer); + UpdateElfAddrAndStValueToSymAddrMap(elfAddr, size); + UpdateElfPathIndexToElfAddrMap(elfAddr, size); +#if WITH_EBPF_HELP + UpdateEbpfElfSymbolTable(elfAddr, size); + elfId_++; +#endif + return true; +} + +bool EbpfDataReader::ReaItemKernelSymbolInfo(const uint8_t* buffer, uint32_t size) +{ + if (size < sizeof(KernelSymbolInfoHeader)) { + TS_LOGE("get symbol addr failed!!!"); + return false; + } + auto elfAddr = reinterpret_cast(buffer); + ReadKernelSymAddrMap(elfAddr, size); + return true; +} +bool EbpfDataReader::ReadItemEventFs(const uint8_t* buffer, uint32_t size) +{ + if (size < sizeof(FsFixedHeader)) { + TS_LOGE("get file system event addr failed!!!"); + return false; + } + auto fsFixedHeaderAddr = reinterpret_cast(buffer); + endTsToFsFixedHeader_.insert(std::make_pair(fsFixedHeaderAddr->endTime, fsFixedHeaderAddr)); + return true; +} + +bool EbpfDataReader::ReadItemEventPagedMemory(const uint8_t* buffer, uint32_t size) +{ + if (size < sizeof(PagedMemoryFixedHeader)) { + TS_LOGE("get page memory event addr failed!!!"); + return false; + } + auto pagedMemoryFixedHeaderAddr = reinterpret_cast(buffer); + endTsToPagedMemoryFixedHeader_.insert(std::make_pair(pagedMemoryFixedHeaderAddr->endTime, pagedMemoryFixedHeaderAddr)); + return true; +} + +bool EbpfDataReader::ReadItemEventBIO(const uint8_t* buffer, uint32_t size) +{ + if (size < sizeof(BIOFixedHeader)) { + TS_LOGE("get Block IO event addr failed!!!"); + return false; + } + auto bioFixedHeaderAddr = reinterpret_cast(buffer); + endTsToBIOFixedHeader_.insert(std::make_pair(bioFixedHeaderAddr->endTime, bioFixedHeaderAddr)); + return true; +} + +bool EbpfDataReader::ReadItemEventStr(const uint8_t* buffer, uint32_t size) +{ + if (size < sizeof(StrEventFixedHeader)) { + TS_LOGE("get str event addr failed!!!"); + return false; + } + auto strFixedHeaderAddr = reinterpret_cast(buffer); + auto itid = + streamFilters_->processFilter_->GetOrCreateThreadWithPid(strFixedHeaderAddr->tid, strFixedHeaderAddr->pid); + auto strAddr = const_cast(reinterpret_cast(strFixedHeaderAddr + 1)); + if ((strFixedHeaderAddr->strLen > size - sizeof(StrEventFixedHeader)) || !strFixedHeaderAddr->strLen) { + TS_LOGE("invalid str event, strEventFixedHeader = %u, strlen = %d, size = %d", + sizeof(StrEventFixedHeader), strFixedHeaderAddr->strLen, size); + return true; + } + strAddr[strFixedHeaderAddr->strLen - 1] = '\0'; + auto strIndex = traceDataCache_->GetDataIndex(strAddr); + tracerEventToStrIndex_.Insert(strFixedHeaderAddr->srcTracer, strFixedHeaderAddr->srcType, itid, + strFixedHeaderAddr->startTime, strIndex); + return true; +} + +QuatraMap& EbpfDataReader::GetTracerEventToStrIndexMap() +{ + return tracerEventToStrIndex_; +} + +SymbolAndFilePathIndex EbpfDataReader::GetSymbolNameIndexFromElfSym(uint64_t ip) +{ + SymbolAndFilePathIndex symbolAndFilePathIndex(false); + auto end = kernelSymbolMap_.upper_bound(ip); + auto length = std::distance(kernelSymbolMap_.begin(), end); + if (length > 0) { + end--; + if (ip < end->first + end->second.size) { + symbolAndFilePathIndex.flag = true; + symbolAndFilePathIndex.symbolIndex = end->second.name; + symbolAndFilePathIndex.filePathIndex = kernelFilePath_; + // TS_LOGD("ok for ip:%lu, kernelip:%lu, size:%lu", ip, end->first, end->second.size); + } else { + TS_LOGD("failed for ip:%lu, kernelip:%lu, size:%lu", ip, end->first, end->second.size); + } + } + if (!symbolAndFilePathIndex.flag) { + TS_LOGD("failed for ip:%lu", ip); + } + return symbolAndFilePathIndex; +} +const DoubleMap& EbpfDataReader::GetPidAndStartAddrToMapsAddr() const +{ + return pidAndStartAddrToMapsAddr_; +} + +const DoubleMap& + EbpfDataReader::GetElfAddrAndStartValueToSymAddr() const +{ + return elfAddrAndStValueToSymAddr_; +} + +const std::multimap& EbpfDataReader::GetFileSystemEventMap() const +{ + return endTsToFsFixedHeader_; +} + +const std::multimap& EbpfDataReader::GetPagedMemoryMap() const +{ + return endTsToPagedMemoryFixedHeader_; +} + +const std::multimap& EbpfDataReader::GetBIOSampleMap() const +{ + return endTsToBIOFixedHeader_; +} + +const std::map& EbpfDataReader::GetElfPathIndexToElfAddr() const +{ + return elfPathIndexToElfFixedHeaderAddr_; +} +const EbpfDataHeader* EbpfDataReader::GetEbpfDataHeader() const +{ + return const_cast(ebpfDataHeader_); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.h b/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..b805fb9e000e001961e44b52d14472f2e0c2239e --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/ebpf_data_reader.h @@ -0,0 +1,91 @@ +/* + * 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. + */ + +#ifndef EBPF_DATA_READER_H +#define EBPF_DATA_READER_H +#include +#include +#include "ebpf_stdtype.h" +#include "htrace_plugin_time_parser.h" +#include "process_filter.h" +#include "quatra_map.h" +#include "string_help.h" +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_filters.h" +#include "unordered_map" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::EbpfStdtype; +class EbpfDataReader : private EventParserBase { +public: + EbpfDataReader(TraceDataCache* dataCache, const TraceStreamerFilters* filter); + ~EbpfDataReader() = default; + bool InitEbpfData(const std::deque& dequeBuffer, uint64_t size); + const EbpfDataHeader* GetEbpfDataHeader() const; + const std::multimap& GetFileSystemEventMap() const; + const std::multimap& GetPagedMemoryMap() const; + const std::multimap& GetBIOSampleMap() const; + const DoubleMap& GetPidAndStartAddrToMapsAddr() const; + const DoubleMap& GetElfAddrAndStartValueToSymAddr() const; + const std::map& GetElfPathIndexToElfAddr() const; + QuatraMap& GetTracerEventToStrIndexMap(); + SymbolAndFilePathIndex GetSymbolNameIndexFromElfSym(uint64_t ip); +private: + bool ReadEbpfData(); + bool InitEbpfHeader(); + bool ReadItemEventMaps(const uint8_t* buffer, uint32_t size); + bool ReadItemSymbolInfo(const uint8_t* buffer, uint32_t size); + bool ReaItemKernelSymbolInfo(const uint8_t* buffer, uint32_t size); + bool ReadItemEventFs(const uint8_t* buffer, uint32_t size); + bool ReadItemEventPagedMemory(const uint8_t* buffer, uint32_t size); + bool ReadItemEventBIO(const uint8_t* buffer, uint32_t size); + bool ReadItemEventStr(const uint8_t* buffer, uint32_t size); + void UpdateElfAddrAndStValueToSymAddrMap(const ElfEventFixedHeader* elfAddr, uint32_t size); + void ReadKernelSymAddrMap(const KernelSymbolInfoHeader* elfAddr, uint32_t size); + void UpdateElfPathIndexToElfAddrMap(const ElfEventFixedHeader* elfAddr, uint32_t size); +#if WITH_EBPF_HELP + void UpdateEbpfElfSymbolTable(const ElfEventFixedHeader* elfAddr, uint32_t size); +#endif +public: + uint64_t maxKernelAddr_ = 0; + uint64_t minKernelAddr_ = std::numeric_limits::max(); +private: + std::unique_ptr buffer_; + uint64_t bufferSize_ = 0; + uint64_t unresolvedLen_ = 0; + EbpfDataHeader* ebpfDataHeader_; + uint8_t* startAddr_ = nullptr; +#if WITH_EBPF_HELP + uint64_t elfId_ = 0; +#endif + std::multimap endTsToFsFixedHeader_ = {}; + std::multimap endTsToPagedMemoryFixedHeader_ = {}; + std::multimap endTsToBIOFixedHeader_ = {}; + std::map elfPathIndexToElfFixedHeaderAddr_ = {}; + DoubleMap pidAndStartAddrToMapsAddr_; + DoubleMap elfAddrAndStValueToSymAddr_; + QuatraMap tracerEventToStrIndex_; + DataIndex kernelFilePath_; + struct AddrDesc { + uint64_t size = 0; + DataIndex name = 0; + }; + std::map kernelSymbolMap_ = {}; + const uint32_t MAX_SYMBOL_LENGTH = 32; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // EBPF_DATA_READER_H diff --git a/host/trace_streamer/src/parser/ebpf_parser/ebpf_stdtype.h b/host/trace_streamer/src/parser/ebpf_parser/ebpf_stdtype.h new file mode 100644 index 0000000000000000000000000000000000000000..e4b5c1ef8651f21e962e7581523e033932cf3e70 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/ebpf_stdtype.h @@ -0,0 +1,214 @@ +/* + * 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. + */ +#ifndef EBPF_DATA_STD_TYPE_H +#define EBPF_DATA_STD_TYPE_H +#include +#include +#include "ts_common.h" +namespace SysTuning { +namespace EbpfStdtype { +struct EbpfDataHeader { + static constexpr uint32_t EBPF_DATA_HEADER_SIZE = 1024; + static constexpr uint64_t HEADER_MAGIC = 0x454C494646504245uLL; + struct HeaderData { + uint64_t magic = HEADER_MAGIC; + uint32_t headSize = EBPF_DATA_HEADER_SIZE; + uint32_t version; + uint32_t clock; + uint32_t cmdLineLen; + } __attribute__((packed)); + static constexpr uint32_t EBPF_COMMAND_MAX_SIZE = EBPF_DATA_HEADER_SIZE - sizeof(HeaderData); + HeaderData header; + char cmdline[EBPF_COMMAND_MAX_SIZE] = {'\0'}; +}; + +enum EBPF_DATA_TYPE { + ITEM_EVENT_MAPS = 0, + ITEM_SYMBOL_INFO, + ITEM_EVENT_FS, + ITEM_EVENT_VM, + ITEM_EVENT_BIO, + ITEM_EVENT_STR, + ITEM_EVENT_KENEL_SYMBOL_INFO = 0x10001, +}; + +struct EbpfTypeAndLength { + uint32_t type = 0; + uint32_t length = 0; +} __attribute__((packed)); +const uint32_t EBPF_TITLE_SIZE = sizeof(EbpfTypeAndLength); + +struct MapsFixedHeader { + uint64_t start = 0; + uint64_t end = 0; + uint32_t offset = 0; + uint32_t pid = 0; + uint32_t fileNameLen = 0; +} __attribute__((packed)); + +enum SYSTEM_ENTRY_VALUE { ELF32_SYM = 16, ELF64_SYM = 24 }; + +struct ElfEventFixedHeader { + uint64_t textVaddr = 0; + uint32_t textOffset = 0; + uint32_t strTabLen = 0; + uint32_t symTabLen = 0; + uint32_t fileNameLen = 0; + // value range: SYSTEM_ENTRY_LENGTH + uint32_t symEntLen = 0; +} __attribute__((packed)); +// the data following are +// uint8_t aa[strTabLen] // xx, bb, cc, dd +// uint8_t bb[symTabLen] //symEntLen elf64_sym, lef32_sym + +const int ARGS_MAX = 4; +const int MAX_TRACER_SIZE = 8; +const int SINGLE_IP_SIZE = 8; +const int MAX_FS_EVENT_SZIE = 16; +const int MAX_PROCESS_NAME_SZIE = 16; +struct FsFixedHeader { + uint32_t pid = 0; + uint32_t tid = 0; + char tracerName[MAX_TRACER_SIZE] = {0}; + uint64_t startTime = 0; + uint64_t endTime = 0; + char eventType[MAX_FS_EVENT_SZIE] = {0}; + int32_t ret = 0; + uint16_t nrUserIPs = 0; + uint16_t type = 0; + uint64_t args[ARGS_MAX] = {0}; + char processName[MAX_PROCESS_NAME_SZIE] = {0}; +} __attribute__((packed)); +// the data following are ips ... + +const int MAX_TRACER_NAME_LEN = 8; +const int MAX_TYPE_NAME_LEN = 16; +const int MAX_COMM_LEN = 16; +struct PagedMemoryFixedHeader { + uint32_t pid = 0; + uint32_t tid = 0; + char tagName[MAX_TRACER_NAME_LEN] = {0}; + uint64_t startTime = 0; + uint64_t endTime = 0; + char typeName[MAX_TYPE_NAME_LEN] = {0}; + uint64_t addr = 0; + uint32_t size = 0; + uint16_t nips = 0; + uint16_t type = 0; + char comm[MAX_COMM_LEN] = {0}; +} __attribute__((packed)); + +struct BIOFixedHeader { + uint32_t pid = 0; + uint32_t tid = 0; + char processName[MAX_PROCESS_NAME_SZIE] = {0}; + uint64_t startTime = 0; + uint64_t endTime = 0; + uint32_t prio = 0; + uint32_t size = 0; + uint64_t blkcnt = 0; + uint32_t nips = 0; + uint32_t type = 0; + char typeName[MAX_PROCESS_NAME_SZIE] = {0}; +} __attribute__((packed)); + +struct StrEventFixedHeader { + uint32_t pid = 0; + uint32_t tid = 0; + uint64_t startTime = 0; + uint32_t srcTracer = 0; + uint32_t srcType = 0; + uint32_t strLen = 0; + uint32_t padding = 0; +} __attribute__((packed)); + +struct KernelSymbolInfoHeader { + uint64_t vaddrStart = 0; + uint64_t vaddrEnd = 0; + uint32_t symTabLen = 0; + uint32_t strTabLen = 0; + // char* symTab = 0; // this is following the struct + // char* strTab = 0; // the symbols will follow the symTab +} __attribute__((packed)); + +struct KernelSymItem { + uint64_t value = 0; + uint32_t size = 0; + uint32_t nameOffset = 0; +} __attribute__((packed)); + +// EBPF clock relation +enum EbpfClockType { + EBPF_CLOCK_REALTIME = 0, + EBPF_CLOCK_BOOTTIME, + EBPF_CLOCK_MONOTONIC, + EBPF_CLOCK_MONOTONIC_RAW, +}; + +const std::map ebpfToTSClockType_ = { + {EBPF_CLOCK_REALTIME, TS_CLOCK_REALTIME}, + {EBPF_CLOCK_BOOTTIME, TS_CLOCK_BOOTTIME}, + {EBPF_CLOCK_MONOTONIC, TS_MONOTONIC}, + {EBPF_CLOCK_MONOTONIC_RAW, TS_MONOTONIC_RAW}, +}; + +struct SymbolAndFilePathIndex { + SymbolAndFilePathIndex() {} + SymbolAndFilePathIndex(bool invalidValue) : flag(invalidValue) {} + bool flag = false; + DataIndex symbolIndex = INVALID_UINT64; + DataIndex filePathIndex = INVALID_UINT64; +}; +// file system event type +enum FUC_SUB_TYPE { + SYS_OPENAT2 = 1, + SYS_READ = 2, + SYS_WRITE = 3, + SYS_PREAD64 = 4, + SYS_PWRITE64 = 5, + SYS_READV = 6, + SYS_WRITEV = 7, + SYS_PREADV = 8, + SYS_PWRITEV = 9, + SYS_CLOSE = 10, +}; + +const std::map subTypeToName = { + {SYS_OPENAT2, "openat2"}, {SYS_READ, "read"}, {SYS_WRITE, "write"}, {SYS_PREAD64, "pread64"}, + {SYS_PWRITE64, "pwrite64"}, {SYS_READV, "readv"}, {SYS_WRITEV, "writev"}, {SYS_PREADV, "preadv"}, + {SYS_PWRITEV, "pwritev"}, {SYS_CLOSE, "close"}}; + +enum FUC_SUMMARY_TYPE { + OPEN = 0, + CLOSE = 1, + READ = 2, + WRITE = 3, +}; +const std::map fucSubToSummaryType = { + {SYS_OPENAT2, OPEN}, + {SYS_READ, READ}, + {SYS_WRITE, WRITE}, + {SYS_PREAD64, READ}, + {SYS_PWRITE64, WRITE}, + {SYS_READV, READ}, + {SYS_WRITEV, WRITE}, + {SYS_PREADV, READ}, + {SYS_PWRITEV, WRITE}, + {SYS_CLOSE, CLOSE}, +}; +const uint32_t MIN_USER_IP = 0xffffffff; +} // namespace EbpfStdtype +} // namespace SysTuning +#endif // EBPF_DATA_STD_TYPE_H diff --git a/host/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp b/host/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4a9349e85e962b9c109f1ccb7f1750b689b9f11 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.cpp @@ -0,0 +1,143 @@ +/* + * 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. + */ +#include "file_system_data_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +#include "string_to_numerical.h" + +namespace SysTuning { +namespace TraceStreamer { +FileSystemDataParser::FileSystemDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : EventParserBase(dataCache, ctx), + EbpfBase(dataCache, ctx), + timeParser_(std::make_unique(dataCache, ctx)) +{ +} +FileSystemDataParser::~FileSystemDataParser() +{ + TS_LOGI("EBPF FileSystem data ts MIN:%llu, MAX:%llu", + static_cast(timeParser_->GetPluginStartTime()), + static_cast(timeParser_->GetPluginEndTime())); +} +void FileSystemDataParser::ParseFileSystemEvent() +{ + if (!reader_->GetFileSystemEventMap().size()) { + return; + } + auto& tracerEventToStrIndexMap = reader_->GetTracerEventToStrIndexMap(); + for (auto mapItor = reader_->GetFileSystemEventMap().begin(); mapItor != reader_->GetFileSystemEventMap().end(); + mapItor++) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_FILE_SYSTEM, STAT_EVENT_RECEIVED); + auto fsFixedHeadrAddr = mapItor->second; + bool callIdExistFlag = false; + + auto userIpsAddr = reinterpret_cast(fsFixedHeadrAddr + 1); + if (fsFixedHeadrAddr->nrUserIPs) { + std::string ipsToStr(reinterpret_cast(userIpsAddr), + fsFixedHeadrAddr->nrUserIPs * SINGLE_IP_SIZE); + auto ipsHashValue = hashFun_(ipsToStr); + auto value = pidAndipsToCallId_.Find(fsFixedHeadrAddr->pid, ipsHashValue); + if (value != INVALID_UINT64) { + callIdExistFlag = true; + currentCallId_ = value; + } else { + pidAndipsToCallId_.Insert(fsFixedHeadrAddr->pid, ipsHashValue, callChainId_); + currentCallId_ = callChainId_++; + } + } else { + currentCallId_ = INVALID_UINT64; + } + + uint16_t type = INVALID_UINT16; + auto tmp = fucSubToSummaryType.find(fsFixedHeadrAddr->type); + if (tmp == fucSubToSummaryType.end()) { + return; + } + type = fucSubToSummaryType.at(fsFixedHeadrAddr->type); + + // Init process name data + auto processName = const_cast(fsFixedHeadrAddr->processName); + processName[MAX_PROCESS_NAME_SZIE - 1] = '\0'; + uint32_t ipid = + streamFilters_->processFilter_->UpdateOrCreateProcessWithName(fsFixedHeadrAddr->pid, processName); + uint32_t itid = + streamFilters_->processFilter_->GetOrCreateThreadWithPid(fsFixedHeadrAddr->tid, fsFixedHeadrAddr->pid); + auto newStartTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, fsFixedHeadrAddr->startTime); + timeParser_->UpdatePluginTimeRange(clockId_, fsFixedHeadrAddr->startTime, newStartTs); + auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, fsFixedHeadrAddr->endTime); + timeParser_->UpdatePluginTimeRange(clockId_, fsFixedHeadrAddr->endTime, newEndTs); + if (newStartTs > newEndTs) { + TS_LOGE("File system event origin startTs = %lu, endTs = %lu, newStartTs = %lu, newEndTs = %lu", + fsFixedHeadrAddr->startTime, fsFixedHeadrAddr->endTime, newStartTs, newEndTs); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_FILE_SYSTEM, STAT_EVENT_DATA_INVALID); + return; + } + uint64_t duration = newEndTs - newStartTs; + DataIndex returnValue = INVALID_UINT64; + DataIndex errorCode = INVALID_UINT64; + if (fsFixedHeadrAddr->ret < 0) { + returnValue = ConvertToHexTextIndex(0); + errorCode = ConvertToHexTextIndex(-fsFixedHeadrAddr->ret); + } else { + returnValue = ConvertToHexTextIndex(fsFixedHeadrAddr->ret); + } + + int i = 0; + auto firstArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i++]); + auto secondArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i++]); + auto thirdArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i++]); + auto fourthArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i]); + + // get file descriptor + auto fd = GetFileDescriptor(fsFixedHeadrAddr, type); + // get file path + uint64_t filePathId = INVALID_UINT64; + filePathId = + tracerEventToStrIndexMap.Find(ITEM_EVENT_FS, fsFixedHeadrAddr->type, itid, fsFixedHeadrAddr->startTime); + if (filePathId != INVALID_UINT64) { + tracerEventToStrIndexMap.Erase(ITEM_EVENT_FS, fsFixedHeadrAddr->type, itid, + fsFixedHeadrAddr->startTime); + } + + // get read or writ size + size_t size = MAX_SIZE_T; + if ((type == READ || type == WRITE) && fsFixedHeadrAddr->ret >= 0) { + size = fsFixedHeadrAddr->ret; + } + + traceDataCache_->GetFileSystemSample()->AppendNewData( + currentCallId_, type, ipid, itid, newStartTs, newEndTs, duration, returnValue, errorCode, size, fd, + filePathId, firstArgument, secondArgument, thirdArgument, fourthArgument); + if (!callIdExistFlag) { + ParseCallStackData(userIpsAddr, fsFixedHeadrAddr->nrUserIPs, fsFixedHeadrAddr->pid, currentCallId_); + } + } +} + +int32_t FileSystemDataParser::GetFileDescriptor(const FsFixedHeader* fsFixedHeader, uint32_t fucType) +{ + auto returnValue = fsFixedHeader->ret; + int32_t fd = INVALID_INT32; + if (fucType == OPEN and returnValue >= 0) { + fd = returnValue; + } else if (fucType == READ or fucType == WRITE) { + fd = fsFixedHeader->args[0]; + } else if (fucType == CLOSE) { + fd = fsFixedHeader->args[1]; + } + return fd; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.h b/host/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..fb7ed967f6a0d210f45fdd08203d169987013c77 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/file_system_data_parser.h @@ -0,0 +1,38 @@ +/* + * 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. + */ +#ifndef FILE_SYSTEM_DATA_PARSER_H +#define FILE_SYSTEM_DATA_PARSER_H +#include "clock_filter.h" +#include "double_map.h" +#include "ebpf_base.h" +#include "htrace_plugin_time_parser.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::EbpfStdtype; +class FileSystemDataParser : virtual public EbpfBase { +public: + FileSystemDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~FileSystemDataParser(); + void ParseFileSystemEvent(); +protected: + std::unique_ptr timeParser_; +private: + int32_t GetFileDescriptor(const FsFixedHeader* fsFixedHeader, uint32_t fucType); + uint64_t currentCallId_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // FILE_SYSTEM_DATA_PARSER_H diff --git a/host/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp b/host/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02c49eaf4df76b292eb3e50d43dbde77572c5df8 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.cpp @@ -0,0 +1,93 @@ +/* + * 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. + */ +#include "paged_memory_data_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +#include "string_to_numerical.h" + +namespace SysTuning { +namespace TraceStreamer { +PagedMemoryDataParser::PagedMemoryDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : EventParserBase(dataCache, ctx), + EbpfBase(dataCache, ctx), + timeParser_(std::make_unique(dataCache, ctx)) +{ +} +PagedMemoryDataParser::~PagedMemoryDataParser() +{ + TS_LOGI("EBPF paged memory data ts MIN:%llu, MAX:%llu", + static_cast(timeParser_->GetPluginStartTime()), + static_cast(timeParser_->GetPluginEndTime())); +} +void PagedMemoryDataParser::ParsePagedMemoryEvent() +{ + if (!reader_->GetPagedMemoryMap().size()) { + return; + } + for (auto mapItor = reader_->GetPagedMemoryMap().begin(); mapItor != reader_->GetPagedMemoryMap().end(); mapItor++) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_PAGED_MEMORY, STAT_EVENT_RECEIVED); + auto pagedMemoryFixedHeadrAddr = mapItor->second; + bool callIdExistFlag = false; + + auto userIpsAddr = reinterpret_cast(pagedMemoryFixedHeadrAddr + 1); + if (pagedMemoryFixedHeadrAddr->nips) { + std::string ipsToStr(reinterpret_cast(userIpsAddr), + pagedMemoryFixedHeadrAddr->nips * SINGLE_IP_SIZE); + auto ipsHashValue = hashFun_(ipsToStr); + auto value = pidAndipsToCallId_.Find(pagedMemoryFixedHeadrAddr->pid, ipsHashValue); + if (value != INVALID_UINT64) { + callIdExistFlag = true; + currentCallId_ = value; + } else { + pidAndipsToCallId_.Insert(pagedMemoryFixedHeadrAddr->pid, ipsHashValue, callChainId_); + currentCallId_ = callChainId_++; + } + } else { + currentCallId_ = INVALID_UINT64; + } + + auto type = pagedMemoryFixedHeadrAddr->type; + // Init process name data + const char* processName = reinterpret_cast(pagedMemoryFixedHeadrAddr->comm); + uint32_t ipid = + streamFilters_->processFilter_->UpdateOrCreateProcessWithName(pagedMemoryFixedHeadrAddr->pid, processName); + uint32_t itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(pagedMemoryFixedHeadrAddr->tid, + pagedMemoryFixedHeadrAddr->pid); + uint64_t startTs = pagedMemoryFixedHeadrAddr->startTime; + uint64_t endTs = pagedMemoryFixedHeadrAddr->endTime; + auto newStartTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, startTs); + timeParser_->UpdatePluginTimeRange(clockId_, startTs, newStartTs); + auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, endTs); + timeParser_->UpdatePluginTimeRange(clockId_, endTs, newEndTs); + if (newStartTs > newEndTs) { + TS_LOGE("paged memory startTs = %lu, endTs = %lu, newStartTs = %lu, newEndTs = %lu", startTs, endTs, + newStartTs, newEndTs); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_PAGED_MEMORY, STAT_EVENT_DATA_INVALID); + return; + } + uint64_t duration = newEndTs - newStartTs; + + auto addr = ConvertToHexTextIndex(pagedMemoryFixedHeadrAddr->addr); + auto size = pagedMemoryFixedHeadrAddr->size; + + traceDataCache_->GetPagedMemorySampleData()->AppendNewData(currentCallId_, type, ipid, newStartTs, newEndTs, + duration, size, addr, itid); + if (!callIdExistFlag) { + ParseCallStackData(userIpsAddr, pagedMemoryFixedHeadrAddr->nips, pagedMemoryFixedHeadrAddr->pid, currentCallId_); + } + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.h b/host/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..ad7ed41b46eef72a9decfbe3512c81596c60cd26 --- /dev/null +++ b/host/trace_streamer/src/parser/ebpf_parser/paged_memory_data_parser.h @@ -0,0 +1,41 @@ +/* + * 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. + */ +#ifndef PAGED_MEMORY_DATA_PARSER_H +#define PAGED_MEMORY_DATA_PARSER_H +#include "clock_filter.h" +#include "double_map.h" +#include "ebpf_base.h" +#include "ebpf_data_reader.h" +#include "ebpf_stdtype.h" +#include "event_parser_base.h" +#include "htrace_plugin_time_parser.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::EbpfStdtype; + +class PagedMemoryDataParser : virtual public EbpfBase { +public: + PagedMemoryDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~PagedMemoryDataParser(); + void ParsePagedMemoryEvent(); +protected: + std::unique_ptr timeParser_; +private: + uint64_t currentCallId_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PAGED_MEMORY_DATA_PARSER_H diff --git a/host/trace_streamer/src/parser/event_parser_base.h b/host/trace_streamer/src/parser/event_parser_base.h old mode 100644 new mode 100755 index 2df1e46da189ba8b03ad393e4f0d8498d81babcf..60d0dd6b09be4e34a4f66e4895021ac5f5d176d3 --- a/host/trace_streamer/src/parser/event_parser_base.h +++ b/host/trace_streamer/src/parser/event_parser_base.h @@ -16,7 +16,6 @@ #ifndef SRC_EVENT_PARSER_BASE_H #define SRC_EVENT_PARSER_BASE_H #include "trace_data_cache.h" -#include "trace_streamer_config.h" #include "trace_streamer_filters.h" namespace SysTuning { namespace TraceStreamer { @@ -29,8 +28,6 @@ public: public: const TraceStreamerFilters* streamFilters_; TraceDataCache* traceDataCache_; -protected: - TraceStreamerConfig config_; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/hiperf_parser/BUILD.gn b/host/trace_streamer/src/parser/hiperf_parser/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1e76c417a36a47b64ed131636bb67946c76c4fc4 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/BUILD.gn @@ -0,0 +1,67 @@ +# 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("//build/ohos.gni") +import("../../ts.gni") +ohos_source_set("hiperf_parser_src") { + sources = [ "perf_data_parser.cpp" ] + include_dirs = [ + "hiperf/linux", + "hiperf/kernel", + "hiperf/include/linux", + ".", + "../../base", + "../../cfg", + "hiperf/include", + "../../include", + "../../", + "../../filter", + "../../trace_data", + "..", + "../htrace_parser", + "../../trace_streamer", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "//third_party/protobuf/src", + "//third_party/perf_include", + "//third_party/perf_include/libbpf", + ] + include_dirs += [ "//third_party/libunwind/include" ] + + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + if (is_test) { + cflags += [ "-D IS_UT" ] + } + } +} + +group("hiperf_parser") { + deps = [ + ":hiperf_parser_src", + "hiperf:hiperf", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + ] + if (target != "test" && !is_openharmony) { + deps += [ "//prebuilts/protos:ts_proto_data_cpp" ] + } +} diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/BUILD.gn b/host/trace_streamer/src/parser/hiperf_parser/hiperf/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2a31938ad95e44a075e9536fa8445321aba871fe --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/BUILD.gn @@ -0,0 +1,79 @@ +# 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("//build/ohos.gni") +import("../../../ts.gni") +ohos_source_set("hiperf_src") { + sources = [ + "callstack.cpp", + "callstack.h", + "debug_logger.cpp", + "debug_logger.h", + "dwarf_encoding.cpp", + "dwarf_encoding.h", + "elf_file.cpp", + "elf_header.cpp", + "elf_symbol.cpp", + "hashlist.h", + "option.cpp", + "perf_event_record.cpp", + + # "perf_events.cpp", + "perf_file_format.cpp", + "perf_file_reader.cpp", + "program_header.cpp", + "register.cpp", + "register.h", + "report.cpp", + + # "ring_buffer.cpp", + "include/symbols_file.h", + "section_header.cpp", + "subcommand.cpp", + "symbols_file.cpp", + "utilities.cpp", + "virtual_runtime.cpp", + "virtual_thread.cpp", + ] + include_dirs = [ + "linux", + "kernel", + "../", + "./", + "../../../base", + "include", + "../../../include", + "../../../", + "../../../trace_streamer", + "include", + "include/linux", + ] + include_dirs += [ + "//third_party/perf_include/libbpf", + "//third_party/perf_include/musl", + "//third_party/libunwind/include", + "//third_party/libunwind/src", + "//third_party/libunwind/include/tdep-x86_64", + ] +} + +group("hiperf") { + deps = [ + ":hiperf_src", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + ] + if (target != "test" && !is_openharmony) { + deps += [ "//prebuilts/protos:ts_proto_data_cpp" ] + } +} diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/callstack.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/callstack.cpp new file mode 100755 index 0000000000000000000000000000000000000000..4c5e1d4bda05d954ba2c6f68599f678502777299 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/callstack.cpp @@ -0,0 +1,661 @@ +/* + * Copyright (c) 2021-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. + */ +#define HILOG_TAG "CallStack" + +#include "callstack.h" + +#include +#if HAVE_LIBUNWIND +#include +extern "C" { +#include +} +#endif + +#include "register.h" +#if defined(target_cpu_arm) +// reg size is int (unw_word_t) +#define UNW_WORD_PFLAG "x" +#elif defined(__arm__) && defined(target_cpu_x64) +// reg size is long long (unw_word_t) +#define UNW_WORD_PFLAG "llx" +#else +// reg size is long (unw_word_t) +#define UNW_WORD_PFLAG "zx" +#endif +namespace OHOS { +namespace Developtools { +namespace HiPerf { +#if HAVE_LIBUNWIND +const std::map UNW_ERROR_MAP = { + {UNW_ESUCCESS, std::to_string(UNW_ESUCCESS)}, + {UNW_EUNSPEC, std::to_string(UNW_EUNSPEC)}, + {UNW_ENOMEM, std::to_string(UNW_ENOMEM)}, + {UNW_EBADREG, std::to_string(UNW_EBADREG)}, + {UNW_EREADONLYREG, std::to_string(UNW_EREADONLYREG)}, + {UNW_ESTOPUNWIND, std::to_string(UNW_ESTOPUNWIND)}, + {UNW_EINVALIDIP, std::to_string(UNW_EINVALIDIP)}, + {UNW_EBADFRAME, std::to_string(UNW_EBADFRAME)}, + {UNW_EINVAL, std::to_string(UNW_EINVAL)}, + {UNW_EBADVERSION, std::to_string(UNW_EBADVERSION)}, + {UNW_ENOINFO, std::to_string(UNW_ENOINFO)}, +}; +const std::string CallStack::GetUnwErrorName(int error) +{ + if (UNW_ERROR_MAP.count(static_cast(-error)) > 0) { + return UNW_ERROR_MAP.at(static_cast(-error)); + } else { + return "UNKNOW_UNW_ERROR"; + } +} + +void CallStack::dumpUDI(unw_dyn_info_t &di) +{ + HLOGV("unwind_table info: "); + HLOGV(" di.start_ip: 0x%016" UNW_WORD_PFLAG "", di.start_ip); + HLOGV(" di.end_ip: 0x%016" UNW_WORD_PFLAG "", di.end_ip); + HLOGV(" di.u.rti.segbase: 0x%016" UNW_WORD_PFLAG "", di.u.rti.segbase); + HLOGV(" di.u.rti.table_data: 0x%016" UNW_WORD_PFLAG "", di.u.rti.table_data); + HLOGV(" di.u.rti.table_len: 0x%016" UNW_WORD_PFLAG "", di.u.rti.table_len); +} + +bool CallStack::fillUDI(unw_dyn_info_t &di, SymbolsFile &symbolsFile, const MemMapItem &mmap, + const VirtualThread &thread) +{ + di.start_ip = mmap.begin_; + di.end_ip = mmap.end_; +#ifndef target_cpu_arm + uint64_t fdeTableElfOffset, fdeTableSize, ehFrameHdrElfOffset; + if ((UNW_INFO_FORMAT_REMOTE_TABLE == di.format) && + symbolsFile.GetHDRSectionInfo(ehFrameHdrElfOffset, fdeTableElfOffset, fdeTableSize)) { + /* + unw_word_t name_ptr; // addr. of table name (e.g., library name) + unw_word_t segbase; // segment base + unw_word_t table_len; // must be a multiple of sizeof(unw_word_t)! + unw_word_t table_data; + */ + /* + all the rti addr is offset of the elf file + begin - page offset = elf file base addr in vaddr user space + begin - page offset + elf offset = vaddr in real word.(for this thread) + */ + + // segbase is file offset . + /* + 00200000-00344000 r--p 00000000 08:02 46404365 + 00344000-005c4000 r-xp 00143000 08:02 46404365 + + LOAD 0x00000000001439c0 0x00000000003449c0 0x00000000003449c0 + 0x000000000027f3c0 0x000000000027f3c0 R E 0x1000 + + GNU_EH_FRAME 0x00000000000f3248 0x00000000002f3248 0x00000000002f3248 + 0x000000000000bb04 0x000000000000bb04 R 0x4 + + */ + const MemMapItem *ehFrameMmap = thread.FindMapByFileInfo(mmap.name_, ehFrameHdrElfOffset); + + if (ehFrameMmap == nullptr) { + HLOGE("no ehframe mmap found."); + return false; + } + + di.u.rti.segbase = ehFrameMmap->begin_ + ehFrameHdrElfOffset - ehFrameMmap->pageoffset_; + di.u.rti.table_data = ehFrameMmap->begin_ + fdeTableElfOffset - ehFrameMmap->pageoffset_; + di.u.rti.table_len = fdeTableSize / sizeof(unw_word_t); + + HLOGV(" map pageoffset: 0x%016" PRIx64 "", mmap.pageoffset_); + HLOGV(" ehFrameHdrElfOffset: 0x%016" PRIx64 "", ehFrameHdrElfOffset); + HLOGV(" fdeTableElfOffset: 0x%016" PRIx64 "", fdeTableElfOffset); + HLOGV(" fdeTableSize: 0x%016" PRIx64 "", fdeTableSize); + return true; + } else { + HLOGD("SymbolsFile::GetHDRSectionInfo() failed"); + } +#else + uint64_t SectionVaddr, SectionSize, SectionFileOffset; + if ((UNW_INFO_FORMAT_ARM_EXIDX == di.format) && + symbolsFile.GetSectionInfo(ARM_EXIDX, SectionVaddr, SectionSize, SectionFileOffset)) { + const MemMapItem *targetMmap = thread.FindMapByFileInfo(mmap.name_, SectionFileOffset); + if (targetMmap == nullptr) { + HLOGE("no debug mmap found."); + return false; + } + HLOGV(" begin: %" PRIx64 " offset:%" PRIx64 "", targetMmap->begin_, + targetMmap->pageoffset_); + + di.u.rti.table_data = targetMmap->begin_ + SectionFileOffset - targetMmap->pageoffset_; + di.u.rti.table_len = SectionSize; + HLOGV(" SectionName: %s", std::string(ARM_EXIDX).c_str()); + HLOGV(" SectionVaddrt: 0x%016" PRIx64 "", SectionVaddr); + HLOGV(" SectionFileOffset 0x%016" PRIx64 "", SectionFileOffset); + HLOGV(" SectionSize: 0x%016" PRIx64 "", SectionSize); + + // GetSectionInfo return true, but SectionVaddr || SectionSize is 0 ??? + HLOG_ASSERT(SectionVaddr != 0 && SectionSize != 0); + return true; + } else { + HLOGD("SymbolsFile::GetSectionInfo() failed"); + } +#endif + return false; +} + +/* + https://www.nongnu.org/libunwind/man/libunwind-dynamic(3).html +*/ +int CallStack::FindUnwindTable(SymbolsFile *symbolsFile, const MemMapItem &mmap, + UnwindInfo *unwindInfoPtr, unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, void *arg) +{ + HLOGM("try search debug info at %s", symbolsFile->filePath_.c_str()); + auto &dynInfoProcessMap = unwindInfoPtr->callStack.unwindDynInfoMap_; + // all the thread in same process have same mmap and symbols + if (dynInfoProcessMap.find(unwindInfoPtr->thread.pid_) == dynInfoProcessMap.end()) { + dynInfoProcessMap.emplace(unwindInfoPtr->thread.pid_, dsoUnwDynInfoMap {}); + } + dsoUnwDynInfoMap &dynFileMap = dynInfoProcessMap[unwindInfoPtr->thread.pid_]; + // find use dso name as key + if (dynFileMap.find(symbolsFile->filePath_) == dynFileMap.end()) { + unw_dyn_info_t newdi; + if (memset_s(&newdi, sizeof(unw_dyn_info_t), 0, sizeof(unw_dyn_info_t)) != 0) { + HLOGE("memset_s() failed"); + return -UNW_EUNSPEC; + } +#ifdef target_cpu_arm + // arm use .ARM.exidx , not use ehframe + newdi.format = UNW_INFO_FORMAT_ARM_EXIDX; +#else + // otherwise we use EH FRAME + newdi.format = UNW_INFO_FORMAT_REMOTE_TABLE; +#endif + if (fillUDI(newdi, *symbolsFile, mmap, unwindInfoPtr->thread)) { + dumpUDI(newdi); + // we make a option empty value first + std::optional &odi = dynFileMap[symbolsFile->filePath_]; + odi = newdi; + } else { + HLOGV("fillUDI failed()"); + return -UNW_EUNSPEC; + } + } + + HLOG_ASSERT(dynInfoProcessMap.find(unwindInfoPtr->thread.pid_) != dynInfoProcessMap.end()); + HLOG_ASSERT_MESSAGE(dynFileMap.find(symbolsFile->filePath_) != dynFileMap.end(), "%s", + symbolsFile->filePath_.c_str()); + std::optional &odi = + dynInfoProcessMap.at(unwindInfoPtr->thread.pid_).at(symbolsFile->filePath_); + + if (odi.has_value()) { + unw_dyn_info_t &di = odi.value(); + /* + we don't use dwarf_search_unwind_table + because in arm it will search two function: + 1 arm_search_unwind_table first + 2 dwarf_search_unwind_table + + see libunwind_i.h for arm + define tdep_search_unwind_table UNW_OBJ(search_unwind_table) + + */ + int ret = static_cast( + tdep_search_unwind_table(as, ip, &di, pi, need_unwind_info, arg)); + + HLOGM("search_unwind_table ret %d:%s", ret, GetUnwErrorName(ret).c_str()); + + if (UNW_ESUCCESS != ret) { + if (UNW_ENOINFO != ret) { + HLOGW("search_unwind_table ret error %d:%s", ret, GetUnwErrorName(ret).c_str()); + } + return -UNW_EUNSPEC; + } else { + return UNW_ESUCCESS; + } + } else { + HLOGW("no debug info found for thread %d:%s", unwindInfoPtr->thread.tid_, + unwindInfoPtr->thread.name_.c_str()); + return -UNW_EUNSPEC; + } +} + +int CallStack::FindProcInfo(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg) +{ + UnwindInfo *unwindInfoPtr = static_cast(arg); + + HLOGM("need_unwind_info ret %d ip %" UNW_WORD_PFLAG "", need_unwind_info, ip); + const MemMapItem *mmap = unwindInfoPtr->thread.FindMapByAddr(ip); + if (mmap != nullptr) { + SymbolsFile *symbolsFile = unwindInfoPtr->thread.FindSymbolsFileByMap(*mmap); + if (symbolsFile != nullptr) { + return FindUnwindTable(symbolsFile, *mmap, unwindInfoPtr, as, ip, pi, need_unwind_info, + arg); + } else { + HLOGW("no symbols file found for thread %d:%s", unwindInfoPtr->thread.tid_, + unwindInfoPtr->thread.name_.c_str()); + } + } else { + HLOGE("ip 0x%016" UNW_WORD_PFLAG " not found in thread %d:%s", ip, + unwindInfoPtr->thread.tid_, unwindInfoPtr->thread.name_.c_str()); + } + + return -UNW_EUNSPEC; +} + +bool CallStack::ReadVirtualThreadMemory(UnwindInfo &unwindInfoPtr, unw_word_t addr, + unw_word_t *data) +{ + auto process = unwindInfoPtr.callStack.porcessMemoryMap_.find(unwindInfoPtr.thread.pid_); + if (process != unwindInfoPtr.callStack.porcessMemoryMap_.end()) { + auto memory = process->second.find(addr); + if (memory != process->second.end()) { + *data = memory->second; + return true; + } + } + + if (unwindInfoPtr.thread.ReadRoMemory(addr, (uint8_t *)data, sizeof(unw_word_t))) { + unwindInfoPtr.callStack.porcessMemoryMap_[unwindInfoPtr.thread.pid_][addr] = *data; + return true; + } else { + return false; + } +} + +int CallStack::AccessMem([[maybe_unused]] unw_addr_space_t as, unw_word_t addr, + unw_word_t *valuePoint, int writeOperation, void *arg) +{ + UnwindInfo *unwindInfoPtr = static_cast(arg); + *valuePoint = 0; + HLOGDUMMY("try access addr 0x%" UNW_WORD_PFLAG " ", addr); + HLOG_ASSERT(writeOperation == 0); + + /* Check overflow. */ + if (addr + sizeof(unw_word_t) < addr) { + HLOGE("address overfolw at 0x%" UNW_WORD_PFLAG " increase 0x%zu", addr, sizeof(unw_word_t)); + return -UNW_EUNSPEC; + } + + if (addr < unwindInfoPtr->callStack.stackPoint_ or + addr + sizeof(unw_word_t) >= unwindInfoPtr->callStack.stackEnd_) { + if (ReadVirtualThreadMemory(*unwindInfoPtr, addr, valuePoint)) { + HLOGM("access_mem addr %p get val 0x%" UNW_WORD_PFLAG ", from mmap", + reinterpret_cast(addr), *valuePoint); + } else { + HLOGW("access_mem addr %p failed, from mmap, ", reinterpret_cast(addr)); + HLOGW("stack range 0x%" PRIx64 " - 0x%" PRIx64 "(0x%" PRIx64 ")", + unwindInfoPtr->callStack.stackPoint_, unwindInfoPtr->callStack.stackEnd_, + unwindInfoPtr->callStack.stackEnd_ - unwindInfoPtr->callStack.stackPoint_); + return -UNW_EUNSPEC; + } + } else { + size_t stackOffset = addr - unwindInfoPtr->callStack.stackPoint_; + *valuePoint = *(unw_word_t *)&unwindInfoPtr->callStack.stack_[stackOffset]; + HLOGM("access_mem addr %p val %" UNW_WORD_PFLAG ", from stack offset %zu", + reinterpret_cast(addr), *valuePoint, stackOffset); + } + + return UNW_ESUCCESS; +} + +int CallStack::AccessReg([[maybe_unused]] unw_addr_space_t as, unw_regnum_t regnum, + unw_word_t *valuePoint, int writeOperation, void *arg) +{ + UnwindInfo *unwindInfoPtr = static_cast(arg); + uint64_t val; + int perfRegIndex = LibunwindRegIdToPerfReg(regnum); + if (perfRegIndex < 0) { + HLOGE("can't read reg %d", perfRegIndex); + return perfRegIndex; + } + /* Don't support write, I suspect we don't need it. */ + if (writeOperation) { + HLOGE("access_reg %d", regnum); + return -UNW_EINVAL; + } + + if (unwindInfoPtr->callStack.regsNum_ == 0) { + return -UNW_EUNSPEC; + } + + if (!RegisterGetValue(val, unwindInfoPtr->callStack.regs_, static_cast(perfRegIndex), + unwindInfoPtr->callStack.regsNum_)) { + HLOGE("can't read reg %d", perfRegIndex); + return -UNW_EUNSPEC; + } + + *valuePoint = (unw_word_t)val; + HLOGM("reg %d:%s, val 0x%" UNW_WORD_PFLAG "", regnum, RegisterGetName(static_cast(perfRegIndex)).c_str(), + *valuePoint); + return UNW_ESUCCESS; +} + +void CallStack::PutUnwindInfo([[maybe_unused]] unw_addr_space_t as, + [[maybe_unused]] unw_proc_info_t *pi, [[maybe_unused]] void *arg) +{ +} + +int CallStack::AccessFpreg([[maybe_unused]] unw_addr_space_t as, [[maybe_unused]] unw_regnum_t num, + [[maybe_unused]] unw_fpreg_t *val, [[maybe_unused]] int writeOperation, + [[maybe_unused]] void *arg) +{ + return -UNW_EINVAL; +} + +int CallStack::GetDynInfoListAaddr([[maybe_unused]] unw_addr_space_t as, + [[maybe_unused]] unw_word_t *dil_vaddr, + [[maybe_unused]] void *arg) +{ + return -UNW_ENOINFO; +} + +int CallStack::Resume([[maybe_unused]] unw_addr_space_t as, [[maybe_unused]] unw_cursor_t *cu, + [[maybe_unused]] void *arg) +{ + return -UNW_EINVAL; +} + +int CallStack::getProcName([[maybe_unused]] unw_addr_space_t as, [[maybe_unused]] unw_word_t addr, + [[maybe_unused]] char *bufp, [[maybe_unused]] size_t buf_len, + [[maybe_unused]] unw_word_t *offp, [[maybe_unused]] void *arg) +{ + return -UNW_EINVAL; +} + +void CallStack::UnwindStep(unw_cursor_t &c, std::vector &callStack, size_t maxStackLevel) +{ + while (callStack.size() < maxStackLevel) { + int ret = unw_step(&c); + if (ret > 0) { + unw_word_t ip, sp; + unw_get_reg(&c, UNW_REG_IP, &ip); + unw_get_reg(&c, UNW_REG_SP, &sp); + + if (ip == 0) { + HLOGD("ip == 0 something is wrong. break"); + break; + } + + /* + * Decrement the IP for any non-activation frames. + * this is required to properly find the srcline + * for caller frames. + * See also the documentation for dwfl_frame_pc(), + * which this code tries to replicate. + */ + if (unw_is_signal_frame(&c) <= 0) { + --ip; + } + HLOGV("unwind:%zu: ip 0x%" UNW_WORD_PFLAG " sp 0x%" UNW_WORD_PFLAG "", callStack.size(), + ip, sp); + if (callStack.back().ip_ == ip && callStack.back().sp_ == sp) { + HLOGW("we found a same frame, stop here"); + break; + } + callStack.emplace_back(ip, sp); + } else { + HLOGV("no more frame step found. ret %d:%s", ret, GetUnwErrorName(ret).c_str()); + break; + } + } +} +#endif + +bool CallStack::GetIpSP(uint64_t &ip, uint64_t &sp, const u64 *regs, size_t regNum) const +{ + if (regNum > 0) { + if (!RegisterGetSPValue(sp, arch_, regs, regNum)) { + HLOGW("unable get sp"); + return false; + } + if (!RegisterGetIPValue(ip, arch_, regs, regNum)) { + HLOGW("unable get ip"); + return false; + } + if (ip != 0) { + return true; + } + } else { + HLOGW("reg size is 0"); + return false; + } + return false; +} + +#if HAVE_LIBUNWIND +bool CallStack::DoUnwind(const VirtualThread &thread, std::vector &callStack, + size_t maxStackLevel) +{ + unw_addr_space_t addr_space; + UnwindInfo unwindInfo = { + .thread = thread, + .callStack = *this, + }; + unw_cursor_t c; + if (unwindAddrSpaceMap_.count(thread.tid_) == 0) { + addr_space = unw_create_addr_space(&accessors_, 0); + if (!addr_space) { + HLOGE("Can't create unwind vaddress space."); + return false; + } + unwindAddrSpaceMap_.emplace(thread.tid_, addr_space); + unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL); + unw_flush_cache(addr_space, 0, 0); + } else { + addr_space = unwindAddrSpaceMap_.at(thread.tid_); + } + + int ret = unw_init_remote(&c, addr_space, &unwindInfo); + if (ret) { + HLOGE("unwind error %d:%s see unw_error_t.", ret, GetUnwErrorName(ret).c_str()); + return false; + } else { + UnwindStep(c, callStack, maxStackLevel); + } + return true; +} +#endif + +bool CallStack::UnwindCallStack(const VirtualThread &thread, bool abi32, u64 *regs, u64 regsNum, + const u8 *stack, u64 stackSize, std::vector &callStack, + size_t maxStackLevel) +{ + regs_ = regs; + regsNum_ = regsNum; + stack_ = stack; + stackSize_ = stackSize; + + arch_ = GetArchTypeFromABI(abi32); + UpdateRegForABI(arch_, regs_); + if (!RegisterGetSPValue(stackPoint_, arch_, regs_, regsNum_)) { + HLOGE("RegisterGetSPValue failed"); + return false; + } else { + stackEnd_ = stackPoint_ + stackSize_; + } + +#if HAVE_LIBUNWIND + uint64_t ip, sp; + if (!GetIpSP(ip, sp, regs_, regsNum_)) { + HLOGW("unable get sp or sp , unable unwind"); + return false; + } else { + if (ip != 0) { + HLOGV("unwind:%zu: ip 0x%" PRIx64 " sp 0x%" PRIx64 "", callStack.size(), ip, sp); + callStack.emplace_back(ip, sp); + } + } + + /* + * If we need more than one entry, do the DWARF + * unwind itself. + */ + if (maxStackLevel - 1 > 0) { + return DoUnwind(thread, callStack, maxStackLevel); + } +#endif + return true; +} + +void CallStack::LogFrame(const std::string msg, const std::vector &frames) +{ + HLOGM("%s", msg.c_str()); +#ifndef NDEBUG + int level = 0; + for (auto frame : frames) { + HLOGM("%d:%s", level++, frame.ToString().c_str()); + } +#endif +} + +/* +we should have CallStack cache for each thread +end begin +0. A -> B -> C -> E -> F +1. C -> E -> F +2. B -> C +3. A -> B -> C +4. B -> G -> H +5. J -> C + +0 is our cache +1 2 3... is from record + +use expandLimit to setup how may frame match is needs + +*/ +size_t CallStack::DoExpandCallStack(std::vector &newCallFrames, + const std::vector &cachedCallFrames, + size_t expandLimit) +{ + if (expandLimit == 0 or newCallFrames.size() < expandLimit or + cachedCallFrames.size() < expandLimit) { + HLOGM("expandLimit %zu not match new %zu cache %zu", expandLimit, newCallFrames.size(), + cachedCallFrames.size()); + return 0; // size not enough + } + + // called (Stack Buttom) , this will NOT change when compare + // in case1 newIt -> C + // in case2 newIt -> B + const auto newIt = newCallFrames.end() - expandLimit; + + HLOGM("try find new call chain bottom %s for limit %zu", newIt->ToString().c_str(), + expandLimit); + + // first frame search, from called - > caller + // for case 2 it should found B + auto cachedIt = find(cachedCallFrames.begin(), cachedCallFrames.end(), *newIt); + if (cachedIt == cachedCallFrames.end()) { + HLOGM("not found in first search"); + } + + // cache frame found + while (std::distance(cachedIt, cachedCallFrames.end()) >= signed(expandLimit)) { + HLOG_ASSERT_MESSAGE(maxCycle++ < MAX_CALL_FRAME_EXPAND_CYCLE, "MAX_UNWIND_CYCLE = %d reach", + MAX_CALL_FRAME_EXPAND_CYCLE); + + if (std::equal(newIt, newIt + expandLimit, cachedIt)) { + HLOGM("match %s + %zu", newIt->ToString().c_str(), expandLimit); + cachedIt += expandLimit; // in while we check the boundary safe + if (cachedIt == cachedCallFrames.end()) { + // same but no more need expand + break; + } + + // expand the frame and make some log ? + LogFrame("newCallStack:", newCallFrames); + LogFrame("cachedCallStack:", cachedCallFrames); + + newCallFrames.insert(newCallFrames.end(), cachedIt, cachedCallFrames.end()); + auto expands = std::distance(cachedIt, cachedCallFrames.end()); + HLOGV("merge callstack increse to %zu (+%zd) ", newCallFrames.size(), expands); + // we done the deal + return expands; + } else { + // quick search next same farme again + cachedIt++; + if (cachedIt != cachedCallFrames.end()) { + HLOGM("search next"); + cachedIt = find(cachedIt, cachedCallFrames.end(), *newIt); + } + } + } + HLOGM("cachedIt distance %zd , need %zd", std::distance(cachedCallFrames.begin(), cachedIt), + distances); + return 0u; // nothing expand +} + +size_t CallStack::ExpandCallStack(pid_t tid, std::vector &callFrames, size_t expandLimit) +{ + size_t expand = 0u; + if (expandLimit == 0) { + return expand; // nothing need to do + } else if (callFrames.size() < expandLimit) { + HLOGM("new callstack is too small, skip it"); + return expand; + } + if (!cachedCallFramesMap_.count(tid)) { + cachedCallFramesMap_[tid].reserve(MAX_CALL_FRAME_EXPAND_CACHE_SIZE); + } + if (callFrames.size() >= 1u) { + // get top (Earliest caller) + HashList> &cachedCallFrames = cachedCallFramesMap_[tid]; + HLOGV("find call stack frames in cache size %zu", cachedCallFrames.size()); + // compare + using namespace std::rel_ops; // enable complement comparing operators + for (auto itr = cachedCallFrames.begin(); itr < cachedCallFrames.end(); ++itr) { + // each cached callstack + /* + stack 2 1 0 + cache A -> B -> C + new B -> C + check: + 1 if new B == cache C + 2 if new B == cache B + 3 if new C == new C (if limit > 0) + 4 insert A after B in new stack + */ + const std::vector &cachedCallStack = *itr; + if (cachedCallStack.size() < expandLimit) { + HLOGM("cache callstack is too small, skip it"); + continue; // check next + } + expand = DoExpandCallStack(callFrames, cachedCallStack, expandLimit); + if (expand > 0) { + break; + } + } + // add new one in to cache cachedCallFrames. + // further optimization can be done by caching pointer which avoids copying + // vector + cachedCallFrames[callFrames[0].ip_] = callFrames; + } + HLOGM("expand %zu", expand); + return expand; +} + +CallStack::CallStack() {} + +CallStack::~CallStack() +{ +#if HAVE_LIBUNWIND + for (auto &pair : unwindAddrSpaceMap_) { + unw_destroy_addr_space(pair.second); + } +#endif +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/debug_logger.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/debug_logger.cpp new file mode 100755 index 0000000000000000000000000000000000000000..171585d8554d02dfc4565fc38c6b7d48758b0e5e --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/debug_logger.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2021-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. + */ + +#include "debug_logger.h" + +#include + +#include "option.h" +#if is_ohos +#include "hiperf_hilog.h" +#endif + +using namespace std::literals::chrono_literals; +using namespace std::chrono; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +#ifdef HIPERF_DEBUG +DebugLogger::DebugLogger() : timeStamp_(steady_clock::now()), logPath_(DEFAULT_LOG_PATH) +{ + OpenLog(); +} + +ScopeDebugLevel::ScopeDebugLevel(DebugLevel level, bool mix) +{ + savedDebugLevel_ = DebugLogger::GetInstance()->SetLogLevel(level); + savedMixOutput_ = DebugLogger::GetInstance()->SetMixLogOutput(mix); +} + +ScopeDebugLevel::~ScopeDebugLevel() +{ + DebugLogger::GetInstance()->SetLogLevel(savedDebugLevel_); + DebugLogger::GetInstance()->SetMixLogOutput(savedMixOutput_); +} + +DebugLogger::~DebugLogger() +{ + Disable(); + if (file_ != nullptr) { + fclose(file_); + file_ = nullptr; + } +} + +void DebugLogger::Disable(bool disable) +{ + if (logDisabled_ != disable) { + logDisabled_ = disable; + if (!disable) { + // reopen the log file + OpenLog(); + } + } +} + +#if is_ohos +#ifndef CONFIG_NO_HILOG +int DebugLogger::HiLog(std::string &buffer) const +{ + size_t lastLF = buffer.find_last_of('\n'); + if (lastLF != std::string::npos) { + buffer.erase(lastLF, 1); + } + return OHOS::HiviewDFX::HiLog::Debug(HIPERF_HILOG_LABLE[MODULE_DEFAULT], "%{public}s", + buffer.c_str()); +} +#endif +#endif + +int DebugLogger::Log(DebugLevel level, const std::string &logTag, const char *fmt, ...) const +{ + constexpr const int DEFAULT_STRING_BUF_SIZE = 4096; +#ifdef HIPERF_DEBUG_TIME + const auto startSprintf = steady_clock::now(); +#endif + const auto startTime = steady_clock::now(); + if (!ShouldLog(level, logTag) or logDisabled_ or fmt == nullptr) { +#ifdef HIPERF_DEBUG_TIME + logTimes_ += duration_cast(steady_clock::now() - startSprintf); +#endif + return 0; + } + va_list va; + int ret = 0; + + std::string buffer(DEFAULT_STRING_BUF_SIZE, '\0'); + va_start(va, fmt); + ret = vsnprintf_s(buffer.data(), buffer.size(), buffer.size() - 1, fmt, va); + va_end(va); +#ifdef HIPERF_DEBUG_TIME + logSprintfTimes_ += duration_cast(steady_clock::now() - startSprintf); +#endif + if ((mixLogOutput_ and level < LEVEL_FATAL) or level == LEVEL_FATAL) { + ret = fprintf(stdout, "%s", buffer.data()); // to the stdout + } + + if (enableHilog_) { +#if is_ohos && !defined(CONFIG_NO_HILOG) + std::lock_guard lock(logMutex_); + ret = HiLog(buffer); // to the hilog +#endif + } else if (file_ != nullptr) { + std::lock_guard lock(logMutex_); +#ifdef HIPERF_DEBUG_TIME + const auto startWriteTime = steady_clock::now(); +#endif + milliseconds timeStamp = duration_cast(startTime - timeStamp_); + fprintf(file_, "%05" PRId64 "ms %s", (int64_t)timeStamp.count(), buffer.data()); // to the file +#ifdef HIPERF_DEBUG_TIME + logWriteTimes_ += duration_cast(steady_clock::now() - startWriteTime); +#endif + } + +#ifdef HIPERF_DEBUG_TIME + logTimes_ += duration_cast(steady_clock::now() - startTime); + logCount_++; +#endif + if (level == LEVEL_FATAL && exitOnFatal_) { + fflush(file_); + logDisabled_ = true; + exit(-1); + } + return ret; +} + +bool DebugLogger::EnableHiLog(bool enable) +{ + enableHilog_ = enable; + if (enable) { + if (fprintf(stdout, "change to use hilog\n") < 0) { + // what can we do here ??? + } + } + return enableHilog_; +} + +bool DebugLogger::ShouldLog(DebugLevel level, const std::string &logtag) const +{ + return GetLogLevelByTag(logtag) <= level; +} + +DebugLevel DebugLogger::SetLogLevel(DebugLevel debugLevel) +{ + DebugLevel lastLevel = DebugLogger::GetInstance()->debugLevel_; + debugLevel_ = debugLevel; + // force print + printf("setLogLevel %d\n", debugLevel); + return lastLevel; +} + +bool DebugLogger::SetMixLogOutput(bool enable) +{ + bool lastMixLogOutput = mixLogOutput_; + mixLogOutput_ = enable; + return lastMixLogOutput; +} + +bool DebugLogger::SetLogPath(const std::string &newLogPath) +{ + // make sure not write happend when rename + std::lock_guard lock(logMutex_); + if (newLogPath.empty() and newLogPath != logPath_) { + return false; + } + if (file_ != nullptr) { + fclose(file_); + file_ = nullptr; + if (rename(logPath_.c_str(), newLogPath.c_str()) != 0) { + // reopen the old log file path + OpenLog(); + return false; + } + } + logPath_ = newLogPath; + return OpenLog(); +} + +void DebugLogger::SetLogTags(const std::string &tags) +{ + HLOGI(" tags is '%s'", tags.c_str()); + auto tagLevels = StringSplit(tags, ","); + logTagLevelmap_.clear(); + for (auto tagLevel : tagLevels) { + auto tagLevelPair = StringSplit(tagLevel, ":"); + if (tagLevelPair.size() == 1) { // only tag + logTagLevelmap_[tagLevelPair[0]] = LEVEL_MUCH; + } else { // tag:level + logTagLevelmap_[tagLevelPair[0]] = GetLogLevelByName(tagLevelPair[1].c_str()); + } + } + for (auto it = logTagLevelmap_.begin(); it != logTagLevelmap_.end(); it++) { + HLOGD(" '%s'='%s'", it->first.c_str(), GetLogLevelName(it->second).c_str()); + } +} + +DebugLevel DebugLogger::GetLogLevelByTag(const std::string &tag) const +{ + if (logTagLevelmap_.count(tag) > 0) { + return logTagLevelmap_.at(tag); + } else { + return GetLogLevel(); + } +} + +const std::string DebugLogger::GetLogLevelName(DebugLevel level) const +{ + return DebugLevelMap.at(level); +} + +DebugLevel DebugLogger::GetLogLevelByName(const std::string &name) const +{ + for (auto it = DebugLevelMap.begin(); it != DebugLevelMap.end(); it++) { + if (it->second == name) { + return it->first; + } + } + // not found ? + return LEVEL_MUCH; +} + +// only use for UT +void DebugLogger::Reset() +{ + EnableHiLog(false); + SetLogLevel(LEVEL_VERBOSE); + Disable(false); + SetLogPath(DEFAULT_LOG_PATH); + SetLogTags(""); +} + +bool DebugLogger::RestoreLog() +{ + // use append not write for continually write + return OpenLog(logPath_, "a"); +} + +bool DebugLogger::OpenLog(const std::string &tempLogPath, const std::string &flags) +{ + std::lock_guard lock(logMutex_); + + if (logDisabled_) { + // don't reopen it when we crash or something else. + return false; + } + if (!tempLogPath.empty()) { + fclose(file_); + std::string resolvedPath = CanonicalizeSpecPath(tempLogPath.c_str()); + file_ = fopen(resolvedPath.c_str(), flags.c_str()); + } + if (file_ != nullptr) { + // already open + return true; + } else { + std::string resolvedPath = CanonicalizeSpecPath(logPath_.c_str()); + file_ = fopen(resolvedPath.c_str(), "w"); + } + if (file_ == nullptr) { + fprintf(stdout, "unable save log file to '%s' because '%d'\n", logPath_.c_str(), errno); + return false; + } else { + fseek(file_, 0, SEEK_SET); + // ecach log can save 6ms (29ms -> 23ms) + fprintf(stdout, "log will save at '%s'\n", logPath_.c_str()); + return true; + } +} + +__attribute__((weak)) DebugLevel DebugLogger::debugLevel_ = LEVEL_DEBUG; +__attribute__((weak)) bool DebugLogger::logDisabled_ = true; +std::unique_ptr DebugLogger::logInstance_; + +DebugLogger *DebugLogger::GetInstance() +{ + if (logInstance_ == nullptr) { + logInstance_ = std::make_unique(); + } + return logInstance_.get(); +} +#endif +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/dwarf_encoding.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/dwarf_encoding.cpp new file mode 100755 index 0000000000000000000000000000000000000000..1cfb7bcedab01309b217d9d6ba523e98c2037de7 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/dwarf_encoding.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2021-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. + */ +#define HILOG_TAG "Dwarf" + +#include "dwarf_encoding.h" + +#include "utilities.h" +namespace OHOS { +namespace Developtools { +namespace HiPerf { +DwarfEncoding::DwarfEncoding(dw_encode_t dw, const unsigned char *&data, uint64_t vaddrBase, + uint64_t vaddrPC, uint64_t vaddrText) + : dw_(dw), data_(data), vaddrBase_(vaddrBase), vaddrPC_(vaddrPC), vaddrText_(vaddrText) +{ + value_[0] = ReadValue(data); +} + +const std::string DwarfEncoding::ToString() const +{ + std::string debugString = ApplicationName() + ":" + FormatName() + " format:" + ToHex(dw_) + + " value size:" + std::to_string(GetSize()) + " raw:"; + + size_t size = GetSize(); + const unsigned char *data = data_; + while (size-- > 0) { + debugString.append(ToHex(data[0]) + " "); + data++; + } + + debugString.append(" | " + ToHex(GetValue(), GetSize(), true)); + debugString.append(" applied:" + ToHex(GetAppliedValue(), GetSize())); + return debugString; +} + +const unsigned char *DwarfEncoding::GetEnd() const +{ + return data_ + GetSize(); +} + +const unsigned char *DwarfEncoding::GetData() const +{ + return data_; +} + +size_t DwarfEncoding::GetSize() const +{ + return DWFormatSizeMap.at((dw_encode_t)Format()); +} + +uint64_t DwarfEncoding::GetValue() const +{ + return value_[0]; +} + +uint64_t DwarfEncoding::GetAppliedValue() const +{ + if ((Application() & DW_EH_PE_datarel) == DW_EH_PE_datarel) { + return value_[0] + vaddrBase_; + } else if ((Application() & DW_EH_PE_textrel) == DW_EH_PE_textrel) { + return value_[0] + vaddrText_; + } else if ((Application() & DW_EH_PE_pcrel) == DW_EH_PE_pcrel) { + return value_[0] + vaddrPC_; + } + HLOGM("Application is empty"); + + return value_[0]; +} + +bool DwarfEncoding::IsOmit() const +{ + return (dw_ == DW_EH_PE_omit); +} + +dw_encode_t DwarfEncoding::Format() const +{ + return (dw_ & 0x0F); +} +dw_encode_t DwarfEncoding::Application() const +{ + return (dw_ & 0xF0); +} +uint64_t DwarfEncoding::ReadValue(const unsigned char *&data) const +{ + switch (Format()) { + case DW_EH_PE_udata2: + return dwReadAnyTypeData(data, uint16_t()); + case DW_EH_PE_udata4: + return dwReadAnyTypeData(data, uint32_t()); + case DW_EH_PE_udata8: + return dwReadAnyTypeData(data, uint64_t()); + case DW_EH_PE_sdata2: + return dwReadAnyTypeData(data, int16_t()); + case DW_EH_PE_sdata4: + return dwReadAnyTypeData(data, int32_t()); + case DW_EH_PE_sdata8: + return dwReadAnyTypeData(data, int64_t()); + default: + return -1; + } +} +const std::string DwarfEncoding::FormatName() const +{ + switch (Format()) { + case DW_EH_PE_absptr: + return "DW_EH_PE_absptr"; + case DW_EH_PE_uleb128: + return "DW_EH_PE_uleb128"; + case DW_EH_PE_udata2: + return "DW_EH_PE_udata2"; + case DW_EH_PE_udata4: + return "DW_EH_PE_udata4"; + case DW_EH_PE_udata8: + return "DW_EH_PE_udata8"; + case DW_EH_PE_sleb128: + return "DW_EH_PE_sleb128"; + case DW_EH_PE_sdata2: + return "DW_EH_PE_data2"; + case DW_EH_PE_sdata4: + return "DW_EH_PE_sdata4"; + case DW_EH_PE_sdata8: + return "DW_EH_PE_sdata8"; + case DW_EH_PE_omit: + return "DW_EH_PE_omit"; + default: + return "unknown format"; + } +} +const std::string DwarfEncoding::ApplicationName() const +{ + switch (Application()) { + case DW_EH_PE_pcrel: + return "DW_EH_PE_pcrel"; + case DW_EH_PE_textrel: + return "DW_EH_PE_textrel"; + case DW_EH_PE_datarel: + return "DW_EH_PE_datarel"; + case DW_EH_PE_funcrel: + return "DW_EH_PE_funcrel"; + case DW_EH_PE_aligned: + return "DW_EH_PE_aligned"; + case DW_EH_PE_omit: + return "DW_EH_PE_omit"; + case DW_EH_PE_nothing: + return "DW_EH_PE_empty"; + default: + return "unknown format"; + } +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/elf_file.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/elf_file.cpp new file mode 100755 index 0000000000000000000000000000000000000000..53894c94ca15a98f2988d2bcb73145ccb4d60bde --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/elf_file.cpp @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2021-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. + */ + +#include +#include "string_help.h" +#include "utilities.h" + +using namespace OHOS::Developtools::HiPerf::ELF; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +ElfFile::ElfFile(const std::string &filename) +{ +#if is_mingw + std::string resolvedPath = CanonicalizeSpecPath(filename.c_str()); + fd_ = open(resolvedPath.c_str(), O_RDONLY | O_BINARY); +#else + std::string resolvedPath = CanonicalizeSpecPath(filename.c_str()); + fd_ = open(resolvedPath.c_str(), O_RDONLY); +#endif + if (fd_ != -1) { + struct stat sb; + if (fstat(fd_, &sb) == -1) { + HLOGE("unable to check the file size"); + } else { + HLOGD("file stat size %" PRIu64 "", sb.st_size); + + mmap_ = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd_, 0); + if (mmap_ == MMAP_FAILED) { + HLOGE("unable to map the file size %" PRIu64 " ", sb.st_size); + mmapSize_ = 0; + } else { + mmapSize_ = sb.st_size; + HLOGD("mmap build with size %" PRIu64 " ", mmapSize_); + } + } + } +} + +ElfFile::~ElfFile() +{ + if (mmap_ != MMAP_FAILED) { + munmap(mmap_, mmapSize_); + } + + if (fd_ != -1) { + close(fd_); + fd_ = -1; + } +} + +std::unique_ptr ElfFile::MakeUnique(const std::string &filename) +{ + std::unique_ptr file {new (std::nothrow) ElfFile(filename)}; + if (file == nullptr) { + HLOGE("Error in ElfFile::MakeUnique(): ElfFile::ElfFile() failed"); + return nullptr; + } + if (!file->IsOpened()) { + HLOGE("Error in ElfFile::MakeUnique(): elf file not opended"); + return nullptr; + } + if (!file->ParseFile()) { + HLOGE("parse elf file failed"); + return nullptr; + } + return file; +} + +bool ElfFile::ParseFile() +{ + if (!ParseElfHeader()) { + HLOGE("Error in ElfFile::MakeUnique(): ElfFile::ParseElfHeader() failed"); + return false; + } + if (!ParsePrgHeaders()) { + HLOGE("Error in ElfFile::MakeUnique(): ElfFile::ParsePrgHeaders() failed"); + return false; + } + if (!ParseSecNamesStr()) { + HLOGE("Error in ElfFile::MakeUnique(): ElfFile::ParseSecNamesStr() failed"); + return false; + } + if (!ParseSecHeaders()) { + HLOGE("Error in ElfFile::MakeUnique(): ElfFile::ParseSecHeaders() failed"); + return false; + } + return true; +} + +bool ElfFile::ParseElfHeader() +{ + ssize_t ret = lseek(fd_, 0, SEEK_SET); + if (ret != 0) { + HLOGW("lseek ret %zu", ret); + return false; + } + HLOG_ASSERT(ret == 0); + unsigned char ehdrBuf[ehdr64Size] {0}; + size_t readsize = ReadFile(ehdrBuf, ehdr64Size); + if (readsize < ehdr64Size) { + HLOGW("file size not enough, try read %zu, only have %zu", ehdr64Size, readsize); + } + HLOG_ASSERT(readsize > 0); + ehdr_ = ElfHeader::MakeUnique(ehdrBuf, readsize); + return !(ehdr_ == nullptr); +} + +bool ElfFile::ParsePrgHeaders() +{ + size_t phdrSize = ehdr_->phdrEntSize_; + size_t numPhdrs = ehdr_->phdrNumEnts_; + uint64_t phdrOffset = ehdr_->phdrOffset_; + int64_t ret = lseek(fd_, phdrOffset, SEEK_SET); + HLOG_ASSERT(ret == static_cast(phdrOffset)); + char *phdrsBuf = new (std::nothrow) char[phdrSize * numPhdrs]; + if (phdrsBuf == nullptr) { + HLOGE("Error in ELF::ElfFile::ParsePrgHeaders(): new failed"); + return false; + } + (void)memset_s(phdrsBuf, phdrSize * numPhdrs, 0, phdrSize * numPhdrs); + ret = ReadFile(phdrsBuf, phdrSize * numPhdrs); + if (ret != static_cast(phdrSize * numPhdrs)) { + delete[] phdrsBuf; + phdrsBuf = nullptr; + return false; + } + char *phdrBuf = phdrsBuf; + for (size_t count = 0; count < numPhdrs; ++count) { + std::unique_ptr phdr = ProgramHeader::MakeUnique(phdrBuf, phdrSize); + if (phdr == nullptr) { + delete[] phdrsBuf; + phdrsBuf = nullptr; + HLOGE("Error in Elf::ParsePrgHeaders(): ProgramHeader::MakeUnique() failed"); + return false; + } + phdrs_.push_back(std::move(phdr)); + phdrBuf += phdrSize; + } + delete[] phdrsBuf; + phdrsBuf = nullptr; + return true; +} + +bool ElfFile::ParseSecNamesStr() +{ + // get string table section header + size_t shdrSize = ehdr_->shdrEntSize_; + size_t shdrIndex = ehdr_->shdrStrTabIdx_; + uint64_t shdrOffset = ehdr_->shdrOffset_ + ((uint64_t)shdrIndex) * shdrSize; + int64_t ret = lseek(fd_, shdrOffset, SEEK_SET); + HLOG_ASSERT(ret == static_cast(shdrOffset)); + char *shdrBuf = new (std::nothrow) char[shdrSize]; + if (shdrBuf == nullptr) { + HLOGE("Error in ElfFile::ParseSecNamesStr(): new failed"); + return false; + } + (void)memset_s(shdrBuf, shdrSize, 0, shdrSize); + ret = ReadFile(shdrBuf, shdrSize); + HLOG_ASSERT(ret == static_cast(shdrSize)); + const std::string secName {".shstrtab"}; + shdrs_[secName] = SectionHeader::MakeUnique(shdrBuf, shdrSize, shdrIndex); + if (shdrs_[secName] == nullptr) { + HLOGE("Error in ElfFile::ParseSecNamesStr(): SectionHeader::MakeUnique() failed"); + delete[] shdrBuf; + shdrBuf = nullptr; + return false; + } + delete[] shdrBuf; + shdrBuf = nullptr; + + // get content of string section table + uint64_t secOffset = shdrs_[secName]->fileOffset_; + size_t secSize = shdrs_[secName]->secSize_; + ret = lseek(fd_, secOffset, SEEK_SET); + HLOG_ASSERT(ret == static_cast(secOffset)); + char *secNamesBuf = new (std::nothrow) char[secSize]; + if (secNamesBuf == nullptr) { + HLOGE("Error in ElfFile::ParseSecNamesStr(): new secNamesBuf failed"); + return false; + } + (void)memset_s(secNamesBuf, secSize, '\0', secSize); + ret = ReadFile(secNamesBuf, secSize); + if (ret != static_cast(secSize)) { + delete[] secNamesBuf; + secNamesBuf = nullptr; + return false; + } + secNamesStr_ = std::string(secNamesBuf, secNamesBuf + secSize); + delete[] secNamesBuf; + secNamesBuf = nullptr; + return true; +} + +bool ElfFile::ParseSecHeaders() +{ + size_t shdrSize = ehdr_->shdrEntSize_; + size_t numShdrs = ehdr_->shdrNumEnts_; + uint64_t shdrOffset = ehdr_->shdrOffset_; + int64_t ret = lseek(fd_, shdrOffset, SEEK_SET); + HLOG_ASSERT(ret == static_cast(shdrOffset)); + char *shdrsBuf = new (std::nothrow) char[shdrSize * numShdrs]; + if (shdrsBuf == nullptr) { + HLOGE("Error in ELF::ElfFile::ParseSecHeaders(): new failed"); + return false; + } + (void)memset_s(shdrsBuf, shdrSize * numShdrs, '\0', shdrSize * numShdrs); + ret = ReadFile(shdrsBuf, shdrSize * numShdrs); + HLOG_ASSERT(ret == static_cast(shdrSize * numShdrs)); + char *shdrBuf = shdrsBuf; + for (size_t count = 0; count < numShdrs; ++count) { + if (count == ehdr_->shdrStrTabIdx_) { + shdrBuf += shdrSize; + continue; + } + std::unique_ptr shdr = SectionHeader::MakeUnique(shdrBuf, shdrSize, count); + if (shdr == nullptr) { + delete[] shdrsBuf; + shdrsBuf = nullptr; + return false; + } + std::string secName = GetSectionName(shdr->nameIndex_); + shdrs_[secName] = std::move(shdr); + shdr.reset(nullptr); + shdrBuf += shdrSize; + } + delete[] shdrsBuf; + shdrsBuf = nullptr; + return true; +} + +bool ElfFile::ParseSymTable(const std::string secName) +{ + if (shdrs_.find(secName) == shdrs_.end()) { + HLOGE("Error in ELF::ElfFile::ParseSymTable(): section %s does not exist", secName.c_str()); + return false; + } else { + return ParseSymTable(shdrs_[secName].get()); + } +} + +bool ElfFile::ParseSymTable(const SectionHeader *shdr) +{ + if (shdr == nullptr) { + return false; + } + uint64_t secOffset = shdr->fileOffset_; + int64_t ret = lseek(fd_, secOffset, SEEK_SET); + HLOG_ASSERT(ret == static_cast(secOffset)); + uint64_t secSize = shdr->secSize_; + uint64_t entrySize = shdr->secEntrySize_; + char *secBuf = new (std::nothrow) char[secSize]; + if (secBuf == nullptr) { + HLOGE("Error in EFL::ElfFile::ParseSymTable(): new failed"); + return false; + } + ret = ReadFile(secBuf, secSize); + HLOG_ASSERT(ret == static_cast(secSize)); + symTable_ = SymbolTable::MakeUnique(symNamesStr_, secBuf, secSize, entrySize); + if (symTable_ == nullptr) { + delete[] secBuf; + secBuf = nullptr; + return false; + } + delete[] secBuf; + secBuf = nullptr; + return true; +} + +bool ElfFile::ParseSymNamesStr() +{ + const std::string secName {".strtab"}; + if (shdrs_.find(secName) == shdrs_.end()) { + HLOGE("Error in ElfFile::ParseSymNamesStr(): section %s does not exist", secName.c_str()); + return false; + } + const auto &shdr = shdrs_[secName]; + uint64_t secOffset = shdr->fileOffset_; + uint64_t secSize = shdr->secSize_; + int64_t ret = lseek(fd_, secOffset, SEEK_SET); + char *secBuf = new (std::nothrow) char[secSize]; + if (secBuf == nullptr) { + HLOGE("Error in ElfFile::ParsesymNamesStr(): new failed"); + return false; + } + (void)memset_s(secBuf, secSize, '\0', secSize); + ret = ReadFile(secBuf, secSize); + HLOG_ASSERT(ret == static_cast(secSize)); + symNamesStr_ = std::string(secBuf, secSize); + if (symNamesStr_ == "") { + delete[] secBuf; + secBuf = nullptr; + return false; + } + delete[] secBuf; + secBuf = nullptr; + return true; +} + +bool ElfFile::ParseDynSymTable() +{ + const std::string secName {".dynsym"}; + if (shdrs_.find(secName) == shdrs_.end()) { + HLOGE("Error in ELF::ElfFile::ParseSymTable(): section %s does not exist", secName.c_str()); + return false; + } + const auto &shdr = shdrs_[secName]; + uint64_t secOffset = shdr->fileOffset_; + int64_t ret = lseek(fd_, secOffset, SEEK_SET); + HLOG_ASSERT(ret == static_cast(secOffset)); + uint64_t secSize = shdr->secSize_; + uint64_t entrySize = shdr->secEntrySize_; + char *secBuf = new (std::nothrow) char[secSize]; + if (secBuf == nullptr) { + HLOGE("Error in EFL::ElfFile::ParseDynSymTable(): new failed"); + return false; + } + ret = ReadFile(secBuf, secSize); + HLOG_ASSERT(ret == static_cast(secSize)); + dynSymTable_ = SymbolTable::MakeUnique(symNamesStr_, secBuf, secSize, entrySize); + if (dynSymTable_ == nullptr) { + delete[] secBuf; + secBuf = nullptr; + return false; + } + delete[] secBuf; + secBuf = nullptr; + return true; +} + +std::string ElfFile::GetSectionName(const uint32_t startIndex) +{ + if (startIndex >= secNamesStr_.size()) { + HLOGF("out_of_range %s ,endIndex %d ", secNamesStr_.c_str(), startIndex); + return ""; + } + size_t endIndex {startIndex}; + for (; endIndex < secNamesStr_.size(); ++endIndex) { + if (secNamesStr_[endIndex] == '\0') { + break; + } + } + return secNamesStr_.substr(startIndex, endIndex - startIndex); +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/elf_header.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/elf_header.cpp new file mode 100755 index 0000000000000000000000000000000000000000..c444eb910eac8ea1622a1d761ba0e848bc51aad4 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/elf_header.cpp @@ -0,0 +1,194 @@ +/* + * 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. + */ + +#include "elf_parser.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +namespace ELF { +std::unique_ptr ElfHeader::MakeUnique(unsigned char * const ehdrBuf, + const std::size_t bufSize) +{ + std::unique_ptr ehdr {new (std::nothrow) ElfHeader()}; + if (ehdr == nullptr) { + HLOGV("ElfHeader() failed"); + return nullptr; + } + if (!ehdr->Init(ehdrBuf, bufSize)) { + HLOGV("ElfHeader::Init(ehdrBuf, bufSize) failed\n"); + DumpEhdrBuf(reinterpret_cast(ehdrBuf), bufSize); + return nullptr; + } + return ehdr; +} + +bool ElfHeader::Init(unsigned char * const ehdrBuf, const std::size_t bufSize) +{ + std::string magicStr {ehdrBuf, ehdrBuf + SELFMAG}; + std::string elfMagic {ELFMAG}; + if (magicStr.compare(elfMagic) != 0) { + HLOGE("elf magic not found"); + return false; + } + if (memcpy_s(ehdrIdent_, EI_NIDENT, ehdrBuf, EI_NIDENT) != 0) { + HLOGE("init ehdrIdent_ failed"); + return false; + } + if (ehdrBuf[EI_CLASS] == ELFCLASS32 and ParseElf32Header(ehdrBuf, bufSize)) { + return true; + } + if (ehdrBuf[EI_CLASS] == ELFCLASS64 and ParseElf64Header(ehdrBuf, bufSize)) { + return true; + } + HLOGE("init elf header failed, elf header buffer dumped"); + return false; +} + +bool ElfHeader::ParseElf32Header(unsigned char * const ehdrBuf, const std::size_t bufSize) +{ + if (bufSize < ehdr32Size) { + HLOGE("bad elf32 header buffer"); + return false; + } + size_t curIndex {EI_NIDENT}; + uint16_t *u2Buf = reinterpret_cast(ehdrBuf + curIndex); + type_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + machine_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + uint32_t *u4Buf = reinterpret_cast(ehdrBuf + curIndex); + elfVersion_ = u4Buf[0]; + curIndex += sizeof(uint32_t); + + u4Buf = reinterpret_cast(ehdrBuf + curIndex); + prgEntryVaddr_ = u4Buf[0]; + curIndex += sizeof(uint32_t); + + u4Buf = reinterpret_cast(ehdrBuf + curIndex); + phdrOffset_ = u4Buf[0]; + curIndex += sizeof(uint32_t); + + u4Buf = reinterpret_cast(ehdrBuf + curIndex); + shdrOffset_ = u4Buf[0]; + curIndex += sizeof(uint32_t); + + u4Buf = reinterpret_cast(ehdrBuf + curIndex); + ehdrFlags_ = u4Buf[0]; + curIndex += sizeof(uint32_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + ehdrSize_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + phdrEntSize_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + phdrNumEnts_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + shdrEntSize_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + shdrNumEnts_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + shdrStrTabIdx_ = u2Buf[0]; + +#ifdef HIPERF_DEBUG_ASSERT + curIndex += sizeof(uint16_t); + HLOG_ASSERT(curIndex == ehdrSize_); + HLOG_ASSERT(shdr32Size == ehdrSize_); +#endif + return true; +} + +bool ElfHeader::ParseElf64Header(unsigned char * const ehdrBuf, const std::size_t bufSize) +{ + if (bufSize < ehdr64Size) { + HLOGE("bad elf64 header buffer"); + return false; + } + size_t curIndex {EI_NIDENT}; + uint16_t *u2Buf = reinterpret_cast(ehdrBuf + curIndex); + type_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + machine_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + uint32_t *u4Buf = reinterpret_cast(ehdrBuf + curIndex); + elfVersion_ = u4Buf[0]; + curIndex += sizeof(uint32_t); + + uint64_t *u8Buf = reinterpret_cast(ehdrBuf + curIndex); + prgEntryVaddr_ = u8Buf[0]; + curIndex += sizeof(uint64_t); + + u8Buf = reinterpret_cast(ehdrBuf + curIndex); + phdrOffset_ = u8Buf[0]; + curIndex += sizeof(uint64_t); + + u8Buf = reinterpret_cast(ehdrBuf + curIndex); + shdrOffset_ = u8Buf[0]; + curIndex += sizeof(uint64_t); + + u4Buf = reinterpret_cast(ehdrBuf + curIndex); + ehdrFlags_ = u4Buf[0]; + curIndex += sizeof(uint32_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + ehdrSize_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + phdrEntSize_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + phdrNumEnts_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + shdrEntSize_ = u2Buf[0]; + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + shdrNumEnts_ = static_cast(*u2Buf); + curIndex += sizeof(uint16_t); + + u2Buf = reinterpret_cast(ehdrBuf + curIndex); + shdrStrTabIdx_ = u2Buf[0]; + +#ifdef HIPERF_DEBUG_ASSERT + curIndex += sizeof(uint16_t); + HLOG_ASSERT(curIndex == ehdrSize_); + HLOG_ASSERT(shdr64Size == ehdrSize_); +#endif + return true; +} +} // namespace ELF +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/elf_symbol.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/elf_symbol.cpp new file mode 100755 index 0000000000000000000000000000000000000000..7f2681051fe949d495e7df947ee1841cfee5f85d --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/elf_symbol.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021-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. + */ + +#include + +using namespace OHOS::Developtools::HiPerf::ELF; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +std::unique_ptr ElfSymbol::MakeUnique(char * const symBuf, const std::size_t bufSize) +{ + std::unique_ptr sym {new (std::nothrow) ElfSymbol()}; + if (sym == nullptr) { + HLOGE("Error in ElfSymbol::MakeUnique(): ElfSymbol::ElfSymbol() failed"); + return nullptr; + } + if (!sym->Init(symBuf, bufSize)) { + HLOGE("ElfSymbol::Init(symBuf, bufSize) failed"); + DumpSymBuf(symBuf, bufSize); + return nullptr; + } + return sym; +} + +bool ElfSymbol::ParseElf32Symbol(char * const symBuf) +{ + uint32_t *u4Buf = reinterpret_cast(symBuf); + constexpr uint32_t nameOffset {0}; + nameIndex_ = u4Buf[nameOffset]; + constexpr uint32_t valueOffset {1}; + symValue_ = u4Buf[valueOffset]; + constexpr uint32_t sizeOffset {2}; + symSize_ = u4Buf[sizeOffset]; + constexpr uint32_t infoOffset {12}; + symInfo_ = symBuf[infoOffset]; + constexpr uint32_t otherInfoOffset {13}; + symOtherInfo_ = symBuf[otherInfoOffset]; + uint16_t *u2Buf = reinterpret_cast(symBuf); + constexpr uint32_t secOffset {7}; + secIndex_ = u2Buf[secOffset]; + return true; +} + +bool ElfSymbol::ParseElf64Symbol(char * const symBuf) +{ + uint32_t *u4Buf = reinterpret_cast(symBuf); + constexpr uint32_t nameOffset {0}; + nameIndex_ = u4Buf[nameOffset]; + constexpr uint32_t infoOffset {4}; + symInfo_ = symBuf[infoOffset]; + constexpr uint32_t otherInfoOffset {5}; + symOtherInfo_ = symBuf[otherInfoOffset]; + uint16_t *u2Buf = reinterpret_cast(symBuf); + constexpr uint32_t secOffset {3}; + secIndex_ = u2Buf[secOffset]; + uint64_t *u8Buf = reinterpret_cast(symBuf); + constexpr uint32_t valueOffset {1}; + symValue_ = u8Buf[valueOffset]; + constexpr uint32_t sizeOffset {2}; + symSize_ = u8Buf[sizeOffset]; + return true; +} + +std::unique_ptr SymbolTable::MakeUnique(const std::string &symNamesStr, + const char * const secBuf, + const uint64_t secSize, + const uint64_t entrySize) +{ + std::unique_ptr symTable {new (std::nothrow) SymbolTable(symNamesStr)}; + if (symNamesStr.empty()) { + HLOGE("symNamesStr is empty"); + } + if (symTable == nullptr) { + HLOGE("Error in SymbleTable::MakeUnique(): SymbleTable::SymbolTable() failed"); + return nullptr; + } + char *symBuf = const_cast(secBuf); + for (uint64_t curPos = 0; curPos < secSize; curPos += entrySize) { + symBuf = const_cast(secBuf + curPos); + /* + not >= , change to > + Section Headers: + [Nr] Name Type Address Offset + Size EntSize Flags Link Info Align + [ 0] NULL 0000000000000000 00000000 + 0000000000000000 0000000000000000 0 0 0 + [ 1] .text NOBITS 000000009c868f20 00000000 + 0000000000000164 0000000000000000 AX 0 0 4096 + [ 2] .strtab STRTAB 0000000000000000 00000040 + 0000000000000042 0000000000000000 0 0 4096 + [ 3] .symtab SYMTAB 0000000000000000 00000082 + 0000000000000030 0000000000000018 2 1 8 + [ 4] .debug_frame PROGBITS 0000000000000000 000000b2 + 00000000000000c8 0000000000000000 0 0 8 + [ 5] .shstrtab STRTAB 0000000000000000 0000017a + 000000000000002e 0000000000000000 0 0 1 + + Symbol table '.symtab' contains 2 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 000000009c868f20 356 FUNC GLOBAL DEFAULT 1 + */ + if ((curPos + entrySize) > secSize) { + break; + } + std::unique_ptr sym = ElfSymbol::MakeUnique(symBuf, entrySize); + if (sym == nullptr) { + HLOGE("Error in SymbolTable::MakeUnique(): ElfSymbol::MakeUnique() failed"); + return nullptr; + } + symTable->symbols_.emplace_back(std::move(sym)); + } + return symTable; +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/callstack.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/callstack.h new file mode 100755 index 0000000000000000000000000000000000000000..a91e708e5c438e069c53de98d207432fbad049d8 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/callstack.h @@ -0,0 +1,136 @@ +/* + * 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. + */ +#ifndef HIPERF_CALLSTACK_H +#define HIPERF_CALLSTACK_H + +#if HAVE_LIBUNWIND +// for libunwind.h empty struct has size 0 in c, size 1 in c++ +#define UNW_EMPTY_STRUCT uint8_t unused +#include +#endif + +#include +#include +#include +#include +#include + +#if !is_mingw +#include +#endif + +#include "hashlist.hpp" +#include "register.h" +#include "utilities.h" +#include "virtual_thread.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +const int MAX_CALL_FRAME_EXPAND_CYCLE = 10; +const size_t MAX_CALL_FRAME_EXPAND_CACHE_SIZE = 10; +const size_t MAX_CALL_FRAME_UNWIND_SIZE = 256; +// if ip is 0 , 1 both not useful +const uint64_t BAD_IP_ADDRESS = 2; + +#if HAVE_LIBUNWIND +struct UnwindInfo; +#endif + +class CallStack { +public: + CallStack(); + ~CallStack(); + bool UnwindCallStack(const VirtualThread &thread, bool abi32, u64 *regs, u64 regsNum, + const u8 *stack, u64 stackSize, std::vector &, + size_t maxStackLevel = MAX_CALL_FRAME_UNWIND_SIZE); + size_t ExpandCallStack(pid_t tid, std::vector &callFrames, size_t expandLimit = 1u); + +private: + uint64_t stackPoint_ = 0; + uint64_t stackEnd_ = 0; + u64 *regs_ = nullptr; // not const , be cause we will fix it for arm64 cpu in UpdateRegForABI + u64 regsNum_ = 0; + const u8 *stack_ = nullptr; + u64 stackSize_ = 0; + + void LogFrame(const std::string msg, const std::vector &frames); + size_t DoExpandCallStack(std::vector &newCallFrames, + const std::vector &cachedCallFrames, size_t expandLimit); + + // we have a cache for all thread + std::map>> cachedCallFramesMap_; + bool GetIpSP(uint64_t &ip, uint64_t &sp, const u64 *regs, size_t regNum) const; + ArchType arch_ = ArchType::UNSUPPORT; +#if HAVE_LIBUNWIND + static bool ReadVirtualThreadMemory(UnwindInfo &unwindInfoPtr, unw_word_t addr, + unw_word_t *data); + static const std::string GetUnwErrorName(int error); + static void dumpUDI(unw_dyn_info_t &di); + static bool fillUDI(unw_dyn_info_t &di, SymbolsFile &symbolsFile, const MemMapItem &mmap, + const VirtualThread &thread); + static int FindProcInfo(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi, + int need_unwind_info, void *arg); + static int AccessMem(unw_addr_space_t as, unw_word_t addr, unw_word_t *valuePoint, + int writeOperation, void *arg); + static int AccessReg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valuePoint, + int writeOperation, void *arg); + static void PutUnwindInfo(unw_addr_space_t as, unw_proc_info_t *pi, void *arg); + static int AccessFpreg(unw_addr_space_t as, unw_regnum_t num, unw_fpreg_t *val, + int writeOperation, void *arg); + static int GetDynInfoListAaddr(unw_addr_space_t as, unw_word_t *dil_vaddr, void *arg); + static int Resume(unw_addr_space_t as, unw_cursor_t *cu, void *arg); + static int getProcName(unw_addr_space_t as, unw_word_t addr, char *bufp, size_t buf_len, + unw_word_t *offp, void *arg); + static int FindUnwindTable(SymbolsFile *symbolsFile, const MemMapItem &mmap, + UnwindInfo *unwindInfoPtr, unw_addr_space_t as, unw_word_t ip, + unw_proc_info_t *pi, int need_unwind_info, void *arg); + void UnwindStep(unw_cursor_t &c, std::vector &callFrames, size_t maxStackLevel); + std::unordered_map unwindAddrSpaceMap_; + + using dsoUnwDynInfoMap = std::unordered_map>; + std::unordered_map unwindDynInfoMap_; + + using unwMemoryCache = std::unordered_map; + std::unordered_map porcessMemoryMap_; + + unw_accessors_t accessors_ = { + .find_proc_info = FindProcInfo, + .put_unwind_info = PutUnwindInfo, + .get_dyn_info_list_addr = GetDynInfoListAaddr, + .access_mem = AccessMem, + .access_reg = AccessReg, + .access_fpreg = AccessFpreg, + .resume = Resume, + .get_proc_name = getProcName, + }; + bool DoUnwind(const VirtualThread &thread, std::vector &callStack, + size_t maxStackLevel); +#endif +}; + +#if HAVE_LIBUNWIND +struct UnwindInfo { + const VirtualThread &thread; + const u64 *regs; + size_t regNumber; + ArchType arch; + CallStack &callStack; +}; +#endif +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_CALLSTACK_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/debug_logger.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/debug_logger.h new file mode 100644 index 0000000000000000000000000000000000000000..b3e2befece57a8c3af86b21ad9da94435cea29f5 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/debug_logger.h @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2021-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. + * + */ +#ifndef HIPERF_DEBUG_H +#define HIPERF_DEBUG_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !is_mingw +#include +#undef gettid +#define gettid() syscall(SYS_gettid) +#else +#include "windows.h" +inline long gettid() +{ + return GetCurrentThreadId(); +} +#endif // !is_mingw + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +enum DebugLevel { + LEVEL_MUCH = 1, + LEVEL_VERBOSE, + LEVEL_DEBUG, + LEVEL_INFO, + LEVEL_WARNING, + LEVEL_ERROR, + LEVEL_FATAL, + LEVEL_STDOUT, // printf + LEVEL_MAX, // max +}; + +#ifdef HIPERF_DEBUG +#if is_ohos || is_double_framework +const std::string DEFAULT_UT_LOG_DIR = "/data/local/tmp/"; +const std::string DEFAULT_LOG_PATH = "/data/local/tmp/hiperf_log.txt"; +#elif is_mingw +const std::string DEFAULT_LOG_PATH = ".\\hiperf_log.txt"; +#elif is_linux +const std::string DEFAULT_UT_LOG_DIR = "./"; +const std::string DEFAULT_LOG_PATH = "hiperf_log.txt"; +#else +#error unkow os +#endif + +#define HILOG_BASE_TAG "HILOG" +#ifndef HILOG_TAG +#define HILOG_TAG "" +#define HILOG_TAG_NAME HILOG_BASE_TAG +#else +#define HILOG_TAG_NAME HILOG_BASE_TAG "_" HILOG_TAG +#endif + +#define SHORT_FILENAME \ + (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__) + +const std::map DebugLevelMap = { + {LEVEL_MUCH, "M"}, {LEVEL_VERBOSE, "V"}, {LEVEL_DEBUG, "D"}, {LEVEL_INFO, "I"}, + {LEVEL_WARNING, "W"}, {LEVEL_ERROR, "E"}, {LEVEL_FATAL, "F"}, +}; +constexpr const int LOG_BUFFER_SIZE = 4 * 1024 * 1024; + +class DebugLogger { +public: + DebugLogger(); + ~DebugLogger(); + + static DebugLogger *GetInstance(); + DebugLevel SetLogLevel(DebugLevel debugLevel); + bool SetMixLogOutput(bool enable); + bool SetLogPath(const std::string &logPath); + void SetLogTags(const std::string &tags); + + int Log(DebugLevel level, const std::string &logTag, const char *fmt, ...) const + __attribute__((format(printf, 4, 5))); + // for class, pointer need add 1 offset (first one is *this) + + bool EnableHiLog(bool = true); + DebugLevel GetLogLevel() const + { + return debugLevel_; + }; + + void Disable(bool disable = true); + static bool logDisabled_; + +#ifdef HIPERF_DEBUG_TIME + mutable size_t logCount_ = 0; + mutable std::chrono::microseconds logTimes_ = std::chrono::microseconds::zero(); + mutable std::chrono::microseconds logWriteTimes_ = std::chrono::microseconds::zero(); + mutable std::chrono::microseconds logSprintfTimes_ = std::chrono::microseconds::zero(); +#endif + + // used in UT + bool OpenLog(const std::string & = "", const std::string & = "w"); + bool RestoreLog(); + void Reset(); + +private: + bool ShouldLog(DebugLevel debugLevel, const std::string &logTag) const; + DebugLevel GetLogLevelByName(const std::string &) const; + DebugLevel GetLogLevelByTag(const std::string &) const; + const std::string GetLogLevelName(DebugLevel) const; + + int HiLog(std::string &buffer) const; + + static std::unique_ptr logInstance_; + + mutable std::recursive_mutex logMutex_; + static DebugLevel debugLevel_; + const std::chrono::steady_clock::time_point timeStamp_; + FILE *file_ = nullptr; + bool mixLogOutput_ = false; // log mix to std + bool enableHilog_ = false; + bool exitOnFatal_ = true; + std::string logPath_; + std::map logTagLevelmap_; + + friend class OptionDebugTest; + friend class DebugLoggerTest; + FRIEND_TEST(DebugLoggerTest, SetLogTags); + FRIEND_TEST(DebugLoggerTest, Disable); +}; + +#ifdef HIPERF_DEBUG_PRINTF +#ifndef printf +#define printf(format, ...) \ + do { \ + std::printf(format, ##__VA_ARGS__); \ + DebugLogger::GetInstance()->Log(LEVEL_STDOUT, HILOG_TAG, format, ##__VA_ARGS__); \ + } while (0) +#endif + +#ifndef perror +#define perror(format, ...) \ + do { \ + std::perror(format); \ + DebugLogger::GetInstance()->Log(LEVEL_STDOUT, HILOG_TAG, format "<%d>\n", \ + ##__VA_ARGS__, errno); \ + } while (0) +#endif +#endif + +class ScopeDebugLevel { +public: + ScopeDebugLevel(DebugLevel level, bool mix = false); + ~ScopeDebugLevel(); + +private: + DebugLevel savedDebugLevel_; + bool savedMixOutput_ = false; // log mix to std +}; +#define TempMixLogLevel(level) ScopeDebugLevel tempLogLevel(level, true) + +#define LOG_LEVEL(LEVEL) LOG_##LEVEL +#define LOG_LEVEL_MUCH "M:" +#define LOG_LEVEL_VERBOSE "V:" +#define LOG_LEVEL_DEBUG "D:" +#define LOG_LEVEL_INFO "I:" +#define LOG_LEVEL_WARNING "W:" +#define LOG_LEVEL_ERROR "E:" +#define LOG_LEVEL_FATAL "F:" + +#ifndef HLOG +#define HLOG(level, format, ...) \ + do { \ + if (__builtin_expect(!DebugLogger::logDisabled_, false)) { \ + DebugLogger::GetInstance()->Log( \ + level, HILOG_TAG, \ + HILOG_TAG_NAME "/" LOG_LEVEL(level) "<%ld>[%s:%d]%s:" format "\n", gettid(), \ + SHORT_FILENAME, __LINE__, __FUNCTION__, ##__VA_ARGS__); \ + } \ + } while (0) +#endif + +// only log first n times +#ifndef HLOGV_FIRST +#define HLOGV_FIRST(first, format, ...) \ + do { \ + static int limit = first; \ + if (limit > 0) { \ + HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__); \ + if (--limit == 0) { \ + HLOG(LEVEL_VERBOSE, " nexttime log will be suppressed..."); \ + } \ + } \ + } while (0) +#endif + +#ifndef HLOGV_FIRST_LOCAL +#define HLOGV_FIRST_LOCAL(local_limit, format, ...) \ + { \ + if (local_limit != 0) { \ + HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__); \ + if (local_limit > 0 && --local_limit == 0) { \ + HLOG(LEVEL_VERBOSE, " nexttime log will be suppressed..."); \ + } \ + } \ + } +#endif + +#ifndef HLOGV +#define HLOGV_IF(condition, format, ...) \ + if (condition) { \ + HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__) \ + } +#define HLOGVVV HLOGV +#endif + +#ifndef HLOGDUMMY +#define HLOGDUMMY(format, ...) while (0) +#endif + +#ifndef HLOGM +#define HLOGM(format, ...) HLOG(LEVEL_MUCH, format, ##__VA_ARGS__) +#define HLOGMMM HLOGM +#endif + +#ifndef HLOGV +#define HLOGV(format, ...) HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__) +#endif + +#ifndef HLOGD +#define HLOGD(format, ...) HLOG(LEVEL_DEBUG, format, ##__VA_ARGS__) +#define HLOGDDD HLOGM +#endif + +#ifndef HLOGI +#define HLOGI(format, ...) HLOG(LEVEL_INFO, format, ##__VA_ARGS__) +#endif + +#ifndef HLOGW +#define HLOGW(format, ...) HLOG(LEVEL_WARNING, format, ##__VA_ARGS__) +#endif + +#ifndef HLOGE +#define HLOGE(format, ...) HLOG(LEVEL_ERROR, format, ##__VA_ARGS__) +#endif + +#ifndef HLOGEP +#define HLOGEP(format, ...) \ + HLOG(LEVEL_ERROR, format "(errno %d)", ##__VA_ARGS__, errno) +#endif + +#ifndef HLOGF +#define HLOGF(format, ...) \ + HLOG(LEVEL_FATAL, "FATAL error at %s:%d " format, __FILE__, __LINE__, ##__VA_ARGS__) +#endif + +#ifndef HLOG_ASSERT_MESSAGE +#define HLOG_ASSERT_MESSAGE(condition, format, ...) \ + if (!(condition)) { \ + HLOG(LEVEL_FATAL, " assert failed: '%s' " format, #condition, ##__VA_ARGS__); \ + } +#endif + +#ifndef HLOG_ASSERT +#define HLOG_ASSERT(condition) HLOG_ASSERT_MESSAGE(condition, "") +#endif + +#undef assert +#else +#define HLOGDUMMY(...) \ + do { \ + } while (0) +#define HLOGEP(...) \ + do { \ + } while (0) +#define HLOGM(...) \ + do { \ + } while (0) +#define HLOGMMM(...) \ + do { \ + } while (0) +#define HLOGV(...) \ + do { \ + } while (0) +#define HLOGVVV(...) \ + do { \ + } while (0) +#define HLOGD(...) \ + do { \ + } while (0) +#define HLOGDDD(...) \ + do { \ + } while (0) +#define HLOGI(...) \ + do { \ + } while (0) +#define HLOGW(...) \ + do { \ + } while (0) +#define HLOGE(...) \ + do { \ + } while (0) +#define HLOGF(...) \ + do { \ + } while (0) +#define HLOG_ASSERT_MESSAGE(...) \ + do { \ + } while (0) +#define HLOG_ASSERT(...) \ + do { \ + } while (0) + +class ScopeDebugLevel { +public: + ScopeDebugLevel(DebugLevel level, bool mix = false) {} +}; +#endif +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // _HIPERF_DEBUG_H_ diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/dwarf_encoding.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/dwarf_encoding.h new file mode 100755 index 0000000000000000000000000000000000000000..0417890bd93fa89471d19e580eb374a63dd70e5c --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/dwarf_encoding.h @@ -0,0 +1,193 @@ +/* + * 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. + */ +#ifndef DWARF_ENCODING_H +#define DWARF_ENCODING_H + +#include "utilities.h" + +// now we only support 64 bit. +using uleb128_t = uint64_t; +using sleb128_t = int64_t; + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +static constexpr const int LEB_BYTE_EFFECTIVE_LENGTH = 7; +static constexpr const int SIGN_BIT_OF_BYTE = 0x40; +static constexpr const int MAX_VALUE_OF_BYTE = 0x7f; +static constexpr const int MORE_BIT_OF_BYTE = 0x80; + +/* +10.5.1. DWARF Exception Header Encoding +The DWARF Exception Header Encoding is used to describe the type of data used in the .eh_frame and +.eh_frame_hdr section. The upper 4 bits indicate how the value is to be applied. The lower 4 bits +indicate the format of the data. +using dw_encode_t = unsigned char; // 4 bits + 4 bits +*/ + +using dw_encode_t = unsigned char; // 4 bits + 4 bits + +// Table 10-5. DWARF Exception Header value format + +enum DW_EH_PE_VF { + DW_EH_PE_absptr = 0x00, // a literal pointer whose size is determined by the architecture. + DW_EH_PE_uleb128 = 0x01, // Unsigned value is encoded using the Little Endian Base 128 (LEB128) + DW_EH_PE_udata2 = 0x02, // A 2 bytes unsigned value. + DW_EH_PE_udata4 = 0x03, // A 4 bytes unsigned value. + DW_EH_PE_udata8 = 0x04, // An 8 bytes unsigned value. + DW_EH_PE_sleb128 = 0x09, // Signed value is encoded using the Little Endian Base 128(LEB128) + DW_EH_PE_sdata2 = 0x0A, // A 2 bytes signed value. + DW_EH_PE_sdata4 = 0x0B, // A 4 bytes signed value. + DW_EH_PE_sdata8 = 0x0C, // An 8 bytes signed value. +}; + +// Table 10-6. DWARF Exception Header application +enum DW_EH_PE_A { + DW_EH_PE_nothing = 0x00, // nothing to do + DW_EH_PE_pcrel = 0x10, // relative to the current program counter. + DW_EH_PE_textrel = 0x20, // relative to the beginning of the .text section. + DW_EH_PE_datarel = 0x30, // relative to the beginning of the .got or .eh_frame_hdr section. + DW_EH_PE_funcrel = 0x40, // relative to the beginning of the function. + DW_EH_PE_aligned = 0x50, // aligned to an address unit sized boundary. + DW_EH_PE_omit = 0xff, // indicate that no value ispresent. +}; + +const std::map DWFormatSizeMap = { +#ifdef ARM + {DW_EH_PE_absptr, 4}, +#else + {DW_EH_PE_absptr, 8}, +#endif +#ifdef NOT_USE + {DW_EH_PE_uleb128, sizeof(char) * 128}, +#endif + {DW_EH_PE_udata2, sizeof(char) * 2}, + {DW_EH_PE_udata4, sizeof(char) * 4}, + {DW_EH_PE_udata8, sizeof(char) * 8}, +#ifdef NOT_USE + {DW_EH_PE_sleb128, sizeof(char) * 128}, +#endif + {DW_EH_PE_sdata2, sizeof(char) * 2}, + {DW_EH_PE_sdata4, sizeof(char) * 4}, + {DW_EH_PE_sdata8, sizeof(char) * 8}, +}; + +template +uint64_t dwReadAnyTypeData(const unsigned char *&buffer, T) +{ + T value; + if (memcpy_s(&value, sizeof(T), buffer, sizeof(T)) != 0) { + return 0; + } + buffer += sizeof(T); + return static_cast(value); +} + +class DwarfEncoding { +public: + DwarfEncoding(dw_encode_t dw, const unsigned char *&data, uint64_t vaddrBase = 0, + uint64_t vaddrPC = 0, uint64_t vaddrText = 0); + + const std::string ToString() const; + + const unsigned char *GetEnd() const; + + const unsigned char *GetData() const; + + size_t GetSize() const; + + uint64_t GetValue() const; + + uint64_t GetAppliedValue() const; + + bool IsOmit() const; + +private: + dw_encode_t dw_; + const unsigned char *data_; + uint64_t vaddrBase_ = 0; + uint64_t vaddrPC_ = 0; + uint64_t vaddrText_ = 0; + uint64_t value_[2] = {0, 0}; + + dw_encode_t Format() const; + + dw_encode_t Application() const; + + uint64_t ReadValue(const unsigned char *&data) const; + + const std::string FormatName() const; + + const std::string ApplicationName() const; +}; + +/* +Linux Standard Base Core Specification 4.1 +Chapter 10. Object Format +10.6.2. The .eh_frame_hdr section + +Table 10-11. .eh_frame_hdr Section Format + +Encoding Field +unsigned byte version +unsigned byte eh_frame_ptr_enc +unsigned byte fde_count_enc +unsigned byte table_enc +encoded eh_frame_ptr +encoded fde_count + binary search table +*/ + +struct binary_search_table { + uint64_t ipVaddrOffset; + uint64_t fdeVaddrOffset; +}; + +struct eh_frame_hdr { + // Version of the .eh_frame_hdr format. This value shall be 1. + dw_encode_t version; + + // The encoding format of the eh_frame_ptr field. + dw_encode_t eh_frame_ptr_enc; + + // The encoding format of the fde_count field. A value of DW_EH_PE_omit indicates the binary + // search table is not present. + dw_encode_t fde_count_enc; + + // The encoding format of the entries in the binary search table. A value of DW_EH_PE_omit + // indicates the binary search table is not present. + dw_encode_t table_enc; + + // The encoded value of the pointer to the start of the .eh_frame section. + /* + dw_encode_t eh_frame_ptr + dw_encode_t fde_count + */ + // A binary search table containing fde_count entries. Each entry of the table consist of two + // encoded values, the initial location, and the address. The entries are sorted in an + // increasing order by the initial location value. + + /* + * struct { + * encoded start_ip + * encoded fde_addr + * } binary_search_table[fde_count] + */ + unsigned char encode_data[0]; +} PACKED; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // DWARF_ENCODING_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/elf_parser.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/elf_parser.h new file mode 100755 index 0000000000000000000000000000000000000000..f757d24be57ccc27b57ed9a67589f7f6ec175a71 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/elf_parser.h @@ -0,0 +1,305 @@ +/* + * 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. + */ + +#ifndef ELF_PARSER_H_ +#define ELF_PARSER_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "debug_logger.h" +#include "noncopyable.h" +#include "utilities.h" + +#if !is_mingw +#include +#include +#endif + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +namespace ELF { +using namespace std::string_literals; + +constexpr std::size_t ehdr32Size {52}; +constexpr std::size_t ehdr64Size {64}; +constexpr std::size_t shdr32Size {40}; +constexpr std::size_t shdr64Size {64}; +constexpr std::size_t phdr32Size {32}; +constexpr std::size_t phdr64Size {56}; +constexpr std::size_t symEnt32Size {16}; +constexpr std::size_t symEnt64Size {24}; + +class ElfHeader { +public: + static std::unique_ptr MakeUnique(unsigned char * const ehdrBuf, + const std::size_t bufSize); + bool Init(unsigned char * const ehdrBuf, const std::size_t bufSize); + + unsigned char ehdrIdent_[EI_NIDENT]; + uint16_t type_; + uint16_t machine_; + uint16_t ehdrSize_; + uint16_t phdrEntSize_; + uint16_t phdrNumEnts_; + uint16_t shdrEntSize_; + uint16_t shdrNumEnts_; + uint16_t shdrStrTabIdx_; + uint32_t elfVersion_; + uint32_t ehdrFlags_; + uint64_t prgEntryVaddr_; + uint64_t phdrOffset_; + uint64_t shdrOffset_; + +private: + explicit ElfHeader() = default; + bool ParseElf32Header(unsigned char * const ehdrBuf, const std::size_t bufSize); + bool ParseElf64Header(unsigned char * const ehdrBuf, const std::size_t bufSize); + static inline void DumpEhdrBuf(const char * const ehdrBuf, const std::size_t bufSize) + { + const std::string fileName {"ehdr_buffer_dump"}; + std::ofstream ofs {fileName, std::ios::binary}; + if (ofs.is_open()) { + ofs.write(ehdrBuf, bufSize); + } + } +}; + +class ProgramHeader { +public: + static std::unique_ptr MakeUnique(char * const phdrBuf, const size_t bufSize); + inline bool Init(char * const phdrBuf, const size_t bufSize) + { + if (bufSize == phdr32Size and ParsePrgHeader32(phdrBuf)) { + return true; + } + if (bufSize == phdr64Size and ParsePrgHeader64(phdrBuf)) { + return true; + } + HLOGE("parse program header failed, program header buffer dumped"); + return false; + } + + uint32_t type_; + uint32_t flags_; + uint64_t offset_; + uint64_t vaddr_; + uint64_t paddr_; + uint64_t fileSize_; + uint64_t memSize_; + uint64_t secAlign_; + +private: + explicit ProgramHeader() = default; + bool ParsePrgHeader32(char * const phdrBuf); + bool ParsePrgHeader64(char * const phdrBuf); + static inline void DumpPhdrBuf(const char * const phdrBuf, const std::size_t bufSize) + { + const std::string fileName {"phdr_buffer_dump"}; + std::ofstream ofs {fileName, std::ios::binary}; + if (ofs.is_open()) { + ofs.write(phdrBuf, bufSize); + } + } +}; + +class SectionHeader { +public: + static std::unique_ptr MakeUnique(char * const shdrBuf, const size_t bufSize, + const size_t index); + + inline bool Init(char * const shdrBuf, const size_t bufSize, const size_t index) + { + secIndex_ = index; + if (bufSize == shdr32Size and ParseSecHeader32(shdrBuf)) { + return true; + } + if (bufSize == shdr64Size and ParseSecHeader64(shdrBuf)) { + return true; + } + HLOGE("parse section header failed, section header buffer dumped"); + return false; + } + + uint32_t nameIndex_; + uint32_t link_; + uint32_t info_; + uint64_t secFlags_; + uint64_t secVaddr_; + uint64_t fileOffset_; + uint64_t secSize_; + uint64_t secAddrAlign_; + uint64_t secEntrySize_; + uint64_t secType_; + uint32_t secIndex_; + std::string secTypeName_; + +private: + explicit SectionHeader() = default; + bool ParseSecHeader32(char * const shdrBuf); + bool ParseSecHeader64(char * const shdrBuf); + static inline void DumpShdrBuf(const char * const shdrBuf, const std::size_t bufSize) + { + const std::string fileName {"shdr_buffer_dump"}; + std::ofstream ofs {fileName, std::ios::binary}; + if (ofs.is_open()) { + ofs.write(shdrBuf, bufSize); + } + } +}; + +class ElfSymbol { +public: + static std::unique_ptr MakeUnique(char * const symBuf, const std::size_t bufSize); + inline bool Init(char * const symBuf, const std::size_t bufSize) + { + if (bufSize == symEnt32Size and ParseElf32Symbol(symBuf)) { + return true; + } + if (bufSize == symEnt64Size and ParseElf64Symbol(symBuf)) { + return true; + } + HLOGE("parse elf symbol failed, symbol buffer dumped"); + return false; + } + + uint16_t secIndex_; + uint32_t nameIndex_; + uint64_t symValue_; + uint64_t symSize_; + unsigned char symInfo_; + unsigned char symOtherInfo_; + +private: + explicit ElfSymbol() = default; + bool ParseElf32Symbol(char * const symBuf); + bool ParseElf64Symbol(char * const symBuf); + static inline void DumpSymBuf(const char * const symBuf, const std::size_t bufSize) + { + const std::string fileName {"shdr_buffer_dump"}; + std::ofstream ofs {fileName, std::ios::binary}; + if (ofs.is_open()) { + ofs.write(symBuf, bufSize); + } + } +}; + +class SymbolTable { +public: + static std::unique_ptr MakeUnique(const std::string &symNamesStr, + const char * const secBuf, + const uint64_t secSize, + const uint64_t entrySize); + + std::vector> symbols_; + +private: + explicit SymbolTable(const std::string &symNamesStr) : symNamesStr_ {symNamesStr} {} + + const std::string symNamesStr_ {}; +}; + +class ElfFile : public Noncopyable { +public: + virtual ~ElfFile(); + static std::unique_ptr MakeUnique(const std::string &filename); + bool ParseFile(); + bool ParseSymTable(const SectionHeader *shdr); + std::string GetSectionName(const uint32_t startIndex); + + inline bool IsOpened() const + { + return fd_ != -1; + } + + inline const char *GetStrPtr(uint32_t sh_link, uint32_t st_name) + { + for (const auto &shdrsItem : shdrs_) { + if (shdrsItem.second->secIndex_ == sh_link) { + if (mmap_ != MMAP_FAILED) { + char *elfFileBegin = (char *)mmap_; + return elfFileBegin + shdrsItem.second->fileOffset_ + st_name; + } + } + } + HLOGE("string not found sh_link %u st_name %d", sh_link, st_name); + return nullptr; + } + + inline const unsigned char *GetSectionData(uint32_t shIndex) + { + for (const auto &shdrsItem : shdrs_) { + if (shdrsItem.second->secIndex_ == shIndex) { + if (mmap_ != MMAP_FAILED) { + const unsigned char *elfFileBegin = (const unsigned char *)mmap_; + return elfFileBegin + shdrsItem.second->fileOffset_; + } + } + } + HLOGE("string not found shIndex %u ", shIndex); + return nullptr; + } + + using SecHeaderTableType = std::unordered_map>; + using PrgHeaderTableType = std::vector>; + int fd_ {-1}; + std::unique_ptr ehdr_ {nullptr}; + SecHeaderTableType shdrs_ {}; + PrgHeaderTableType phdrs_ {}; + std::string secNamesStr_ {}; + std::string symNamesStr_ {}; + std::unique_ptr symTable_ {nullptr}; + std::unique_ptr dynSymTable_ {nullptr}; + +protected: + // for fuzz test we make a virtual function + virtual ssize_t ReadFile(void *buf, size_t count) + { + return read(fd_, buf, count); + }; + explicit ElfFile(const std::string &filename); + +private: + bool ParseElfHeader(); + bool ParsePrgHeaders(); + bool ParseSecNamesStr(); + bool ParseSecHeaders(); + bool ParseSymNamesStr(); + bool ParseSymTable(const std::string = ".symtab"); + bool ParseDynSymTable(); + + void *mmap_ = MMAP_FAILED; + uint64_t mmapSize_ = 0; +}; +} // namespace ELF +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // ELF_PARSER_H_ diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/hashlist.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/hashlist.h new file mode 100644 index 0000000000000000000000000000000000000000..da8b6cf31ae763f018162656b4cba7ef17241b49 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/hashlist.h @@ -0,0 +1,225 @@ +/* + * 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. + */ + +#ifndef HIPERF_HASHLIST_H +#define HIPERF_HASHLIST_H + +#include + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +class Link { +public: + Link() = default; + ~Link() = default; + Link(const Link &link) : prev_ {link.prev_}, next_ {link.next_} {} + Link(Link &&link) : prev_ {link.prev_}, next_ {link.next_} + { + link.prev_ = nullptr; + link.next_ = nullptr; + } + Link &operator=(const Link &link) + { + prev_ = link.prev_; + next_ = link.next_; + return *this; + } + Link &operator=(Link &&link) + { + prev_ = link.prev_; + link.prev_ = nullptr; + next_ = link.next_; + link.next_ = nullptr; + return *this; + } + Link *prev_ {nullptr}; + Link *next_ {nullptr}; +}; + +template +class LinkNode { +public: + Link link_ {}; + Key key_ {}; + Val val_ {}; + + explicit LinkNode() = default; + ~LinkNode() = default; + explicit LinkNode(const Key &key); + explicit LinkNode(const Key &key, const Val &val); + explicit LinkNode(const Key &key, Val &&val); + LinkNode(const LinkNode &node); + LinkNode(LinkNode &&node); + LinkNode &operator=(const LinkNode &node); + LinkNode &operator=(LinkNode &&node); + static LinkNode *GetLinkNode(Val *pval); + static LinkNode *GetLinkNode(Link *plink); +}; + +template +class HashList { +public: + class Iterator { + public: + Iterator() = default; + ~Iterator() = default; + explicit Iterator(LinkNode *pnode, HashList *phashList); + explicit Iterator(const LinkNode *pnode, const HashList *phashList); + Iterator(const Iterator &itr); + Iterator(Iterator &&itr); + Iterator &operator=(const Iterator &itr); + Iterator &operator=(Iterator &&itr); + Iterator &operator++() noexcept; + Iterator operator++(int) noexcept; + Iterator &operator--() noexcept; + Iterator operator--(int) noexcept; + bool operator<(const Iterator &itr) const noexcept; + bool operator==(const Iterator &itr) const noexcept; + Val &operator*(); + const Val &operator*() const; + Val *operator->(); + const Val *operator->() const; + void swap(HashList::Iterator &other); + LinkNode *GetNode() const + { + return pnode_; + } + + private: + bool IsDangled() const noexcept + { + return phashList_ == nullptr; + } + + LinkNode *pnode_ {nullptr}; + HashList *phashList_ {nullptr}; + }; + + class ReverseIterator { + public: + ReverseIterator() = default; + ~ReverseIterator() = default; + explicit ReverseIterator(LinkNode *pnode, HashList *phashList); + explicit ReverseIterator(const LinkNode *pnode, const HashList *phashList); + ReverseIterator(const ReverseIterator &itr); + ReverseIterator(ReverseIterator &&itr); + ReverseIterator &operator=(const ReverseIterator &itr); + ReverseIterator &operator=(ReverseIterator &&itr); + ReverseIterator &operator++() noexcept; + ReverseIterator operator++(int) noexcept; + ReverseIterator &operator--() noexcept; + ReverseIterator operator--(int) noexcept; + bool operator<(const ReverseIterator &itr) const noexcept; + bool operator==(const ReverseIterator &itr) const noexcept; + Val &operator*(); + const Val &operator*() const; + Val *operator->(); + const Val *operator->() const; + void swap(HashList::ReverseIterator &other); + + LinkNode *GetNode() + { + return pnode_; + } + + private: + bool IsDangled() const noexcept + { + return phashList_ == nullptr; + } + + LinkNode *pnode_ {nullptr}; + HashList *phashList_ {nullptr}; + }; + +public: + explicit HashList(const std::size_t numItem = 0); + ~HashList(); + + HashList(const HashList &source) = delete; + HashList &operator=(const HashList &source) = delete; + HashList(HashList &&source); + HashList &operator=(HashList &&source); + + // capacity + inline std::size_t size() const + { + return valueTab_.size(); + } + inline bool empty() const + { + return (dataHead_.next_ == &dataHead_) and (dataHead_.prev_ == &dataHead_); + } + inline std::size_t capacity() const + { + return numItem_; + } + inline bool IsFull() const + { + return freeHead_.next_ == &freeHead_; + } + inline std::size_t count(const Key &key) const + { + return valueTab_.count(key); + } + + int reserve(const std::size_t numItem); + // iterators + Iterator begin(); + const Iterator cbegin() const; + Iterator end(); + const Iterator cend() const; + ReverseIterator rbegin(); + const ReverseIterator crbegin() const; + ReverseIterator rend(); + const ReverseIterator crend() const; + // element access + Val &front(); + const Val &front() const; + Val &back(bool prepend = false); + Val &operator[](const Key &key); + // lookup + Iterator find(const Key &key); + // modifiers + void push_front(const Key &key, const Val &val); + void push_front(const Key &key, Val &&val); + void push_back(const Key &key, const Val &val); + void push_back(const Key &key, Val &&val); + void pop_front(); + void pop_back(); + Iterator erase(const Key &key); + Iterator erase(const Iterator pos); + Iterator erase(const Iterator first, const Iterator last); + +private: + void MoveToHead(LinkNode *&pnode); + void MoveToTail(LinkNode *&pnode); + bool MoveNode(const Iterator &pos, LinkNode *&pnode); + LinkNode *AllocateNode(const Key &key); + LinkNode *AllocateNode(const Key &key, const Val &val); + LinkNode *AllocateNode(const Key &key, Val &&val); + void ReclaimNode(LinkNode *&pnode); + + std::size_t numItem_ {0}; + LinkNode *pData_ {nullptr}; + Link dataHead_ {}; + Link freeHead_ {}; + std::unordered_map *> valueTab_ {}; +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_HASHLIST_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/hashlist.hpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/hashlist.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5893c6dd5b0d4d75f52c811ea65eaf984d3bf295 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/hashlist.hpp @@ -0,0 +1,949 @@ +/* + * Copyright (c) 2021-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. + */ + +#ifndef HIPERF_HASHLIST_HPP +#define HIPERF_HASHLIST_HPP + +#include "hashlist.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +// implementation of template class LinkNode +template +LinkNode::LinkNode(const Key &key) : key_ {key} {} + +template +LinkNode::LinkNode(const Key &key, const Val &val) : key_ {key}, val_ {val} {} + +template +LinkNode::LinkNode(const Key &key, Val &&val) : key_ {key}, val_ {std::move(val)} {} + +template +LinkNode::LinkNode(const LinkNode& node) + :link_ {node.link_}, + key_ {node.key_}, + val_ {node.val_} +{} + +template +LinkNode::LinkNode(LinkNode&& node) + :link_ {std::move(node.link_)}, + key_ {std::move(node.key_)}, + val_ {std::move(node.val_)} +{} + +template +auto LinkNode::operator=(const LinkNode& node) +-> LinkNode& +{ + link_ = node.link_; + key_ = node.key_; + val_ = node.val_; +} + +template +auto LinkNode::operator=(LinkNode&& node) +-> LinkNode& +{ + link_ = std::move(node.link_); + key_ = std::move(node.key_); + val_ = std::move(node.val_); +} + +template +auto LinkNode::GetLinkNode(Val *pval) +-> LinkNode* +{ + if (pval) { + LinkNode *pnode {nullptr}; + Val* offset = &pnode->val_; + auto nodeAddr = reinterpret_cast(pval) - reinterpret_cast(offset); + return reinterpret_cast*>(nodeAddr); + } + return nullptr; +} + +template +auto LinkNode::GetLinkNode(Link *plink) +-> LinkNode* +{ + if (plink) { + LinkNode *pnode {nullptr}; + Link* offset = &pnode->link_; + auto nodeAddr = reinterpret_cast(plink) - reinterpret_cast(offset); + return reinterpret_cast*>(nodeAddr); + } + return nullptr; +} +// end of LinkNode + +// implementation of template class Iterator +template +HashList::Iterator::Iterator(LinkNode *pnode, HashList *phashList) + : pnode_ {pnode}, phashList_ {phashList} +{ + if (phashList_ == nullptr) { + pnode_ = nullptr; + } +} + +template +HashList::Iterator::Iterator(const LinkNode *pnode, const HashList *phashList) + : pnode_ {const_cast*>(pnode)}, + phashList_ {const_cast(phashList)} +{ + if (phashList_ == nullptr) { + pnode_ = nullptr; + } +} + +template +HashList::Iterator::Iterator(const Iterator& itr) + : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} +{} + +template +HashList::Iterator::Iterator(Iterator&& itr) + : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} +{ + itr.pnode_ = nullptr; + itr.phashList_ = nullptr; +} + +template +auto HashList::Iterator::operator=(const Iterator& itr) +-> HashList::Iterator& +{ + Iterator temp {itr}; + swap(temp); + return *this; +} + +template +auto HashList::Iterator::operator=(Iterator&& itr) +-> HashList::Iterator& +{ + Iterator temp {std::move(itr)}; + swap(temp); + return *this; +} + +template +auto HashList::Iterator::operator++() noexcept +-> HashList::Iterator & +{ + if (pnode_ == nullptr or phashList_ == nullptr) { + phashList_ = nullptr; + return *this; + } + Link* plink = pnode_->link_.next_; + if (plink == &phashList_->dataHead_) { + pnode_ = nullptr; + return *this; + } + auto pnode = LinkNode::GetLinkNode(plink); + pnode_ = pnode; + return *this; +} + +template +auto HashList::Iterator::operator++(int) noexcept +-> HashList::Iterator +{ + Iterator res {*this}; + if (pnode_ == nullptr or phashList_ == nullptr) { + phashList_ = nullptr; + return res; + } + Link* plink = pnode_->link_.next_; + if (plink == &phashList_->dataHead_) { + pnode_ = nullptr; + return res; + } + auto pnode = LinkNode::GetLinkNode(plink); + pnode_ = pnode; + return res; +} + +template +auto HashList::Iterator::operator--() noexcept +-> HashList::Iterator & +{ + if (phashList_ == nullptr) { + return *this; + } + Link* plink {nullptr}; + if (pnode_ == nullptr) { + plink = phashList_->dataHead_.prev_; + } else { + plink = pnode_->link_.prev_; + } + if (plink == &phashList_->dataHead_) { + pnode_ = nullptr; + phashList_ = nullptr; + return *this; + } + pnode_ = LinkNode::GetLinkNode(plink); + return *this; +} + +template +auto HashList::Iterator::operator--(int) noexcept +-> HashList::Iterator +{ + Iterator res {*this}; + if (phashList_ == nullptr) { + return res; + } + Link* plink {nullptr}; + if (pnode_ == nullptr) { + plink = phashList_->dataHead_.prev_; + } else { + plink = pnode_->link_.prev_; + } + if (plink == &phashList_->dataHead_) { + pnode_ = nullptr; + phashList_ = nullptr; + return res; + } + pnode_ = LinkNode::GetLinkNode(plink); + return res; +} + +template +bool HashList::Iterator::operator<(const HashList::Iterator &itr) const noexcept +{ + if (IsDangled() or itr.IsDangled()) { + return false; + } + if (phashList_ != itr.phashList_) { + return false; + } + Iterator tempItr {*this}; + if (tempItr == itr) { + return false; + } + while (!tempItr.IsDangled()) { + tempItr++; + if (tempItr == itr) { + return true; + } + } + return false; +} + +template +bool HashList::Iterator::operator==(const HashList::Iterator &itr) const noexcept +{ + if (IsDangled() or itr.IsDangled()) { + return false; + } + if (phashList_ != itr.phashList_) { + return false; + } + return pnode_ == itr.pnode_; +} + +template +Val& HashList::Iterator::operator*() +{ + return pnode_->val_; +} + +template +const Val& HashList::Iterator::operator*() const +{ + return pnode_->val_; +} + +template +Val* HashList::Iterator::operator->() +{ + return &pnode_->val_; +} + +template +const Val* HashList::Iterator::operator->() const +{ + return &pnode_->val_; +} + +template +void HashList::Iterator::swap(HashList::Iterator& other) +{ + using std::swap; + swap(pnode_, other.pnode_); + swap(phashList_, other.phashList_); +} +// end of Iterator + +// Implementation of ReverseIterator +template +HashList::ReverseIterator::ReverseIterator(LinkNode *pnode, HashList *phashList) + : pnode_ {pnode}, phashList_ {phashList} +{ + if (phashList_ == nullptr) { + pnode_ = nullptr; + } +} + +template +HashList::ReverseIterator::ReverseIterator(const LinkNode *pnode, const HashList *phashList) + : pnode_ {const_cast *>(pnode)}, + phashList_ {const_cast(phashList)} +{ + if (phashList_ == nullptr) { + pnode_ = nullptr; + } +} + +template +HashList::ReverseIterator::ReverseIterator(const ReverseIterator &itr) + : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} +{} + +template +HashList::ReverseIterator::ReverseIterator(ReverseIterator &&itr) + : pnode_ {itr.pnode_}, phashList_ {itr.phashList_} +{ + itr.pnode_ = nullptr; + itr.phashList_ = nullptr; +} + +template +auto HashList::ReverseIterator::operator=(const ReverseIterator& itr) +-> HashList::ReverseIterator& +{ + ReverseIterator temp {itr}; + swap(temp); + return *this; +} + +template +auto HashList::ReverseIterator::operator=(ReverseIterator&& itr) +-> HashList::ReverseIterator& +{ + ReverseIterator temp {std::move(itr)}; + swap(temp); + return *this; +} + +template +auto HashList::ReverseIterator::operator++() noexcept +-> HashList::ReverseIterator & +{ + if (pnode_ == nullptr or phashList_ == nullptr) { + phashList_ = nullptr; + return *this; + } + Link* plink = &pnode_->link_; + plink = plink->prev_; + if (plink == &phashList_->dataHead_) { + pnode_ = nullptr; + return *this; + } + pnode_ = LinkNode::GetLinkNode(plink); + return *this; +} + +template +auto HashList::ReverseIterator::operator++(int) noexcept +-> HashList::ReverseIterator +{ + ReverseIterator res {*this}; + if (pnode_ == nullptr or phashList_ == nullptr) { + phashList_ = nullptr; + return res; + } + Link* plink = &pnode_->link_; + plink = plink->prev_; + if (plink == &phashList_->dataHead_) { + pnode_ = nullptr; + return res; + } + pnode_ = LinkNode::GetLinkNode(plink); + return res; +} + +template +auto HashList::ReverseIterator::operator--() noexcept +-> HashList::ReverseIterator & +{ + if (phashList_ == nullptr) { + return *this; + } + Link* plink {nullptr}; + if (pnode_ == nullptr) { + plink = phashList_->dataHead_.next_; + } else { + plink = pnode_->link_.next_; + } + if (plink == &phashList_->dataHead_) { + pnode_ = nullptr; + phashList_ = nullptr; + return *this; + } + pnode_ = LinkNode::GetLinkNode(plink); + return *this; +} + +template +auto HashList::ReverseIterator::operator--(int) noexcept +-> HashList::ReverseIterator +{ + ReverseIterator res {*this}; + if (phashList_ == nullptr) { + return res; + } + Link* plink {nullptr}; + if (pnode_ == nullptr) { + plink = phashList_->dataHead_.next_; + } else { + plink = pnode_->link_.next_; + } + if (plink == &phashList_->dataHead_) { + pnode_ = nullptr; + phashList_ = nullptr; + return res; + } + pnode_ = LinkNode::GetLinkNode(plink); + return res; +} + +template +bool HashList::ReverseIterator::operator<( + const HashList::ReverseIterator &itr) const noexcept +{ + if (IsDangled() or itr.IsDangled()) { + return false; + } + if (phashList_ != itr.phashList_) { + return false; + } + HashList::ReverseIterator tempItr {*this}; + if (tempItr == itr) { + return false; + } + while (!tempItr.IsDangled()) { + tempItr++; + if (tempItr == itr) { + return true; + } + } + return false; +} + +template +bool HashList::ReverseIterator::operator==( + const HashList::ReverseIterator &itr) const noexcept +{ + if (IsDangled() or itr.IsDangled()) { + return false; + } + if (phashList_ != itr.phashList_) { + return false; + } + return pnode_ == itr.pnode_; +} + +template +Val& HashList::ReverseIterator::operator*() +{ + return pnode_->val_; +} + +template +const Val& HashList::ReverseIterator::operator*() const +{ + return pnode_->val_; +} + +template +Val* HashList::ReverseIterator::operator->() +{ + return &pnode_->val_; +} + +template +const Val* HashList::ReverseIterator::operator->() const +{ + return &pnode_->val_; +} + +template +void HashList::ReverseIterator::swap(HashList::ReverseIterator& other) +{ + using std::swap; + swap(pnode_, other.pnode_); + swap(phashList_, other.phashList_); +} +// end of ReverseIterator + +// implementation of template class HashList +template +HashList::HashList(const std::size_t numItem) : numItem_ {numItem} +{ + dataHead_.next_ = &dataHead_; + dataHead_.prev_ = &dataHead_; + if (numItem_) { + valueTab_.reserve(numItem_); + pData_ = new(std::nothrow) LinkNode[numItem_]; + if (pData_) { + freeHead_.next_ = &(pData_[0].link_); + std::size_t last {numItem_ - 1}; + for (std::size_t index = 0; index < last;) { + LinkNode &curNnode = pData_[index]; + curNnode.link_.next_ = &(pData_[++index].link_); + } + pData_[last].link_.next_ = &freeHead_; + } else { + numItem_ = 0; + freeHead_.next_ = &freeHead_; + freeHead_.prev_ = &freeHead_; + } + } +} + +template +int HashList::reserve(const std::size_t numItem) +{ + if (numItem_ != 0) { + return -1; + } + if (numItem) { + numItem_ = numItem; + valueTab_.reserve(numItem_); + pData_ = new(std::nothrow) LinkNode[numItem_]; + dataHead_.next_ = &dataHead_; + dataHead_.prev_ = &dataHead_; + if (pData_) { + freeHead_.next_ = &(pData_[0].link_); + std::size_t last {numItem_ - 1}; + for (std::size_t index = 0; index < last;) { + LinkNode &curNnode = pData_[index]; + curNnode.link_.next_ = &(pData_[++index].link_); + } + pData_[last].link_.next_ = &freeHead_; + } else { + numItem_ = 0; + freeHead_.next_ = &freeHead_; + freeHead_.prev_ = &freeHead_; + } + } + return numItem_; +} + +template +HashList::~HashList() +{ + if (pData_) { + delete[] pData_; + pData_ = nullptr; + } + valueTab_.clear(); + dataHead_.next_ = &dataHead_; + dataHead_.prev_ = &dataHead_; + freeHead_.next_ = nullptr; + freeHead_.prev_ = nullptr; + numItem_ = 0; +} + +template +HashList::HashList(HashList &&source) + : numItem_ {source.numItem_}, + pData_ {source.pData_}, + dataHead_ {std::move(source.dataHead_)}, + freeHead_ {std::move(source.freeHead_)}, + valueTab_ {std::move(source.valueTab_)} +{ + source.pData_ = nullptr; +} + +template +auto HashList::operator=(HashList &&source) +-> HashList& +{ + if (this == &source) { + return *this; + } + if (pData_) { + delete[] pData_; + pData_ = nullptr; + } + numItem_ = source.numItem_; + pData_ = source.pData_; + source.pData_ = nullptr; + dataHead_ = std::move(source.dataHead_); + freeHead_ = std::move(source.freeHead_); + valueTab_ = std::move(source.valueTab_); + return *this; +} + +template +auto HashList::begin() +-> HashList::Iterator +{ + if (empty()) { + return end(); + } + return Iterator(LinkNode::GetLinkNode(dataHead_.next_), this); +} + +template +auto HashList::cbegin() const +-> const HashList::Iterator +{ + if (empty()) { + return cend(); + } + return Iterator(LinkNode::GetLinkNode(dataHead_.next_), this); +} + +template +auto HashList::end() +-> HashList::Iterator +{ + return Iterator(nullptr, this); +} + +template +auto HashList::cend() const +-> const HashList::Iterator +{ + return Iterator(nullptr, this); +} + +template +auto HashList::rbegin() +-> HashList::ReverseIterator +{ + if (empty()) { + return rend(); + } + return ReverseIterator(LinkNode::GetLinkNode(dataHead_.prev_), this); +} + +template +auto HashList::crbegin() const +-> const HashList::ReverseIterator +{ + if (empty()) { + return crend(); + } + return ReverseIterator(LinkNode::GetLinkNode(dataHead_.prev_), this); +} + +template +auto HashList::rend() +-> HashList::ReverseIterator +{ + return ReverseIterator(nullptr, this); +} + +template +auto HashList::crend() const +-> const HashList::ReverseIterator +{ + return ReverseIterator(nullptr, this); +} + +template +Val& HashList::front() +{ + LinkNode *pnode = LinkNode::GetLinkNode(dataHead_.next_); + return pnode->val_; +} + +template +const Val& HashList::front() const +{ + return front(); +} + +template +Val& HashList::back(bool prepend) +{ + auto pnode = LinkNode::GetLinkNode(dataHead_.prev_); + if (prepend) { + MoveToHead(pnode); + } + return pnode->val_; +} + +template +Val& HashList::operator[](const Key &key) +{ + LinkNode *pnode {nullptr}; + if (valueTab_.find(key) == valueTab_.end()) { + pnode = AllocateNode(key); + valueTab_[key] = pnode; + } else { + pnode = valueTab_[key]; + } + if (pnode) { + MoveToHead(pnode); + } + return pnode->val_; +} + +template +auto HashList::find(const Key &key) +-> HashList::Iterator +{ + const auto &itr = valueTab_.find(key); + if (itr == valueTab_.end()) { + return end(); + } + return Iterator(itr->second, this); +} + +template +void HashList::push_front(const Key& key, const Val& val) +{ + if (valueTab_.find(key) == valueTab_.end()) { + LinkNode* pnode = AllocateNode(key, val); + MoveToHead(pnode); + valueTab_[pnode->key_] = pnode; + } else { + MoveToHead(valueTab_[key]); + this->operator[](key) = val; + } +} + +template +void HashList::push_front(const Key& key, Val&& val) +{ + if (valueTab_.find(key) == valueTab_.end()) { + LinkNode* pnode = AllocateNode(key, std::move(val)); + MoveToHead(pnode); + valueTab_[pnode->key_] = pnode; + } else { + MoveToHead(valueTab_[key]); + this->operator[](key) = val; + } +} + +template +void HashList::push_back(const Key& key, const Val& val) +{ + if (valueTab_.find(key) == valueTab_.end()) { + LinkNode* pnode = AllocateNode(key, val); + MoveToTail(pnode); + valueTab_[pnode->key_] = pnode; + } else { + MoveToTail(valueTab_[key]); + this->operator[](key) = val; + } +} + +template +void HashList::push_back(const Key& key, Val&& val) +{ + if (valueTab_.find(key) == valueTab_.end()) { + LinkNode* pnode = AllocateNode(key, std::move(val)); + MoveToTail(pnode); + valueTab_[pnode->key_] = pnode; + } else { + MoveToTail(valueTab_[key]); + this->operator[](key) = val; + } +} + +template +void HashList::pop_front() +{ + if (empty()) { + return; + } + LinkNode* pnode = LinkNode::GetLinkNode(dataHead_.next_); + valueTab_.erase(pnode->key_); + ReclaimNode(pnode); +} + +template +void HashList::pop_back() +{ + if (empty()) { + return; + } + LinkNode* pnode = LinkNode::GetLinkNode(dataHead_.prev_); + valueTab_.erase(pnode->key_); + ReclaimNode(pnode); +} + +template +auto HashList::erase(const Key& key) +-> HashList::Iterator +{ + if (valueTab_.find(key) == valueTab_.end()) { + return end(); + } + LinkNode *pnode = valueTab_[key]; + valueTab_.erase(key); + Link* plink = pnode->link_.next_; + Iterator tempItr {LinkNode::GetLinkNode(plink), this}; + ReclaimNode(pnode); + return tempItr; +} + +template +auto HashList::erase(const Iterator pos) +-> HashList::Iterator +{ + // assume pos is valid, otherwise the result is undefined + Iterator tempItr {pos}; + ++tempItr; + LinkNode *pnode = pos.GetNode(); + valueTab_.erase(pnode->key_); + ReclaimNode(pnode); + return tempItr; +} + +template +auto HashList::erase(const Iterator first, const Iterator last) +-> HashList::Iterator +{ + // assume pos is valid, otherwise the result is undefined + if (first <= last) { + Iterator curPos {first}; + while (curPos < last) { + curPos = erase(curPos); + } + return last; + } + return end(); +} + +template +bool HashList::MoveNode(const Iterator& pos, LinkNode *&pnode) +{ + LinkNode *curNode = pos.GetNode(); + if (curNode == pnode) { + return true; + } + if (pnode->link_.next_ == &curNode->link_) { + return true; + } + Link* prevLink = pnode->link_.prev_; + Link* nextLink = pnode->link_.next_; + if (prevLink and nextLink) { + prevLink->next_ = nextLink; + nextLink->prev_ = prevLink; + } + Link *currLink = &curNode->link_; + prevLink = currLink->prev_; + nextLink = &pnode->link_; + prevLink->next_ = nextLink; + nextLink->prev_ = prevLink; + nextLink->next_ = currLink; + currLink->prev_ = nextLink; + return true; +} + +template +void HashList::MoveToHead(LinkNode *&pnode) +{ + if (pnode->link_.prev_ and pnode->link_.next_) { + Link* prev = pnode->link_.prev_; + Link* next = pnode->link_.next_; + prev->next_ = next; + next->prev_ = prev; + } + pnode->link_.next_ = dataHead_.next_; + dataHead_.next_->prev_ = &pnode->link_; + dataHead_.next_ = &pnode->link_; + pnode->link_.prev_ = &dataHead_; +} + +template +void HashList::MoveToTail(LinkNode *&pnode) +{ + if (pnode->link_.prev_ and pnode->link_.next_) { + Link* prev = pnode->link_.prev_; + Link* next = pnode->link_.next_; + prev->next_ = next; + next->prev_ = prev; + } + pnode->link_.prev_ = dataHead_.prev_; + dataHead_.prev_->next_ = &pnode->link_; + pnode->link_.next_ = &dataHead_; + dataHead_.prev_ = &pnode->link_; +} + +template +auto HashList::AllocateNode(const Key &key) +->LinkNode * +{ + if (IsFull()) { + pop_back(); + } + LinkNode * pnode = LinkNode::GetLinkNode(freeHead_.next_); + freeHead_.next_ = freeHead_.next_->next_; + pnode->link_.next_ = nullptr; + pnode->link_.prev_ = nullptr; + pnode->key_ = key; + pnode->val_ = Val(); + return pnode; +} + +template +auto HashList::AllocateNode(const Key &key, const Val &val) +->LinkNode * +{ + if (IsFull()) { + pop_back(); + } + LinkNode *pnode = LinkNode::GetLinkNode(freeHead_.next_); + freeHead_.next_ = freeHead_.next_->next_; + pnode->link_.next_ = nullptr; + pnode->link_.prev_ = nullptr; + pnode->key_ = key; + pnode->val_ = val; + return pnode; +} + +template +auto HashList::AllocateNode(const Key &key, Val &&val) +->LinkNode * +{ + if (IsFull()) { + pop_back(); + } + LinkNode * pnode = LinkNode::GetLinkNode(freeHead_.next_); + freeHead_.next_ = freeHead_.next_->next_; + pnode->link_.next_ = nullptr; + pnode->link_.prev_ = nullptr; + pnode->key_ = key; + pnode->val_ = std::move(val); + return pnode; +} + +template +void HashList::ReclaimNode(LinkNode *&pnode) +{ + Link *prevLink = pnode->link_.prev_; + Link *nextLink = pnode->link_.next_; + prevLink->next_ = nextLink; + nextLink->prev_ = prevLink; + pnode->link_.prev_ = nullptr; + pnode->link_.next_ = freeHead_.next_; + freeHead_.next_ = &pnode->link_; + return; +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_HASHLIST_HPP diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/linux/file_ex.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/linux/file_ex.h new file mode 100755 index 0000000000000000000000000000000000000000..65ae00ab25b7c280d7942f7ba7226847cff0d2c9 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/linux/file_ex.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef UTILS_BASE_FILE_EX_H +#define UTILS_BASE_FILE_EX_H + +#include +#include + +namespace OHOS { +bool LoadStringFromFile(const std::string& filePath, std::string& content); +bool SaveStringToFile(const std::string& filePath, const std::string& content, bool truncated = true); +bool LoadStringFromFd(int fd, std::string& content); +bool SaveStringToFd(int fd, const std::string& content); +bool LoadBufferFromFile(const std::string& filePath, std::vector& content); +bool SaveBufferToFile(const std::string& filePath, const std::vector& content, bool truncated = true); +bool FileExists(const std::string& fileName); +bool StringExistsInFile(const std::string& fileName, const std::string& subStr, bool caseSensitive = true); +int CountStrInFile(const std::string& fileName, const std::string& subStr, bool caseSensitive = true); +} + +#endif diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/linux/types.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/linux/types.h new file mode 100644 index 0000000000000000000000000000000000000000..b6ff13102f29f0aa22f7de3356efe3d1576af679 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/linux/types.h @@ -0,0 +1,33 @@ +/* + * 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. + */ +#ifndef NONLINUX_LINUX_TYPES_H +#define NONLINUX_LINUX_TYPES_H +#include + +/* +long long always 64 +only in ILP64 , int is 64, but no OS use this +otherwise int is always 32 +*/ + +// using __s8 = char; +using __u8 = unsigned char; +using __s16 = short; +using __u16 = unsigned short; +using __s32 = int; +using __u32 = unsigned int; +using __s64 = long long; +using __u64 = unsigned long long; +#endif diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/linux/unique_fd.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/linux/unique_fd.h new file mode 100755 index 0000000000000000000000000000000000000000..24a00dedceb48a1443fe93702202eb455e651948 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/linux/unique_fd.h @@ -0,0 +1,186 @@ +/* + * 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. + */ + +#ifndef UNIQUE_FD_H +#define UNIQUE_FD_H + +#include + +namespace OHOS { +class DefaultDeleter { +public: + static void Close(int fd) + { + if (fd >= 0) { + close(fd); + } + } +}; + +template +class UniqueFdAddDeletor; +template +bool operator==(const int& lhs, const UniqueFdAddDeletor& rhs); +template +bool operator!=(const int& lhs, const UniqueFdAddDeletor& rhs); +template +bool operator>=(const int& lhs, const UniqueFdAddDeletor& rhs); +template +bool operator>(const int& lhs, const UniqueFdAddDeletor& rhs); +template +bool operator<=(const int& lhs, const UniqueFdAddDeletor& rhs); +template +bool operator<(const int& lhs, const UniqueFdAddDeletor& rhs); + +template +class UniqueFdAddDeletor final { + + friend bool operator==(const int& lhs, const UniqueFdAddDeletor& rhs); + + friend bool operator!=(const int& lhs, const UniqueFdAddDeletor& rhs); + + friend bool operator>=(const int& lhs, const UniqueFdAddDeletor& rhs); + + friend bool operator>(const int& lhs, const UniqueFdAddDeletor& rhs); + + friend bool operator<=(const int& lhs, const UniqueFdAddDeletor& rhs); + + friend bool operator< (const int& lhs, const UniqueFdAddDeletor& rhs); + +public: + explicit UniqueFdAddDeletor(const int& value) + : fd_(value) + { + } + UniqueFdAddDeletor() + : fd_(-1) + { + } + ~UniqueFdAddDeletor() { Reset(-1); } + + // get fd out + int Release() + { + int tmp = fd_; + fd_ = -1; + return tmp; + } + + // this is dangerous, when you use it , you should know it, donot operator on the ret + operator int() const { return Get(); } // NOLINT + // this is dangerous, when you use it , you should know it, donot operator on the ret + int Get() const + { + return fd_; + } + + // we need move fd from one to another + UniqueFdAddDeletor(UniqueFdAddDeletor&& rhs) + { + int rhsfd = rhs.Release(); + fd_ = rhsfd; + } + + UniqueFdAddDeletor& operator=(UniqueFdAddDeletor&& rhs) + { + int rhsfd = rhs.Release(); + Reset(rhsfd); + return *this; + } + + bool operator==(const int& rhs) const + { + return fd_ == rhs; + } + + bool operator!=(const int& rhs) const + { + return !(fd_ == rhs); + } + bool operator>=(const int& rhs) const + { + return fd_ >= rhs; + } + + bool operator>(const int& rhs) const + { + return fd_ > rhs; + } + + bool operator<=(const int& rhs) const + { + return fd_ <= rhs; + } + + bool operator<(const int& rhs) const + { + return fd_ < rhs; + } + +private: + int fd_ = -1; + + void Reset(int newValue) + { + if (fd_ >= 0) { + Deleter::Close(fd_); + } + fd_ = newValue; + } + + // disallow copy ctor and copy assign + UniqueFdAddDeletor(const UniqueFdAddDeletor& rhs) = delete; + UniqueFdAddDeletor& operator=(const UniqueFdAddDeletor& rhs) = delete; +}; + +template +bool operator==(const int& lhs, const UniqueFdAddDeletor& uniqueFd) +{ + return lhs == uniqueFd.fd_; +} + +template +bool operator!=(const int& lhs, const UniqueFdAddDeletor& uniqueFd) +{ + return !(lhs == uniqueFd.fd_); +} + +template +bool operator>=(const int& lhs, const UniqueFdAddDeletor& uniqueFd) +{ + return lhs >= uniqueFd.fd_; +} + +template +bool operator>(const int& lhs, const UniqueFdAddDeletor& uniqueFd) +{ + return lhs > uniqueFd.fd_; +} + +template +bool operator<=(const int& lhs, const UniqueFdAddDeletor& uniqueFd) +{ + return lhs <= uniqueFd.fd_; +} + +template +bool operator<(const int& lhs, const UniqueFdAddDeletor& uniqueFd) +{ + return lhs < uniqueFd.fd_; +} + +using UniqueFd = UniqueFdAddDeletor; +} // namespace OHOS +#endif diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/mem_map_item.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/mem_map_item.h new file mode 100755 index 0000000000000000000000000000000000000000..c0501a1927662c4982dced003bbf3528dc1a6771 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/mem_map_item.h @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#ifndef MEMMAPITEM_H +#define MEMMAPITEM_H + +#include + +#include +#include + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +class MemMapItem { +public: + uint64_t begin_ = 0; + uint64_t end_ = 0; + uint16_t type_ = 0; // rwx : PROT_READ | PROT_WRITE | PROT_EXEC + uint16_t flags = 0; // ps : MAP_PRIVATE | MAP_SHARED + uint64_t pageoffset_ = 0; + uint64_t major_ = 0; + uint64_t minor_ = 0; + ino_t inode = 0; + std::string name_; + std::string_view nameHold_; + + MemMapItem() {} + MemMapItem(uint64_t begin, uint64_t end, uint64_t offset, const std::string &name) + : begin_(begin), + end_(end), + pageoffset_(offset), + name_(name), + nameHold_(MemoryHold::Get().HoldStringView(name)) + { + } + + // use for find + inline bool operator==(const std::string &name) const + { + return name_ == name; + } + + inline bool operator<(const MemMapItem &other) const + { + return end_ < other.end_; + } + + uint64_t FileOffsetFromAddr(uint64_t addr) const + { + // real vaddr - real map begin = addr offset in section + // section offset + page off set = file offset + return addr - begin_ + pageoffset_; + } + // debug only + const std::string ToString() const + { + std::stringstream sstream; + sstream << "0x" << std::hex << begin_; + sstream << "-0x" << std::hex << end_; + sstream << " type 0x" << std::hex << type_; + sstream << " flags 0x" << std::hex << flags; + sstream << " pageoffset 0x" << std::hex << pageoffset_; + sstream << " " << name_; + return sstream.str(); + } + static bool GreaterSort(const MemMapItem &a, const MemMapItem &b) + { + return (a.begin_ > b.begin_); + } + static bool LessSort(const MemMapItem &a, const MemMapItem &b) + { + return (a.begin_ < b.begin_); + } + // The range [first, last) must be partitioned with respect to the expression !(value < element) + // or !comp(value, element) + static bool ValueLessThan(uint64_t vaddr, const MemMapItem &a) + { + return vaddr <= a.begin_; + } + bool Contain(uint64_t addr) const + { + return addr >= begin_ and addr < end_; + } +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // MEMMAPITEM_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/noncopyable.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/noncopyable.h new file mode 100755 index 0000000000000000000000000000000000000000..846fbd8c4156ca32dc5e2cafe6150aba7c8740aa --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/noncopyable.h @@ -0,0 +1,26 @@ +/* + * 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. + */ +#ifndef NONCOPYABLE_H_ +#define NONCOPYABLE_H_ +class Noncopyable { +public: + Noncopyable() = default; + ~Noncopyable() = default; + +private: + Noncopyable(const Noncopyable &); + const Noncopyable &operator=(const Noncopyable &); +}; +#endif // NONCOPYABLE_H_ diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/option.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/option.h new file mode 100644 index 0000000000000000000000000000000000000000..ad67aec1a63c81fac01d9b89c114cbe1b493870e --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/option.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_OPTION_H_ +#define HIPERF_OPTION_H_ + +#include +#include +#include +#include +#include + +#include "debug_logger.h" +#include "utilities.h" + +using argsVector = std::vector; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +namespace Option { +struct MainOption { + std::string help; + std::function &)> callBackFunction; +}; + +// called from main +bool RegisterMainOption(const std::string &, const std::string &, + std::function &)>); + +void ClearMainOptions(); + +bool CheckOptionFormat(const std::string &optionName); + +argsVector::iterator FindOption(argsVector &args, const std::string &optionName); + +// some option function +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, bool &value); +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, int &); +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, + float &value); +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, + std::string &value); +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, + std::vector &value); +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, + std::vector &value); + +bool GetOptionTrackedCommand(argsVector &args, std::vector &trackedCommand); + +/* +Return false to indicate that the parameter is illegal +The program should exit with an error. + +Return true, indicating that the parameter is legal (but the user does not necessarily enter the +parameter) +*/ +template +bool GetOptionValue(argsVector &args, std::string optionName, T &value) +{ + // we need keep the ref if we got failed + // so we use a local value first. + T localValues = {}; + if constexpr (std::is_same>>::value) { + // try unitl failed. + while (true) { + if (!GetOptionValue(args, optionName, localValues.emplace_back())) { + printf("incorrect option %s\n", optionName.c_str()); + return false; // format error + } else if (localValues.back().size() == 0) { + // if the last one we request is empty , we remove it + localValues.pop_back(); + // nothing more needed + // we don't allow empty value + break; + } + } + if (localValues.size() > 0) { + value = localValues; + } + return true; + } else { + if (!CheckOptionFormat(optionName)) { + if (optionName.empty()) { + printf("unable to use empty option name!\n"); + } else { + printf("format error. must use '-' at the begin of option '%s'!\n", + optionName.c_str()); + } + return false; // something wrong + } + auto it = FindOption(args, optionName); + if (it == args.end()) { + HLOGV("not found option, return default value"); + return true; // not found but also not error + } else { + it = args.erase(it); + // some special case + if constexpr (std::is_same::value) { + // for bool we don't need get value. + // this always return true + GetValueFromString(optionName, optionName, value); + return true; + } else if (it == args.end()) { + // no value means failed + printf("option %s value missed\n", optionName.c_str()); + return false; + } else if (GetValueFromString(*it, optionName, localValues)) { + // got some value + value = localValues; + args.erase(it); + return true; + } else { + // have value but convert failed. + printf("incorrect option value '%s'. View the usage with the --help option.\n", + (*it).c_str()); + return false; + } + } + } +} + +const MainOption *FindMainOption(std::string); + +const std::map> &GetMainOptions(); +} // namespace Option +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_OPTION_H_ diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_event_record.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_event_record.h new file mode 100755 index 0000000000000000000000000000000000000000..8663ce9cc1942d16c528ec71274b17e9cd713941 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_event_record.h @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_PERF_EVENT_RECORD_H +#define HIPERF_PERF_EVENT_RECORD_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug_logger.h" +#include "mem_map_item.h" +#include "perf_record_format.h" +#include "utilities.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +static constexpr uint32_t RECORD_SIZE_LIMIT = 65535; + +enum perf_event_hiperf_ext_type { + PERF_RECORD_HIPERF_CALLSTACK = UINT32_MAX / 2, +}; + +struct CallFrame { + uint64_t ip_ = 0; + uint64_t sp_ = 0; + + uint64_t vaddrInFile_ = 0; // in symbol file vaddr + int32_t symbolIndex_ = -1; // symbols index , should update after sort + std::string_view symbolName_; + std::string_view filePath_; // lib path , elf path + + CallFrame(uint64_t ip, uint64_t sp = 0) : ip_(ip), sp_(sp) {} + + // this is for ut test + CallFrame(uint64_t ip, uint64_t vaddrInFile, const char *name, const char *filePath) + : ip_(ip), vaddrInFile_(vaddrInFile), symbolName_(name), filePath_(filePath) + { + } + bool operator==(const CallFrame &b) const + { + return (ip_ == b.ip_) && (sp_ == b.sp_); + } + bool operator!=(const CallFrame &b) const + { + return (ip_ != b.ip_) || (sp_ != b.sp_); + } + std::string ToString() const + { + return StringPrintf("ip: 0x%016llx sp: 0x%016llx", ip_, sp_); + } + std::string ToSymbolString() const + { + std::string output; + if (vaddrInFile_ != 0) { + output = StringPrintf("va: 0x%016llx(%llx) ", vaddrInFile_, ip_); + } else { + output = StringPrintf("ip: 0x%016llx ", ip_); + } + output.append(": "); + output.append(symbolName_); + + output.append("@"); + output.append(filePath_); + if (symbolIndex_ != -1) { + output.append(":"); + output.append(std::to_string(symbolIndex_)); + } + return output; + } +}; + +struct AttrWithId { + perf_event_attr attr; + std::vector ids; + std::string name; // will be empty in GetAttrSection +}; + +class PerfEventRecord { +public: + PerfEventRecord(const PerfEventRecord &) = delete; + PerfEventRecord &operator=(const PerfEventRecord &) = delete; + + struct perf_event_header header; + const std::string name_ {}; + + PerfEventRecord(perf_event_type type, bool in_kernel, const std::string &name); + PerfEventRecord(perf_event_hiperf_ext_type type, const std::string &name); + + PerfEventRecord(uint8_t *p, const std::string &name); + + virtual ~PerfEventRecord() {} + + virtual size_t GetSize() const + { + return header.size; + }; + size_t GetHeaderSize() const + { + return sizeof(header); + }; + void GetHeaderBinary(std::vector &buf) const; + + uint32_t GetType() const + { + return header.type; + }; + uint16_t GetMisc() const + { + return header.misc; + }; + bool inKernel() + { + return header.misc & PERF_RECORD_MISC_KERNEL; + } + bool inUser() + { + return header.misc & PERF_RECORD_MISC_USER; + } + const std::string &GetName() const + { + return name_; + }; + + // to support --exclude-hiperf, return sample_id.pid to filter record, + virtual pid_t GetPid() const + { + return 0; + }; + + virtual bool GetBinary(std::vector &buf) const = 0; + void Dump(int indent = 0) const; + virtual void DumpData(int indent) const = 0; + virtual void DumpLog(const std::string &prefix) const; +}; + +// define convert from linux/perf_event.h +// description from https://man7.org/linux/man-pages/man2/perf_event_open.2.html + +constexpr __u64 SAMPLE_ID = PERF_SAMPLE_TID | PERF_SAMPLE_TIME | PERF_SAMPLE_ID | + PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_IDENTIFIER; + +constexpr __u64 SAMPLE_TYPE = PERF_SAMPLE_IP | SAMPLE_ID | PERF_SAMPLE_PERIOD; + +constexpr __u32 MIN_SAMPLE_STACK_SIZE = 8; +constexpr __u32 MAX_SAMPLE_STACK_SIZE = 65528; + +class PerfRecordMmap : public PerfEventRecord { +public: + PerfRecordMmapData data_; + + explicit PerfRecordMmap(uint8_t *p); + + PerfRecordMmap(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff, + const std::string &filename); + + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; + void DumpLog(const std::string &prefix) const override; +}; + +class PerfRecordMmap2 : public PerfEventRecord { +public: + PerfRecordMmap2Data data_; + + explicit PerfRecordMmap2(uint8_t *p); + + PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff, u32 maj, u32 min, + u64 ino, u32 prot, u32 flags, const std::string &filename); + + PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, const MemMapItem &item); + + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; + void DumpLog(const std::string &prefix) const override; +}; + +class PerfRecordLost : public PerfEventRecord { +public: + PerfRecordLostData data_; + + explicit PerfRecordLost(uint8_t *p); + + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; + + // only for UT + PerfRecordLost(bool inKernel, u64 id, u64 lost) + : PerfEventRecord(PERF_RECORD_LOST, inKernel, "lost") + { + data_.id = id; + data_.lost = lost; + header.size = sizeof(header) + sizeof(data_); + } +}; + +class PerfRecordComm : public PerfEventRecord { +public: + PerfRecordCommData data_; + + explicit PerfRecordComm(uint8_t *p); + + PerfRecordComm(bool inKernel, u32 pid, u32 tid, const std::string &comm); + + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; + void DumpLog(const std::string &prefix) const override; +}; + +class PerfRecordSample : public PerfEventRecord { +public: + PerfRecordSampleData data_ = {}; + uint64_t sampleType_ = SAMPLE_TYPE; + + // extend + // hold the new ips memory (after unwind) + // used for data_.ips replace (ReplaceWithCallStack) + std::vector ips_; + std::vector callFrames_; + + // referenced input(p) in PerfRecordSample, require caller keep input(p) together + PerfRecordSample(uint8_t *p, const perf_event_attr &attr); + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent = 0) const override; + void DumpLog(const std::string &prefix) const override; + + // originalSize is use for expand callstack + void ReplaceWithCallStack(size_t originalSize = 0); + pid_t GetPid() const override; + + // only for UT + PerfRecordSample(bool inKernel, u32 pid, u32 tid, u64 period = 0, u64 time = 0, u64 id = 0) + : PerfEventRecord(PERF_RECORD_SAMPLE, inKernel, "sample") + { + data_.pid = pid; + data_.tid = tid; + data_.period = period; + data_.time = time; + data_.id = 0; + header.size = sizeof(header) + sizeof(data_); + }; +}; + +class PerfRecordExit : public PerfEventRecord { +public: + PerfRecordExitData data_; + + explicit PerfRecordExit(uint8_t *p); + + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +class PerfRecordThrottle : public PerfEventRecord { +public: + PerfRecordThrottleData data_; + + PerfRecordThrottle(uint8_t *p); + + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +class PerfRecordUnthrottle : public PerfEventRecord { +public: + PerfRecordThrottleData data_; + + explicit PerfRecordUnthrottle(uint8_t *p); + + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +class PerfRecordFork : public PerfEventRecord { +public: + PerfRecordForkData data_; + + explicit PerfRecordFork(uint8_t *p); + + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +/* + This record indicates a read event. +*/ +class PerfRecordRead : public PerfEventRecord { +public: + PerfRecordReadData data_; + + explicit PerfRecordRead(uint8_t *p); + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +/* + This record reports that new data is available in the + separate AUX buffer region. + + aux_offset + offset in the AUX mmap region where the new + data begins. + aux_size + size of the data made available. + flags describes the AUX update. + PERF_AUX_FLAG_TRUNCATED + if set, then the data returned was + truncated to fit the available buffer + size. + + PERF_AUX_FLAG_OVERWRITE + if set, then the data returned has + overwritten previous data. +*/ +class PerfRecordAux : public PerfEventRecord { +public: + PerfRecordAuxData data_; + + explicit PerfRecordAux(uint8_t *p); + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +/* + This record indicates which process has initiated an + instruction trace event, allowing tools to properly + correlate the instruction addresses in the AUX buffer + with the proper executable. + + pid process ID of the thread starting an + instruction trace. + tid thread ID of the thread starting an instruction + trace. +*/ +class PerfRecordItraceStart : public PerfEventRecord { +public: + PerfRecordItraceStartData data_; + + explicit PerfRecordItraceStart(uint8_t *p); + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +/* + When using hardware sampling (such as Intel PEBS) this + record indicates some number of samples that may have + been lost. +*/ +class PerfRecordLostSamples : public PerfEventRecord { +public: + PerfRecordLostSamplesData data_; + + explicit PerfRecordLostSamples(uint8_t *p); + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +/* + This record indicates a context switch has happened. + The PERF_RECORD_MISC_SWITCH_OUT bit in the misc field + indicates whether it was a context switch into or away + from the current process. +*/ +class PerfRecordSwitch : public PerfEventRecord { +public: + PerfRecordSwitchData data_; + explicit PerfRecordSwitch(uint8_t *p); + bool GetBinary(std::vector &buf) const override; + void DumpData([[maybe_unused]] int indent) const override {}; +}; + +/* + As with PERF_RECORD_SWITCH this record indicates a + context switch has happened, but it only occurs when + sampling in CPU-wide mode and provides additional + information on the process being switched to/from. + The PERF_RECORD_MISC_SWITCH_OUT bit in the misc field + indicates whether it was a context switch into or away + from the current process. + + next_prev_pid + The process ID of the previous (if switching + in) or next (if switching out) process on the + CPU. + + next_prev_tid + The thread ID of the previous (if switching in) + or next (if switching out) thread on the CPU. +*/ +class PerfRecordSwitchCpuWide : public PerfEventRecord { +public: + PerfRecordSwitchCpuWideData data_; + explicit PerfRecordSwitchCpuWide(uint8_t *p); + bool GetBinary(std::vector &buf) const override; + void DumpData(int indent) const override; +}; + +std::unique_ptr GetPerfEventRecord(const int type, uint8_t *data, + const perf_event_attr &attr); + +template +void PushToBinary(bool condition, uint8_t *&p, const T &v); + +template +void PushToBinary2(bool condition, uint8_t *&p, const T1 &v1, const T2 &v2); + +template +void PopFromBinary(bool condition, uint8_t *&p, T &v); + +template +void PopFromBinary2(bool condition, uint8_t *&p, T1 &v1, T2 &v2); +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_PERF_EVENT_RECORD_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_events.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_events.h new file mode 100755 index 0000000000000000000000000000000000000000..b39d9e1854a634ff3e66f08587aae7a610724408 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_events.h @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_PERF_EVENTS_H +#define HIPERF_PERF_EVENTS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !is_mingw +#include +#endif + +#include +#include + +#include "debug_logger.h" +#include "perf_event_record.h" +#include "ring_buffer.h" +#include "tracked_command.h" +#include "utilities.h" +#include "virtual_runtime.h" + +// this for some performance debug +#define HIDEBUG_SKIP_CALLBACK 0 + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +using ConfigTable = std::map<__u64, const std::string>; +using SharedConfigTable = std::unique_ptr; + +static const std::string PERF_EVENT_PARANOID = "/proc/sys/kernel/perf_event_paranoid"; +static const std::string PERF_DISABLE_PARAM = "security.perf_harden"; + +// define convert from linux/perf_event.h +// description from https://man7.org/linux/man-pages/man2/perf_event_open.2.html + +static const ConfigTable PERF_HW_CONFIGS = { + {PERF_COUNT_HW_CPU_CYCLES, "hw-cpu-cycles"}, + {PERF_COUNT_HW_INSTRUCTIONS, "hw-instructions"}, + {PERF_COUNT_HW_CACHE_REFERENCES, "hw-cache-references"}, + {PERF_COUNT_HW_CACHE_MISSES, "hw-cache-misses"}, + {PERF_COUNT_HW_BRANCH_INSTRUCTIONS, "hw-branch-instructions"}, + {PERF_COUNT_HW_BRANCH_MISSES, "hw-branch-misses"}, + {PERF_COUNT_HW_BUS_CYCLES, "hw-bus-cycles"}, + {PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, "hw-stalled-cycles-backend"}, + {PERF_COUNT_HW_STALLED_CYCLES_BACKEND, "hw-stalled-cycles-frontend"}, + {PERF_COUNT_HW_REF_CPU_CYCLES, "hw-ref-cpu-cycles"}, +}; +static const ConfigTable PERF_HW_CACHE_CONFIGS = { + {PERF_COUNT_HW_CACHE_L1D, "hw-cache-l1d"}, {PERF_COUNT_HW_CACHE_L1I, "hw-cache-l1i"}, + {PERF_COUNT_HW_CACHE_LL, "hw-cache-ll"}, {PERF_COUNT_HW_CACHE_DTLB, "hw-cache-dtlb"}, + {PERF_COUNT_HW_CACHE_ITLB, "hw-cache-itlb"}, {PERF_COUNT_HW_CACHE_BPU, "hw-cache-bpu"}, + {PERF_COUNT_HW_CACHE_NODE, "hw-cache-node"}, +}; +static const ConfigTable PERF_HW_CACHE_OP_CONFIGS = { + {PERF_COUNT_HW_CACHE_OP_READ, "hw-cache-op-read"}, + {PERF_COUNT_HW_CACHE_OP_WRITE, "hw-cache-op-write"}, + {PERF_COUNT_HW_CACHE_OP_PREFETCH, "hw-cache-op-prefetch"}, +}; +static const ConfigTable PERF_HW_CACHE_OP_RESULT_CONFIGS = { + {PERF_COUNT_HW_CACHE_RESULT_ACCESS, "hw-cache-result-access"}, + {PERF_COUNT_HW_CACHE_RESULT_MISS, "hw-cache-result-miss"}, +}; +static const ConfigTable PERF_SW_CONFIGS = { + {PERF_COUNT_SW_CPU_CLOCK, "sw-cpu-clock"}, + {PERF_COUNT_SW_TASK_CLOCK, "sw-task-clock"}, + {PERF_COUNT_SW_PAGE_FAULTS, "sw-page-faults"}, + {PERF_COUNT_SW_CONTEXT_SWITCHES, "sw-context-switches"}, + {PERF_COUNT_SW_CPU_MIGRATIONS, "sw-cpu-migrations"}, + {PERF_COUNT_SW_PAGE_FAULTS_MIN, "sw-page-faults-min"}, + {PERF_COUNT_SW_PAGE_FAULTS_MAJ, "sw-page-faults-maj"}, + {PERF_COUNT_SW_ALIGNMENT_FAULTS, "sw-alignment-faults"}, + {PERF_COUNT_SW_EMULATION_FAULTS, "sw-emulation-faults"}, + {PERF_COUNT_SW_DUMMY, "sw-dummy"}, + {PERF_COUNT_SW_BPF_OUTPUT, "sw-bpf-output"}, +}; +static const ConfigTable PERF_RAW_CONFIGS = { + {0x0, "raw-sw-incr"}, + {0x1, "raw-l1-icache-refill"}, + {0x2, "raw-l1-itlb-refill"}, + {0x3, "raw-l1-dcache-refill"}, + {0x4, "raw-l1-dcache"}, + {0x5, "raw-l1-dtlb-refill"}, + {0x6, "raw-load-retired"}, + {0x7, "raw-store-retired"}, + {0x8, "raw-instruction-retired"}, + {0x9, "raw-exception-taken"}, + {0xa, "raw-exception-return"}, + {0xb, "raw-cid-write-retired"}, + {0xc, "raw-pc-write-retired"}, + {0xd, "raw-br-immed-retired"}, + {0xe, "raw-br-return-retired"}, + {0xf, "raw-unaligned-ldst-retired"}, + {0x10, "raw-br-mis-pred"}, + {0x11, "raw-cpu-cycles"}, + {0x12, "raw-br-pred"}, + {0x13, "raw-mem-access"}, + {0x14, "raw-l1-icache"}, + {0x15, "raw-l1-dcache-wb"}, + {0x16, "raw-l2-dcache"}, + {0x17, "raw-l2-dcache-refill"}, + {0x18, "raw-l2-dcache-wb"}, + {0x19, "raw-bus-access"}, + {0x1a, "raw-memory-error"}, + {0x1b, "raw-inst-spec"}, + {0x1c, "raw-ttbr-write-retired"}, + {0x1d, "raw-bus-cycles"}, + {0x1f, "raw-l1-dcache-allocate"}, + {0x20, "raw-l2-dcache-allocate"}, + {0x21, "raw-br-retired"}, + {0x22, "raw-br-mis-pred-retired"}, + {0x23, "raw-stall-frontend"}, + {0x24, "raw-stall-backend"}, + {0x25, "raw-l1-dtlb"}, + {0x26, "raw-l1-itlb"}, + {0x27, "raw-l2-icache"}, + {0x28, "raw-l2-icache-refill"}, + {0x29, "raw-l3-dcache-allocate"}, + {0x2a, "raw-l3-dcache-refill"}, + {0x2b, "raw-l3-dcache"}, + {0x2c, "raw-l3-dcache-wb"}, + {0x2d, "raw-l2-dtlb-refill"}, + {0x2e, "raw-l2-itlb-refill"}, + {0x2f, "raw-l2-dtlb"}, + {0x30, "raw-l2-itlb"}, +}; +static ConfigTable PERF_TRACEPOINT_CONFIGS = { + +}; + +static const std::map PERF_TYPES = { + {PERF_TYPE_HARDWARE, "hardware"}, + {PERF_TYPE_SOFTWARE, "software"}, + {PERF_TYPE_TRACEPOINT, "tracepoint"}, + {PERF_TYPE_HW_CACHE, "hardware cache"}, + {PERF_TYPE_RAW, "raw"}, +}; + +static std::map TYPE_CONFIGS = { + {PERF_TYPE_HARDWARE, (PERF_HW_CONFIGS)}, {PERF_TYPE_SOFTWARE, (PERF_SW_CONFIGS)}, + {PERF_TYPE_HW_CACHE, (PERF_HW_CACHE_CONFIGS)}, {PERF_TYPE_RAW, (PERF_RAW_CONFIGS)}, + {PERF_TYPE_TRACEPOINT, (PERF_TRACEPOINT_CONFIGS)}, +}; + +// default config +static const std::vector<__u64> DEFAULT_HW_CONFIGS = { + PERF_COUNT_HW_CPU_CYCLES, +#if defined(__aarch64__) + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, + PERF_COUNT_HW_STALLED_CYCLES_BACKEND, +#endif + PERF_COUNT_HW_INSTRUCTIONS, + PERF_COUNT_HW_BRANCH_INSTRUCTIONS, + PERF_COUNT_HW_BRANCH_MISSES, +}; +static const std::vector<__u64> DEFAULT_SW_CONFIGS = { + PERF_COUNT_SW_TASK_CLOCK, + PERF_COUNT_SW_CONTEXT_SWITCHES, + PERF_COUNT_SW_PAGE_FAULTS, +}; +static const std::map> DEFAULT_TYPE_CONFIGS = { + {PERF_TYPE_HARDWARE, DEFAULT_HW_CONFIGS}, + {PERF_TYPE_SOFTWARE, DEFAULT_SW_CONFIGS}, +}; + +struct read_format_event { + __u64 value; /* The value of the event */ + __u64 id; /* if PERF_FORMAT_ID */ +}; + +struct read_format_group { + __u64 nr; /* The number of events */ + __u64 time_enabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */ + __u64 time_running; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */ + read_format_event events[1]; +}; + +struct read_format_no_group { + __u64 value; /* The value of the event */ + __u64 time_enabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */ + __u64 time_running; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */ + __u64 id; /* if PERF_FORMAT_ID */ +}; + +/* +2 allow only user-space measurements (default since + Linux 4.6). +1 allow both kernel and user measurements (default + before Linux 4.6). +0 allow access to CPU-specific data but not raw + tracepoint samples. +-1 no restrictions. +*/ +enum PerfEventParanoid { + NOLIMIT = -1, + KERNEL_USER_CPU = 0, + KERNEL_USER = 1, + USER = 2, + UNKNOW = 99, +}; + +class PerfEvents { +public: + static constexpr uint64_t DEFAULT_SAMPLE_FREQUNCY = 4000; + static constexpr uint64_t DEFAULT_SAMPLE_PERIOD = 1; + static constexpr uint64_t DEFAULT_TIMEOUT = 10 * 1000; + static constexpr size_t MIN_BUFFER_SIZE = 64 * 1024 * 1024; +#ifdef LITTLE_MEMORY + static constexpr size_t MAX_BUFFER_SIZE = 128 * 1024 * 1024; +#else + static constexpr size_t MAX_BUFFER_SIZE = 256 * 1024 * 1024; +#endif + static constexpr size_t BUFFER_LOW_LEVEL = 10 * 1024 * 1024; + static constexpr size_t BUFFER_CRITICAL_LEVEL = 5 * 1024 * 1024; + + PerfEvents(); + ~PerfEvents(); + + bool AddEvents(const std::vector &eventStrings, bool group = false); + bool PrepareTracking(void); + bool StartTracking(bool immediately = true); + bool StopTracking(void); + bool PauseTracking(void); + bool ResumeTracking(void); + /* call sequence + 1. setXXX + 2. AddEvents() + 3. PrepareTracking + 4. StartTracking (blocking...) + */ + bool EnableTracking(); + bool IsTrackRunning(); + + void SetSystemTarget(bool); + void SetCpu(const std::vector cpus); // cpu id must be [0~N] + void SetPid(const std::vector pids); // tis is same as pid in kernel + void SetTimeOut(float timeOut); + void SetTimeReport(int); + void SetVerboseReport(bool); + bool AddOffCpuEvent(); + + inline void SetTrackedCommand(const std::vector &trackedCommand) + { + if (!trackedCommand.empty()) { + trackedCommand_ = TrackedCommand::CreateInstance(trackedCommand); + } + } + + void SetSampleFrequency(unsigned int frequency); + void SetSamplePeriod(unsigned int period); + + enum SampleStackType { + NONE, + FP, + DWARF, + }; + void SetSampleStackType(SampleStackType type); + void SetDwarfSampleStackSize(uint32_t stackSize); + void SetMmapPages(size_t mmapPages); + std::vector GetAttrWithId() const; + + void SetInherit(bool inherit) + { + inherit_ = inherit; + }; + void SetClockId(int clockId) + { + clockId_ = clockId; + }; + bool SetBranchSampleType(uint64_t value); + bool AddDefaultEvent(perf_type_id type); + + std::map<__u64, std::string> GetSupportEvents(perf_type_id type); + + struct CountEvent { + bool userOnly = false; + bool kernelOnly = false; + __u64 eventCount = 0; + __u64 time_enabled = 0; + __u64 time_running = 0; + __u64 id = 0; + double used_cpus = 0; + }; + using StatCallBack = + std::function> &)>; + using RecordCallBack = std::function)>; + + void SetStatCallBack(StatCallBack reportCallBack); + void SetRecordCallBack(RecordCallBack recordCallBack); + void GetLostSamples(size_t &lostSamples, size_t &lostNonSamples) + { + lostSamples = lostSamples_; + lostNonSamples = lostNonSamples_; + } + + // review: remove this function. + static const std::string GetStaticConfigName(perf_type_id type_id, __u64 config_id) + { + auto typeConfigs = TYPE_CONFIGS.find(type_id); + if (typeConfigs != TYPE_CONFIGS.end()) { + auto configs = typeConfigs->second; + auto config = configs.find(config_id); + if (config != configs.end()) { + return config->second; + } else { + HLOGW("config not found for %u:%lld in %zu:%zu", type_id, config_id, + TYPE_CONFIGS.size(), configs.size()); + // dump all config size + for (auto types : TYPE_CONFIGS) { + HLOGV("type id %d %zu", types.first, types.second.size()); + } + } + } else { + HLOGW("type not found for %d in %zu", type_id, TYPE_CONFIGS.size()); + } + return ""; + }; + + const std::string GetTraceConfigName(__u64 config_id) + { + auto config = traceConfigTable.find(config_id); + if (config != traceConfigTable.end()) { + return config->second; + } else { + HLOGW("config not found for %lld in traceConfigTable.", config_id); + } + return ""; + }; + + static const std::string GetTypeName(perf_type_id type_id); + bool ParseEventName(const std::string &nameStr, std::string &name, bool &excludeUser, + bool &excludeKernel, bool &isTracePoint); + + // mmap one fd for each cpu + struct MmapFd { + int fd; + perf_event_mmap_page *mmapPage = nullptr; + uint8_t *buf = nullptr; + size_t bufSize = 0; + // for read and sort + size_t dataSize = 0; + perf_event_header header; + uint64_t timestamp = 0; + const perf_event_attr *attr = nullptr; + size_t posCallChain = 0; + }; + +private: + size_t recordEventCount_ = 0; // only for debug time +#ifdef HIPERF_DEBUG_TIME + std::chrono::microseconds recordCallBackTime_ = std::chrono::microseconds::zero(); + std::chrono::microseconds recordWaitDataTime_ = std::chrono::microseconds::zero(); + std::chrono::microseconds recordSleepTime_ = std::chrono::microseconds::zero(); + std::chrono::microseconds recordKernelReadTime_ = std::chrono::microseconds::zero(); +#endif + size_t lostSamples_ = 0; + size_t lostNonSamples_ = 0; + + std::unique_ptr recordBuf_ {nullptr}; + std::mutex mtxRrecordBuf_; + std::condition_variable cvRecordBuf_; + std::thread readRecordBufThread_; + std::atomic_bool readRecordThreadRunning_ = false; + bool startedTracking_ = false; + bool isLowPriorityThread_ = false; + void RecordLoop(); + void StatLoop(); + bool IsRecordInMmap(); + void ReadRecordsFromMmaps(); + bool GetRecordFromMmap(MmapFd &mmap); + void GetRecordFieldFromMmap(MmapFd &mmap, void *dest, size_t pos, size_t size); + void MoveRecordToBuf(MmapFd &mmap); + size_t GetCallChainPosInSampleRecord(const perf_event_attr &attr); + size_t GetStackSizePosInSampleRecord(MmapFd &mmap); + bool CutStackAndMove(MmapFd &mmap); + void ReadRecordFromBuf(); + size_t CalcBufferSize(); + bool PrepareRecordThread(); + void WaitRecordThread(); + bool HaveTargetsExit(const std::chrono::steady_clock::time_point &startTime); + void ExitReadRecordBufThread(); + + enum EventSpaceType { + UNKNOW = 0, + USER = 1, + KERNEL = 2, + USER_KERNEL = 3, + }; + uint8_t eventSpaceType_ = EventSpaceType::UNKNOW; + + PerfEventParanoid requestPermission_ = PerfEventParanoid::USER; + bool CheckPermissions(PerfEventParanoid request = KERNEL_USER_CPU); + bool CheckOhosPermissions(); + + static PerfEventParanoid perfEventParanoid_; + + bool inherit_ = false; + std::vector pids_; + std::vector cpus_; + std::vector groups_; + std::chrono::milliseconds timeOut_; // milliseconds + std::chrono::milliseconds timeReport_; // means same as timeOut + bool verboseReport_ = false; + bool prepared_ = false; + ConfigTable traceConfigTable; + + unsigned int samplePeriod_ = 0; + unsigned int sampleFreq_ = 0; + + struct FdItem { + OHOS::UniqueFd fd; + int cpu; + pid_t pid; + __u64 eventCount; + mutable uint64_t perf_id_ = 0; + uint64_t GetPrefId() const + { + if (perf_id_ == 0) { + read_format_no_group readNoGroupValue; + if (read(fd, &readNoGroupValue, sizeof(readNoGroupValue)) > 0) { + perf_id_ = readNoGroupValue.id; + } else { + HLOGW("read failed with fd %d", fd.Get()); + } + } + return perf_id_; + } + }; + struct EventItem { + std::string typeName; + std::string configName; + perf_event_attr attr = {}; + std::vector fdItems; + }; + struct EventGroupItem { + std::vector eventItems; + }; + std::vector eventGroupItem_; + + std::map cpuMmap_; + std::vector MmapRecordHeap_; + +#if !is_mingw + std::vector pollFds_; +#endif + const int pollTimeOut_ = 100; // ms + size_t pageSize_ = 4096; + bool systemTarget_ = false; + bool excludeHiperf_ = false; + pid_t selfPid_ = -1; + unsigned int mmapPages_ = 0; + int clockId_ = -1; + uint64_t branchSampleType_ = 0; + + SampleStackType sampleStackType_ = SampleStackType::NONE; + uint32_t dwarfSampleStackSize_ = MAX_SAMPLE_STACK_SIZE; + + // read records from the ring buffer singleton + void ReadRecordFromBuffer(); + void ReadRecordFromBufferThread(); + + std::unique_ptr trackedCommand_ = {}; + + StatCallBack reportCallBack_; + RecordCallBack recordCallBack_; + + void LoadTracepointEventTypesFromSystem(); + bool PerfEventsEnable(bool); + bool AddEvent(perf_type_id type, __u64 config, bool excludeUser = false, + bool excludeKernel = false, bool followGroup = false); + bool AddEvent(const std::string &eventString, bool followGroup = false); + bool IsEventSupport(perf_type_id type, __u64 config); + bool IsEventAttrSupport(perf_event_attr &attr); + + std::chrono::time_point trackingStartTime_; + std::chrono::time_point trackingEndTime_; + std::chrono::time_point readingStartTime_; + + std::map> countEvents_; + + void PutAllCpus(); + bool PrepareFdEvents(); + bool CreateFdEvents(); + bool StatReport(const __u64 &durationInSec); + bool CreateMmap(const FdItem &item, const perf_event_attr &attr); + + const perf_event_attr *GetDefaultAttr() + { + HLOG_ASSERT(eventGroupItem_.size() > 0); + HLOG_ASSERT(eventGroupItem_[0].eventItems.size() > 0); + return &(eventGroupItem_.at(0).eventItems.at(0).attr); + }; + + OHOS::UniqueFd Open(perf_event_attr &attr, pid_t pid = 0, int cpu = -1, int group_fd = -1, + unsigned long flags = 0); + std::unique_ptr CreateDefaultAttr(perf_type_id type, __u64 config); +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_PERF_EVENTS_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_file_format.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_file_format.h new file mode 100755 index 0000000000000000000000000000000000000000..84f28f9a451f9721e467f4d7c7d5c6716696079c --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_file_format.h @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_PERF_FILE_FORMAT_H +#define HIPERF_PERF_FILE_FORMAT_H + +#include + +#include "perf_event_record.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +enum class FEATURE { + RESERVED = 0, /* always cleared */ + FIRST_FEATURE = 1, + TRACING_DATA = 1, + BUILD_ID, // build_id_event + + HOSTNAME, // A perf_header_string with the hostname where the data was collected (uname -n) + OSRELEASE, // A perf_header_string with the os release where the data was collected (uname -r) + VERSION, // A perf_header_string with the perf user tool version where the data was collected. + // This is the same as the version of the source tree the perf tool was built from. + ARCH, // A perf_header_string with the CPU architecture (uname -m) + NRCPUS, // A structure defining the number of CPUs. + CPUDESC, // A perf_header_string with description of the CPU. On x86 this is the model name + // in /proc/cpuinfo + CPUID, // A perf_header_string with the exact CPU type. On x86 this is + // vendor,family,model,stepping. For example: GenuineIntel,6,69,1 + TOTAL_MEM, // An uint64_t with the total memory in kilobytes. + CMDLINE, // A perf_header_string_list with the perf arg-vector used to collect the data. + EVENT_DESC, // Another description of the perf_event_attrs + CPU_TOPOLOGY, // + NUMA_TOPOLOGY, // A list of NUMA node descriptions + BRANCH_STACK, // Not implemented in perf. + PMU_MAPPINGS, // A list of PMU structures, defining the different PMUs supported by perf. + GROUP_DESC, // Description of counter groups ({...} in perf syntax) + AUXTRACE, // Define additional auxtrace areas in the perf.data. auxtrace is used to store + // undecoded hardware tracing information, such as Intel Processor Trace data. + STAT, + CACHE, + SAMPLE_TIME, + MEM_TOPOLOGY, + LAST_FEATURE, + + HIPERF_FIRST_FEATURE = 192, + HIPERF_FILES_SYMBOL = HIPERF_FIRST_FEATURE, + HIPERF_WORKLOAD_CMD, + HIPERF_RECORD_TIME, + HIPERF_CPU_OFF, + HIPERF_LAST_FEATURE = HIPERF_CPU_OFF, + + FEATURE_MAX_BITS = 256, +}; + +const static std::vector FeatureStrings = { + FEATURE::HOSTNAME, + FEATURE::OSRELEASE, + FEATURE::VERSION, + FEATURE::ARCH, + FEATURE::CPUDESC, + FEATURE::CPUID, + FEATURE::CMDLINE, + + FEATURE::HIPERF_WORKLOAD_CMD, + FEATURE::HIPERF_RECORD_TIME, +}; + +struct perf_file_section { + uint64_t offset; + uint64_t size; +}; + +struct perf_file_attr { + perf_event_attr attr; + perf_file_section ids; +}; + +struct perf_header_string { + uint32_t len; + char string[0]; /* zero terminated */ +}; + +constexpr char PERF_MAGIC[] = "PERFILE2"; +constexpr int BITS_IN_BYTE = 8; +constexpr int NUM_FEATURES_FILE_HEADER = 256; + +struct perf_file_header { + char magic[8] = {'P', 'E', 'R', 'F', 'I', 'L', 'E', '2'}; + uint64_t size = sizeof(perf_file_header); + uint64_t attrSize = sizeof(perf_file_attr); + perf_file_section attrs; + perf_file_section data; + perf_file_section eventTypes; + uint8_t features[NUM_FEATURES_FILE_HEADER / BITS_IN_BYTE] = {0}; +}; + +static const std::vector extFeatureNames = { + "hiperf_files_symbol", + "hiperf_workloader_cmd", + "hiperf_record_time", + "hiperf_cpu_off", +}; +static const std::vector featureNames = { + "unknown_feature", "tracing_data", "build_id", "hostname", "osrelease", + "version", "arch", "nrcpus", "cpudesc", "cpuid", + "total_mem", "cmdline", "event_desc", "cpu_topology", "numa_topology", + "branch_stack", "pmu_mappings", "group_desc", "auxtrace", "stat", + "cache", "sample_time", "mem_topology", "last_feature", +}; + +class PerfFileSection { +public: + struct perf_file_section header; + const FEATURE featureId_; + + virtual bool GetBinary(char *buf, size_t size) = 0; + virtual size_t GetSize() = 0; + virtual ~PerfFileSection() {} + explicit PerfFileSection(const FEATURE featureId) : featureId_(featureId) + { + header.size = 0; + header.offset = 0; + } + static std::string GetFeatureName(FEATURE featureId); + +protected: + const char *rBuffer_ = nullptr; + char *wBuffer_ = nullptr; + size_t maxSize_ = 0; + size_t offset_ = 0; + + // for read + void Init(const char *buffer, size_t maxSize); + // for write + void Init(char *buffer, size_t maxSize); + bool Write(uint32_t u32); + bool Write(uint64_t u64); + bool Write(const std::string &str); + + bool Write(const char *buf, size_t size); + bool Write(const char *buf, size_t size, size_t max); + + bool Read(uint32_t &value); + bool Read(uint64_t &value); + bool Read(std::string &value); + bool Read(char *buf, size_t size); + void Skip(size_t size); + + uint32_t SizeOf(std::string &string); +}; + +class PerfFileSectionString : public PerfFileSection { + std::string stdString_; + +public: + // convert buff to PerfFileSectionString, used to read file + // if the data in buf is incorrect, ...... + PerfFileSectionString(FEATURE id, const char *buf, size_t size); + PerfFileSectionString(FEATURE id, const std::string &charString); + + bool GetBinary(char *buf, size_t size); + size_t GetSize(); + const std::string toString() const; +}; + +// ref struct +struct SymbolStruct { + uint64_t vaddr_ = 0; + uint32_t len_ = 0; + std::string symbolName_ = EMPTY_STRING; + SymbolStruct() {} + SymbolStruct(uint64_t vaddr, uint32_t len, const std::string &symbolName) + : vaddr_(vaddr), len_(len), symbolName_(symbolName) + { + } +}; + +struct SymbolFileStruct { + std::string filePath_ = EMPTY_STRING; + uint32_t symbolType_; + uint64_t textExecVaddr_; + uint64_t textExecVaddrFileOffset_; + std::string buildId_; + std::vector symbolStructs_; +}; + +class PerfFileSectionSymbolsFiles : public PerfFileSection { +public: + std::vector symbolFileStructs_; + + size_t GetSize(); + PerfFileSectionSymbolsFiles(FEATURE id, const std::vector &symbolFileStructs) + : PerfFileSection(id), symbolFileStructs_(symbolFileStructs) + { + } + // if the data in buf is incorrect, ...... + PerfFileSectionSymbolsFiles(FEATURE id, const char *buf, size_t size); + + bool GetBinary(char *buf, size_t size); + +private: + // issue from fuzz test + const size_t MAX_SYMBOLS_FILE_NUMBER = 300; + const size_t MAX_SYMBOLS_NUMBER = 3000; +}; + +// NRCPUS: A structure defining the number of CPUs. +class PerfFileSectionNrCpus : public PerfFileSection { + uint32_t nrCpusAvailable_; /* CPUs not yet onlined */ + uint32_t nrCpusOnline_; + +public: + PerfFileSectionNrCpus(FEATURE id, const char *buf, size_t size); + PerfFileSectionNrCpus(FEATURE id, uint32_t nrCpusAvailable, uint32_t nrCpusOnline); + + bool GetBinary(char *buf, size_t size); + size_t GetSize(); + void GetValue(uint32_t &nrCpusAvailable, uint32_t &nrCpusOnline) const; +}; + +class PerfFileSectionU64 : public PerfFileSection { + uint64_t value_; + +public: + PerfFileSectionU64(FEATURE id, const char *buf, size_t size); + PerfFileSectionU64(FEATURE id, uint64_t v); + + bool GetBinary(char *buf, size_t size); + size_t GetSize(); + void GetValue(uint64_t &v) const; +}; + +struct AttrWithId; +class PerfFileSectionEventDesc : public PerfFileSection { +public: + std::vector eventDesces_; + + PerfFileSectionEventDesc(FEATURE id, const char *buf, size_t size); + PerfFileSectionEventDesc(FEATURE id, const std::vector &eventDesces); + + bool GetBinary(char *buf, size_t size); + size_t GetSize(); + void GetValue(std::vector &eventDesces) const; +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_PERF_FILE_FORMAT_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_file_reader.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_file_reader.h new file mode 100755 index 0000000000000000000000000000000000000000..fb68017252c46b17d03030d877ab7138dd1c455a --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_file_reader.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2021-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. + */ + +#ifndef HIPERF_FILE_READER +#define HIPERF_FILE_READER + +#include +#include +#include +#include "perf_event_record.h" +#include "perf_file_format.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +using ProcessRecordCB = const std::function record)>; +// read record from data file, like perf.data. +// format of file follow +// tools/perf/Documentation/perf.data-file-format.txt +class PerfFileReader { +public: + virtual ~PerfFileReader(); + + static std::unique_ptr Instance(const std::string &fileName, size_t begin = 0); + static std::unique_ptr Instance(const uint8_t *buff, size_t size); + + const perf_file_header &GetHeader() const; + + std::vector GetAttrSection() const; + + // read data section, construct record, call callback for each record + bool ReadDataSection(ProcessRecordCB &callback); + + bool ReadFeatureSection(); + const std::vector &GetFeatures() const; + const std::vector> &GetFeatureSections() const; + const PerfFileSection *GetFeatureSection(FEATURE feature) const; + explicit PerfFileReader(const std::string &fileName, FILE *fp, size_t begin = 0); + explicit PerfFileReader(const uint8_t *buff, size_t size); + + const std::string GetFeatureString(const FEATURE feature) const; + + bool IsFeatrureStringSection(const FEATURE featureId) const + { + return find(FeatureStrings.begin(), FeatureStrings.end(), featureId) != + FeatureStrings.end(); + } + + // fuzz user this +protected: + virtual bool Read(void *buf, size_t len); + virtual bool Read(char *buf, uint64_t offset, size_t len); + FILE *fp_ = nullptr; + bool ReadFileHeader(); + bool ReadAttrSection(); + +private: + bool ReadRecord(ProcessRecordCB &callback); + bool IsValidDataFile(); + bool IsGzipFile(); + + // file header must be read first + + bool ReadIdsForAttr(const perf_file_attr &attr, std::vector *ids); + + const perf_event_attr *GetDefaultAttr(); + + const std::string fileName_; + uint64_t dataSectionSize_; + bool compressData_ = false; + + perf_file_header header_; + std::vector vecAttr_; + std::vector> vecAttrIds_; + + std::unordered_map mapId2Attr_; + uint64_t featureSectionOffset_; + std::vector features_; + std::vector> perfFileSections_; + + size_t fileSize_ = 0; + size_t fileBegin_ = 0; + bool isMemory_ = false; + const uint8_t *buff_ = nullptr; + const size_t buffSize_ = 0; + size_t buffCurrent_ = 0; + + bool SeekFromBegin(size_t offset) + { + if (isMemory_) { + if (offset > buffSize_) { + HLOGE("seek offset(%zu) >= buffer size(%zu)", offset, buffSize_); + return false; + } + buffCurrent_ = offset; + } else { + if (fseek(fp_, fileBegin_ + offset, SEEK_SET) != 0) { + HLOGE("fseek(%zu) failed", offset); + return false; + } + } + + return true; + } + +#ifdef HIPERF_DEBUG_TIME + std::chrono::microseconds readRecordTime_ = std::chrono::microseconds::zero(); + std::chrono::microseconds readCallbackTime_ = std::chrono::microseconds::zero(); +#endif +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_FILE_READER diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_record_format.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_record_format.h new file mode 100755 index 0000000000000000000000000000000000000000..6a1fc90d7bd9e63d38907e5951358160552e32d0 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/perf_record_format.h @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_PERF_RECORD_FORMAT_H +#define HIPERF_PERF_RECORD_FORMAT_H + +#include +#include "utilities.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +// description from https://man7.org/linux/man-pages/man2/perf_event_open.2.html + +#define SAMPLE_ID_ALL 0 + +struct sample_id { + u32 pid; + u32 tid; /* if PERF_SAMPLE_TID set */ + u64 time; /* if PERF_SAMPLE_TIME set */ + u64 id; /* if PERF_SAMPLE_ID set */ + u64 stream_id; /* if PERF_SAMPLE_STREAM_ID set */ + u32 cpu, res; /* if PERF_SAMPLE_CPU set */ + u64 id2; /* if PERF_SAMPLE_IDENTIFIER set */ +}; + +// If PERF_FORMAT_GROUP was not specified +struct read_format { + __u64 value; /* The value of the event */ + __u64 time_enabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */ + __u64 time_running; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */ + __u64 id; /* if PERF_FORMAT_ID */ +}; + +/* + The MMAP events record the PROT_EXEC mappings so that + we can correlate user-space IPs to code. They have + the following structure: + pid is the process ID. + tid is the thread ID. + addr is the address of the allocated memory. + len is the length of the allocated memory. + pgoff is the page offset of the allocated memory. + filename + is a string describing the backing of + the allocated memory. +*/ +struct PerfRecordMmapData { + u32 pid, tid; + u64 addr; + u64 len; + u64 pgoff; + char filename[KILO]; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + This record includes extended information on mmap(2) + calls returning executable mappings. The format is + similar to that of the PERF_RECORD_MMAP record, but + includes extra values that allow uniquely identifying + shared mappings. + + pid is the process ID. + tid is the thread ID. + addr is the address of the allocated memory. + len is the length of the allocated memory. + pgoff is the page offset of the allocated memory. + maj is the major ID of the underlying device. + min is the minor ID of the underlying device. + ino is the inode number. + ino_generation + is the inode generation. + prot is the protection information. + flags is the flags information. + filename + is a string describing the backing of the + allocated memory. +*/ +struct PerfRecordMmap2Data { + u32 pid; + u32 tid; + u64 addr; + u64 len; + u64 pgoff; + u32 maj; + u32 min; + u64 ino; + u64 ino_generation; + u32 prot; + u32 flags; + char filename[KILO]; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + This record indicates when events are lost. + id is the unique event ID for the samples that were lost. + lost is the number of events that were lost. +*/ +struct PerfRecordLostData { + u64 id; + u64 lost; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + This record indicates a change in the process name. + pid is the process ID. + tid is the thread ID. + comm is a string containing the new name of the process. +*/ +struct PerfRecordCommData { + u32 pid; + u32 tid; + char comm[KILO]; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +// This record indicates a sample. +struct PerfRecordSampleData { + u64 sample_id; /* if PERF_SAMPLE_IDENTIFIER */ + u64 ip; /* if PERF_SAMPLE_IP */ + u32 pid, tid; /* if PERF_SAMPLE_TID */ + u64 time; /* if PERF_SAMPLE_TIME */ + u64 addr; /* if PERF_SAMPLE_ADDR */ + u64 id; /* if PERF_SAMPLE_ID */ + u64 stream_id; /* if PERF_SAMPLE_STREAM_ID */ + u32 cpu, res; /* if PERF_SAMPLE_CPU */ + u64 period; /* if PERF_SAMPLE_PERIOD */ + struct read_format v; + /* if PERF_SAMPLE_READ */ + u64 nr; /* if PERF_SAMPLE_CALLCHAIN */ + u64 *ips; /* if PERF_SAMPLE_CALLCHAIN */ + u32 raw_size; /* if PERF_SAMPLE_RAW */ + u8 *raw_data; /* if PERF_SAMPLE_RAW */ + u64 bnr; /* if PERF_SAMPLE_BRANCH_STACK */ + struct perf_branch_entry *lbr; /* if PERF_SAMPLE_BRANCH_STACK */ + u64 user_abi; /* if PERF_SAMPLE_REGS_USER */ + u64 reg_mask; + u64 reg_nr; + u64 *user_regs; /* if PERF_SAMPLE_REGS_USER */ + u64 stack_size; /* if PERF_SAMPLE_STACK_USER */ + u8 *stack_data; /* if PERF_SAMPLE_STACK_USER */ + u64 dyn_size; /* if PERF_SAMPLE_STACK_USER && stack_size != 0 */ + u64 weight; /* if PERF_SAMPLE_WEIGHT */ + u64 data_src; /* if PERF_SAMPLE_DATA_SRC */ + u64 transaction; /* if PERF_SAMPLE_TRANSACTION */ + u64 intr_abi; /* if PERF_SAMPLE_REGS_INTR */ + u64 intr_regs[0]; /* if PERF_SAMPLE_REGS_INTR */ + u64 phys_addr; /* if PERF_SAMPLE_PHYS_ADDR */ + u64 cgroup; /* if PERF_SAMPLE_CGROUP */ +}; + +/* + This record indicates a process exit event. +*/ +struct PerfRecordExitData { + u32 pid, ppid; + u32 tid, ptid; + u64 time; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + This record indicates a throttle/unthrottle event. +*/ +struct PerfRecordThrottleData { + u64 time; + u64 id; + u64 stream_id; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + This record indicates a fork event. +*/ +struct PerfRecordForkData { + u32 pid, ppid; + u32 tid, ptid; + u64 time; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + When using hardware sampling (such as Intel PEBS) this + record indicates some number of samples that may have + been lost. +*/ +struct PerfRecordLostSamplesData { + u64 lost; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + This record indicates which process has initiated an + instruction trace event, allowing tools to properly + correlate the instruction addresses in the AUX buffer + with the proper executable. + + pid process ID of the thread starting an + instruction trace. + tid thread ID of the thread starting an instruction + trace. +*/ +struct PerfRecordItraceStartData { + u32 pid; + u32 tid; +}; + +/* + This record reports that new data is available in the + separate AUX buffer region. + + aux_offset + offset in the AUX mmap region where the new + data begins. + aux_size + size of the data made available. + flags describes the AUX update. + PERF_AUX_FLAG_TRUNCATED + if set, then the data returned was + truncated to fit the available buffer + size. + + PERF_AUX_FLAG_OVERWRITE + if set, then the data returned has + overwritten previous data. +*/ +struct PerfRecordAuxData { + u64 aux_offset; + u64 aux_size; + u64 flags; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + This record indicates a read event. +*/ +struct PerfRecordReadData { + u32 pid, tid; + read_format values; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + This record indicates a context switch has happened. + The PERF_RECORD_MISC_SWITCH_OUT bit in the misc field + indicates whether it was a context switch into or away + from the current process. +*/ +struct PerfRecordSwitchData { +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + As with PERF_RECORD_SWITCH this record indicates a + context switch has happened, but it only occurs when + sampling in CPU-wide mode and provides additional + information on the process being switched to/from. + The PERF_RECORD_MISC_SWITCH_OUT bit in the misc field + indicates whether it was a context switch into or away + from the current process. + + next_prev_pid + The process ID of the previous (if switching + in) or next (if switching out) process on the + CPU. + + next_prev_tid + The thread ID of the previous (if switching in) + or next (if switching out) thread on the CPU. +*/ +struct PerfRecordSwitchCpuWideData { + u32 next_prev_pid; + u32 next_prev_tid; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; + +/* + This record includes various namespace information of + a process. + + pid is the process ID + tid is the thread ID + + nr_namespace + is the number of namespaces in this record + + Each namespace has dev and inode fields and is + recorded in the fixed position like below: + + NET_NS_INDEX=0 + Network namespace + UTS_NS_INDEX=1 + UTS namespace + IPC_NS_INDEX=2 + IPC namespace + PID_NS_INDEX=3 + PID namespace + USER_NS_INDEX=4 + User namespace + MNT_NS_INDEX=5 + Mount namespace + CGROUP_NS_INDEX=6 + Cgroup namespace +*/ +struct PerfRecordNamespacesData { + u32 pid; + u32 tid; + u64 nr_namespaces; + struct name_space { + u64 dev; + u64 inode; + } namespaces[0]; +#if SAMPLE_ID_ALL + struct sample_id sample_id; +#endif +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_PERF_RECORD_FORMAT_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/register.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/register.h new file mode 100755 index 0000000000000000000000000000000000000000..f88a14d67d0289f0585b1d7bdf4701cdb3ffd68d --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/register.h @@ -0,0 +1,184 @@ +/* + * 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. + */ +#ifndef HIPERF_REGISTER_H +#define HIPERF_REGISTER_H + +#include + +#include +#include + +#include "utilities.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +// these define copy from kernel uapi +enum perf_event_x86_regs { + PERF_REG_X86_AX, + PERF_REG_X86_BX, + PERF_REG_X86_CX, + PERF_REG_X86_DX, + PERF_REG_X86_SI, + PERF_REG_X86_DI, + PERF_REG_X86_BP, + PERF_REG_X86_SP, + PERF_REG_X86_IP, + PERF_REG_X86_FLAGS, + PERF_REG_X86_CS, + PERF_REG_X86_SS, + PERF_REG_X86_DS, + PERF_REG_X86_ES, + PERF_REG_X86_FS, + PERF_REG_X86_GS, + PERF_REG_X86_R8, + PERF_REG_X86_R9, + PERF_REG_X86_R10, + PERF_REG_X86_R11, + PERF_REG_X86_R12, + PERF_REG_X86_R13, + PERF_REG_X86_R14, + PERF_REG_X86_R15, + PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1, + PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1, +}; + +enum perf_event_arm64_regs { + PERF_REG_ARM64_X0, + PERF_REG_ARM64_X1, + PERF_REG_ARM64_X2, + PERF_REG_ARM64_X3, + PERF_REG_ARM64_X4, + PERF_REG_ARM64_X5, + PERF_REG_ARM64_X6, + PERF_REG_ARM64_X7, + PERF_REG_ARM64_X8, + PERF_REG_ARM64_X9, + PERF_REG_ARM64_X10, + PERF_REG_ARM64_X11, + PERF_REG_ARM64_X12, + PERF_REG_ARM64_X13, + PERF_REG_ARM64_X14, + PERF_REG_ARM64_X15, + PERF_REG_ARM64_X16, + PERF_REG_ARM64_X17, + PERF_REG_ARM64_X18, + PERF_REG_ARM64_X19, + PERF_REG_ARM64_X20, + PERF_REG_ARM64_X21, + PERF_REG_ARM64_X22, + PERF_REG_ARM64_X23, + PERF_REG_ARM64_X24, + PERF_REG_ARM64_X25, + PERF_REG_ARM64_X26, + PERF_REG_ARM64_X27, + PERF_REG_ARM64_X28, + PERF_REG_ARM64_X29, + PERF_REG_ARM64_LR, + PERF_REG_ARM64_SP, + PERF_REG_ARM64_PC, + PERF_REG_ARM64_MAX, +}; + +enum perf_event_arm_regs { + PERF_REG_ARM_R0, + PERF_REG_ARM_R1, + PERF_REG_ARM_R2, + PERF_REG_ARM_R3, + PERF_REG_ARM_R4, + PERF_REG_ARM_R5, + PERF_REG_ARM_R6, + PERF_REG_ARM_R7, + PERF_REG_ARM_R8, + PERF_REG_ARM_R9, + PERF_REG_ARM_R10, + PERF_REG_ARM_FP = 11, + PERF_REG_ARM_IP = 12, + PERF_REG_ARM_SP = 13, + PERF_REG_ARM_LR = 14, + PERF_REG_ARM_PC = 15, + PERF_REG_ARM_MAX, +}; + +enum ArchType { + X86_32, + X86_64, + ARM, + ARM64, + UNSUPPORT, +}; + +// order is IP , SP for ut +static const std::map PERF_REG_NAME_MAP = { +#if defined(target_cpu_x64) + {PERF_REG_X86_IP, "PERF_REG_X86_IP"}, + {PERF_REG_X86_SP, "PERF_REG_X86_SP"}, +#elif defined(target_cpu_arm) + {PERF_REG_ARM_PC, "PERF_REG_ARM_PC"}, + {PERF_REG_ARM_SP, "PERF_REG_ARM_SP"}, +#elif defined(target_cpu_arm64) + {PERF_REG_ARM64_PC, "PERF_REG_ARM64_PC"}, + {PERF_REG_ARM64_SP, "PERF_REG_ARM64_SP"}, +#endif +}; + +// context name +static const std::map PERF_CONTEXT_NAME = { + {PERF_CONTEXT_HV, "PERF_CONTEXT_HV"}, + {PERF_CONTEXT_KERNEL, "PERF_CONTEXT_KERNEL"}, + {PERF_CONTEXT_USER, "PERF_CONTEXT_USER"}, + {PERF_CONTEXT_GUEST, "PERF_CONTEXT_GUEST"}, + {PERF_CONTEXT_GUEST_KERNEL, "PERF_CONTEXT_GUEST_KERNEL"}, + {PERF_CONTEXT_GUEST_USER, "PERF_CONTEXT_GUEST_USER"}, + {PERF_CONTEXT_MAX, "PERF_CONTEXT_MAX"}, +}; + +constexpr ArchType buildArchType = ArchType::X86_64; +const std::string UpdatePerfContext(uint64_t addr, perf_callchain_context &perfCallChainContext); +const std::string GetArchName(ArchType arch); +uint64_t GetSupportedRegMask(ArchType arch); + +// this is only for debug +const std::string RegisterGetName(size_t registerIndex); + +bool RegisterGetValue(uint64_t &value, const u64 registers[], const size_t registerIndex, + const size_t registerNumber); + +size_t RegisterGetSP(ArchType arch); +size_t RegisterGetIP(ArchType arch); + +inline bool RegisterGetSPValue(uint64_t &value, ArchType arch, const u64 registers[], + const size_t registerNumber) +{ + return RegisterGetValue(value, registers, RegisterGetSP(arch), registerNumber); +} + +inline bool RegisterGetIPValue(uint64_t &value, ArchType arch, const u64 registers[], + const size_t registerNumber) +{ + return RegisterGetValue(value, registers, RegisterGetIP(arch), registerNumber); +} + +int LibunwindRegIdToPerfReg(int regnum); + +ArchType GetDeviceArch(); +ArchType SetDeviceArch(ArchType arch); +ArchType GetArchTypeFromUname(const std::string &machine); +ArchType GetArchTypeFromABI(bool abi32); +void UpdateRegForABI(ArchType arch, u64 registers[]); +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_REGISTER_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/report.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/report.h new file mode 100755 index 0000000000000000000000000000000000000000..3b7d566b43d9ba90cc697d2bb9139f48503bfc06 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/report.h @@ -0,0 +1,559 @@ +/* + * Copyright (c) 2021-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. + */ + +#ifndef REPORT_H +#define REPORT_H + +#include +#include +#include + +#include "debug_logger.h" +#include "utilities.h" +#include "virtual_runtime.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +class ReportItemCallFrame { +public: + std::string_view func_; + uint64_t vaddr_; + std::string_view dso_; + uint64_t eventCount_ = 0; // call chain event + uint64_t selfEventCount_ = 0; // call chain event end in this function + std::vector childs; + ReportItemCallFrame(std::string_view func, uint64_t vaddr, std::string_view dso, + uint64_t eventCount, uint64_t selfEventCount) + : func_(func), + vaddr_(vaddr), + dso_(dso), + eventCount_(eventCount), + selfEventCount_(selfEventCount) + { + } + + bool operator==(const ReportItemCallFrame &b) const + { + return Same(b); + } + + bool operator!=(const ReportItemCallFrame &b) const + { + return !Same(b); + } + + static int CompareSortingEventCount(const ReportItemCallFrame &a, const ReportItemCallFrame &b) + { + return a.eventCount_ > b.eventCount_; + } + + static void OrderCallFrames(std::vector &callframes, int indent = 2) + { + int i = 2; + if (callframes.size() > 0) { + std::sort(callframes.begin(), callframes.end(), + &ReportItemCallFrame::CompareSortingEventCount); + + for (auto &callframe : callframes) { + HLOGDUMMY("%*s%s", indent, "", callframe.ToDebugString().c_str()); + if (callframe.childs.size() > 0) { + OrderCallFrames(callframe.childs, indent + i); + } + } + } + } + + // just a log + static void DumpCallFrames(std::vector &callframes, int indent = 2) + { + int y = 2; + if (callframes.size() > 0) { + for (auto &callframe : callframes) { + HLOGV("%*s%s", indent, "", callframe.ToDebugString().c_str()); + if (callframe.childs.size() > 0) { + DumpCallFrames(callframe.childs, indent + y); + } + } + } + } + + const std::string ToDebugString() const + { + return StringPrintf("%" PRIu64 "(%" PRIu64 ")%s(%s+0x%" PRIx64 ") child %zu", eventCount_, + selfEventCount_, func_.data(), dso_.data(), vaddr_, childs.size()); + } + +private: + bool Same(const ReportItemCallFrame &b) const + { + return (func_ == b.func_) and (vaddr_ == b.vaddr_) and (dso_ == b.dso_); + } +}; + +// one item or one line in report +class ReportItem { +public: + pid_t pid_ = 0; + pid_t tid_ = 0; + std::string_view comm_ = ""; + std::string_view dso_ = ""; + std::string_view fromDso_ = ""; + std::string_view fromFunc_ = ""; + std::string_view func_ = ""; + uint64_t vaddr_ = 0; + uint64_t eventCount_ = 0; // event count + std::vector callStacks_; + float heat = 0.0f; + static unsigned long long allIndex_; // debug only + unsigned long long index_; + + // only for ut test + ReportItem(pid_t pid, pid_t tid, const char *comm, const char *dso, const char *func, + uint64_t vaddr, uint64_t eventCount) + : pid_(pid), + tid_(tid), + comm_(comm), + dso_(dso), + func_(func), + vaddr_(vaddr), + eventCount_(eventCount) + { + HLOG_ASSERT(comm != nullptr); + index_ = allIndex_++; + } + + ReportItem(pid_t pid, pid_t tid, std::string &comm, const std::string_view &dso, + const std::string_view &func, uint64_t vaddr, uint64_t eventCount) + : pid_(pid), + tid_(tid), + comm_(comm), + dso_(dso), + func_(func), + vaddr_(vaddr), + eventCount_(eventCount) + { + HLOG_ASSERT(!comm.empty()); + index_ = allIndex_++; + } + + bool operator==(const ReportItem &b) const + { + return Same(b); + } + + bool operator!=(const ReportItem &b) const + { + return !Same(b); + } + + // debug only + const std::string ToDebugString() const + { + return StringPrintf("%d:%d:%s-%s(%s):%zu i:%llu", pid_, tid_, comm_.data(), func_.data(), + dso_.data(), eventCount_, index_); + } + + // Count + static int CompareEventCount(const ReportItem &a, const ReportItem &b) + { + if (a.eventCount_ != b.eventCount_) { + return (a.eventCount_ > b.eventCount_) ? 1 : -1; + } else { + return 0; + } + } + + static int CompareSortingEventCount(const ReportItem &a, const ReportItem &b) + { + return a.eventCount_ > b.eventCount_; + } + + static const std::string GetEventCount(const ReportItem &a, size_t len, + const std::string &format) + { + return StringPrintf(format.c_str(), len, a.eventCount_); + } + + // Pid + static int ComparePid(const ReportItem &a, const ReportItem &b) + { + if (a.pid_ != b.pid_) { + return (a.pid_ > b.pid_) ? 1 : -1; + } else { + return 0; + } + } + static const std::string GetPid(const ReportItem &a, size_t len, const std::string &format) + { + return StringPrintf(format.c_str(), len, a.pid_); + } + + // Tid + static int CompareTid(const ReportItem &a, const ReportItem &b) + { + if (a.tid_ != b.tid_) { + return (a.tid_ > b.tid_) ? 1 : -1; + } else { + return 0; + } + } + static const std::string GetTid(const ReportItem &a, size_t len, const std::string &format) + { + return StringPrintf(format.c_str(), len, a.tid_); + } + + // Comm + static int CompareComm(const ReportItem &a, const ReportItem &b) + { + int result = a.comm_.compare(b.comm_); + return result; + } + static const std::string GetComm(const ReportItem &a, size_t len, const std::string &format) + { + return StringPrintf(format.c_str(), len, a.comm_.data()); + } + + // Func + static int CompareFunc(const ReportItem &a, const ReportItem &b) + { + return a.func_.compare(b.func_); + } + static const std::string GetFunc(const ReportItem &a, size_t len, const std::string &format) + { + return StringPrintf(format.c_str(), len, a.func_.data()); + } + + // Dso + static int CompareDso(const ReportItem &a, const ReportItem &b) + { + return a.dso_.compare(b.dso_); + } + static const std::string GetDso(const ReportItem &a, size_t len, const std::string &format) + { + return StringPrintf(format.c_str(), len, a.dso_.data()); + } + + // fromDso + static int CompareFromDso(const ReportItem &a, const ReportItem &b) + { + return a.fromDso_.compare(b.fromDso_); + } + static const std::string GetFromDso(const ReportItem &a, size_t len, const std::string &format) + { + return StringPrintf(format.c_str(), len, a.fromDso_.data()); + } + + // fromFunc + static int CompareFromFunc(const ReportItem &a, const ReportItem &b) + { + return a.fromFunc_.compare(b.fromFunc_); + } + static const std::string GetFromFunc(const ReportItem &a, size_t len, const std::string &format) + { + return StringPrintf(format.c_str(), len, a.fromFunc_.data()); + } + +private: + bool Same(const ReportItem &b) const + { + return (comm_ == b.comm_) && (pid_ == b.pid_) && (tid_ == b.tid_) && (func_ == b.func_) && + (dso_ == b.dso_) && (vaddr_ == b.vaddr_); + } +}; + +using ReportKeyCompareFunction = int(const ReportItem &, const ReportItem &); +using ReportKeyGetFunction = const std::string(const ReportItem &, size_t, const std::string &); + +constexpr const int MAX_FILED_LEN = 20; +constexpr const int CALLSTACK_INDENT = 4; +struct ReportKey { + const std::string keyName_; + const std::string valueFormat_; + size_t maxLen_ = 0u; + std::string maxValue_; + ReportKeyCompareFunction &compareFunction_; + ReportKeyGetFunction &GetFunction_; + const std::vector &displayFilter_; + + ReportKey(const std::string keyName, ReportKeyCompareFunction &compareFunction, + ReportKeyGetFunction &GetFunction, const std::string valueFormat, + const std::vector &displayFilter) + : keyName_(keyName), + valueFormat_(valueFormat), + compareFunction_(compareFunction), + GetFunction_(GetFunction), + displayFilter_(displayFilter) + { + maxLen_ = keyName.size(); + } + + void UpdateValueMaxLen(const std::string &value) + { + size_t newMaxLen = std::max(maxLen_, value.size()); + if (maxLen_ < newMaxLen) { + maxValue_ = value; + maxLen_ = newMaxLen; + } + } + + void UpdateValueMaxLen(size_t value) + { + size_t newMaxLen = std::max(maxLen_, std::to_string(value).size()); + if (maxLen_ < newMaxLen) { + maxValue_ = std::to_string(value); + maxLen_ = newMaxLen; + } + } + + std::string GetValue(const ReportItem &i) + { + return GetFunction_(i, maxLen_, valueFormat_); + } + + bool ShouldDisplay(const ReportItem &i) + { + if (displayFilter_.size() == 0) { + return true; + } else { + std::string value = GetFunction_(i, 0, valueFormat_); + auto it = find(displayFilter_.begin(), displayFilter_.end(), value); + if (it == displayFilter_.end()) { + HLOGV(" not found '%s' in %s", value.c_str(), + VectorToString(displayFilter_).c_str()); + } + return (it != displayFilter_.end()); + } + } +}; + +using ReportItems = std::vector; +using ReportItemsIt = ReportItems::iterator; +using ReportItemsConstIt = ReportItems::const_iterator; + +struct ReportOption { + float heatLimit_ = 0.0f; + float callStackHeatLimit_ = 0.0f; + + // display filter + std::vector displayComms_ {}; + std::vector displayPids_ {}; + std::vector displayTids_ {}; + std::vector displayDsos_ {}; + std::vector displayFromDsos_ {}; + std::vector displayFuncs_ {}; + std::vector displayFromFuncs_ {}; + std::vector displayDummy_ {}; + + std::vector sortKeys_ = {"comm", "pid", "tid", "dso", "func"}; + + bool debug_ = false; + bool hideCount_ = false; +}; + +class Report { +public: + Report() : option_(defaultOption_), virtualRuntime_(false) + { + // works for ut test + } + Report(ReportOption &option) : option_(option), virtualRuntime_(false) {} + bool MultiLevelSame(const ReportItem &a, const ReportItem &b); + void AdjustReportItems(); + void AddReportItem(const PerfRecordSample &sample, bool includeCallStack); + void AddReportItemBranch(const PerfRecordSample &sample); + void OutputStd(FILE *output); + void OutputStdDiff(FILE *output, Report &other); + + ReportOption &option_; + + VirtualRuntime virtualRuntime_; + + std::map reportKeyMap_ = { + { + "count", + { + "count", + ReportItem::CompareEventCount, + ReportItem::GetEventCount, + "%*" PRIu64 "", + option_.displayDummy_, + }, + }, + { + "comm", + { + "comm", + ReportItem::CompareComm, + ReportItem::GetComm, + "%-*s", + option_.displayComms_, + }, + }, + { + "pid", + { + "pid", + ReportItem::ComparePid, + ReportItem::GetPid, + "%*d", + option_.displayPids_, + }, + }, + { + "tid", + { + "tid", + ReportItem::CompareTid, + ReportItem::GetTid, + "%*d", + option_.displayTids_, + }, + }, + { + "dso", + { + "dso", + ReportItem::CompareDso, + ReportItem::GetDso, + "%-*s", + option_.displayDsos_, + }, + }, + { + "from_dso", + { + "from_dso", + ReportItem::CompareFromDso, + ReportItem::GetFromDso, + "%-*s", + option_.displayFromDsos_, + }, + }, + { + "func", + { + "func", + ReportItem::CompareFunc, + ReportItem::GetFunc, + "%-*s", + option_.displayFuncs_, + }, + }, + { + "from_func", + { + "from_func", + ReportItem::CompareFromFunc, + ReportItem::GetFromFunc, + "%-*s", + option_.displayFromFuncs_, + }, + }, + }; + struct ReportEventConfigItem { + ReportEventConfigItem(const ReportEventConfigItem &) = delete; + ReportEventConfigItem &operator=(const ReportEventConfigItem &) = delete; + ReportEventConfigItem(ReportEventConfigItem &&) = default; + std::string eventName_; + uint64_t sampleCount_ = 0; + uint64_t eventCount_ = 0; + std::vector reportItems_; + uint32_t type_; + uint64_t config_; + std::vector ids_; + + bool coutMode_ = true; // use cout or time ? + bool operator==(const ReportEventConfigItem &o) const + { + return (type_ == o.type_) && (config_ == o.config_); + } + bool operator!=(const ReportEventConfigItem &o) const + { + return !(operator==(o)); + } + std::string toDebugString() + { + return StringPrintf("%s(%" PRIu32 "-%" PRIu64 "):PRIu64", eventName_.c_str(), type_, + config_, sampleCount_); + } + ReportEventConfigItem(std::string eventName, uint32_t type, uint64_t config, + bool coutMode = true) + : eventName_(eventName), type_(type), config_(config), coutMode_(coutMode) + { + } + }; + std::vector configs_; + virtual ~Report() {} + + std::map configIdIndexMaps_; // index of configNames_ + std::string GetConfigName(uint64_t id) + { + return configs_[GetConfigIndex(id)].eventName_; + } + size_t GetConfigIndex(uint64_t id) + { + HLOG_ASSERT_MESSAGE(configIdIndexMaps_.find(id) != configIdIndexMaps_.end(), + "unable found id %" PRIx64 "", id); + return configIdIndexMaps_.at(id); + } + +private: + FILE *output_ = nullptr; + const std::string TEXT_RED = "\x1b[31m"; + const std::string TEXT_GREEN = "\x1b[32m"; + const std::string TEXT_RESET = "\033[0m"; + const unsigned int ConsoleDefaultWidth = 80; + + // sometime caller don't give the option + ReportOption defaultOption_; + + std::vector displayKeyNames_; + + // use virtual only for gmock test + bool MultiLevelSorting(const ReportItem &a, const ReportItem &b); + bool MultiLevelSameAndUpdateCount(ReportItem &l, ReportItem &r); + void MergeCallFrameCount(ReportItem &l, ReportItem &r); + virtual int MultiLevelCompare(const ReportItem &a, const ReportItem &b); + + void StatisticsRecords(); + void FilterDisplayRecords(); + void UpdateReportItemsAfterAdjust(); + + // std out + int consoleWidth_ = 0; + void PrepareConsole(); + + void OutputStdStatistics(ReportEventConfigItem &); + bool OutputStdStatistics(ReportEventConfigItem &config, ReportEventConfigItem &otherConfig); + + void OutputStdHead(ReportEventConfigItem &, bool diffMode = false); + + void OutputStdContent(ReportEventConfigItem &); + void OutputStdContentDiff(ReportEventConfigItem &, ReportEventConfigItem &); + + void OutputStdContentItem(const ReportItem &reportItem); + void OutputStdContentDiffOneSide(bool leftOnly, ReportItem &reportItem); + + void OutputStdCallFrames(int indent, const ReportItemCallFrame &callFrames, + uint64_t totalEventCount); + bool OutputStdCallFrame(int indent, const std::string_view &funcName, uint64_t eventCount, + uint64_t totalEventCount); + void OutputStdItemHeating(float heat, float heat2); +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // REPORT_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/ring_buffer.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/ring_buffer.h new file mode 100755 index 0000000000000000000000000000000000000000..3a839310a74a09401dc206f626c423a23b665e6a --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/ring_buffer.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_RING_BUFFER_H +#define HIPERF_RING_BUFFER_H + +// #ifdef target_cpu_x64 +#include +// #endif +#include + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +class RingBuffer { +public: + // little endian, perf_event_header.type is less than 0xff, so set it + static constexpr uint8_t MARGIN_BYTE = 0xFF; + + explicit RingBuffer(size_t size); + ~RingBuffer(); + // get size of the writable space + size_t GetFreeSize() const; + + // before writing data to rbuff, alloc space first + uint8_t *AllocForWrite(size_t writeSize); + // after writing data, move head pointer + void EndWrite(); + // get data from buff, return nullptr if no readable data + uint8_t *GetReadData(); + // after reading, move tail pointer + void EndRead(); + +private: + std::unique_ptr buf_ = nullptr; + const size_t size_; + std::atomic head_ {0}; + // std::atomic_size_t head_ = 0; // write after this, always increase + // std::atomic_size_t tail_ = 0; // read from this, always increase + std::atomic tail_ {0}; + size_t writeSize_ = 0; + size_t readSize_ = 0; +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_RING_BUFFER_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/subcommand_dump.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/subcommand_dump.h new file mode 100644 index 0000000000000000000000000000000000000000..e2cf826d2c722f455bca9b066f9458d97ecaf746 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/subcommand_dump.h @@ -0,0 +1,119 @@ +/* + * 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. + */ +#ifndef SUBCOMMAND_DUMP_H +#define SUBCOMMAND_DUMP_H + +#include "perf_file_reader.h" + +#include + +#if HAVE_PROTOBUF +#include "report_protobuf_file.h" +#endif +#include "subcommand.h" +#include "symbols_file.h" +#include "virtual_runtime.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +static const std::string DEFAULT_DUMP_FILENAME = "perf.data"; + +class SubCommandDump : public SubCommand { +public: + SubCommandDump() + // clang-format off + : SubCommand("dump", "Dump content of a perf data file, like perf.data", + + "Usage: hiperf dump [option] \n" + " Dump specific parts of specified file .\n" + " --head\n" + " Dump header and attrs only.\n" + " -d\n" + " Dump data section only.\n" + " -f\n" + " Dump addtional features only.\n" + " --sympath \n" + " use symbols path to find symbols.\n" + " --elf \n" + " dump elf not perf data.\n" +#if HAVE_PROTOBUF + " --proto \n" + " dump perf data from protobuf file.\n" +#endif + " --export \n" + " also export the user stack data to some split file,\n" + " use this command to produce ut data." + " named with sample index(0 base):\n" + " hiperf___user_regs_.dump\n" + " hiperf___user_data_.dump\n" + " \n" + " perf data file to dump, default is perf.data\n\n" + ) + // clang-format on + { + } + ~SubCommandDump() override; + + bool OnSubCommand(std::vector &args) override; + bool ParseOption(std::vector &args) override; + + static bool RegisterSubCommandDump(void); + + static void DumpPrintEventAttr(const perf_event_attr &attr, int indent = 0); + std::unique_ptr reader_; + +private: + static void DumpSampleType(uint64_t sampleType, int indent); + int exportSampleIndex_ = -1; + int currectSampleIndex_ = 0; + std::string dumpFileName_; + std::string elfFileName_; + std::string protobufDumpFileName_; + int indent_ = 0; +#if HAVE_PROTOBUF + std::unique_ptr protobufInputFileReader_ = nullptr; +#endif + + std::vector attrIds_; + + bool dumpHeader_ = false; + bool dumpFeatures_ = false; + bool dumpData_ = false; + bool dumpAll_ = true; + + std::vector dumpSymbolsPaths_; + + bool CheckInputFile(); + bool DumpElfFile(); +#if HAVE_PROTOBUF + bool DumpProtoFile(); +#endif + void DumpPrintFileHeader(int indent = 0); + void DumpAttrPortion(int indent = 0); + void DumpDataPortion(int indent = 0); + void DumpCallChain(int indent, std::unique_ptr &sample); + void DumpFeaturePortion(int indent = 0); + void ExprotUserData(std::unique_ptr &record); + void ExprotUserStack(const PerfRecordSample &recordSample); + void PrintHeaderInfo(const int &indent); + void PrintSymbolFile(const int &indent, const SymbolFileStruct &symbolFileStruct); + void PrintFeatureEventdesc(int indent, const PerfFileSectionEventDesc §ionEventdesc); + VirtualRuntime vr_; +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // SUBCOMMAND_DUMP_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/subcommand_help.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/subcommand_help.h new file mode 100644 index 0000000000000000000000000000000000000000..18a6eb2da302c92133f96f0ca5911f157db183c6 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/subcommand_help.h @@ -0,0 +1,45 @@ +/* + * 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. + */ +#ifndef HIPERF_SUBCOMMAND_HELP_H_ +#define HIPERF_SUBCOMMAND_HELP_H_ + +#include "option.h" +#include "subcommand.h" +namespace OHOS { +namespace Developtools { +namespace HiPerf { +class SubCommandHelp : public SubCommand { +public: + SubCommandHelp() + // clang-format off + : SubCommand("help", "Show more help information for hiperf", + "Usage: hiperf help [subcommand]\n" + " By default, all options help information and subcommand brief information are output.\n" + " If you provide a subcommand, only the help information for this command will be output.\n\n" + ) + // clang-format on + { + Option::RegisterMainOption("--help", "show help", OnHelp); + Option::RegisterMainOption("-h", "show help", OnHelp); + } + + bool OnSubCommand(std::vector &args) override; + static void RegisterSubCommandHelp(void); + static bool OnHelp(std::vector &args); +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_SUBCOMMAND_HELP_H_ diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/symbols_file.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/symbols_file.h new file mode 100755 index 0000000000000000000000000000000000000000..f6670c0fecdae522111352321ad2d5194f8d711c --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/symbols_file.h @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2021-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. + */ + +#ifndef HIPERF_SYMBOLS_H +#define HIPERF_SYMBOLS_H + +#include +#include +#include +#include + +#include "perf_file_format.h" +#include "utilities.h" + +#define HIPERF_ELF_READ_USE_MMAP + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +constexpr const char KERNEL_MMAP_NAME[] = "[kernel.kallsyms]"; +constexpr const char KERNEL_MODULES_EXT_NAME[] = ".ko"; +constexpr const char KERNEL_ELF_NAME[] = "vmlinux"; +constexpr const char MMAP_VDSO_NAME[] = "[vdso]"; +constexpr const char MMAP_ANONYMOUS_NAME[] = "[anon]"; +constexpr const char MMAP_ANONYMOUS_OHOS_NAME[] = "//anon"; + +const std::string NOTE_GNU_BUILD_ID = ".note.gnu.build-id"; +const std::string EH_FRAME_HR = ".eh_frame_hdr"; +const std::string EH_FRAME = ".eh_frame"; +const std::string ARM_EXIDX = ".ARM.exidx"; +const std::string SYMTAB = ".symtab"; +const std::string DYNSYM = ".dynsym"; +const std::string GNU_DEBUGDATA = ".gnu_debugdata"; +const std::string PLT = ".plt"; +const std::string LINKER_PREFIX = "__dl_"; +const std::string LINKER_PREFIX_NAME = "[linker]"; + +const int MAX_SYMBOLS_TYPE_NAME_LEN = 10; + +class FileSymbol { + [[maybe_unused]] uint64_t vaddr_ = 0; + [[maybe_unused]] uint64_t len_ = 0; + std::string name_ = ""; + std::string demangle_ = ""; // demangle string + FileSymbol(uint64_t vaddr, uint64_t len, const char *name, const char *demangle) + : vaddr_(vaddr), len_(len), name_(name), demangle_(demangle) + { + } +}; + +struct Symbol { + uint64_t funcVaddr_ = 0; + uint64_t fileVaddr_ = 0; + uint64_t taskVaddr_ = 0; + uint64_t len_ = 0; + int32_t index_ = -1; + std::string_view name_ = ""; + std::string_view demangle_ = ""; // demangle string + std::string_view module_ = ""; // maybe empty + std::string_view comm_ = ""; // we need a comm name like comm@0x1234 + mutable std::string_view unknow_ = ""; + mutable bool matched_ = false; // if some callstack match this + int32_t hit_ = 0; + + // elf use this + Symbol(uint64_t vaddr, uint64_t len, const std::string &name, const std::string &demangle, + const std::string module) + : funcVaddr_(vaddr), + fileVaddr_(vaddr), + len_(len), + name_(MemoryHold::Get().HoldStringView(name)), + demangle_(MemoryHold::Get().HoldStringView(demangle)), + module_(MemoryHold::Get().HoldStringView(module)) {} + Symbol(uint64_t vaddr, uint64_t len, const std::string &name, const std::string &module) + : Symbol(vaddr, len, name, name, module) {} + + // kernel use this + Symbol(uint64_t vaddr, const std::string &name, const std::string &module) + : Symbol(vaddr, 0, name, name, module) {} + + // Symbolic use this + Symbol(uint64_t taskVaddr = 0, const std::string &comm = "") + : taskVaddr_(taskVaddr), comm_(comm) + { + } + + // copy + Symbol(const Symbol &other) = default; + + static bool SameVaddr(const Symbol &a, const Symbol &b) + { + return (a.funcVaddr_ == b.funcVaddr_); + } + bool Same(const Symbol &b) const + { + return (funcVaddr_ == b.funcVaddr_ and demangle_ == b.demangle_); + } + bool operator==(const Symbol &b) const + { + return Same(b); + } + + bool operator!=(const Symbol &b) const + { + return !Same(b); + } + + bool isValid() const + { + return !module_.empty(); + } + + void SetMatchFlag() const + { + matched_ = true; + } + + inline bool HasMatched() const + { + return matched_; + } + + std::string_view Name() const + { + if (!demangle_.empty()) { + return demangle_; + } + if (!name_.empty()) { + return name_; + } + if (unknow_.empty()) { + std::stringstream sstream; + if (!module_.empty()) { + sstream << module_ << "+0x" << std::hex << fileVaddr_; + } else { + sstream << comm_ << "@0x" << std::hex << taskVaddr_; + } + std::string hold = sstream.str(); + unknow_ = MemoryHold::Get().HoldStringView(hold); + } + return unknow_; + } + + std::string ToString() const + { + std::stringstream sstream; + if (fileVaddr_ != 0) { + sstream << "0x" << std::hex << fileVaddr_; + } else { + sstream << "0x" << std::hex << taskVaddr_; + } + sstream << " " << Name(); + return sstream.str(); + }; + + std::string ToDebugString() const + { + std::stringstream sstream; + sstream << "0x" << std::setfill('0') << std::setw(sizeof(funcVaddr_) * BYTE_PRINT_WIDTH) + << std::hex << funcVaddr_; + sstream << "|"; + sstream << std::setfill('0') << std::setw(sizeof(len_)) << len_; + sstream << "|"; + sstream << demangle_ << "|"; + sstream << name_ << "|"; + sstream << (matched_ ? "matched" : ""); + sstream << " unknowname:" << unknow_.size(); + sstream << " task:" << (comm_.size() > 0 ? comm_ : ""); + sstream << "@" << taskVaddr_; + sstream << " file:" << (module_.size() > 0 ? module_ : ""); + sstream << "@" << fileVaddr_; + + return sstream.str(); + }; + + bool Contain(uint64_t addr) const + { + if (len_ == 0) { + return funcVaddr_ <= addr; + } else { + return (funcVaddr_ <= addr) and ((funcVaddr_ + len_) > addr); + } + } + + // The range [first, last) must be partitioned with respect to the expression !(value < element) + // or !comp(value, element) + static bool ValueLessThen(uint64_t vaddr, const Symbol &a) + { + return vaddr < a.funcVaddr_; + } + static bool ValueLessEqual(uint64_t vaddr, const Symbol &a) + { + return vaddr <= a.funcVaddr_; + } + static bool CompareLessThen(const Symbol &a, const Symbol &b) + { + return a.funcVaddr_ < b.funcVaddr_; // we should use vaddr to sort + }; + static bool CompareByPointer(const Symbol *a, const Symbol *b) + { + return a->funcVaddr_ < b->funcVaddr_; // we should use vaddr to sort + }; +}; + +enum SymbolsFileType { + SYMBOL_KERNEL_FILE, + SYMBOL_KERNEL_MODULE_FILE, + SYMBOL_ELF_FILE, + SYMBOL_JAVA_FILE, + SYMBOL_JS_FILE, + SYMBOL_UNKNOW_FILE, +}; + +class SymbolsFile { +public: + SymbolsFileType symbolFileType_; + std::string filePath_ = ""; + + // [14] .text PROGBITS 00000000002c5000 000c5000 + // min exec addr , general it point to .text + // we make a default value for min compare + static const uint64_t maxVaddr = std::numeric_limits::max(); + + uint64_t textExecVaddr_ = maxVaddr; + uint64_t textExecVaddrFileOffset_ = 0; + uint64_t textExecVaddrRange_ = maxVaddr; + + SymbolsFile(SymbolsFileType symbolType, const std::string path) + : symbolFileType_(symbolType), filePath_(path) {}; + virtual ~SymbolsFile(); + + // create the symbols file object + static std::unique_ptr CreateSymbolsFile( + SymbolsFileType = SYMBOL_UNKNOW_FILE, const std::string symbolFilePath = EMPTY_STRING); + static std::unique_ptr CreateSymbolsFile(const std::string &symbolFilePath); + + // set symbols path + bool setSymbolsFilePath(const std::string &symbolsSearchPath) + { + std::vector symbolsSearchPaths = {symbolsSearchPath}; + return setSymbolsFilePath(symbolsSearchPaths); + }; + bool setSymbolsFilePath(const std::vector &); + + // load symbol from file + virtual bool LoadSymbols([[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING) + { + HLOGV("virtual dummy function called"); + symbolsLoaded_ = true; + return false; + }; + // load debug info for unwind + virtual bool LoadDebugInfo([[maybe_unused]] const std::string &symbolFilePath = EMPTY_STRING) + { + HLOGV("virtual dummy function called"); + debugInfoLoaded_ = true; + return false; + }; + // get the build if from symbols + const std::string GetBuildId() const; + + // get the symbols vector + const std::vector &GetSymbols(); + const std::vector &GetMatchedSymbols(); + + // get vaddr(in symbol) from ip(real addr , after mmap reloc) + virtual uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t mapOffset) const; + + // get symbols from vaddr + const Symbol GetSymbolWithVaddr(uint64_t vaddr); + + // read the .text section and .eh_frame section (RO) memory from elf mmap + // unwind use this to check the DWARF and so on + virtual size_t ReadRoMemory(uint64_t, uint8_t * const, size_t) const + { + HLOGV("virtual dummy function called"); + return 0; // default not support + } + + // get the section info , like .ARM.exidx + virtual bool GetSectionInfo([[maybe_unused]] const std::string &name, + [[maybe_unused]] uint64_t §ionVaddr, + [[maybe_unused]] uint64_t §ionSize, + [[maybe_unused]] uint64_t §ionFileOffset) const + { + HLOGV("virtual dummy function called"); + return false; + } +#ifndef target_cpu_arm + // get hdr info for unwind , need provide the fde table location and entry count + virtual bool GetHDRSectionInfo([[maybe_unused]] uint64_t &ehFrameHdrElfOffset, + [[maybe_unused]] uint64_t &fdeTableElfOffset, + [[maybe_unused]] uint64_t &fdeTableSize) const + { + HLOGV("virtual dummy function called"); + return false; + } +#endif + // load from symbols from the perf.data format + static std::unique_ptr LoadSymbolsFromSaved(const SymbolFileStruct &); + // save the symbols to perf.data format + void ExportSymbolToFileFormat(SymbolFileStruct &symbolFileStruct); + + bool SymbolsLoaded() + { + return symbolsLoaded_; + } + + // this means we are in recording + // will try read some elf in runtime path + static bool onRecording_; + +protected: + bool symbolsLoaded_ = false; + bool debugInfoLoaded_ = false; + const std::string FindSymbolFile(const std::vector &, + std::string symboleFilePath = EMPTY_STRING) const; + + std::string SearchReadableFile(const std::vector &searchPaths, + const std::string &filePath) const; + bool UpdateBuildIdIfMatch(std::string buildId); + std::string buildId_; + std::vector symbolsFileSearchPaths_; + std::vector symbols_{}; + std::vector matchedSymbols_{}; + std::vector fileSymbols_{}; + + void AdjustSymbols(); + void SortMatchedSymbols(); + bool CheckPathReadable(const std::string& path) const; + + friend class VirtualRuntimeTest; + + friend class ReportProtobufFileTest; +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_SYMBOLS_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/tracked_command.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/tracked_command.h new file mode 100644 index 0000000000000000000000000000000000000000..628128b8027d14cc1d3da9125e7944225913fe20 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/tracked_command.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_TRACKED_COMMAND_H_ +#define HIPERF_TRACKED_COMMAND_H_ + +#include +#include +#include +namespace OHOS { +namespace Developtools { +namespace HiPerf { +class TrackedCommand : public Noncopyable { +public: + enum class State { + COMMAND_WAITING, // child process blocked to execute command + COMMAND_STARTED, // child process executing command + COMMAND_FAILURE, // command failed to start + COMMAND_STOPPED // no child process or command execution + }; + + static std::unique_ptr CreateInstance(const std::vector &args); + + ~TrackedCommand(); + + bool CreateChildProcess(); + bool StartCommand(); + bool WaitCommand(int &wstatus); + void Stop(); + + inline std::string GetCommandName() + { + if (!command_.empty()) { + return command_[0]; + } + return EMPTY_STRING; + } + + inline State GetState() + { + return state_; + } + + inline pid_t GetChildPid() + { + return childPid_; + } + +private: + explicit TrackedCommand(const std::vector &args); + + bool InitSignalPipes(int &startFd, int &ackFd); + void ExecuteCommand(const int &startFd, const int &ackFd); + void MakeInvalid(); + + std::vector command_ {}; + int startFd_ {-1}; + int ackFd_ {-1}; + pid_t childPid_ {-1}; + State state_ {State::COMMAND_STOPPED}; +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_TRACKED_COMMAND_H_ diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/utilities.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/utilities.h new file mode 100755 index 0000000000000000000000000000000000000000..3399c5d6061e94daa9978f42439ddfa297836a57 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/utilities.h @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_UTILITIES_H_ +#define HIPERF_UTILITIES_H_ + +// for security function +#include "string_help.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#if !is_mingw +#include +#endif +#include + +#include "debug_logger.h" +#include "noncopyable.h" +#include "string_help.h" +using namespace SysTuning::base; + +#ifndef __ASSEMBLY__ +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#ifdef __GNUC__ +__extension__ typedef __signed__ long long __s64; +__extension__ typedef unsigned long long __u64; +#else +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +#endif /* __ASSEMBLY__ */ + +// data and value +/* +long long always 64 only in ILP64, int is 64 otherwise int is always 32 +*/ +using s8 = __s8; +using u8 = __u8; +using s16 = __s16; +using u16 = __u16; +using s32 = __s32; +using u32 = __u32; +using s64 = __s64; +using u64 = __u64; + +constexpr const int NUMBER_FORMAT_HEX_BASE = 16; +constexpr const int BYTE_PRINT_WIDTH = 2; +constexpr const int UINT64_PRINT_WIDTH = BYTE_PRINT_WIDTH * 8; +constexpr const int BITS_OF_BYTE = 8; +constexpr const int BITS_OF_TWO_BYTE = 2 * BITS_OF_BYTE; +constexpr const int BITS_OF_FOUR_BYTE = 4 * BITS_OF_BYTE; +constexpr const int FULL_PERCENTAGE = 100; +constexpr const int FULL_PERCENTAGE_NUM_LEN = 5; // 100.00 +constexpr const int FULL_PERCENTAGE_DIFF_NUM_LEN = 6; // +100.00 +constexpr const int FULL_PERCENTAGE_LEN = 6; // 100.00% +constexpr const int FULL_PERCENTAGE_DIFF_LEN = 7; // +100.00% +constexpr const int THOUSANDS = 1000; +constexpr const int HUNDREDS = 100; +constexpr const int DEFAULT_STRING_BUF_SIZE = 4096; +constexpr const int FIVE_THOUSANDS = 5000; +#if !is_mingw +#ifndef O_BINARY +#define O_BINARY 0 +#endif +#endif + +constexpr const double MS_DUARTION = + static_cast(std::chrono::milliseconds::duration::period::den); + +constexpr uint64_t KILO = 1024; + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +std::string CanonicalizeSpecPath(const char* src); +const std::string EMPTY_STRING = ""; +const ssize_t ERRINFOLEN = 512; + +// string function +class MemoryHold { +public: + ~MemoryHold() + { + Clean(); + } + const char *HoldStringView(std::string_view view); + // only use in UT + void Clean() + { + for (auto &p : holder_) { + delete[] p; + } + holder_.clear(); + } + static MemoryHold &Get() + { + static MemoryHold instance; + return instance; + } + +private: + std::vector holder_; +}; + +std::string StringReplace(std::string source, const std::string &from, const std::string &to); + +template +std::string VectorToString(const std::vector &items) +{ + if constexpr (std::is_same>::value) { + std::vector stringItems; + for (auto item : items) { + stringItems.push_back("[" + VectorToString(item) + "]"); + } + return VectorToString(stringItems); + } else { + std::string itemsString; + const std::string split = ","; + for (auto item : items) { + if (!itemsString.empty()) + itemsString.append(split); + if constexpr (std::is_same::value) { + itemsString.append(item); + } else { + itemsString.append(std::to_string(item)); + } + } + if (itemsString.empty()) + itemsString.append(""); + return itemsString; + } +} + +std::string BufferToHexString(const std::vector &vec); +std::string BufferToHexString(const unsigned char buf[], size_t size); +void HexDump(const void *buf, size_t size, size_t max_size = 0); + +std::string &StringTrim(std::string &s); + +std::vector StringSplit(std::string source, std::string split = ","); + +size_t SubStringCount(const std::string &source, const std::string &sub); + +bool StringStartsWith(const std::string &string, const std::string &with); + +bool StringEndsWith(const std::string &string, const std::string &with); + +bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName); + +std::vector GetSubthreadIDs(const pid_t pid); + +bool IsDigits(const std::string &str); + +bool IsHexDigits(const std::string &str); + +constexpr const int COMPRESS_READ_BUF_SIZE = 4096; +// compress specified dataFile into gzip file +bool CompressFile(const std::string &dataFile, const std::string &destFile); +// uncompress specified gzip file into dataFile +bool UncompressFile(const std::string &gzipFile, const std::string &dataFile); + +template +std::string StringPrintf(const char *stringFormat, VA... args) +{ + // check howmany bytes we need + char bytes[DEFAULT_STRING_BUF_SIZE]; + bytes[DEFAULT_STRING_BUF_SIZE - 1] = '\0'; + + if (stringFormat == nullptr) { + return EMPTY_STRING; + } + + // print it to bytes + if (snprintf_s(bytes, sizeof(bytes), sizeof(bytes) - 1, stringFormat, + args...) < 0) { + return EMPTY_STRING; + } + + // make a string return + return std::string(bytes); +} + +// path check +std::vector GetEntriesInDir(const std::string &basePath); + +std::vector GetSubDirs(const std::string &basePath); + +bool IsDir(const std::string &path); + +bool IsPath(const std::string &fileName); + +#if is_mingw +const char PATH_SEPARATOR = '\\'; +#else +const char PATH_SEPARATOR = '/'; +#endif +const std::string PATH_SEPARATOR_STR = std::string(1, PATH_SEPARATOR); + +std::string PlatformPathConvert(const std::string &path); + +// attribute +#define PACKED __attribute__((packed)) + +// data align + +// some time u will meet signal 7 (SIGBUS), code 1 (BUS_ADRALN) in 32 or 64 arch cpu +#define HIPERF_BUF_ALIGN alignas(64) + +#define ALIGN(size, align) (((size) + (align) - 1) & (~((align) - 1))) + +uint32_t RoundUp(uint32_t x, const int align); + +// data convert function +template +std::string ToHex(const T &source, int size = sizeof(T), bool prefix = false) +{ + std::stringstream ss; + if (prefix) { + ss << "0x"; + } + ss << std::hex << std::setw(BYTE_PRINT_WIDTH * size) << std::setfill('0') << (uint64_t)source; + return ss.str(); +} + +// data move and copy +template +size_t inline CopyFromBufferAndMove(S *&buffer, T *dest, size_t size = 0) +{ + if (size == 0) { + size = sizeof(T); + } + if (memcpy_s(dest, size, buffer, size) != 0) { + return size; + } + buffer = buffer + size; + return size; +} + +// file read write +bool ReadIntFromProcFile(const std::string &path, int &value); +bool WriteIntToProcFile(const std::string &path, int value); +std::string ReadFileToString(const std::string &fileName); +bool ReadFileToString(const std::string &fileName, std::string &content, size_t fileSize = 0); +bool WriteStringToFile(const std::string &fileName, const std::string &value); + +// stdout +class StdoutRecord { +public: + ~StdoutRecord() + { + Stop(); // stdout need restore + } + StdoutRecord(const std::string &tempFile = EMPTY_STRING, + const std::string &mode = EMPTY_STRING); + + bool Start(); + std::string Stop(); + +private: + OHOS::UniqueFd stdoutFile_; // back and restore stdout + std::FILE *recordFile_ = nullptr; // save the output + bool stop_ = true; + std::string content_ = EMPTY_STRING; +}; + +// misc +template +float Percentage(const T &a, const T &b) +{ + return static_cast(a) / static_cast(b) * FULL_PERCENTAGE; +} + +bool IsRoot(); +bool PowerOfTwo(uint64_t n); + +#define INDENT_ONE_LEVEL (indent + 1) +#define INDENT_TWO_LEVEL (indent + 2) + +#define PrintIndent(indent, format, ...) \ + if (indent >= 0) { \ + printf("%*s" format, (indent)*2, "", ##__VA_ARGS__); \ + } else { \ + HLOGV("%s" format, "", ##__VA_ARGS__); \ + } + +#ifndef MMAP_FAILED +#define MMAP_FAILED reinterpret_cast(-1) +#endif +#ifndef MAP_FAILED +#define MAP_FAILED MMAP_FAILED +#endif +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS + +// this will also used for libunwind head (out of namespace) +#if is_mingw +#if !is_double_framework +#define HAVE_MMAP 1 +#define MAP_PRIVATE 0x02 +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 +void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset); +int munmap(void *addr, size_t); +#endif +#endif + +#endif // HIPERF_UTILITIES_H_ diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/virtual_runtime.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/virtual_runtime.h new file mode 100755 index 0000000000000000000000000000000000000000..ff81c99eb24931a45328c1ca96054220b5ec1382 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/virtual_runtime.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_VIRTUAL_RUNTIME_H +#define HIPERF_VIRTUAL_RUNTIME_H + +#include + +#include "callstack.h" +#include "perf_event_record.h" +#include "symbols_file.h" +#include "virtual_thread.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +/* +This Class contains userspace thread objects. and kernel space objects +It represents a virtual operating environment, mainly referring to the relationship between pid, +mmaps, and symbols. + +It mainly receives data is ip pointer (virtual address), pid +According to these data, it will find the corresponding mmap and its corresponding elf (also called +DSO) + +Then find the corresponding symbol in the corresponding elf symbol file according to the offset +recorded in the corresponding mmap. +*/ + +class VirtualRuntime { +public: + VirtualRuntime(bool onDevice = true); + + // thread need hook the record + // from the record , it will call back to write some Simulated Record + // case 1. some mmap will be create when it read mmaps for each new process (from record sample) + + using RecordCallBack = std::function)>; + void SetRecordMode(RecordCallBack recordCallBack); + + // this both used in report and record follow + // it process the record, and rebuild the trhread maps + // It internally determines whether to go to the Record process (which will generate virtual + // events) or the Report process by judging whether SetRecordMode has been passed. + void UpdateFromRecord(PerfEventRecord &reocrd); + + // in reocrd mode + // we make a kernel symbols from some proc file + void UpdateKernelSpaceMaps(); + void UpdateKernelModulesSpaceMaps(); + // load vdso + void LoadVdso(); + + void UpdateKernelSymbols(); + void UpdateKernelModulesSymbols(); + + // set symbols path , it will send to every symobile file for search + bool SetSymbolsPaths(const std::vector &symbolsPaths); + + // any mode + static_assert(sizeof(pid_t) == sizeof(int)); + + const std::vector> &GetSymbolsFiles() const + { + return symbolsFiles_; + } + + void SetCallStackExpend(size_t mergeLevel = 0) + { + callstackMergeLevel_ = mergeLevel; + } + + void SetDisableUnwind(bool disableUnwind) + { + HLOGV("disableUnwind change to %d", disableUnwind); + disableUnwind_ = disableUnwind; + } + + const Symbol GetSymbol(uint64_t ip, pid_t pid, pid_t tid, + const perf_callchain_context &context = PERF_CONTEXT_MAX); + + VirtualThread &GetThread(pid_t pid, pid_t tid); + const std::map &GetThreads() const + { + return userSpaceThreadMap_; + } + void SymbolicRecord(PerfRecordSample &recordSample); + + // report use + void UpdateFromPerfData(const std::vector &); + void UnwindFromRecord(PerfRecordSample &recordSample); + + // debug time +#ifdef HIPERF_DEBUG_TIME + std::chrono::microseconds updateSymbolsTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds unwindFromRecordTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds unwindCallStackTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds symbolicRecordTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds updateThreadTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds prcessSampleRecordTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds prcessMmapRecordTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds prcessMmap2RecordTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds prcessCommRecordTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds threadParseMapsTimes_ = std::chrono::microseconds::zero(); + std::chrono::microseconds threadCreateMmapTimes_ = std::chrono::microseconds::zero(); +#endif + const bool loadSymboleWhenNeeded_ = true; // this is a feature config + +private: + bool disableUnwind_ = true; + size_t callstackMergeLevel_ = 1; + CallStack callstack_; + // pid map with user space thread + std::map userSpaceThreadMap_; + // not pid , just memmap + std::vector kernelSpaceMemMaps_; + RecordCallBack recordCallBack_; + std::vector> symbolsFiles_; + enum SymbolCacheLimit : std::size_t { + KERNEL_SYMBOL_CACHE_LIMIT = 4000, + THREAD_SYMBOL_CACHE_LIMIT = 2000, + }; + std::unordered_map> threadSymbolCache_; + HashList kernelSymbolCache_ {KERNEL_SYMBOL_CACHE_LIMIT}; + bool GetSymbolCache(uint64_t ip, pid_t pid, pid_t tid, Symbol &symbol, + const perf_callchain_context &context); + // find synbols function name + void MakeCallFrame(Symbol &symbol, CallFrame &callFrame); + // records + void UpdateSymbols(std::string filename); + void UpdateFromRecord(PerfRecordSample &recordSample); + void UpdateFromRecord(PerfRecordMmap &recordMmap); + void UpdateFromRecord(PerfRecordMmap2 &recordMmap2); + void UpdateFromRecord(PerfRecordComm &recordComm); + + // threads + VirtualThread &UpdateThread(pid_t pid, pid_t tid, const std::string name = ""); + std::string ReadThreadName(pid_t tid); + VirtualThread &CreateThread(pid_t pid, pid_t tid); + + // maps + void UpdateThreadMaps(pid_t pid, pid_t tid, const std::string filename, uint64_t begin, + uint64_t len, uint64_t offset); + void UpdatekernelMap(uint64_t begin, uint64_t end, uint64_t offset, std::string filename); + + const Symbol GetKernelSymbol(uint64_t ip, const std::vector &memMaps, + const VirtualThread &thread); + const Symbol GetUserSymbol(uint64_t ip, const VirtualThread &thread); +#ifdef HIPERF_DEBUG + std::unordered_set missedRuntimeVaddr_; +#endif + void SymbolicCallFrame(PerfRecordSample& recordSample, uint64_t ip, perf_callchain_context context); + std::vector symbolsPaths_; + friend class VirtualRuntimeTest; +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_VIRTUAL_RUNTIME_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/virtual_thread.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/virtual_thread.h new file mode 100755 index 0000000000000000000000000000000000000000..5c2c85f120304bfa44973f3e8d468927b2e52989 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/include/virtual_thread.h @@ -0,0 +1,111 @@ +/* + * 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. + */ +#ifndef HIPERF_VIRTUAL_THREAD_H +#define HIPERF_VIRTUAL_THREAD_H + +#include +#include + +#include "debug_logger.h" +#include "mem_map_item.h" +#include "perf_event_record.h" +#include "symbols_file.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +/* +03284000-03289000 r--p 00000000 b3:05 289 /system/bin/sh +032b7000-032b9000 rw-p 00000000 00:00 0 +aff60000-aff96000 r--p 00000000 b3:05 923 /system/lib/libc++.so +affeb000-affed000 rw-p 00000000 00:00 0 +b0023000-b0024000 r--p 00000000 b3:05 959 /system/lib/libdl.so +*/ +const std::string MMAP_NAME_HEAP = "[heap]"; +const std::string MMAP_NAME_ANON = "[anon]"; + +class VirtualThread { +public: + VirtualThread(const VirtualThread &) = delete; + VirtualThread &operator=(const VirtualThread &) = delete; + + VirtualThread(pid_t pid, const std::vector> &symbolsFiles) + : pid_(pid), + tid_(pid), + symbolsFiles_(symbolsFiles), + processMemMaps_(), + memMaps_(processMemMaps_), + parent_(*this) {} + + VirtualThread(pid_t pid, pid_t tid, VirtualThread &thread, + const std::vector> &symbolsFiles) + : pid_(pid), + tid_(tid), + symbolsFiles_(symbolsFiles), + processMemMaps_(), + memMaps_(thread.processMemMaps_), + parent_(thread) + { + HLOG_ASSERT(pid != tid); + HLOGV("%d %d map from parent size is %zu", pid, tid, memMaps_.size()); + }; + + pid_t pid_; + pid_t tid_; + std::string name_; + + const std::vector &GetMaps() const + { + return memMaps_; + } + + void ParseMap(); + void CreateMapItem(const std::string filename, uint64_t begin, uint64_t len, uint64_t offset); + const MemMapItem *FindMapByAddr(uint64_t addr) const; + const MemMapItem *FindMapByAddr2(uint64_t addr) const; + const MemMapItem *FindMapByFileInfo(const std::string name, uint64_t offset) const; + SymbolsFile *FindSymbolsFileByMap(const MemMapItem &inMap) const; + bool ReadRoMemory(uint64_t vaddr, uint8_t *data, size_t size) const; +// #ifdef HIPERF_DEBUG + void ReportVaddrMapMiss(uint64_t vaddr) const; +// #endif + // caller want to check if new mmap is legal + static bool IsLegalFileName(const std::string &filename); + +private: + void SortMemMaps(); +#ifdef DEBUG_TIME + bool IsSorted() const; +#endif + const std::vector> &symbolsFiles_; + + // proc/xx/map + // use to put the parent thread's map + // only process have memmap + std::vector processMemMaps_; + // thread must use ref from process + std::vector &memMaps_; + VirtualThread &parent_; +#ifdef HIPERF_DEBUG + mutable std::unordered_set missedRuntimeVaddr_; +#endif +#ifdef DEBUG_MISS_SYMBOL + mutable std::vector missedSymbolFile_; +#endif +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_VIRTUAL_THREAD_H diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/option.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/option.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3cdb7187b7826b9a241362a854e98c1483bfb13 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/option.cpp @@ -0,0 +1,164 @@ +/* + * 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. + */ + +#include "option.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +namespace Option { +static std::map> g_MainOptions; + +bool CheckOptionFormat(const std::string &optionName) +{ + if (optionName.empty()) { + HLOGE("unable to use empty option name!"); + return false; + } + if (optionName.front() != '-') { + HLOGE("must use '-' at the begin of option name!"); + return false; + } + + return true; +} + +const std::map> &GetMainOptions() +{ + return g_MainOptions; +} + +const MainOption *FindMainOption(std::string argName) +{ + HLOGV("%s", argName.c_str()); + auto found = g_MainOptions.find(argName); + if (found != g_MainOptions.end()) { + // remove the subcmd itself + return found->second.get(); + } else { + return nullptr; + } +} + +std::vector::iterator FindOption(std::vector &args, + const std::string &optionName) +{ + HLOGV("try find '%s' in args: %s", optionName.c_str(), VectorToString(args).c_str()); + auto tmpit = args.begin(); + std::string::size_type position; + for (; tmpit != args.end(); tmpit++) { + position = (*tmpit).find("hiperf"); + if (position != (*tmpit).npos && (*tmpit)[(position + strlen("hiperf"))] == '\0') { + break; + } + } + auto it = find(args.begin(), args.end(), optionName); + if (it != args.end()) { + if (tmpit != args.end() && it > tmpit) { + it = args.end(); + } else { + // we found it , we remove it for next process + HLOGD("have found '%s'", optionName.c_str()); + } + } + return it; +} + +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, bool &value) +{ + value = true; + HLOGD("get bool result:'%s':'%d'", optionName.c_str(), value); + return true; +} + +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, int &value) +{ + value = std::stoi(optionValue); + HLOGD("get int result:'%s':'%d'", optionName.c_str(), value); + return true; +} + +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, float &value) +{ + value = std::stof(optionValue); + HLOGD("get float result:'%s':'%f'", optionName.c_str(), value); + return true; +} + +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, + std::string &value) +{ + value = optionValue; + return true; // every thing done +} + +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, + std::vector &values) +{ + std::vector stringValues = StringSplit(optionValue, ","); + HLOGD("split int result:'%s':'%s'", optionName.c_str(), VectorToString(stringValues).c_str()); + while (!stringValues.empty()) { + values.push_back(std::stoi(stringValues.front())); + stringValues.erase(stringValues.begin()); // remove for next process + } + return values.size() > 0; // convert successed ? +} + +bool GetValueFromString(const std::string &optionValue, const std::string &optionName, + std::vector &values) +{ + values = StringSplit(optionValue, ","); + HLOGD("split string result:'%s':'%s' from '%s'", optionName.c_str(), + VectorToString(values).c_str(), optionValue.c_str()); + return values.size() > 0; // convert successed ? +} + +bool GetOptionTrackedCommand(std::vector &args, + std::vector &trackedCommand) +{ + if (!args.empty()) { + trackedCommand.insert(trackedCommand.begin(), args.begin(), args.end()); + args.clear(); + } + return true; +} + +void ClearMainOptions() +{ + g_MainOptions.clear(); +} + +bool RegisterMainOption(const std::string &optionName, const std::string &help, + std::function &)> callBackFunction) +{ + HLOGV("%s", optionName.c_str()); + if (!CheckOptionFormat(optionName)) { + return false; + } + + if (g_MainOptions.count(optionName) == 0) { + g_MainOptions[optionName] = std::make_unique(); + g_MainOptions[optionName].get()->help = help; + g_MainOptions[optionName].get()->callBackFunction = std::move(callBackFunction); + return true; + } else { + HLOGE("main args %s already registered!", optionName.c_str()); + return false; + } +} +} // namespace Option +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_event_record.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_event_record.cpp new file mode 100755 index 0000000000000000000000000000000000000000..60d5ba81c77ccd170eb3d999686843e3ae685508 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_event_record.cpp @@ -0,0 +1,892 @@ +/* + * Copyright (c) 2021-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. + */ +#define HILOG_TAG "PerfRecord" + +#include "perf_event_record.h" +#include +#include "string_help.h" +#include "utilities.h" + + +using namespace std; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +std::unique_ptr GetPerfEventRecord(const int type, uint8_t *p, + const perf_event_attr &attr) +{ + HLOG_ASSERT(p); + uint8_t *data = p; + + // check kernel + switch (type) { + case PERF_RECORD_SAMPLE: + return std::make_unique(data, attr); + case PERF_RECORD_MMAP: + return std::make_unique(data); + case PERF_RECORD_MMAP2: + return std::make_unique(data); + case PERF_RECORD_LOST: + return std::make_unique(data); + case PERF_RECORD_COMM: + return std::make_unique(data); + case PERF_RECORD_EXIT: + return std::make_unique(data); + case PERF_RECORD_THROTTLE: + return std::make_unique(data); + case PERF_RECORD_UNTHROTTLE: + return std::make_unique(data); + case PERF_RECORD_FORK: + return std::make_unique(data); + case PERF_RECORD_READ: + return std::make_unique(data); + case PERF_RECORD_AUX: + return std::make_unique(data); + case PERF_RECORD_ITRACE_START: + return std::make_unique(data); + case PERF_RECORD_LOST_SAMPLES: + return std::make_unique(data); + case PERF_RECORD_SWITCH: + return std::make_unique(data); + case PERF_RECORD_SWITCH_CPU_WIDE: + return std::make_unique(data); + default: + HLOGE("unknown record type %d\n", type); + return nullptr; + } +} + +template +inline void PushToBinary(bool condition, uint8_t *&p, const T &v) +{ + if (condition) { + *(reinterpret_cast(p)) = v; + p += sizeof(T); + } +} + +template +inline void PushToBinary2(bool condition, uint8_t *&p, const T1 &v1, const T2 &v2) +{ + if (condition) { + *(reinterpret_cast(p)) = v1; + p += sizeof(T1); + *(reinterpret_cast(p)) = v2; + p += sizeof(T2); + } +} + +template +inline void PopFromBinary(bool condition, uint8_t *&p, T &v) +{ + if (condition) { + v = *(reinterpret_cast(p)); + p += sizeof(T); + } +} + +template +inline void PopFromBinary2(bool condition, uint8_t *&p, T1 &v1, T2 &v2) +{ + if (condition) { + v1 = *(reinterpret_cast(p)); + p += sizeof(T1); + v2 = *(reinterpret_cast(p)); + p += sizeof(T2); + } +} + +// PerfEventRecord +PerfEventRecord::PerfEventRecord(perf_event_type type, bool in_kernel, const std::string &name) + : name_(name) +{ + header.type = type; + header.misc = in_kernel ? PERF_RECORD_MISC_KERNEL : PERF_RECORD_MISC_USER; + header.size = sizeof(header); +} + +PerfEventRecord::PerfEventRecord(perf_event_hiperf_ext_type type, const std::string &name) + : name_(name) +{ + header.type = type; + header.misc = PERF_RECORD_MISC_USER; + header.size = sizeof(header); +} + +PerfEventRecord::PerfEventRecord(uint8_t *p, const std::string &name) : name_(name) +{ + header = *(reinterpret_cast(p)); +} + +void PerfEventRecord::GetHeaderBinary(std::vector &buf) const +{ + if (buf.size() < GetHeaderSize()) { + buf.resize(GetHeaderSize()); + } + uint8_t *p = buf.data(); + *(reinterpret_cast(p)) = header; +} + +void PerfEventRecord::Dump(int indent) const +{ + PrintIndent(indent, "\n"); + PrintIndent(indent, "record %s: type %u, misc %u, size %zu\n", GetName().c_str(), GetType(), + GetMisc(), GetSize()); + DumpData(indent + 1); +} + +void PerfEventRecord::DumpLog(const std::string &prefix) const +{ + HLOGV("%s: record %s: type %u, misc %u, size %zu\n", prefix.c_str(), GetName().c_str(), + GetType(), GetMisc(), GetSize()); +} + +void PerfRecordSample::DumpLog(const std::string &prefix) const +{ + HLOGV("%s: SAMPLE: id= %llu size %d pid %u tid %u ips %llu regs %llu, stacks %llu time %llu", + prefix.c_str(), data_.sample_id, header.size, data_.pid, data_.tid, data_.nr, + data_.reg_nr, data_.dyn_size, data_.time); +} + +void PerfRecordSample::ReplaceWithCallStack(size_t originalSize) +{ + // first we check if we have some user unwind stack need to merge ? + if (callFrames_.size() != 0) { + // when we have some kernel ips , we cp it first + // new size is user call frames + kernel call frames + // + PERF_CONTEXT_USER(last + 1) + expand mark(also PERF_CONTEXT_USER) + const unsigned int perfContextSize = 2; + ips_.reserve(data_.nr + callFrames_.size() + perfContextSize); + if (data_.nr > 0) { + ips_.assign(data_.ips, data_.ips + data_.nr); + } + // add user context mark + ips_.emplace_back(PERF_CONTEXT_USER); + // we also need make a expand mark just for debug only + const size_t beginIpsSize = ips_.size(); + bool ret = std::all_of(callFrames_.begin(), callFrames_.end(), [&](const CallFrame &frame) { + ips_.emplace_back(frame.ip_); + if (originalSize != 0 and (originalSize != callFrames_.size()) and + ips_.size() == (originalSize + beginIpsSize)) { + // just for debug + // so we can see which frame begin is expand call frames + ips_.emplace_back(PERF_CONTEXT_USER); + } + return true; + }); + if (ret) { + HLOGV("combed %zu", callFrames_.size()); + } else { + HLOGV("failed to combed %zu", callFrames_.size()); + } + + if (sampleType_ & PERF_SAMPLE_REGS_USER) { + data_.reg_nr = 0; + header.size -= data_.reg_nr * sizeof(u64); + } + + if (sampleType_ & PERF_SAMPLE_STACK_USER) { + // 1. remove the user stack + header.size -= data_.stack_size; + + // 2. clean the size + data_.user_abi = 0; + data_.stack_size = 0; + data_.dyn_size = 0; + } + + if (sampleType_ & PERF_SAMPLE_CALLCHAIN) { + HLOGV("ips change from %llu -> %zu", data_.nr, ips_.size()); + + // 3. remove the nr size + header.size -= data_.nr * sizeof(u64); + + // 4. add new nr size + data_.nr = ips_.size(); + header.size += data_.nr * sizeof(u64); + + // 5. change ips potin to our ips array and hold it. + data_.ips = ips_.data(); + } + } else { + // nothing need change + return; + } +} + +PerfRecordSample::PerfRecordSample(uint8_t *p, const perf_event_attr &attr) + : PerfEventRecord(p, "sample") +{ + if (p == nullptr) { + HLOG_ASSERT(p); + return; + } + sampleType_ = attr.sample_type; + + p += sizeof(header); + + // parse record according SAMPLE_TYPE + PopFromBinary(sampleType_ & PERF_SAMPLE_IDENTIFIER, p, data_.sample_id); + PopFromBinary(sampleType_ & PERF_SAMPLE_IP, p, data_.ip); + PopFromBinary2(sampleType_ & PERF_SAMPLE_TID, p, data_.pid, data_.tid); + PopFromBinary(sampleType_ & PERF_SAMPLE_TIME, p, data_.time); + PopFromBinary(sampleType_ & PERF_SAMPLE_ADDR, p, data_.addr); + PopFromBinary(sampleType_ & PERF_SAMPLE_ID, p, data_.id); + PopFromBinary(sampleType_ & PERF_SAMPLE_STREAM_ID, p, data_.stream_id); + PopFromBinary2(sampleType_ & PERF_SAMPLE_CPU, p, data_.cpu, data_.res); + PopFromBinary(sampleType_ & PERF_SAMPLE_PERIOD, p, data_.period); + PopFromBinary(sampleType_ & PERF_SAMPLE_CALLCHAIN, p, data_.nr); + if (data_.nr > 0) { + // the pointer is from input(p), require caller keep input(p) with *this together + // think it in next time + data_.ips = reinterpret_cast(p); + p += data_.nr * sizeof(u64); + } + PopFromBinary(sampleType_ & PERF_SAMPLE_RAW, p, data_.raw_size); + if (data_.raw_size > 0) { + data_.raw_data = p; + p += data_.raw_size * sizeof(u8); + } + PopFromBinary(sampleType_ & PERF_SAMPLE_BRANCH_STACK, p, data_.bnr); + if (data_.bnr > 0) { + data_.lbr = reinterpret_cast(p); + p += data_.bnr * sizeof(perf_branch_entry); + } + PopFromBinary(sampleType_ & PERF_SAMPLE_REGS_USER, p, data_.user_abi); + if (data_.user_abi > 0) { + data_.reg_mask = attr.sample_regs_user; + data_.reg_nr = __builtin_popcountll(data_.reg_mask); + data_.user_regs = reinterpret_cast(p); + p += data_.reg_nr * sizeof(u64); + } + PopFromBinary(sampleType_ & PERF_SAMPLE_STACK_USER, p, data_.stack_size); + if (data_.stack_size > 0) { + data_.stack_data = p; + p += data_.stack_size; + PopFromBinary(true, p, data_.dyn_size); + } +} + +bool PerfRecordSample::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + PushToBinary(sampleType_ & PERF_SAMPLE_IDENTIFIER, p, data_.sample_id); + PushToBinary(sampleType_ & PERF_SAMPLE_IP, p, data_.ip); + PushToBinary2(sampleType_ & PERF_SAMPLE_TID, p, data_.pid, data_.tid); + PushToBinary(sampleType_ & PERF_SAMPLE_TIME, p, data_.time); + PushToBinary(sampleType_ & PERF_SAMPLE_ADDR, p, data_.addr); + PushToBinary(sampleType_ & PERF_SAMPLE_ID, p, data_.id); + PushToBinary(sampleType_ & PERF_SAMPLE_STREAM_ID, p, data_.stream_id); + PushToBinary2(sampleType_ & PERF_SAMPLE_CPU, p, data_.cpu, data_.res); + PushToBinary(sampleType_ & PERF_SAMPLE_PERIOD, p, data_.period); + PushToBinary(sampleType_ & PERF_SAMPLE_CALLCHAIN, p, data_.nr); + if (data_.nr > 0) { + std::copy(data_.ips, data_.ips + data_.nr, reinterpret_cast(p)); + p += data_.nr * sizeof(u64); + } + PushToBinary(sampleType_ & PERF_SAMPLE_RAW, p, data_.raw_size); + if (data_.raw_size > 0) { + std::copy(data_.raw_data, data_.raw_data + data_.raw_size, p); + p += data_.raw_size * sizeof(u8); + } + PushToBinary(sampleType_ & PERF_SAMPLE_BRANCH_STACK, p, data_.bnr); + if (data_.bnr > 0) { + std::copy(data_.lbr, data_.lbr + data_.bnr, reinterpret_cast(p)); + p += data_.bnr * sizeof(perf_branch_entry); + } + PushToBinary(sampleType_ & PERF_SAMPLE_REGS_USER, p, data_.user_abi); + if (data_.user_abi > 0 && data_.reg_nr > 0) { + std::copy(data_.user_regs, data_.user_regs + data_.reg_nr, reinterpret_cast(p)); + p += data_.reg_nr * sizeof(u64); + } + PushToBinary(sampleType_ & PERF_SAMPLE_STACK_USER, p, data_.stack_size); + if (data_.stack_size > 0) { + std::copy(data_.stack_data, data_.stack_data + data_.stack_size, p); + p += data_.stack_size * sizeof(u8); + PushToBinary(true, p, data_.dyn_size); + } + + return true; +} + +void PerfRecordSample::DumpData(int indent) const +{ + PrintIndent(indent, "sample_type: 0x%" PRIx64 "\n", sampleType_); + + // dump record according sampleType + if (sampleType_ & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER)) { + PrintIndent(indent, "ID %lld\n", data_.sample_id); + } + if (sampleType_ & PERF_SAMPLE_IP) { + PrintIndent(indent, "ip %llx\n", data_.ip); + } + if (sampleType_ & PERF_SAMPLE_TID) { + PrintIndent(indent, "pid %u, tid %u\n", data_.pid, data_.tid); + } + if (sampleType_ & PERF_SAMPLE_TIME) { + PrintIndent(indent, "time %llu\n", data_.time); + } + if (sampleType_ & PERF_SAMPLE_ADDR) { + PrintIndent(indent, "addr %p\n", reinterpret_cast(data_.addr)); + } + if (sampleType_ & PERF_SAMPLE_STREAM_ID) { + PrintIndent(indent, "stream_id %lld\n", data_.stream_id); + } + if (sampleType_ & PERF_SAMPLE_CPU) { + PrintIndent(indent, "cpu %u, res %u\n", data_.cpu, data_.res); + } + if (sampleType_ & PERF_SAMPLE_PERIOD) { + PrintIndent(indent, "period %lld\n", data_.period); + } + if (sampleType_ & PERF_SAMPLE_CALLCHAIN) { + bool userContext = false; + PrintIndent(indent, "callchain nr=%lld\n", data_.nr); + for (uint64_t i = 0; i < data_.nr; ++i) { + std::string_view supplement = ""; + if ((sampleType_ & PERF_SAMPLE_STACK_USER) == 0 || data_.ips[i] != PERF_CONTEXT_USER) { + PrintIndent(indent + 1, "0x%llx%s\n", data_.ips[i], supplement.data()); + continue; + } + // is PERF_SAMPLE_STACK_USER type and is PERF_CONTEXT_USER + if (!userContext) { + userContext = true; + supplement = " "; + } else { + supplement = " "; + } + PrintIndent(indent + 1, "0x%llx%s\n", data_.ips[i], supplement.data()); + } + } + if (sampleType_ & PERF_SAMPLE_RAW) { + PrintIndent(indent, "raw size=%u\n", data_.raw_size); + const uint32_t *data = reinterpret_cast(data_.raw_data); + size_t size = data_.raw_size / sizeof(uint32_t); + for (size_t i = 0; i < size; ++i) { + PrintIndent(indent + 1, "0x%08x (%x)\n", data[i], data[i]); + } + } + if (sampleType_ & PERF_SAMPLE_BRANCH_STACK) { + PrintIndent(indent, "branch_stack nr=%lld\n", data_.bnr); + for (uint64_t i = 0; i < data_.bnr; ++i) { + auto &item = data_.lbr[i]; + PrintIndent(indent + 1, "from 0x%llx, to 0x%llx %s%s\n", item.from, item.to, + item.mispred ? "mispred" : "", item.predicted ? "predicted" : ""); + } + } + if (sampleType_ & PERF_SAMPLE_REGS_USER) { + PrintIndent(indent, "user regs: abi=%lld, reg_nr=%lld\n", data_.user_abi, data_.reg_nr); + for (uint64_t i = 0; i < data_.reg_nr; ++i) { + PrintIndent(indent + 1, "0x%llx\n", data_.user_regs[i]); + } + } + if (sampleType_ & PERF_SAMPLE_STACK_USER) { + PrintIndent(indent, "user stack: size %llu dyn_size %lld\n", data_.stack_size, + data_.dyn_size); + } +} + +inline pid_t PerfRecordSample::GetPid() const +{ + return data_.pid; +} + +PerfRecordMmap::PerfRecordMmap(uint8_t *p) : PerfEventRecord(p, "mmap") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +PerfRecordMmap::PerfRecordMmap(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff, + const std::string &filename) + : PerfEventRecord(PERF_RECORD_MMAP, inKernel, "mmap") +{ + data_.pid = pid; + data_.tid = tid; + data_.addr = addr; + data_.len = len; + data_.pgoff = pgoff; + if (strncpy_s(data_.filename, KILO, filename.c_str(), filename.size()) != 0) { + HLOGE("strncpy_s failed"); + } + + header.size = sizeof(header) + sizeof(data_) - KILO + filename.size() + 1; +} + +bool PerfRecordMmap::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + // data_.filename[] is variable-length + std::copy((uint8_t *)&data_, (uint8_t *)&data_ + GetSize() - GetHeaderSize(), p); + return true; +} + +void PerfRecordMmap::DumpData(int indent) const +{ + PrintIndent(indent, "pid %u, tid %u, addr 0x%llx, len 0x%llx\n", data_.pid, data_.tid, + data_.addr, data_.len); + PrintIndent(indent, "pgoff 0x%llx, filename %s\n", data_.pgoff, data_.filename); +} + +void PerfRecordMmap::DumpLog(const std::string &prefix) const +{ + HLOGV("%s: MMAP: size %d pid %u tid %u dso '%s' (0x%llx-0x%llx)@0x%llx", prefix.c_str(), + header.size, data_.pid, data_.tid, data_.filename, data_.addr, data_.addr + data_.len, + data_.pgoff); +} + +PerfRecordMmap2::PerfRecordMmap2(uint8_t *p) : PerfEventRecord(p, "mmap2") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +PerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, u64 addr, u64 len, u64 pgoff, + u32 maj, u32 min, u64 ino, u32 prot, u32 flags, + const std::string &filename) + : PerfEventRecord(PERF_RECORD_MMAP2, inKernel, "mmap2") +{ + data_.pid = pid; + data_.tid = tid; + data_.addr = addr; + data_.len = len; + data_.pgoff = pgoff; + data_.maj = maj; + data_.min = min; + data_.ino = ino; + data_.ino_generation = 0; + data_.prot = prot; + data_.flags = flags; + if (strncpy_s(data_.filename, KILO, filename.c_str(), filename.size()) != 0) { + HLOGE("strncpy_s failed"); + } + + header.size = sizeof(header) + sizeof(data_) - KILO + filename.size() + 1; +} + +PerfRecordMmap2::PerfRecordMmap2(bool inKernel, u32 pid, u32 tid, const MemMapItem &item) + : PerfEventRecord(PERF_RECORD_MMAP2, inKernel, "mmap2") +{ + data_.pid = pid; + data_.tid = tid; + data_.addr = item.begin_; + data_.len = item.end_ - item.begin_; + data_.pgoff = item.pageoffset_; + data_.maj = item.major_; + data_.min = item.minor_; + data_.ino = item.inode; + data_.ino_generation = 0; + data_.prot = item.type_; + data_.flags = item.flags; + if (strncpy_s(data_.filename, KILO, item.name_.c_str(), item.name_.size()) != 0) { + HLOGE("strncpy_s failed"); + } + + header.size = sizeof(header) + sizeof(data_) - KILO + item.name_.size() + 1; +} + +bool PerfRecordMmap2::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + // data_.filename[] is variable-length + std::copy((uint8_t *)&data_, (uint8_t *)&data_ + GetSize() - GetHeaderSize(), p); + return true; +} + +void PerfRecordMmap2::DumpData(int indent) const +{ + PrintIndent(indent, "pid %u, tid %u, addr 0x%llx, len 0x%llx\n", data_.pid, data_.tid, + data_.addr, data_.len); + PrintIndent(indent, "pgoff 0x%llx, maj %u, min %u, ino %llu, ino_generation %llu\n", + data_.pgoff, data_.maj, data_.min, data_.ino, data_.ino_generation); + PrintIndent(indent, "prot %u, flags %u, filename %s\n", data_.prot, data_.flags, + data_.filename); +} +void PerfRecordMmap2::DumpLog(const std::string &prefix) const +{ + HLOGV("%s: MMAP2: size %d pid %u tid %u dso '%s' (0x%llx-0x%llx)@0x%llx", prefix.c_str(), + header.size, data_.pid, data_.tid, data_.filename, data_.addr, data_.addr + data_.len, + data_.pgoff); +} + +PerfRecordLost::PerfRecordLost(uint8_t *p) : PerfEventRecord(p, "lost") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordLost::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + + return true; +} + +void PerfRecordLost::DumpData(int indent) const +{ + PrintIndent(indent, "id %llu, lost %llu\n", data_.id, data_.lost); +} + +PerfRecordComm::PerfRecordComm(uint8_t *p) : PerfEventRecord(p, "comm") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +PerfRecordComm::PerfRecordComm(bool inKernel, u32 pid, u32 tid, const std::string &comm) + : PerfEventRecord(PERF_RECORD_COMM, inKernel, "comm") +{ + data_.pid = pid; + data_.tid = tid; + if (strncpy_s(data_.comm, KILO, comm.c_str(), comm.size()) != 0) { + HLOGE("strncpy_s failed !!!"); + } + + header.size = sizeof(header) + sizeof(data_) - KILO + comm.size() + 1; +} + +bool PerfRecordComm::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + // data_.comm[] is variable-length + std::copy((uint8_t *)&data_, (uint8_t *)&data_ + GetSize() - GetHeaderSize(), p); + + return true; +} + +void PerfRecordComm::DumpData(int indent) const +{ + PrintIndent(indent, "pid %u, tid %u, comm %s\n", data_.pid, data_.tid, data_.comm); +} + +void PerfRecordComm::DumpLog(const std::string &prefix) const +{ + HLOGV("pid %u, tid %u, comm %s\n", data_.pid, data_.tid, data_.comm); +} + +PerfRecordExit::PerfRecordExit(uint8_t *p) : PerfEventRecord(p, "exit") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordExit::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} + +void PerfRecordExit::DumpData(int indent) const +{ + PrintIndent(indent, "pid %u, ppid %u, tid %u, ptid %u time 0x%llx\n", data_.pid, data_.ppid, + data_.tid, data_.ptid, data_.time); +} + +PerfRecordThrottle::PerfRecordThrottle(uint8_t *p) : PerfEventRecord(p, "throttle") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordThrottle::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} + +void PerfRecordThrottle::DumpData(int indent) const +{ + PrintIndent(indent, "time 0x%llx, id %llx, stream_id %llx\n", data_.time, data_.id, + data_.stream_id); +} + +PerfRecordUnthrottle::PerfRecordUnthrottle(uint8_t *p) : PerfEventRecord(p, "unthrottle") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordUnthrottle::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} +void PerfRecordUnthrottle::DumpData(int indent) const +{ + PrintIndent(indent, "time 0x%llx, id %llx, stream_id %llx\n", data_.time, data_.id, + data_.stream_id); +} + +PerfRecordFork::PerfRecordFork(uint8_t *p) : PerfEventRecord(p, "fork") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordFork::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} + +void PerfRecordFork::DumpData(int indent) const +{ + PrintIndent(indent, "pid %u, ppid %u, tid %u, ptid %u\n", data_.pid, data_.ppid, data_.tid, + data_.ptid); +} + +PerfRecordRead::PerfRecordRead(uint8_t *p) : PerfEventRecord(p, "read") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordRead::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} + +void PerfRecordRead::DumpData(int indent) const +{ + PrintIndent(indent, "pid %u, tid %u\n", data_.pid, data_.tid); + PrintIndent(indent, "values: value %llx, time_enabled %llx, time_running %llx, id %llx\n", + data_.values.value, data_.values.time_enabled, data_.values.time_running, + data_.values.id); +} + +PerfRecordAux::PerfRecordAux(uint8_t *p) : PerfEventRecord(p, "aux") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((void *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordAux::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} + +void PerfRecordAux::DumpData(int indent) const +{ + PrintIndent(indent, "aux_offset %llx, aux_size %llx, flags %llx\n", data_.aux_offset, + data_.aux_size, data_.flags); +} + +PerfRecordItraceStart::PerfRecordItraceStart(uint8_t *p) : PerfEventRecord(p, "itraceStart") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordItraceStart::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} + +void PerfRecordItraceStart::DumpData(int indent) const +{ + PrintIndent(indent, "pid %u, tid %u\n", data_.pid, data_.tid); +} + +PerfRecordLostSamples::PerfRecordLostSamples(uint8_t *p) : PerfEventRecord(p, "lostSamples") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordLostSamples::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} + +void PerfRecordLostSamples::DumpData(int indent) const +{ + PrintIndent(indent, "lost %llu\n", data_.lost); +} + +PerfRecordSwitch::PerfRecordSwitch(uint8_t *p) : PerfEventRecord(p, "switch") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordSwitch::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} + +PerfRecordSwitchCpuWide::PerfRecordSwitchCpuWide(uint8_t *p) : PerfEventRecord(p, "switchCpuWide") +{ + size_t copySize = GetSize() - sizeof(header); + if (memcpy_s((uint8_t *)&data_, sizeof(data_), p + sizeof(header), copySize) != 0) { + HLOGE("memcpy_s retren failed !!!"); + } +} + +bool PerfRecordSwitchCpuWide::GetBinary(std::vector &buf) const +{ + if (buf.size() < GetSize()) { + buf.resize(GetSize()); + } + + GetHeaderBinary(buf); + uint8_t *p = buf.data() + GetHeaderSize(); + + auto pDest = reinterpret_cast(p); + *pDest = data_; + return true; +} + +void PerfRecordSwitchCpuWide::DumpData(int indent) const +{ + PrintIndent(indent, "next_prev_pid %u, next_prev_tid %u\n", data_.next_prev_pid, + data_.next_prev_tid); +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_events.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_events.cpp new file mode 100755 index 0000000000000000000000000000000000000000..d53d2a0e58e2bd36ff1f3583ec99fb4270f349d0 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_events.cpp @@ -0,0 +1,1645 @@ +/* + * Copyright (c) 2021-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. + */ +#include "perf_events.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_HAS_SYSPARA) +#include +#endif + +#include "debug_logger.h" +#include "register.h" +#include "subcommand_dump.h" +#include "symbols_file.h" +#include "utilities.h" +#include "tracked_command.h" + +using namespace std; +using namespace std::chrono; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +static std::atomic_bool g_trackRunning = false; + +OHOS::UniqueFd PerfEvents::Open(perf_event_attr &attr, pid_t pid, int cpu, int group_fd, + unsigned long flags) +{ + if (perfEventParanoid_ >= PerfEventParanoid::USER) { + attr.exclude_kernel = true; // kernel restrict + } + OHOS::UniqueFd fd = UniqueFd(syscall(__NR_perf_event_open, &attr, pid, cpu, group_fd, flags)); + if (fd < 0) { + HLOGEP("syscall perf_event_open failed. "); + // dump when open failed. + SubCommandDump::DumpPrintEventAttr(attr, std::numeric_limits::min()); + } + HLOGV("perf_event_open: got fd %d for pid %d cpu %d group %d flags %lu perfEventParanoid %d", + fd.Get(), pid, cpu, group_fd, flags, perfEventParanoid_); + return fd; +} + +PerfEvents::PerfEvents() : timeOut_(DEFAULT_TIMEOUT * THOUSANDS), timeReport_(0) +{ + pageSize_ = sysconf(_SC_PAGESIZE); + HLOGI("BuildArch %s", GetArchName(buildArchType).c_str()); +} + +PerfEvents::~PerfEvents() +{ + // close mmap + for (auto it = cpuMmap_.begin(); it != cpuMmap_.end();) { + const MmapFd &mmapItem = it->second; + munmap(mmapItem.mmapPage, (1 + mmapPages_) * pageSize_); + it = cpuMmap_.erase(it); + } + + // close file descriptor of perf_event_open() created + for (auto eventGroupItem = eventGroupItem_.begin(); eventGroupItem != eventGroupItem_.end();) { + for (const auto &eventItem : eventGroupItem->eventItems) { + for (const auto &fdItem : eventItem.fdItems) { + close(fdItem.fd); + } + } + eventGroupItem = eventGroupItem_.erase(eventGroupItem); + } + + ExitReadRecordBufThread(); +} + +PerfEventParanoid PerfEvents::perfEventParanoid_ = PerfEventParanoid::UNKNOW; + +bool PerfEvents::CheckOhosPermissions() +{ +#if defined(CONFIG_HAS_SYSPARA) + std::string perfHarden = "0"; + perfHarden = OHOS::system::GetParameter(PERF_DISABLE_PARAM, perfHarden); + HLOGD("%s is %s", PERF_DISABLE_PARAM.c_str(), perfHarden.c_str()); + if (perfHarden == "1") { + printf("param '%s' is disabled, try to enable it\n", PERF_DISABLE_PARAM.c_str()); + // we will try to set it as 0 + perfHarden = OHOS::system::SetParameter(PERF_DISABLE_PARAM, "0"); + // wait init config the param + std::this_thread::sleep_for(1s); + if (OHOS::system::GetParameter(PERF_DISABLE_PARAM, perfHarden) == "1") { + printf("setparam failed. pls try setparam %s 0\n", PERF_DISABLE_PARAM.c_str()); + } + } + return perfHarden == "0"; +#else + return true; // not ohos +#endif +} + +bool PerfEvents::CheckPermissions(PerfEventParanoid request) +{ + // check the ohos param "security.perf_harden" + + if (getuid() == 0) { + // we are root perfEventParanoid as -1 + perfEventParanoid_ = PerfEventParanoid::NOLIMIT; + printf("this is root mode, perfEventParanoid assume as -1\n"); + return true; + } + + std::string perfEventParanoid = ReadFileToString(PERF_EVENT_PARANOID); + if (perfEventParanoid.empty()) { + printf("unable to read %s, assume as 2\n", PERF_EVENT_PARANOID.c_str()); + perfEventParanoid_ = PerfEventParanoid::USER; + } else { + perfEventParanoid_ = static_cast(stoi(perfEventParanoid)); + } + +#if is_ohos + // not root and in ohos + if (!CheckOhosPermissions()) { + return false; + } +#endif + + if (perfEventParanoid_ == PerfEventParanoid::NOLIMIT) { + return true; + } + printf("%s is %d\n", PERF_EVENT_PARANOID.c_str(), perfEventParanoid_); + if (perfEventParanoid_ >= PerfEventParanoid::USER) { + printf("allow only user-space measurements (default since Linux 4.6).\n"); + } else if (perfEventParanoid_ == PerfEventParanoid::KERNEL_USER) { + printf("allow both kernel and user measurements (default before Linux 4.6).\n"); + } else if (perfEventParanoid_ == PerfEventParanoid::KERNEL_USER_CPU) { + printf("allow access to CPU-specific data but not raw tracepoint samples.\n"); + } else if (perfEventParanoid_ <= PerfEventParanoid::NOLIMIT) { + printf("unable to read anything\n"); + } + printf("request level is %d\n", request); + return perfEventParanoid_ <= request; +} + +bool PerfEvents::IsEventSupport(perf_type_id type, __u64 config) +{ + HLOGV("enter"); + unique_ptr attr = PerfEvents::CreateDefaultAttr(type, config); + UniqueFd fd = Open(*attr.get()); + if (fd < 0) { + printf("event not support %s\n", GetStaticConfigName(type, config).c_str()); + return false; + } else { + return true; + } +} +bool PerfEvents::IsEventAttrSupport(perf_event_attr &attr) +{ + HLOGV("enter"); + UniqueFd fd = Open(attr); + if (fd < 0) { + return false; + } else { + return true; + } +} + +bool PerfEvents::SetBranchSampleType(uint64_t value) +{ + if (value != 0) { + // cpu-clcles event must be supported + unique_ptr attr = + PerfEvents::CreateDefaultAttr(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); + attr->sample_type |= PERF_SAMPLE_BRANCH_STACK; + attr->branch_sample_type = value; + if (!IsEventAttrSupport(*attr.get())) { + return false; + } + } + branchSampleType_ = value; + return true; +} + +bool PerfEvents::AddDefaultEvent(perf_type_id type) +{ + HLOGV("enter"); + auto it = DEFAULT_TYPE_CONFIGS.find(type); + if (it != DEFAULT_TYPE_CONFIGS.end()) { + for (auto config : it->second) { + AddEvent(type, config); + } + } + return true; +} + +bool PerfEvents::AddOffCpuEvent() +{ + std::string eventName = "sched:sched_switch"; + if (eventSpaceType_ == EventSpaceType::USER) { + eventName += ":u"; + } else if (eventSpaceType_ == EventSpaceType::KERNEL) { + eventName += ":k"; + } + return AddEvent(eventName); +} + +bool PerfEvents::AddEvents(const std::vector &eventStrings, bool group) +{ + bool followGroup = false; + HLOGV(" %s %s", VectorToString(eventStrings).c_str(), followGroup ? "followGroup" : ""); + + for (std::string eventString : eventStrings) { + if (!AddEvent(eventString, followGroup)) { + return false; + } + // this is group request , Follow-up events need to follow the previous group + if (group) { + followGroup = true; + } + } + return true; +} + +// event name can have :k or :u suffix +// tracepoint event name is like sched:sched_switch +// clang-format off +bool PerfEvents::ParseEventName(const std::string &nameStr, + std::string &name, bool &excludeUser, bool &excludeKernel, bool &isTracePoint) +// clang-format on +{ + name = nameStr; + excludeUser = false; + excludeKernel = false; + isTracePoint = false; + if (nameStr.find(":") != std::string::npos) { + static constexpr size_t maxNumberTokensNoTracePoint = 2; + static constexpr size_t maxNumberTokensTracePoint = 3; + std::vector eventTokens = StringSplit(nameStr, ":"); + if (eventTokens.size() == maxNumberTokensTracePoint) { + // tracepoint event with :u or :k + if (eventTokens.back() == "k") { + excludeUser = true; + HLOGV("kernelOnly event"); + } else if (eventTokens.back() == "u") { + excludeKernel = true; + HLOGV("userOnly event"); + } else { + HLOGV("unknown event name %s", nameStr.c_str()); + return false; + } + name = eventTokens[0] + ":" + eventTokens[1]; + isTracePoint = true; + } else if (eventTokens.size() == maxNumberTokensNoTracePoint) { + name = eventTokens[0]; + if (eventTokens.back() == "k") { + excludeUser = true; + HLOGV("kernelOnly event"); + } else if (eventTokens.back() == "u") { + excludeKernel = true; + HLOGV("userOnly event"); + } else { + name = nameStr; + isTracePoint = true; + HLOGV("tracepoint event is in form of xx:xxx"); + } + } else { + printf("unknown ':' format:'%s'\n", nameStr.c_str()); + return false; + } + if (reportCallBack_) { + if ((eventTokens[0] == "sw-task-clock" || eventTokens[0] == "sw-cpu-clock") && + (excludeUser || excludeKernel)) { + printf( + "event type %s with modifier u and modifier k is not supported by the kernel.", + eventTokens[0].c_str()); + return false; + } + } + } + return true; +} + +bool PerfEvents::AddEvent(const std::string &eventString, bool followGroup) +{ + std::string eventName; + bool excludeUser = false; + bool excludeKernel = false; + bool isTracePointEvent = false; + if (!ParseEventName(eventString, eventName, excludeUser, excludeKernel, isTracePointEvent)) { + return false; + } + if (excludeUser) { + if (requestPermission_ > PerfEventParanoid::KERNEL_USER) { + requestPermission_ = PerfEventParanoid::KERNEL_USER; + } + + eventSpaceType_ |= EventSpaceType::KERNEL; + } else if (excludeKernel) { + eventSpaceType_ |= EventSpaceType::USER; + } else { + eventSpaceType_ |= EventSpaceType::USER_KERNEL; + } + + if (isTracePointEvent) { + if (PERF_TRACEPOINT_CONFIGS.empty()) { + LoadTracepointEventTypesFromSystem(); + } + } + + // find if + if (isTracePointEvent) { + for (auto traceType : traceConfigTable) { + if (traceType.second == eventName) { + return AddEvent(PERF_TYPE_TRACEPOINT, traceType.first, excludeUser, excludeKernel, + followGroup); + } + } + } else { + for (auto type : TYPE_CONFIGS) { + for (auto config : (type.second)) { + if (config.second == eventName) { + return AddEvent(type.first, config.first, excludeUser, excludeKernel, + followGroup); + } + } + } + } + + printf("%s event is not supported by the kernel.\n", eventName.c_str()); + return false; +} + +bool PerfEvents::AddEvent(perf_type_id type, __u64 config, bool excludeUser, bool excludeKernel, + bool followGroup) +{ + HLOG_ASSERT(!excludeUser or !excludeKernel); + if (followGroup && eventGroupItem_.empty()) { + HLOGE("no group leader create before"); + return false; + } + // found the event name + if (!IsEventSupport(type, config)) { + return false; + } + HLOGV("type %d config %llu excludeUser %d excludeKernel %d followGroup %d", type, config, + excludeUser, excludeKernel, followGroup); + + // if use follow ? + EventGroupItem &eventGroupItem = followGroup ? eventGroupItem_.back() + : eventGroupItem_.emplace_back(); + // always new item + EventItem &eventItem = eventGroupItem.eventItems.emplace_back(); + + eventItem.typeName = GetTypeName(type); + if (type == PERF_TYPE_TRACEPOINT) { + eventItem.configName = GetTraceConfigName(config); + } else { + eventItem.configName = GetStaticConfigName(type, config); + } + + // attr + if (memset_s(&eventItem.attr, sizeof(perf_event_attr), 0, sizeof(perf_event_attr)) != EOK) { + HLOGE("memset_s failed in PerfEvents::AddEvent"); + return false; + } + eventItem.attr.size = sizeof(perf_event_attr); + eventItem.attr.type = type; + eventItem.attr.config = config; + eventItem.attr.disabled = 1; + eventItem.attr.read_format = + PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING | PERF_FORMAT_ID; + + eventItem.attr.inherit = (inherit_ ? 1 : 0); + eventItem.attr.exclude_kernel = excludeKernel; + eventItem.attr.exclude_user = excludeUser; + + // we also need mmap for record + if (recordCallBack_) { + if (samplePeriod_ > 0) { + eventItem.attr.freq = 0; + eventItem.attr.sample_period = samplePeriod_; + } else if (sampleFreq_ > 0) { + eventItem.attr.freq = 1; + eventItem.attr.sample_freq = sampleFreq_; + } else { + if (type == PERF_TYPE_TRACEPOINT) { + eventItem.attr.freq = 0; + eventItem.attr.sample_period = DEFAULT_SAMPLE_PERIOD; + } else { + eventItem.attr.freq = 1; + eventItem.attr.sample_freq = DEFAULT_SAMPLE_FREQUNCY; + } + } + + eventItem.attr.watermark = 1; + if (eventItem.attr.watermark == 1) { + eventItem.attr.wakeup_watermark = (mmapPages_ * pageSize_) >> 1; + static constexpr unsigned int maxWakeupMark = 1024 * 1024; + if (eventItem.attr.wakeup_watermark > maxWakeupMark) { + eventItem.attr.wakeup_watermark = maxWakeupMark; + } + } + + // for a group of events, only enable comm/mmap on the first event + if (!followGroup) { + eventItem.attr.comm = 1; + eventItem.attr.mmap = 1; + eventItem.attr.mmap2 = 1; + eventItem.attr.mmap_data = 1; + } + + if (sampleStackType_ == SampleStackType::DWARF) { + eventItem.attr.sample_type = SAMPLE_TYPE | PERF_SAMPLE_CALLCHAIN | + PERF_SAMPLE_STACK_USER | PERF_SAMPLE_REGS_USER; + eventItem.attr.exclude_callchain_user = 1; + eventItem.attr.sample_regs_user = GetSupportedRegMask(GetDeviceArch()); + eventItem.attr.sample_stack_user = dwarfSampleStackSize_; + } else if (sampleStackType_ == SampleStackType::FP) { + eventItem.attr.sample_type = SAMPLE_TYPE | PERF_SAMPLE_CALLCHAIN; + } else { + eventItem.attr.sample_type = SAMPLE_TYPE; + } + } + + // set clock id + if (clockId_ != -1) { + eventItem.attr.use_clockid = 1; + eventItem.attr.clockid = clockId_; + } + if (branchSampleType_ != 0) { + eventItem.attr.sample_type |= PERF_SAMPLE_BRANCH_STACK; + eventItem.attr.branch_sample_type = branchSampleType_; + } + + HLOGV("Add Event: '%s':'%s' %s %s %s", eventItem.typeName.c_str(), eventItem.configName.c_str(), + excludeUser ? "excludeUser" : "", excludeKernel ? "excludeKernel" : "", + followGroup ? "" : "group leader"); + + return true; +} + +std::unique_ptr PerfEvents::CreateDefaultAttr(perf_type_id type, __u64 config) +{ + unique_ptr attr = make_unique(); + if (memset_s(attr.get(), sizeof(perf_event_attr), 0, sizeof(perf_event_attr)) != EOK) { + HLOGE("memset_s failed in PerfEvents::CreateDefaultAttr"); + return nullptr; + } + attr->size = sizeof(perf_event_attr); + attr->type = type; + attr->config = config; + attr->disabled = 1; + return attr; +} + +// should move to upper caller +static struct sigaction g_oldSig { +}; +static bool CaptureSig() +{ + HLOGD("capture Ctrl + C to end sampling decently"); + struct sigaction sig { + }; + + sig.sa_handler = [](int sig) { + printf("\n Ctrl + C detected.\n"); + g_trackRunning = false; + }; + + sig.sa_flags = 0; + if (sigaction(SIGINT, &sig, &g_oldSig) < 0) { + perror("Fail to call sigaction for SIGINT"); + return false; + } + return true; +} + +static void RecoverCaptureSig() +{ + if (sigaction(SIGINT, &g_oldSig, nullptr) < 0) { + perror("Fail to call sigaction for SIGINT"); + } +} + +// split to two part +// because WriteAttrAndId need fd id before start tracking +bool PerfEvents::PrepareTracking(void) +{ + HLOGV("enter"); + + if (!CheckPermissions(requestPermission_)) { + return false; + } + + // 1. prepare cpu pid + if (!PrepareFdEvents()) { + HLOGE("PrepareFdEvents() failed"); + return false; + } + + // 2. create events + if (!CreateFdEvents()) { + HLOGE("CreateFdEvents() failed"); + return false; + } + + prepared_ = true; + return true; +} + +void PerfEvents::ExitReadRecordBufThread() +{ + if (isLowPriorityThread_) { + if (setpriority(PRIO_PROCESS, gettid(), 0) != 0) { + HLOGW("failed to decrease priority of reading kernel"); + } + } + if (readRecordBufThread_.joinable()) { + readRecordThreadRunning_ = false; + __sync_synchronize(); + cvRecordBuf_.notify_one(); + readRecordBufThread_.join(); + } +} + +bool PerfEvents::PrepareRecordThread() +{ + try { + recordBuf_ = std::make_unique(CalcBufferSize()); + } catch (const std::exception &e) { + printf("create record buffer(size %zu) failed: %s\n", CalcBufferSize(), e.what()); + return false; + } + readRecordThreadRunning_ = true; + readRecordBufThread_ = std::thread(&PerfEvents::ReadRecordFromBuf, this); + + rlimit rlim; + int result = getrlimit(RLIMIT_NICE, &rlim); + const rlim_t lowPriority = 40; + if (result == 0 && rlim.rlim_cur == lowPriority) { + const int highPriority = -20; + result = setpriority(PRIO_PROCESS, gettid(), highPriority); + if (result != 0) { + HLOGW("failed to increase priority of reading kernel"); + } else { + isLowPriorityThread_ = true; + } + } + + return true; +} + +void PerfEvents::WaitRecordThread() +{ + printf("Process and Saving data...\n"); + ExitReadRecordBufThread(); + + const auto usedTimeMsTick = duration_cast(steady_clock::now() - trackingEndTime_); + if (verboseReport_) { + printf("Record Process Completed (wait %" PRId64 " ms)\n", (uint64_t)usedTimeMsTick.count()); + } + HLOGV("Record Process Completed (wait %" PRId64 " ms)\n", (uint64_t)usedTimeMsTick.count()); +#ifdef HIPERF_DEBUG_TIME + printf("%zu record processed, used %0.3f ms(%4.2f us/record)\n", recordEventCount_, + recordCallBackTime_.count() / MS_DUARTION, + recordCallBackTime_.count() / static_cast(recordEventCount_)); + printf("total wait sleep time %0.3f ms.\n", recordSleepTime_.count() / MS_DUARTION); + printf("read from kernel time %0.3f ms.\n", recordKernelReadTime_.count() / MS_DUARTION); +#endif +} + +bool PerfEvents::StartTracking(bool immediately) +{ + if (!prepared_) { + return false; + } + + HLOGD("step: 1. enable event"); + trackingStartTime_ = steady_clock::now(); + if (immediately) { + if (!EnableTracking()) { + HLOGE("PerfEvents::EnableTracking() failed"); + return false; + } + } + + if (recordCallBack_) { + if (!PrepareRecordThread()) { + return false; + } + } + + if (immediately) { + printf("Profiling duration is %.3f seconds.\n", float(timeOut_.count()) / THOUSANDS); + printf("Start Profiling...\n"); + } + + g_trackRunning = true; + if (!CaptureSig()) { + HLOGE("captureSig() failed"); + g_trackRunning = false; + ExitReadRecordBufThread(); + return false; + } + + HLOGD("step: 2. thread loop"); + if (recordCallBack_) { + RecordLoop(); + } else { + StatLoop(); + } + + HLOGD("step: 3. disable event"); + if (!PerfEventsEnable(false)) { + HLOGE("PerfEvents::PerfEventsEnable() failed"); + } + trackingEndTime_ = steady_clock::now(); + + RecoverCaptureSig(); + + if (recordCallBack_) { + WaitRecordThread(); + } + + HLOGD("step: 4. exit"); + return true; +} + +bool PerfEvents::StopTracking(void) +{ + if (g_trackRunning) { + printf("some one called StopTracking\n"); + g_trackRunning = false; + if (trackedCommand_) { + if (trackedCommand_->GetState() == TrackedCommand::State::COMMAND_STARTED) { + trackedCommand_->Stop(); + } + } + if (!PerfEventsEnable(false)) { + HLOGE("StopTracking : PerfEventsEnable(false) failed"); + return false; + } + } + return true; +} + +bool PerfEvents::PauseTracking(void) +{ + if (!startedTracking_) { + return false; + } + return PerfEventsEnable(false); +} + +bool PerfEvents::ResumeTracking(void) +{ + if (!startedTracking_) { + return false; + } + return PerfEventsEnable(true); +} + +bool PerfEvents::EnableTracking() +{ + if (startedTracking_) { + return true; + } + if (!PerfEventsEnable(true)) { + HLOGE("PerfEvents::PerfEventsEnable() failed"); + return false; + } + + if (trackedCommand_) { + // start tracked Command + if (trackedCommand_->GetState() == TrackedCommand::State::COMMAND_WAITING) { + if (!trackedCommand_->StartCommand()) { + int wstatus; + if (!trackedCommand_->WaitCommand(wstatus)) { + trackedCommand_->Stop(); + } + std::string commandName = trackedCommand_->GetCommandName(); + printf("failed to execute command: %zu: %s\n", commandName.size(), commandName.c_str()); + return false; + } + } else if (trackedCommand_->GetState() != TrackedCommand::State::COMMAND_STARTED) { + return false; + } + } + startedTracking_ = true; + return true; +} + +bool PerfEvents::IsTrackRunning() +{ + return g_trackRunning; +} + +void PerfEvents::SetSystemTarget(bool systemTarget) +{ + systemTarget_ = systemTarget; +} + +void PerfEvents::SetCpu(std::vector cpus) +{ + cpus_ = cpus; + + if (!cpus_.empty()) { + if (requestPermission_ > PerfEventParanoid::KERNEL_USER_CPU) { + requestPermission_ = PerfEventParanoid::KERNEL_USER_CPU; + } + } +} + +void PerfEvents::SetPid(std::vector pids) +{ + pids_ = pids; +} + +void PerfEvents::SetTimeOut(float timeOut) +{ + if (timeOut > 0) { + timeOut_ = milliseconds(static_cast(timeOut * THOUSANDS)); + } +} + +void PerfEvents::SetTimeReport(int timeReport) +{ + static constexpr int minMsReportInterval = 100; + if (timeReport < minMsReportInterval && timeReport != 0) { + timeReport = minMsReportInterval; + printf("time report min value is %d.\n", timeReport); + } + + timeReport_ = milliseconds(timeReport); +} + +std::map<__u64, std::string> PerfEvents::GetSupportEvents(perf_type_id type) +{ + if (type == PERF_TYPE_TRACEPOINT) { + LoadTracepointEventTypesFromSystem(); + } + + std::map<__u64, std::string> eventConfigs; + auto configTable = TYPE_CONFIGS.find(type); + if (configTable != TYPE_CONFIGS.end()) { + auto configs = configTable->second; + for (auto config : configs) { + if (type == PERF_TYPE_TRACEPOINT || IsEventSupport(type, (__u64)config.first)) { + eventConfigs.insert(config); + } else { + HLOGD("'%s' not support", config.second.c_str()); + } + } + } + return eventConfigs; +} + +void PerfEvents::LoadTracepointEventTypesFromSystem() +{ + if (PERF_TRACEPOINT_CONFIGS.empty()) { + std::string basePath {"/sys/kernel/tracing/events"}; + if (access(basePath.c_str(), R_OK) != 0) { + basePath = "/sys/kernel/debug/tracing/events"; + } + for (const auto &eventName : GetSubDirs(basePath)) { + std::string eventPath = basePath + "/" + eventName; + for (const auto &concreteEvent : GetSubDirs(eventPath)) { + std::string idPath = eventPath + "/" + concreteEvent + "/id"; + { + std::ifstream ifs {idPath}; + // clang-format off + const std::string idStr = { + std::istreambuf_iterator(ifs), + std::istreambuf_iterator() + }; + // clang-format on + __u64 id {0}; + try { + id = std::stoul(idStr, nullptr); + } catch (...) { + continue; + } + auto typeConfigs = TYPE_CONFIGS.find(PERF_TYPE_TRACEPOINT); + HLOG_ASSERT(typeConfigs != TYPE_CONFIGS.end()); + auto configPair = typeConfigs->second.insert( + std::make_pair(id, eventName + ":" + concreteEvent)); + traceConfigTable.insert(std::make_pair(id, eventName + ":" + concreteEvent)); + ConfigTable::iterator it = configPair.first; + HLOGV("TYPE_CONFIGS add %llu:%s in %zu", it->first, it->second.c_str(), + typeConfigs->second.size()); + } + } + } + } +} + +void PerfEvents::SetVerboseReport(bool verboseReport) +{ + verboseReport_ = verboseReport; +} + +void PerfEvents::SetSampleFrequency(unsigned int frequency) +{ + if (frequency > 0) { + sampleFreq_ = frequency; + } +} + +void PerfEvents::SetSamplePeriod(unsigned int period) +{ + if (period > 0) { + samplePeriod_ = period; + } +} + +void PerfEvents::SetMmapPages(size_t mmapPages) +{ + mmapPages_ = mmapPages; +} + +void PerfEvents::SetSampleStackType(SampleStackType type) +{ + sampleStackType_ = type; +} + +void PerfEvents::SetDwarfSampleStackSize(uint32_t stackSize) +{ + HLOGD("request stack size is %u", stackSize); + dwarfSampleStackSize_ = stackSize; +} + +bool PerfEvents::PerfEventsEnable(bool enable) +{ + HLOGV("%s", std::to_string(enable).c_str()); + for (const auto &eventGroupItem : eventGroupItem_) { + for (const auto &eventItem : eventGroupItem.eventItems) { + for (const auto &fdItem : eventItem.fdItems) { + int result = + ioctl(fdItem.fd, enable ? PERF_EVENT_IOC_ENABLE : PERF_EVENT_IOC_DISABLE, 0); + if (result < 0) { + printf("Cannot '%s' perf fd! type config name: '%s:%s'\n", + enable ? "enable" : "disable", eventItem.typeName.c_str(), + eventItem.configName.c_str()); + return false; + } + } + } + } + return true; +} + +void PerfEvents::SetStatCallBack(StatCallBack reportCallBack) +{ + reportCallBack_ = reportCallBack; +} +void PerfEvents::SetRecordCallBack(RecordCallBack recordCallBack) +{ + recordCallBack_ = recordCallBack; +} + +inline void PerfEvents::PutAllCpus() +{ + int cpuConfigs = sysconf(_SC_NPROCESSORS_CONF); + for (int i = 0; i < cpuConfigs; i++) { + cpus_.push_back(i); // put all cpu + } +} + +bool PerfEvents::PrepareFdEvents(void) +{ + HLOGV("enter"); + /* + https://man7.org/linux/man-pages/man2/perf_event_open.2.html + pid == 0 and cpu == -1 + This measures the calling process/thread on any CPU. + + pid == 0 and cpu >= 0 + This measures the calling process/thread only when running + on the specified CPU. + + pid > 0 and cpu == -1 + This measures the specified process/thread on any CPU. + + pid > 0 and cpu >= 0 + This measures the specified process/thread only when + running on the specified CPU. + + pid == -1 and cpu >= 0 + This measures all processes/threads on the specified CPU. + This requires CAP_PERFMON (since Linux 5.8) or + CAP_SYS_ADMIN capability or a + /proc/sys/kernel/perf_event_paranoid value of less than 1. + + pid == -1 and cpu == -1 + This setting is invalid and will return an error. + */ + if (systemTarget_) { + pids_.clear(); + pids_.push_back(-1); + + if (cpus_.empty()) { + PutAllCpus(); + } + } else { + if (trackedCommand_) { + pids_.push_back(trackedCommand_->GetChildPid()); + } + if (pids_.empty()) { + pids_.push_back(0); // no pid means use 0 as self pid + } + if (cpus_.empty()) { + // new review . if perfEventParanoid_ < CPU, how should be CreateMmap work? + if (perfEventParanoid_ <= PerfEventParanoid::KERNEL_USER_CPU) { + // PERF_EVENT_IOC_SET_OUTPUT doesn't support using -1 as all cpu + PutAllCpus(); + } else { + cpus_.push_back(-1); // no cpu as all cpu + } + } + } + + // print info tell user which cpu and process we will select. + if (pids_.size() == 1 && pids_[0] == -1) { + HLOGI("target process: system scope \n"); + } else { + HLOGI("target process: %zu (%s)\n", pids_.size(), + (pids_[0] == 0) ? std::to_string(gettid()).c_str() : VectorToString(pids_).c_str()); + } + if (cpus_.size() == 1 && cpus_[0] == -1) { + HLOGI("target cpus: %ld \n", sysconf(_SC_NPROCESSORS_CONF)); + } else { + HLOGI("target cpus: %zu / %ld (%s)\n", cpus_.size(), sysconf(_SC_NPROCESSORS_CONF), + VectorToString(cpus_).c_str()); + } + + return true; +} + +bool PerfEvents::CreateFdEvents(void) +{ + HLOGV("enter"); + + // must be some events , or will failed + if (eventGroupItem_.empty()) { + printf("no event select.\n"); + return false; + } + + // create each fd by cpu and process user select + /* + https://man7.org/linux/man-pages/man2/perf_event_open.2.html + + (A single event on its own is created with group_fd = -1 and is + considered to be a group with only 1 member.) + */ + // Even if there is only one event, it is counted as a group. + + uint fdNumber = 0; + uint eventNumber = 0; + uint groupNumber = 0; + for (auto &eventGroupItem : eventGroupItem_) { + /* + Explain what is the configuration of the group: + Suppose we have 2 Event, 2 PID, and 3 CPU settings + According to verification, + Group's fd requires the pid to be the same as the cpu, the only difference is event + In other words, if you want to bind E1 and E2 to the same group + That can only be like this: + + event E1 pid P1 cpu C1 [Group 1] + event E1 pid P1 cpu C2 [Group 2] + event E1 pid P1 cpu C3 [Group 3] + + event E1 pid P2 cpu C1 [Group 4] + event E1 pid P2 cpu C2 [Group 5] + event E1 pid P2 cpu C3 [Group 6] + + event E2 pid P1 cpu C1 [Group 1] + event E2 pid P1 cpu C2 [Group 2] + event E2 pid P1 cpu C3 [Group 3] + + event E2 pid P2 cpu C1 [Group 4] + event E2 pid P2 cpu C2 [Group 5] + event E2 pid P2 cpu C3 [Group 6] + */ + HLOGV("group %2u. eventGroupItem leader: '%s':", groupNumber++, + eventGroupItem.eventItems[0].configName.c_str()); + + int groupFdCache[cpus_.size()][pids_.size()]; + for (size_t i = 0; i < cpus_.size(); i++) { // each cpu + for (size_t j = 0; j < pids_.size(); j++) { // each pid + // The leader is created first, with group_fd = -1. + groupFdCache[i][j] = -1; + } + } + + uint eventIndex = 0; + for (auto &eventItem : eventGroupItem.eventItems) { + HLOGV(" - event %2u. eventName: '%s:%s'", eventIndex++, eventItem.typeName.c_str(), + eventItem.configName.c_str()); + + for (size_t icpu = 0; icpu < cpus_.size(); icpu++) { // each cpu + for (size_t ipid = 0; ipid < pids_.size(); ipid++) { // each pid + // one fd event group must match same cpu and same pid config (event can be + // different) + // clang-format off + UniqueFd fd = Open(eventItem.attr, pids_[ipid], cpus_[icpu], + groupFdCache[icpu][ipid], 0); + // clang-format on + if (fd < 0) { + if (errno == ESRCH) { + if (verboseReport_) { + printf("pid %d does not exist.\n", pids_[ipid]); + } + HLOGE("pid %d does not exist.\n", pids_[ipid]); + continue; + } else { + // clang-format off + if (verboseReport_) { + char errInfo[ERRINFOLEN] = { 0 }; + strerror_r(errno, errInfo, ERRINFOLEN); + printf("%s event is not supported by the kernel on cpu %d. reason: %d:%s\n", + eventItem.configName.c_str(), cpus_[icpu], errno, errInfo); + } + char errInfo[ERRINFOLEN] = { 0 }; + strerror_r(errno, errInfo, ERRINFOLEN); + HLOGE("%s event is not supported by the kernel on cpu %d. reason: %d:%s\n", + eventItem.configName.c_str(), cpus_[icpu], errno, errInfo); + // clang-format on + break; // jump to next cpu + } + } + // after open successed , fill the result + // make a new FdItem + FdItem &fdItem = eventItem.fdItems.emplace_back(); + fdItem.fd = move(fd); + fdItem.cpu = cpus_[icpu]; + fdItem.pid = pids_[ipid]; + fdNumber++; + + // if sampling, mmap ring buffer + if (recordCallBack_) { + CreateMmap(fdItem, eventItem.attr); + } + // update group leader + if (groupFdCache[icpu][ipid] == -1) { + groupFdCache[icpu][ipid] = fd.Get(); + } + } + } + eventNumber++; + } + } + + if (fdNumber == 0) { + HLOGE("open %d fd for %d events", fdNumber, eventNumber); + return false; + } + + HLOGD("will try read %u events from %u fd (%zu groups):", eventNumber, fdNumber, + eventGroupItem_.size()); + + return true; +} + +bool PerfEvents::StatReport(const __u64 &durationInSec) +{ + read_format_no_group readNoGroupValue; + + // only need read when need report + HLOGM("eventGroupItem_:%zu", eventGroupItem_.size()); + __u64 groupId = 0; + // clear countEvents data + countEvents_.clear(); + for (const auto &eventGroupItem : eventGroupItem_) { + HLOGM("eventItems:%zu", eventGroupItem.eventItems.size()); + groupId++; + for (const auto &eventItem : eventGroupItem.eventItems) { + // count event info together (every cpu , every pid) + std::string configName = ""; + if (eventItem.attr.exclude_kernel) { + configName = eventItem.configName + ":u"; + } else if (eventItem.attr.exclude_user) { + configName = eventItem.configName + ":k"; + } else { + configName = eventItem.configName; + } + if (countEvents_.count(configName) == 0) { + auto countEvent = make_unique(CountEvent {}); + countEvents_[configName] = std::move(countEvent); + countEvents_[configName]->userOnly = eventItem.attr.exclude_kernel; + countEvents_[configName]->kernelOnly = eventItem.attr.exclude_user; + } + std::unique_ptr &countEvent = countEvents_[configName]; + HLOGM("eventItem.fdItems:%zu", eventItem.fdItems.size()); + for (const auto &fditem : eventItem.fdItems) { + if (read(fditem.fd, &readNoGroupValue, sizeof(readNoGroupValue)) > 0) { + countEvent->eventCount += readNoGroupValue.value; + countEvent->time_enabled += readNoGroupValue.time_enabled; + countEvent->time_running += readNoGroupValue.time_running; + countEvent->id = groupId; + if (durationInSec != 0) { + countEvent->used_cpus = + (countEvent->eventCount / 1e9) / (durationInSec / THOUSANDS); + } + if (verboseReport_) { + printf("%s id:%llu(c%d:p%d) time_enabled:%llu time_running:%llu " + "value:%llu\n", + eventItem.configName.c_str(), readNoGroupValue.id, fditem.cpu, + fditem.pid, readNoGroupValue.time_enabled, + readNoGroupValue.time_running, readNoGroupValue.value); + } + } else { + printf("read failed from event '%s'\n", eventItem.configName.c_str()); + } + } + } + } + + reportCallBack_(countEvents_); + + return true; +} + +bool PerfEvents::CreateMmap(const FdItem &item, const perf_event_attr &attr) +{ + auto it = cpuMmap_.find(item.cpu); + if (it == cpuMmap_.end()) { + void *rbuf = mmap(nullptr, (1 + mmapPages_) * pageSize_, PROT_READ | PROT_WRITE, MAP_SHARED, + item.fd.Get(), 0); + if (rbuf == MMAP_FAILED) { + perror("Fail to call mmap \n"); + return false; + } + MmapFd mmapItem; + mmapItem.fd = item.fd.Get(); + mmapItem.mmapPage = reinterpret_cast(rbuf); + mmapItem.buf = reinterpret_cast(rbuf) + pageSize_; + mmapItem.bufSize = mmapPages_ * pageSize_; + mmapItem.attr = &attr; + mmapItem.posCallChain = GetCallChainPosInSampleRecord(attr); + + cpuMmap_[item.cpu] = mmapItem; + pollFds_.emplace_back(pollfd {mmapItem.fd, POLLIN, 0}); + HLOGD("CreateMmap success cpu %d fd %d", item.cpu, mmapItem.fd); + } else { + const MmapFd &mmapItem = it->second; + int rc = ioctl(item.fd.Get(), PERF_EVENT_IOC_SET_OUTPUT, mmapItem.fd); + if (rc != 0) { + HLOGEP("ioctl PERF_EVENT_IOC_SET_OUTPUT (%d -> %d) ", item.fd.Get(), mmapItem.fd); + perror("failed to share mapped buffer\n"); + return false; + } + } + return true; +} + +std::vector PerfEvents::GetAttrWithId() const +{ + std::vector result; + HLOGV("eventGroupItem_ %zu :", eventGroupItem_.size()); + + for (const auto &eventGroupItem : eventGroupItem_) { + HLOGV(" eventItems %zu eventItems:", eventGroupItem.eventItems.size()); + for (const auto &eventItem : eventGroupItem.eventItems) { + AttrWithId attrId; + attrId.attr = eventItem.attr; + attrId.name = eventItem.configName; + HLOGV(" fdItems %zu fdItems:", eventItem.fdItems.size()); + for (const auto &fdItem : eventItem.fdItems) { + auto &id = attrId.ids.emplace_back(fdItem.GetPrefId()); + HLOGV(" eventItem.fdItems GetPrefId %" PRIu64 "", id); + } + result.emplace_back(attrId); + } + } + return result; +} + +size_t PerfEvents::CalcBufferSize() +{ + size_t bufferSize = MAX_BUFFER_SIZE; + if (!systemTarget_) { + // suppose ring buffer is 4 times as much as mmap + static constexpr int TIMES = 4; + bufferSize = cpuMmap_.size() * mmapPages_ * pageSize_ * TIMES; + if (bufferSize < MIN_BUFFER_SIZE) { + bufferSize = MIN_BUFFER_SIZE; + } else if (bufferSize > MAX_BUFFER_SIZE) { + bufferSize = MAX_BUFFER_SIZE; + } + } + HLOGD("CalcBufferSize return %zu", bufferSize); + return bufferSize; +} + +inline bool PerfEvents::IsRecordInMmap() +{ + if (pollFds_.size() > 0) { + if (poll((struct pollfd *)pollFds_.data(), pollFds_.size(), pollTimeOut_) <= 0) { + // time out try again + return false; + } + } + return true; +} + +static bool CompareRecordTime(const PerfEvents::MmapFd *left, const PerfEvents::MmapFd *right) +{ + return left->timestamp > right->timestamp; +} + +void PerfEvents::ReadRecordsFromMmaps() +{ +#ifdef HIPERF_DEBUG_TIME + const auto readKenelStartTime = steady_clock::now(); +#endif + // get readable mmap at this time + for (auto &it : cpuMmap_) { + ssize_t dataSize = it.second.mmapPage->data_head - it.second.mmapPage->data_tail; + __sync_synchronize(); // this same as rmb in gcc, after reading mmapPage->data_head + if (dataSize <= 0) { + continue; + } + it.second.dataSize = dataSize; + MmapRecordHeap_.push_back(&(it.second)); + } + if (MmapRecordHeap_.empty()) { + return; + } + + if (MmapRecordHeap_.size() > 1) { + for (auto &it : MmapRecordHeap_) { + GetRecordFromMmap(*it); + } + std::make_heap(MmapRecordHeap_.begin(), MmapRecordHeap_.end(), CompareRecordTime); + + size_t heapSize = MmapRecordHeap_.size(); + while (heapSize > 1) { + std::pop_heap(MmapRecordHeap_.begin(), MmapRecordHeap_.begin() + heapSize, + CompareRecordTime); + MoveRecordToBuf(*MmapRecordHeap_[heapSize - 1]); + if (GetRecordFromMmap(*MmapRecordHeap_[heapSize - 1])) { + std::push_heap(MmapRecordHeap_.begin(), MmapRecordHeap_.begin() + heapSize, + CompareRecordTime); + } else { + heapSize--; + } + } + } + + while (GetRecordFromMmap(*MmapRecordHeap_.front())) { + MoveRecordToBuf(*MmapRecordHeap_.front()); + } + MmapRecordHeap_.clear(); + cvRecordBuf_.notify_one(); + +#ifdef HIPERF_DEBUG_TIME + recordKernelReadTime_ += duration_cast(steady_clock::now() - readKenelStartTime); +#endif +} + +bool PerfEvents::GetRecordFromMmap(MmapFd &mmap) +{ + if (mmap.dataSize <= 0) { + return false; + } + + GetRecordFieldFromMmap(mmap, &(mmap.header), mmap.mmapPage->data_tail, sizeof(mmap.header)); + if (mmap.header.type != PERF_RECORD_SAMPLE) { + mmap.timestamp = 0; + return true; + } + // in PERF_RECORD_SAMPLE : header + u64 sample_id + u64 ip + u32 pid + u32 tid + u64 time + constexpr size_t timePos = sizeof(perf_event_header) + sizeof(uint64_t) + sizeof(uint64_t) + + sizeof(uint32_t) + sizeof(uint32_t); + GetRecordFieldFromMmap(mmap, &(mmap.timestamp), mmap.mmapPage->data_tail + timePos, + sizeof(mmap.timestamp)); + return true; +} + +void PerfEvents::GetRecordFieldFromMmap(MmapFd &mmap, void *dest, size_t pos, size_t size) +{ + pos = pos % mmap.bufSize; + size_t tailSize = mmap.bufSize - pos; + size_t copySize = std::min(size, tailSize); + if (memcpy_s(dest, copySize, mmap.buf + pos, copySize) != 0) { + HLOGEP("memcpy_s %p to %p failed. size %zd", mmap.buf + pos, dest, copySize); + } + if (copySize < size) { + size -= copySize; + if (memcpy_s(static_cast(dest) + copySize, size, mmap.buf, size) != 0) { + HLOGEP("memcpy_s %p to %p failed. size %zd", mmap.buf, + static_cast(dest) + copySize, size); + } + } +} + +size_t PerfEvents::GetCallChainPosInSampleRecord(const perf_event_attr &attr) +{ + // reference struct PerfRecordSampleData + int fixedFieldNumber = __builtin_popcountll( + attr.sample_type & (PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_IP | PERF_SAMPLE_TID | + PERF_SAMPLE_TIME | PERF_SAMPLE_ADDR | PERF_SAMPLE_ID | + PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)); + size_t pos = sizeof(perf_event_header) + sizeof(uint64_t) * fixedFieldNumber; + if (attr.sample_type & PERF_SAMPLE_READ) { + pos += sizeof(read_format); + } + return pos; +} + +size_t PerfEvents::GetStackSizePosInSampleRecord(MmapFd &mmap) +{ + size_t pos = mmap.posCallChain; + if (mmap.attr->sample_type & PERF_SAMPLE_CALLCHAIN) { + uint64_t nr = 0; + GetRecordFieldFromMmap(mmap, &nr, mmap.mmapPage->data_tail + pos, sizeof(nr)); + pos += (sizeof(nr) + nr * sizeof(uint64_t)); + } + if (mmap.attr->sample_type & PERF_SAMPLE_RAW) { + uint32_t raw_size = 0; + GetRecordFieldFromMmap(mmap, &raw_size, mmap.mmapPage->data_tail + pos, sizeof(raw_size)); + pos += (sizeof(raw_size) + raw_size); + } + if (mmap.attr->sample_type & PERF_SAMPLE_BRANCH_STACK) { + uint64_t bnr = 0; + GetRecordFieldFromMmap(mmap, &bnr, mmap.mmapPage->data_tail + pos, sizeof(bnr)); + pos += (sizeof(bnr) + bnr * sizeof(perf_branch_entry)); + } + if (mmap.attr->sample_type & PERF_SAMPLE_REGS_USER) { + uint64_t user_abi = 0; + GetRecordFieldFromMmap(mmap, &user_abi, mmap.mmapPage->data_tail + pos, sizeof(user_abi)); + pos += sizeof(user_abi); + if (user_abi > 0) { + uint64_t reg_nr = __builtin_popcountll(mmap.attr->sample_regs_user); + pos += reg_nr * sizeof(uint64_t); + } + } + return pos; +} + +bool PerfEvents::CutStackAndMove(MmapFd &mmap) +{ + constexpr uint32_t alignSize = 64; + if (!(mmap.attr->sample_type & PERF_SAMPLE_STACK_USER)) { + return false; + } + size_t stackSizePos = GetStackSizePosInSampleRecord(mmap); + uint64_t stackSize = 0; + GetRecordFieldFromMmap(mmap, &stackSize, mmap.mmapPage->data_tail + stackSizePos, + sizeof(stackSize)); + if (stackSize == 0) { + return false; + } + size_t dynSizePos = stackSizePos + sizeof(uint64_t) + stackSize; + uint64_t dynSize = 0; + GetRecordFieldFromMmap(mmap, &dynSize, mmap.mmapPage->data_tail + dynSizePos, sizeof(dynSize)); + uint64_t newStackSize = std::min(ALIGN(dynSize, alignSize), stackSize); + if (newStackSize >= stackSize) { + return false; + } + HLOGM("stackSize %" PRIx64 " dynSize %" PRIx64 " newStackSize %" PRIx64 "\n", stackSize, dynSize, newStackSize); + // move and cut stack_data + // mmap: |<+++copy1+++>|<++++++copy2++++++>|<---------------cut--------------->|<+++copy3+++>| + // ^ ^ ^ ^ + // new_header stackSizePos dynSizePos + uint16_t recordSize = mmap.header.size; + mmap.header.size -= stackSize - newStackSize; // reduce the stack size + uint8_t *buf = recordBuf_->AllocForWrite(mmap.header.size); + // copy1: new_header + if (memcpy_s(buf, sizeof(perf_event_header), &(mmap.header), sizeof(perf_event_header)) != 0) { + HLOGEP("memcpy_s %p to %p failed. size %zd", &(mmap.header), buf, + sizeof(perf_event_header)); + } + size_t copyPos = sizeof(perf_event_header); + size_t copySize = stackSizePos - sizeof(perf_event_header) + sizeof(stackSize) + newStackSize; + // copy2: copy stack_size, data[stack_size], + GetRecordFieldFromMmap(mmap, buf + copyPos, mmap.mmapPage->data_tail + copyPos, copySize); + copyPos += copySize; + // copy3: copy dyn_size + GetRecordFieldFromMmap(mmap, buf + copyPos, mmap.mmapPage->data_tail + dynSizePos, + recordSize - dynSizePos); + // update stack_size + if (memcpy_s(buf + stackSizePos, sizeof(stackSize), &(newStackSize), sizeof(newStackSize)) != 0) { + HLOGEP("memcpy_s %p to %p failed. size %zd", &(newStackSize), buf + stackSizePos, sizeof(newStackSize)); + } + recordBuf_->EndWrite(); + __sync_synchronize(); + mmap.mmapPage->data_tail += recordSize; + mmap.dataSize -= recordSize; + return true; +} + +void PerfEvents::MoveRecordToBuf(MmapFd &mmap) +{ + uint8_t *buf = nullptr; + if (mmap.header.type == PERF_RECORD_SAMPLE) { + if (recordBuf_->GetFreeSize() <= BUFFER_CRITICAL_LEVEL) { + lostSamples_++; + HLOGD("BUFFER_CRITICAL_LEVEL: lost sample record"); + goto RETURN; + } + if (CutStackAndMove(mmap)) { + return; + } + } else if (mmap.header.type == PERF_RECORD_LOST) { + // in PERF_RECORD_LOST : header + u64 id + u64 lost + constexpr size_t lostPos = sizeof(perf_event_header) + sizeof(uint64_t); + uint64_t lost = 0; + GetRecordFieldFromMmap(mmap, &lost, mmap.mmapPage->data_tail + lostPos, sizeof(lost)); + lostSamples_ += lost; + HLOGD("PERF_RECORD_LOST: lost sample record"); + goto RETURN; + } + + if ((buf = recordBuf_->AllocForWrite(mmap.header.size)) == nullptr) { + // this record type must be Non-Sample + lostNonSamples_++; + HLOGD("alloc buffer failed: lost non-sample record"); + goto RETURN; + } + + GetRecordFieldFromMmap(mmap, buf, mmap.mmapPage->data_tail, mmap.header.size); + recordBuf_->EndWrite(); +RETURN: + __sync_synchronize(); + mmap.mmapPage->data_tail += mmap.header.size; + mmap.dataSize -= mmap.header.size; +} + +void PerfEvents::ReadRecordFromBuf() +{ + HLOGV("enter"); + + const perf_event_attr *attr = GetDefaultAttr(); + uint8_t *p = nullptr; + + while (readRecordThreadRunning_) { + { + std::unique_lock lk(mtxRrecordBuf_); + cvRecordBuf_.wait(lk); + } + while ((p = recordBuf_->GetReadData()) != nullptr) { + uint32_t *type = reinterpret_cast(p); +#ifdef HIPERF_DEBUG_TIME + const auto readingStartTime_ = steady_clock::now(); +#endif +#if !HIDEBUG_SKIP_CALLBACK + recordCallBack_(GetPerfEventRecord(*type, p, *attr)); +#endif + recordEventCount_++; +#ifdef HIPERF_DEBUG_TIME + recordCallBackTime_ += + duration_cast(steady_clock::now() - readingStartTime_); +#endif + recordBuf_->EndRead(); + } + } + HLOGD("exit because trackStoped"); + + // read the data left over in buffer + while ((p = recordBuf_->GetReadData()) != nullptr) { + uint32_t *type = reinterpret_cast(p); +#ifdef HIPERF_DEBUG_TIME + const auto readingStartTime_ = steady_clock::now(); +#endif +#if !HIDEBUG_SKIP_CALLBACK + recordCallBack_(GetPerfEventRecord(*type, p, *attr)); +#endif + recordEventCount_++; +#ifdef HIPERF_DEBUG_TIME + recordCallBackTime_ += duration_cast(steady_clock::now() - readingStartTime_); +#endif + recordBuf_->EndRead(); + } + HLOGD("read all records from buffer"); +} + +bool PerfEvents::HaveTargetsExit(const std::chrono::steady_clock::time_point &startTime) +{ + if (systemTarget_) { + return false; + } + if (trackedCommand_) { + if (trackedCommand_->GetState() < TrackedCommand::State::COMMAND_STARTED) { + return false; // not start yet + } + int wstatus; + if (trackedCommand_->WaitCommand(wstatus)) { + milliseconds usedMsTick = duration_cast(steady_clock::now() - startTime); + printf("tracked command(%s) has exited (total %" PRId64 " ms)\n", + trackedCommand_->GetCommandName().c_str(), (uint64_t)usedMsTick.count()); + return true; + } + return false; + } + + for (auto it = pids_.begin(); it != pids_.end();) { + int rc = kill(*it, 0); + if (rc == -1 or rc == ESRCH) { + it = pids_.erase(it); + } else { + ++it; + } + } + if (pids_.empty()) { + milliseconds usedMsTick = duration_cast(steady_clock::now() - startTime); + printf("tracked processes have exited (total %" PRId64 " ms)\n", (uint64_t)usedMsTick.count()); + return true; + } + return false; +} + +void PerfEvents::RecordLoop() +{ + HLOGV("enter"); + + // calc the time + const auto startTime = steady_clock::now(); + const auto endTime = startTime + timeOut_; + milliseconds usedTimeMsTick {}; + + while (g_trackRunning) { + // time check point + const auto thisTime = steady_clock::now(); + + if (IsRecordInMmap()) { + ReadRecordsFromMmaps(); + } + + if (HaveTargetsExit(startTime)) { + break; + } + + if (thisTime >= endTime) { + usedTimeMsTick = duration_cast(thisTime - startTime); + printf("Timeout exit (total %" PRId64 " ms)\n", (uint64_t)usedTimeMsTick.count()); + if (trackedCommand_) { + trackedCommand_->Stop(); + } + break; + } + } + ReadRecordsFromMmaps(); + + if (!g_trackRunning) { + // for user interrupt situation, print time statistic + usedTimeMsTick = duration_cast(steady_clock::now() - startTime); + printf("User interrupt exit (total %" PRId64 " ms)\n", (uint64_t)usedTimeMsTick.count()); + } +} + +void PerfEvents::StatLoop() +{ + HLOGV("enter"); + + // calc the time + const auto startTime = steady_clock::now(); + const auto endTime = startTime + timeOut_; + auto nextReportTime = startTime + timeReport_; + milliseconds usedTimeMsTick {}; + __u64 durationInSec = 0; + int64_t thesholdTimeInMs = 2 * HUNDREDS; + + while (g_trackRunning) { + // time check point + const auto thisTime = steady_clock::now(); + if (timeReport_ != milliseconds::zero()) { + // stat cmd + if (thisTime >= nextReportTime) { + // only for log or debug? + usedTimeMsTick = duration_cast(thisTime - startTime); + durationInSec = usedTimeMsTick.count(); + auto lefTimeMsTick = duration_cast(endTime - thisTime); + printf("\nReport at %" PRId64 " ms (%" PRId64 " ms left):\n", + (uint64_t)usedTimeMsTick.count(), (uint64_t)lefTimeMsTick.count()); + // end of comments + nextReportTime += timeReport_; + StatReport(durationInSec); + } + } + + if (HaveTargetsExit(startTime)) { + break; + } + + if (thisTime >= endTime) { + usedTimeMsTick = duration_cast(thisTime - startTime); + durationInSec = usedTimeMsTick.count(); + printf("Timeout exit (total %" PRId64 " ms)\n", (uint64_t)usedTimeMsTick.count()); + if (trackedCommand_) { + trackedCommand_->Stop(); + } + break; + } + + // lefttime > 200ms sleep 100ms, else sleep 200us + uint64_t defaultSleepUs = 2 * HUNDREDS; // 200us + if (timeReport_ == milliseconds::zero() + && (timeOut_.count() * THOUSANDS) > thesholdTimeInMs) { + milliseconds leftTimeMsTmp = duration_cast(endTime - thisTime); + if (leftTimeMsTmp.count() > thesholdTimeInMs) { + defaultSleepUs = HUNDREDS * THOUSANDS; // 100ms + } + } + std::this_thread::sleep_for(microseconds(defaultSleepUs)); + } + + if (!g_trackRunning) { + // for user interrupt situation, print time statistic + usedTimeMsTick = duration_cast(steady_clock::now() - startTime); + printf("User interrupt exit (total %" PRId64 " ms)\n", (uint64_t)usedTimeMsTick.count()); + } + + if (timeReport_ == milliseconds::zero()) { + StatReport(durationInSec); + } +} + +const std::string PerfEvents::GetTypeName(perf_type_id type_id) +{ + auto it = PERF_TYPES.find(type_id); + if (it != PERF_TYPES.end()) { + return it->second; + } else { + return ""; + } +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_file_format.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_file_format.cpp new file mode 100755 index 0000000000000000000000000000000000000000..0f53ebd286c5d6b44b7949c5e28dcda7eaaa408b --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_file_format.cpp @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2021-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. + */ +#include "perf_file_format.h" + +#include "debug_logger.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +std::string PerfFileSection::GetFeatureName(FEATURE featureId) +{ + unsigned int index = static_cast(featureId); + if (featureId >= FEATURE::HIPERF_FIRST_FEATURE) { + index -= static_cast(FEATURE::HIPERF_FIRST_FEATURE); + if (index >= extFeatureNames.size()) { + return featureNames[0]; + } + return extFeatureNames[index]; + } else { + if (index >= featureNames.size()) { + return featureNames[0]; + } + return featureNames[index]; + } +} + +// for read +void PerfFileSection::Init(const char *buffer, size_t maxSize) +{ + rBuffer_ = buffer; + maxSize_ = maxSize; + offset_ = 0; +} + +// for write +void PerfFileSection::Init(char *buffer, size_t maxSize) +{ + wBuffer_ = buffer; + maxSize_ = maxSize; + offset_ = 0; +} + +bool PerfFileSection::Write(uint32_t u32) +{ + uint32_t value = u32; + return Write((char *)&value, sizeof(uint32_t)); +} + +bool PerfFileSection::Write(uint64_t u64) +{ + uint64_t value = u64; + return Write((char *)&value, sizeof(uint64_t)); +} + +bool PerfFileSection::Write(const std::string &str) +{ + if (Write((uint32_t)str.size() + 1)) { // include the ending \0 + return Write(str.c_str(), str.size(), str.size() + 1); + } else { + return false; + } +} + +bool PerfFileSection::Write(const char *buf, size_t size) +{ + return Write(buf, size, size); +} + +bool PerfFileSection::Write(const char *buf, size_t size, size_t max) +{ + if (offset_ + size > maxSize_) { + HLOGE("write out of size!!! offset_ %zu size %zu max %zu", offset_, size, maxSize_); + return false; + } + if (offset_ + max > maxSize_) { + HLOGE("write out of size!!! offset_ %zu size %zu max %zu", offset_, size, maxSize_); + return false; + } + std::copy(buf, buf + size, wBuffer_ + offset_); + if (size >= max) { + offset_ += size; + } else { + offset_ += max; + } + return true; +} + +bool PerfFileSection::Read(uint32_t &value) +{ + static_assert(sizeof(uint32_t) == 4); + return Read((char *)&value, sizeof(uint32_t)); +} + +bool PerfFileSection::Read(uint64_t &value) +{ + static_assert(sizeof(uint64_t) == 8); + + return Read((char *)&value, sizeof(uint64_t)); +} + +bool PerfFileSection::Read(std::string &value) +{ + uint32_t size = 0; + if (!Read(size)) { + return false; + } + // if size large than buf size or 0 size ? + // don't assert for fuzz test + if (size == 0 or size > maxSize_) { + return false; + } + char buf[size]; + if (!Read(buf, size)) { + return false; + } + if (buf[size - 1] != 0) { + return false; + } + value = buf; + HLOGDUMMY("Read String size %u buf : %s", size, value.c_str()); + return true; +} +void PerfFileSection::Skip(size_t size) +{ + offset_ += size; +} + +bool PerfFileSection::Read(char *buf, size_t size) +{ + HLOG_ASSERT(buf != nullptr); + if (size == 0) { + HLOGE("read zero size!!! offset_ %zu size %zu max %zu", offset_, size, maxSize_); + return false; + } else if (offset_ + size > maxSize_) { + HLOGE("read out of size!!! offset_ %zu size %zu max %zu", offset_, size, maxSize_); + if (memset_s(buf, size, 0, size) != 0) { // make sure the content return is 0 when failed + HLOGE("memset_s failed in PerfFileSection::Read"); + return false; + } + return false; + } + HLOGD("PerfFileSection::Read offset_ %zu size %zu maxSize_ %zu", offset_, size, maxSize_); + std::copy((rBuffer_ + offset_), (rBuffer_ + offset_ + size), buf); + offset_ += size; + HLOGDUMMY("after read offset_ %zx size %zu buf %x", offset_, size, buf[0]); + return true; +} + +uint32_t PerfFileSection::SizeOf(std::string &string) +{ + return sizeof(uint32_t) + string.size() + 1; /* '\0' */ +} + +PerfFileSectionString::PerfFileSectionString(FEATURE id, const char *buf, size_t size) + : PerfFileSection(id) +{ + Init(buf, size); + if (!Read(stdString_)) { + return; // or throw ... + } +} + +PerfFileSectionString::PerfFileSectionString(FEATURE id, const std::string &charString) + : PerfFileSection(id) +{ + stdString_ = charString; +} + +bool PerfFileSectionString::GetBinary(char *buf, size_t size) +{ + if (size < GetSize()) { + return false; + } + + Init(buf, size); + Write(stdString_); + return true; +} + +size_t PerfFileSectionString::GetSize() +{ + return SizeOf(stdString_); +} + +const std::string PerfFileSectionString::toString() const +{ + return stdString_; +} + +size_t PerfFileSectionSymbolsFiles::GetSize() +{ + size_t size = 0; + + size += sizeof(uint32_t); // how many SymbolFileStruct + for (auto &symbolFileStruct : symbolFileStructs_) { + size += SizeOf(symbolFileStruct.filePath_); + size += sizeof(symbolFileStruct.symbolType_); + size += sizeof(symbolFileStruct.textExecVaddr_); + size += sizeof(symbolFileStruct.textExecVaddrFileOffset_); + size += SizeOf(symbolFileStruct.buildId_); + + size += sizeof(uint32_t); // how many SymbolStruct + for (auto &symbolStruct : symbolFileStruct.symbolStructs_) { + size += sizeof(symbolStruct.vaddr_); + size += sizeof(symbolStruct.len_); + size += SizeOf(symbolStruct.symbolName_); + } + } + return size; +} + +PerfFileSectionSymbolsFiles::PerfFileSectionSymbolsFiles(FEATURE id, const char *buf, size_t size) + : PerfFileSection(id) +{ + Init(buf, size); + uint32_t symbolFileNumber = 0; + if (!Read(symbolFileNumber)) { + HLOGE("symbolFileNumber read failed"); + return; + } else if (symbolFileNumber > MAX_SYMBOLS_FILE_NUMBER) { + HLOGE("symbolFileNumber %u too large, only parse %zu symbolFile\n", symbolFileNumber, MAX_SYMBOLS_FILE_NUMBER); + symbolFileNumber = MAX_SYMBOLS_FILE_NUMBER; + } else { + HLOGV("symbolFileNumber %u", symbolFileNumber); + } + + for (uint32_t i = symbolFileNumber; i > 0; i--) { + auto &symbolFileStruct = symbolFileStructs_.emplace_back(); + + Read(symbolFileStruct.filePath_); + HLOGV(" symbolFileStruct.filePath_ %s", symbolFileStruct.filePath_.c_str()); + + Read(symbolFileStruct.symbolType_); + Read(symbolFileStruct.textExecVaddr_); + Read(symbolFileStruct.textExecVaddrFileOffset_); + Read(symbolFileStruct.buildId_); + + uint32_t symbolsNumber = 0; + if (!Read(symbolsNumber)) { + HLOGE(" symbols read failed"); + return; + } else if (symbolsNumber > MAX_SYMBOLS_NUMBER) { + HLOGE(" symbols %u too large", symbolsNumber); + return; + } else { + HLOGV(" symbols %u", symbolsNumber); + } + for (; symbolsNumber > 0; symbolsNumber--) { + auto &symbolStruct = symbolFileStruct.symbolStructs_.emplace_back(); + Read(symbolStruct.vaddr_); + Read(symbolStruct.len_); + Read(symbolStruct.symbolName_); + } + HLOGV(" %zu SymbolStruct read.", symbolFileStruct.symbolStructs_.size()); + } + HLOGV(" %zu SymbolFileStruct read.", symbolFileStructs_.size()); +} + +bool PerfFileSectionSymbolsFiles::GetBinary(char *buf, size_t size) +{ + HLOGV("PerfFileSectionSymbolsFiles get buffer size %zu.", size); + HLOG_ASSERT(size >= GetSize()); + + Init(buf, size); + if (!Write((uint32_t)symbolFileStructs_.size())) { + HLOGE("PerfFileSectionSymbolsFiles write failed with %zu.", symbolFileStructs_.size()); + return false; + } + for (auto &symbolFileStruct : symbolFileStructs_) { + Write(symbolFileStruct.filePath_); + Write(symbolFileStruct.symbolType_); + Write(symbolFileStruct.textExecVaddr_); + Write(symbolFileStruct.textExecVaddrFileOffset_); + Write(symbolFileStruct.buildId_); + + Write((uint32_t)symbolFileStruct.symbolStructs_.size()); + for (auto &symbolStruct : symbolFileStruct.symbolStructs_) { + Write(symbolStruct.vaddr_); + Write(symbolStruct.len_); + Write(symbolStruct.symbolName_); + } + HLOGV(" %zu SymbolStruct writed. for %s at 0x%016" PRIx64 "@0x%08" PRIx64 ": %s", + symbolFileStruct.symbolStructs_.size(), symbolFileStruct.filePath_.c_str(), + symbolFileStruct.textExecVaddr_, symbolFileStruct.textExecVaddrFileOffset_, + symbolFileStruct.buildId_.c_str()); + } + HLOGV("%zu SymbolFileStruct writed.", symbolFileStructs_.size()); + + return true; +} + +PerfFileSectionNrCpus::PerfFileSectionNrCpus(FEATURE id, const char *buf, size_t size) + : PerfFileSection(id) +{ + Init(buf, size); + if (!Read(nrCpusAvailable_) || !Read(nrCpusOnline_)) { + return; + } +} + +PerfFileSectionNrCpus::PerfFileSectionNrCpus(FEATURE id, uint32_t nrCpusAvailable, + uint32_t nrCpusOnline) + : PerfFileSection(id), nrCpusAvailable_(nrCpusAvailable), nrCpusOnline_(nrCpusOnline) +{ +} + +bool PerfFileSectionNrCpus::GetBinary(char *buf, size_t size) +{ + if (size < GetSize()) { + return false; + } + + Init(buf, size); + Write(nrCpusAvailable_); + Write(nrCpusOnline_); + return true; +} + +size_t PerfFileSectionNrCpus::GetSize() +{ + return (sizeof(nrCpusAvailable_) + sizeof(nrCpusOnline_)); +} + +void PerfFileSectionNrCpus::GetValue(uint32_t &nrCpusAvailable, uint32_t &nrCpusOnline) const +{ + nrCpusAvailable = nrCpusAvailable_; + nrCpusOnline = nrCpusOnline_; +} + +PerfFileSectionU64::PerfFileSectionU64(FEATURE id, const char *buf, size_t size) + : PerfFileSection(id) +{ + Init(buf, size); + if (!Read(value_)) { + return; + } +} + +PerfFileSectionU64::PerfFileSectionU64(FEATURE id, uint64_t v) : PerfFileSection(id) +{ + value_ = v; +} + +bool PerfFileSectionU64::GetBinary(char *buf, size_t size) +{ + if (size < GetSize()) { + return false; + } + + Init(buf, size); + Write(value_); + return true; +} + +size_t PerfFileSectionU64::GetSize() +{ + return sizeof(value_); +} + +void PerfFileSectionU64::GetValue(uint64_t &v) const +{ + v = value_; +} + +PerfFileSectionEventDesc::PerfFileSectionEventDesc(FEATURE id, + const std::vector &eventDesces) + : PerfFileSection(id) +{ + eventDesces_ = eventDesces; +} + +PerfFileSectionEventDesc::PerfFileSectionEventDesc(FEATURE id, const char *buf, size_t size) + : PerfFileSection(id) +{ + constexpr uint32_t maxIds = 500; + Init(buf, size); + uint32_t nr = 0; + if (!Read(nr)) { + return; + } + uint32_t attrSize = 0; + if (!Read(attrSize)) { + return; + } + if (attrSize != sizeof(perf_event_attr)) { // only for log or debug + HLOGW("perf_event_attr version is different, attrSize %d vs %zu", attrSize, + sizeof(perf_event_attr)); + } + + for (; nr > 0; nr--) { + AttrWithId eventDesc; + // compatible with the different version of 'perf_event_attr' + if (attrSize > sizeof(perf_event_attr)) { + if (!Read((char *)&(eventDesc.attr), sizeof(perf_event_attr))) { + return; + } + // skip tail bytes + HLOGW("skip %zu byte for diff attr size", attrSize - sizeof(perf_event_attr)); + Skip(attrSize - sizeof(perf_event_attr)); + } else if (!Read((char *)&(eventDesc.attr), attrSize)) { + return; + } + + uint32_t nrIds = 0; + if (!Read(nrIds)) { + return; + } else if (nrIds == 0 or nrIds > maxIds) { + HLOGW("nrIds is not correct ! %u", nrIds); + return; + } + if (!Read(eventDesc.name)) { + return; + } + eventDesc.ids.resize(nrIds, 0); + if (!Read((char *)eventDesc.ids.data(), sizeof(uint64_t) * nrIds)) { + return; + } + eventDesces_.emplace_back(std::move(eventDesc)); + } + HLOGV("read complete. %zu events", eventDesces_.size()); +} + +bool PerfFileSectionEventDesc::GetBinary(char *buf, size_t size) +{ + if (size < GetSize()) { + return false; + } + Init(buf, size); + + if (!Write((uint32_t)eventDesces_.size())) { + return false; + } + if (!Write((uint32_t)sizeof(perf_event_attr))) { + return false; + } + for (auto &eventDesc : eventDesces_) { + if (!Write((char *)&(eventDesc.attr), sizeof(perf_event_attr))) { + return false; + } + if (!Write((uint32_t)eventDesc.ids.size())) { + return false; + } + if (!Write(eventDesc.name)) { + return false; + } + // clang-format off + if (!Write((char *)eventDesc.ids.data(), + sizeof(uint64_t) * eventDesc.ids.size())) { + // clang-format on + return false; + } + } + return true; +} + +size_t PerfFileSectionEventDesc::GetSize() +{ + size_t size = sizeof(uint32_t); // nr + size += sizeof(uint32_t); // attr_size + + size += (eventDesces_.size() * sizeof(perf_event_attr)); + size += (eventDesces_.size() * sizeof(uint32_t)); // nr_ids + for (auto &eventDesc : eventDesces_) { + size += SizeOf(eventDesc.name); + size += (sizeof(uint64_t) * eventDesc.ids.size()); + } + return size; +} + +void PerfFileSectionEventDesc::GetValue(std::vector &eventDesces) const +{ + eventDesces = eventDesces_; +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_file_reader.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_file_reader.cpp new file mode 100755 index 0000000000000000000000000000000000000000..d60700f10ed72026ca7b2bcd0a8826028cfe9909 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/perf_file_reader.cpp @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2021-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. + */ +#include "perf_file_reader.h" + +#include +#include +#include +#include + +#include +#include + +#include "utilities.h" + +using namespace std::chrono; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +const int FETURE_MAX = 256; +const int SIZE_FETURE_COUNT = 8; + +std::unique_ptr PerfFileReader::Instance(const std::string &fileName, size_t begin) +{ + std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str()); + FILE *fp = fopen(resolvedPath.c_str(), "rb"); + if (fp == nullptr) { + HLOGE("fail to open file %s", fileName.c_str()); + return nullptr; + } + + std::unique_ptr reader = std::make_unique(fileName, fp, begin); + if (!reader->ReadFileHeader()) { + // Fail to read header, maybe its compressed + if (reader->IsGzipFile()) { + fclose(fp); + reader->fp_ = nullptr; + + if (!UncompressFile(fileName, ".perf.data")) { + HLOGE("Fail to UncompressFile(%s)", fileName.c_str()); + return nullptr; + } + + // open the uncompressed hidden file .perf.data + FILE *fp2 = fopen(".perf.data", "rb"); + if (fp2 == nullptr) { + HLOGE("fail to open uncompressed file .perf.data"); + return nullptr; + } + + reader->fp_ = fp2; + reader->compressData_ = true; + + if (!reader->ReadFileHeader()) { + HLOGE("fail to read header of file .perf.data"); + return nullptr; + } + goto end; + } + return nullptr; + } +end: + if (!reader->ReadAttrSection()) { + return nullptr; + } + return reader; +} + +std::unique_ptr PerfFileReader::Instance(const uint8_t *buff, size_t size) +{ + std::unique_ptr reader = std::make_unique(buff, size); + if (!reader->ReadFileHeader()) { + return nullptr; + } + if (!reader->ReadAttrSection()) { + return nullptr; + } + return reader; +} + +PerfFileReader::PerfFileReader(const std::string &fileName, FILE *fp, size_t begin) + : fp_(fp), fileName_(fileName), fileBegin_(begin) +{ + isMemory_ = false; + featureSectionOffset_ = 0; + struct stat fileStat; + if (fp != nullptr) { + if (fstat(fileno(fp), &fileStat) != -1 and fileStat.st_size > 0) { + fileSize_ = fileStat.st_size - fileBegin_; + } + } + + if (fseek(fp_, fileBegin_, SEEK_SET) != 0) { + HLOGE("fseek() failed"); + } +} + +PerfFileReader::PerfFileReader(const uint8_t *buff, size_t size) : buff_(buff), buffSize_(size) +{ + isMemory_ = true; + buffCurrent_ = 0; +} + +PerfFileReader::~PerfFileReader() +{ + if (isMemory_) { + return; + } + // if file was not closed properly + if (fp_ != nullptr) { + fclose(fp_); + fp_ = nullptr; + } + + // remove the uncompressed .perf.data + if (compressData_) { + if (remove(".perf.data") != 0) { + HLOGE("Fail to remove uncompressed file .perf.data"); + perror("Fail to remove temp file"); + } + } +} + +bool PerfFileReader::IsValidDataFile() +{ + return (memcmp(header_.magic, PERF_MAGIC, sizeof(header_.magic)) == 0); +} + +bool PerfFileReader::IsGzipFile() +{ + return header_.magic[0] == '\x1f' and header_.magic[1] == '\x8b'; +} + +bool PerfFileReader::ReadFileHeader() +{ + if (Read(&header_, sizeof(header_))) { + dataSectionSize_ = header_.data.size; + if (IsValidDataFile()) { + featureSectionOffset_ = header_.data.offset + header_.data.size; + for (int i = 0; i < FETURE_MAX / SIZE_FETURE_COUNT; i++) { + std::bitset features(header_.features[i]); + for (int j = 0; j < SIZE_FETURE_COUNT; j++) { + if (features.test(j)) { + features_.emplace_back((FEATURE)(((uint64_t)i) * SIZE_FETURE_COUNT + j)); + } + } + } + return true; + } + } + return false; +} + +bool PerfFileReader::ReadAttrSection() +{ + if (header_.attrSize != sizeof(perf_file_attr)) { + // 4.19 and 5.1 use diff size , 128 vs 136 + HLOGW("attr size %" PRId64 " doesn't match expected size %zu", header_.attrSize, + sizeof(perf_file_attr)); + } + + int attrCount = header_.attrs.size / header_.attrSize; + if (attrCount == 0) { + HLOGE("no attr in file"); + return false; + } + if (!SeekFromBegin(header_.attrs.offset)) { + return false; + } + for (int i = 0; i < attrCount; ++i) { + std::vector buf(header_.attrSize); + if (!Read(buf.data(), buf.size())) { + return false; + } + // size of perf_event_attr change between different linux kernel versions. + // can not memcpy to perf_file_attr as a whole + perf_file_attr attr {}; + size_t attr_size = header_.attrSize - sizeof(attr.ids); + + // If the size is smaller, you can use a pointer to point directly. + // Our UAPI is 4.19. is less than 5.1 + if (sizeof(perf_event_attr) > header_.attrSize) { + HLOGE("size not match, ptr of perf_event_attr maybe overfollow %zu vs %zu", + sizeof(perf_event_attr), attr_size); + } + + attr.attr = *(reinterpret_cast(&buf[0])); + attr.ids = *(reinterpret_cast(&buf[attr_size])); + vecAttr_.push_back(attr); + } + + // read ids for attr + for (size_t i = 0; i < vecAttr_.size(); ++i) { + std::vector ids; + if (!ReadIdsForAttr(vecAttr_[i], &ids)) { + return false; + } + vecAttrIds_.push_back(ids); + + // map ids to attr index + for (auto id : ids) { + mapId2Attr_[id] = i; + } + } + + return true; +} + +bool PerfFileReader::ReadIdsForAttr(const perf_file_attr &attr, std::vector *ids) +{ + if (attr.ids.size > 0) { + size_t count = attr.ids.size / sizeof(uint64_t); + if (!SeekFromBegin(attr.ids.offset)) { + return false; + } + + ids->resize(count); + if (!Read(ids->data(), attr.ids.size)) { + return false; + } + } + return true; +} + +std::vector PerfFileReader::GetAttrSection() const +{ + std::vector result(vecAttr_.size()); + + for (size_t i = 0; i < vecAttr_.size(); ++i) { + result[i].attr = vecAttr_[i].attr; + result[i].ids = vecAttrIds_[i]; + } + return result; +} + +bool PerfFileReader::ReadDataSection(ProcessRecordCB &callback) +{ + if (!SeekFromBegin(header_.data.offset)) { + return false; + } + + HLOGD("dataSection_ at offset %" PRId64 " + %" PRId64 "", header_.data.offset, + header_.data.size); + + if (!ReadRecord(callback)) { + printf("some record format is error!\n"); + return false; + }; + +#ifdef HIPERF_DEBUG_TIME + printf("readRecordTime: %" PRId64 " ms\n", + duration_cast(readRecordTime_).count()); + printf("readCallbackTime: %" PRId64 " ms\n", + duration_cast(readCallbackTime_).count()); +#endif + return dataSectionSize_ == 0; +} + +const perf_event_attr *PerfFileReader::GetDefaultAttr() +{ + if (vecAttr_.empty()) + return nullptr; + + return &(vecAttr_[0].attr); +} + +bool PerfFileReader::ReadRecord(ProcessRecordCB &callback) +{ +#ifdef HIPERF_DEBUG_TIME + const auto startReadTime = steady_clock::now(); +#endif + // record size can not exceed 64K + HIPERF_BUF_ALIGN uint8_t buf[RECORD_SIZE_LIMIT]; + // diff with reader + uint64_t remainingSize = header_.data.size; + size_t recordNumber = 0; + while (remainingSize > 0) { + if (remainingSize < sizeof(perf_event_header)) { + HLOGW("not enough sizeof perf_event_header"); + return false; + } else if (!Read(buf, sizeof(perf_event_header))) { + HLOGW("read perf_event_header failed."); + return false; + } else { + perf_event_header *header = reinterpret_cast(buf); + if (header->size > sizeof(buf)) { + HLOGE("read record header size error %hu", header->size); + return false; + } + if (remainingSize >= header->size) { + size_t headerSize = sizeof(perf_event_header); + if (Read(buf + headerSize, header->size - headerSize)) { + uint8_t *data = buf; + std::unique_ptr record = GetPerfEventRecord( + static_cast(header->type), data, *GetDefaultAttr()); + // unknown record , break the process + if (!record) { + return false; + } else { + HLOGV("record type %u", record->GetType()); + } + remainingSize -= header->size; +#ifdef HIPERF_DEBUG_TIME + const auto startCallbackTime = steady_clock::now(); +#endif + // call callback to process, then destroy record + callback(std::move(record)); + recordNumber++; +#ifdef HIPERF_DEBUG_TIME + readCallbackTime_ += + duration_cast(steady_clock::now() - startCallbackTime); +#endif + } else { + HLOGE("read record data size failed %zu", header->size - headerSize); + return false; + } + } else { + HLOGE("not enough header->size."); + return false; + } + } + } + HLOGD("read back %zu records", recordNumber); +#ifdef HIPERF_DEBUG_TIME + readRecordTime_ += duration_cast(steady_clock::now() - startReadTime); +#endif + return true; +} + +bool PerfFileReader::Read(void *buf, size_t len) +{ + if (buf == nullptr || len == 0) { + HLOG_ASSERT(buf != nullptr); + HLOG_ASSERT(len > 0); + return false; + } + + if (isMemory_) { + if (buffCurrent_ + len > buffSize_) { + return false; + } + std::copy(buff_ + buffCurrent_, buff_ + buffCurrent_ + len, reinterpret_cast(buf)); + buffCurrent_ += len; + } else if (fread(buf, len, 1, fp_) != 1) { + printf("failed to read file: %d", errno); + return false; + } + return true; +} + +const perf_file_header &PerfFileReader::GetHeader() const +{ + return header_; +} + +bool PerfFileReader::Read(char *buf, uint64_t offset, size_t len) +{ + if (buf == nullptr || len == 0) { + HLOG_ASSERT(buf != nullptr); + HLOG_ASSERT(len > 0); + return false; + } + if (!SeekFromBegin(offset)) { + return false; + } + + if (isMemory_) { + if (buffCurrent_ + len > buffSize_) { + return false; + } + std::copy(buff_ + buffCurrent_, buff_ + buffCurrent_ + len, reinterpret_cast(buf)); + buffCurrent_ += len; + } else if (fread(buf, len, 1, fp_) != 1) { + printf("failed to read file: %d", errno); + return false; + } + HLOGM("offset %" PRIx64 " len %zu buf %x %x %x %x", offset, len, buf[0], buf[1], buf[2], + buf[3]); + return true; +} +const std::vector &PerfFileReader::GetFeatures() const +{ + return features_; +} + +const std::vector> &PerfFileReader::GetFeatureSections() const +{ + return perfFileSections_; +} + +const std::string PerfFileReader::GetFeatureString(const FEATURE feature) const +{ + std::string featureName = PerfFileSection::GetFeatureName(feature); + HLOGV("GetFeatureSection %s", featureName.c_str()); + if (!IsFeatrureStringSection(feature)) { + HLOGV("not a string feature: %s", featureName.c_str()); + } else { + const PerfFileSection *featureSection = GetFeatureSection(feature); + if (featureSection != nullptr) { + const PerfFileSectionString *sectionString = + static_cast(featureSection); + return sectionString->toString(); + } else { + HLOGV("have not found: %s", featureName.c_str()); + } + } + return EMPTY_STRING; +} + +const PerfFileSection *PerfFileReader::GetFeatureSection(FEATURE feature) const +{ + HLOGV("enter"); + for (auto const &it : perfFileSections_) { + HLOGV("perfFileSections %p", it.get()); + if (it->featureId_ == feature) { + return it.get(); + } + } + return nullptr; +} + +bool PerfFileReader::ReadFeatureSection() +{ + uint64_t featureSectionOffsetRead = featureSectionOffset_; + HLOGV(" ReadDataSection data offset '0x%" PRIx64 " ", featureSectionOffset_); + + for (FEATURE feature : features_) { + perf_file_section sectionHeader; + if (!Read((char *)§ionHeader, featureSectionOffsetRead, sizeof(sectionHeader))) { + // read failed ?? + printf("file format not correct. featureSectionOffsetRead '0x%" PRIx64 "\n", + featureSectionOffsetRead); + return false; + } + + HLOGV("process feature %d:%s", feature, PerfFileSection::GetFeatureName(feature).c_str()); + HLOGV(" sectionHeader -> read offset '0x%" PRIx64 " size '0x%" PRIx64 "'", + sectionHeader.offset, sectionHeader.size); + if (isMemory_) { + if (sectionHeader.size == 0 or sectionHeader.size > buffSize_) { + HLOGE("sectionHeader.size %" PRIu64 " is not correct", sectionHeader.size); + return false; + } + } else { + if (sectionHeader.size == 0 or sectionHeader.size > fileSize_) { + HLOGE("sectionHeader.size %" PRIu64 " is not correct", sectionHeader.size); + return false; + } + } + std::vector buf(sectionHeader.size); + if (!Read(&buf[0], sectionHeader.offset, buf.size())) { + // read failed ?? + printf("file format not correct. featureSectionDataOffset '0x%" PRIx64 "\n", + sectionHeader.offset); + return false; + } + if (IsFeatrureStringSection(feature)) { + perfFileSections_.emplace_back( + std::make_unique(feature, (char *)&buf[0], buf.size())); + } else if (feature == FEATURE::HIPERF_FILES_SYMBOL) { + perfFileSections_.emplace_back(std::make_unique( + feature, (char *)&buf[0], buf.size())); + } else if (feature == FEATURE::EVENT_DESC) { + perfFileSections_.emplace_back( + std::make_unique(feature, (char *)&buf[0], buf.size())); + } else { + HLOGW("still not imp how to process with feature %d", feature); + } + + featureSectionOffsetRead += sizeof(sectionHeader); // next feaure + } + return true; +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/program_header.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/program_header.cpp new file mode 100755 index 0000000000000000000000000000000000000000..636ac74934becf670b375484a0236fb8bdd476ae --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/program_header.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021-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. + */ + +#include + +using namespace OHOS::Developtools::HiPerf::ELF; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +std::unique_ptr ProgramHeader::MakeUnique(char * const phdrBuf, const size_t bufSize) +{ + std::unique_ptr phdr {new (std::nothrow) ProgramHeader()}; + if (phdr == nullptr) { + HLOGE("ProgramHeader() failed"); + return nullptr; + } + if (!phdr->Init(phdrBuf, bufSize)) { + HLOGE("ProgramHeader::Init(phdrBuf, bufSize) failed"); + DumpPhdrBuf(phdrBuf, bufSize); + return nullptr; + } + return phdr; +} + +bool ProgramHeader::ParsePrgHeader32(char * const phdrBuf) +{ + uint32_t *u4Buf = reinterpret_cast(phdrBuf); + size_t index {0}; + type_ = u4Buf[index]; + ++index; + offset_ = u4Buf[index]; + ++index; + vaddr_ = u4Buf[index]; + ++index; + paddr_ = u4Buf[index]; + ++index; + fileSize_ = u4Buf[index]; + ++index; + memSize_ = u4Buf[index]; + ++index; + flags_ = u4Buf[index]; + ++index; + secAlign_ = u4Buf[index]; + return true; +} + +bool ProgramHeader::ParsePrgHeader64(char * const phdrBuf) +{ + uint32_t *u4Buf = reinterpret_cast(phdrBuf); + size_t index {0}; + type_ = u4Buf[index]; + ++index; + flags_ = u4Buf[index]; + + uint64_t *u8Buf = reinterpret_cast(phdrBuf); + offset_ = u8Buf[index]; + ++index; + vaddr_ = u8Buf[index]; + ++index; + paddr_ = u8Buf[index]; + ++index; + fileSize_ = u8Buf[index]; + ++index; + memSize_ = u8Buf[index]; + ++index; + secAlign_ = u8Buf[index]; + return true; +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/register.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/register.cpp new file mode 100755 index 0000000000000000000000000000000000000000..40538c100fc95288779e7b67212dc1ff3466797a --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/register.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2021-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. + */ + +// for libunwind.h empty struct has size 0 in c, size 1 in c++ +#define UNW_EMPTY_STRUCT uint8_t unused + +#include "register.h" + +#if !is_mingw +#include +#endif + +#if HAVE_LIBUNWIND +#include +#endif + +#include "debug_logger.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +static ArchType deviceArchType = ArchType::UNSUPPORT; + +// these copy from kerne uapi perf_regs.h +uint64_t GetSupportedRegMask(ArchType arch) +{ + uint64_t result = 0; + switch (arch) { + case ArchType::X86_32: + result = ((1ULL << PERF_REG_X86_32_MAX) - 1); + break; + case ArchType::X86_64: + result = ((1ULL << PERF_REG_X86_64_MAX) - 1); + result &= ~((1ULL << PERF_REG_X86_DS) | (1ULL << PERF_REG_X86_ES) | + (1ULL << PERF_REG_X86_FS) | (1ULL << PERF_REG_X86_GS)); + break; + case ArchType::ARM: + result = ((1ULL << PERF_REG_ARM_MAX) - 1); + break; + case ArchType::ARM64: + result = ((1ULL << PERF_REG_ARM64_MAX) - 1); + break; + default: + result = std::numeric_limits::max(); + HLOGE("unsupport arch %d", arch); + break; + } + return result; +} + +#if HAVE_LIBUNWIND +const std::map LibUnwindRegMap = { +#if defined(target_cpu_x64) + {UNW_X86_64_RAX, PERF_REG_X86_AX}, {UNW_X86_64_RDX, PERF_REG_X86_DX}, + {UNW_X86_64_RCX, PERF_REG_X86_CX}, {UNW_X86_64_RBX, PERF_REG_X86_BX}, + {UNW_X86_64_RSI, PERF_REG_X86_SI}, {UNW_X86_64_RDI, PERF_REG_X86_DI}, + {UNW_X86_64_RBP, PERF_REG_X86_BP}, {UNW_X86_64_RSP, PERF_REG_X86_SP}, + {UNW_X86_64_R8, PERF_REG_X86_R8}, {UNW_X86_64_R9, PERF_REG_X86_R9}, + {UNW_X86_64_R10, PERF_REG_X86_R10}, {UNW_X86_64_R11, PERF_REG_X86_R11}, + {UNW_X86_64_R12, PERF_REG_X86_R12}, {UNW_X86_64_R13, PERF_REG_X86_R13}, + {UNW_X86_64_R14, PERF_REG_X86_R14}, {UNW_X86_64_R15, PERF_REG_X86_R15}, + {UNW_X86_64_RIP, PERF_REG_X86_IP}, +#elif defined(target_cpu_arm64) + {UNW_AARCH64_X0, PERF_REG_ARM64_X0}, {UNW_AARCH64_X1, PERF_REG_ARM64_X1}, + {UNW_AARCH64_X2, PERF_REG_ARM64_X2}, {UNW_AARCH64_X3, PERF_REG_ARM64_X3}, + {UNW_AARCH64_X4, PERF_REG_ARM64_X4}, {UNW_AARCH64_X5, PERF_REG_ARM64_X5}, + {UNW_AARCH64_X6, PERF_REG_ARM64_X6}, {UNW_AARCH64_X7, PERF_REG_ARM64_X7}, + {UNW_AARCH64_X8, PERF_REG_ARM64_X8}, {UNW_AARCH64_X9, PERF_REG_ARM64_X9}, + {UNW_AARCH64_X10, PERF_REG_ARM64_X10}, {UNW_AARCH64_X11, PERF_REG_ARM64_X11}, + {UNW_AARCH64_X12, PERF_REG_ARM64_X12}, {UNW_AARCH64_X13, PERF_REG_ARM64_X13}, + {UNW_AARCH64_X14, PERF_REG_ARM64_X14}, {UNW_AARCH64_X15, PERF_REG_ARM64_X15}, + {UNW_AARCH64_X16, PERF_REG_ARM64_X16}, {UNW_AARCH64_X17, PERF_REG_ARM64_X17}, + {UNW_AARCH64_X18, PERF_REG_ARM64_X18}, {UNW_AARCH64_X19, PERF_REG_ARM64_X19}, + {UNW_AARCH64_X20, PERF_REG_ARM64_X20}, {UNW_AARCH64_X21, PERF_REG_ARM64_X21}, + {UNW_AARCH64_X22, PERF_REG_ARM64_X22}, {UNW_AARCH64_X23, PERF_REG_ARM64_X23}, + {UNW_AARCH64_X24, PERF_REG_ARM64_X24}, {UNW_AARCH64_X25, PERF_REG_ARM64_X25}, + {UNW_AARCH64_X26, PERF_REG_ARM64_X26}, {UNW_AARCH64_X27, PERF_REG_ARM64_X27}, + {UNW_AARCH64_X28, PERF_REG_ARM64_X28}, {UNW_AARCH64_X29, PERF_REG_ARM64_X29}, + {UNW_AARCH64_X30, PERF_REG_ARM64_LR}, {UNW_AARCH64_SP, PERF_REG_ARM64_SP}, + {UNW_AARCH64_PC, PERF_REG_ARM64_PC}, +#elif defined(target_cpu_arm) + {UNW_ARM_R0, PERF_REG_ARM_R0}, {UNW_ARM_R1, PERF_REG_ARM_R1}, {UNW_ARM_R2, PERF_REG_ARM_R2}, + {UNW_ARM_R3, PERF_REG_ARM_R3}, {UNW_ARM_R4, PERF_REG_ARM_R4}, {UNW_ARM_R5, PERF_REG_ARM_R5}, + {UNW_ARM_R6, PERF_REG_ARM_R6}, {UNW_ARM_R7, PERF_REG_ARM_R7}, {UNW_ARM_R8, PERF_REG_ARM_R8}, + {UNW_ARM_R9, PERF_REG_ARM_R9}, {UNW_ARM_R10, PERF_REG_ARM_R10}, {UNW_ARM_R11, PERF_REG_ARM_FP}, + {UNW_ARM_R12, PERF_REG_ARM_IP}, {UNW_ARM_R13, PERF_REG_ARM_SP}, {UNW_ARM_R14, PERF_REG_ARM_LR}, + {UNW_ARM_R15, PERF_REG_ARM_PC}, +#else +#error not support +#endif +}; + +int LibunwindRegIdToPerfReg(int libUnwindReg) +{ + if (LibUnwindRegMap.count(libUnwindReg)) { + return LibUnwindRegMap.at(libUnwindReg); + } else { + HLOGE("unwind: invalid reg id %d", libUnwindReg); + return -EINVAL; + } +} +#endif + +const std::string UpdatePerfContext(uint64_t addr, perf_callchain_context &perfCallChainContext) +{ + if (PERF_CONTEXT_NAME.count(addr) != 0) { + perfCallChainContext = static_cast(addr); + return StringPrintf("%s: %" PRIx64 "", PERF_CONTEXT_NAME.at(addr).c_str(), addr); + } else { + perfCallChainContext = PERF_CONTEXT_MAX; + return StringPrintf("unknow context: %" PRIx64 "", addr); + } +} + +const std::string GetArchName(ArchType arch) +{ + switch (arch) { + case ArchType::X86_32: + return "X86_32"; + case ArchType::X86_64: + return "X86_64"; + case ArchType::ARM: + return "ARM"; + case ArchType::ARM64: + return "ARM64"; + default: + return "Unsupport"; + } +} + +size_t RegisterGetIP(ArchType arch) +{ + switch (arch) { + case ArchType::X86_32: + case ArchType::X86_64: + return PERF_REG_X86_IP; + case ArchType::ARM: + return PERF_REG_ARM_PC; + case ArchType::ARM64: + return PERF_REG_ARM64_PC; + default: + return std::numeric_limits::max(); + } +} + +size_t RegisterGetSP(ArchType arch) +{ + switch (arch) { + case ArchType::X86_32: + case ArchType::X86_64: + return PERF_REG_X86_SP; + case ArchType::ARM: + return PERF_REG_ARM_SP; + case ArchType::ARM64: + return PERF_REG_ARM64_SP; + default: + return std::numeric_limits::max(); + } +} + +const std::string RegisterGetName(size_t registerIndex) +{ + std::string name; + name.append("PerfReg["); + name.append(std::to_string(registerIndex)); + if (PERF_REG_NAME_MAP.count(registerIndex) > 0) { + name.append(":"); + name.append(PERF_REG_NAME_MAP.at(registerIndex)); + } + name.append("]"); + return name; +} + +bool RegisterGetValue(uint64_t &value, const u64 registers[], const size_t registerIndex, + const size_t registerNumber) +{ + if (registerIndex >= registerNumber) { + HLOGE("registerIndex is %zu, max is %zu", registerIndex, registerNumber); + return false; + } + value = registers[registerIndex]; + return true; +} + +ArchType GetArchTypeFromUname(const std::string &machine) +{ + if (StringStartsWith(machine, "arm")) { + if (machine == "armv8l") { + // 32 bit elf run in 64 bit cpu + return ArchType::ARM64; + } + return ArchType::ARM; + } else if (machine == "aarch64") { + return ArchType::ARM64; + } else if (machine == "x86_64") { + return ArchType::X86_64; + } else if (machine == "x86" || machine == "i686") { + return ArchType::X86_32; + } else { + HLOGE("unsupport machine %s", machine.c_str()); + return ArchType::UNSUPPORT; + } +} + +ArchType GetArchTypeFromABI(bool abi32) +{ + if (deviceArchType == ArchType::UNSUPPORT) { + deviceArchType = GetDeviceArch(); + } + if (abi32) { + if (deviceArchType == ArchType::ARM64) { + return ArchType::ARM; + } else if (deviceArchType == ArchType::X86_64) { + return ArchType::X86_32; + } + } + return deviceArchType; +} + +ArchType SetDeviceArch(ArchType arch) +{ + HLOGD("deviceArchType change to %s", GetArchName(arch).c_str()); + deviceArchType = arch; + return deviceArchType; +} + +ArchType GetDeviceArch() +{ +#if is_mingw + return deviceArchType; +#else + if (deviceArchType != ArchType::UNSUPPORT) { + return deviceArchType; + } else { + utsname systemName; + if ((uname(&systemName)) != 0) { + // fallback + deviceArchType = buildArchType; + } else { + deviceArchType = GetArchTypeFromUname(systemName.machine); + HLOGD("machine arch is %s : %s", systemName.machine, + GetArchName(deviceArchType).c_str()); + if (deviceArchType == ArchType::UNSUPPORT) { + deviceArchType = buildArchType; + } + } + } + return deviceArchType; +#endif +} + +void UpdateRegForABI(ArchType arch, u64 *regs) +{ + if (deviceArchType == ArchType::ARM64 and arch == ArchType::ARM) { + // arm in arm64 + regs[PERF_REG_ARM_PC] = regs[PERF_REG_ARM64_PC]; + } +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/report.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/report.cpp new file mode 100755 index 0000000000000000000000000000000000000000..caf9680ba6a386b64515747822d8434a9c8a7cbd --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/report.cpp @@ -0,0 +1,650 @@ +/* + * Copyright (c) 2021-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. + */ +#define HILOG_TAG "Report" + +#include "report.h" +#include "log.h" + +#include +#include +#include + +#if is_mingw +#include +#else +#include +#endif + +using namespace std::placeholders; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +unsigned long long ReportItem::allIndex_ = 0; +void Report::AddReportItem(const PerfRecordSample &sample, bool includeCallStack) +{ + size_t configIndex = GetConfigIndex(sample.data_.id); + HLOG_ASSERT_MESSAGE(configs_.size() > configIndex, + "in %zu configs found index %zu, from ids %llu", configs_.size(), + configIndex, sample.data_.id); + VirtualThread &thread = virtualRuntime_.GetThread(sample.data_.pid, sample.data_.tid); + HLOG_ASSERT(sample.callFrames_.size() > 0); + if (sample.callFrames_.size() > 0) { + // if we need callstack ? + if (includeCallStack) { + // we will use caller mode , from last to first + auto frameIt = sample.callFrames_.rbegin(); + ReportItem &item = configs_[configIndex].reportItems_.emplace_back( + sample.data_.pid, sample.data_.tid, thread.name_, frameIt->filePath_, + frameIt->symbolName_, frameIt->vaddrInFile_, sample.data_.period); + HLOGV("%s", item.ToDebugString().c_str()); + HLOG_ASSERT(!item.func_.empty()); + + std::vector *currentCallFrames = &item.callStacks_; + for (frameIt = sample.callFrames_.rbegin(); frameIt != sample.callFrames_.rend(); + frameIt++) { + HLOG_ASSERT(frameIt->ip_ < PERF_CONTEXT_MAX); + // in add items case , right one should only have 1 callstack + // so just new callfames and move to next level + ReportItemCallFrame &nextCallFrame = currentCallFrames->emplace_back( + frameIt->symbolName_, frameIt->vaddrInFile_, frameIt->filePath_, + sample.data_.period, + (std::next(frameIt) == sample.callFrames_.rend()) ? sample.data_.period : 0); + HLOGV("add callframe %s", nextCallFrame.ToDebugString().c_str()); + currentCallFrames = &nextCallFrame.childs; + } + HLOGV("callstack %zu", item.callStacks_.size()); + if (item.callStacks_.size() > 0) { + HLOGV("callstack 2nd level %zu", item.callStacks_[0].childs.size()); + } + } else { + auto frameIt = sample.callFrames_.begin(); + HLOG_ASSERT(frameIt->ip_ < PERF_CONTEXT_MAX); + ReportItem &item = configs_[configIndex].reportItems_.emplace_back( + sample.data_.pid, sample.data_.tid, thread.name_, frameIt->filePath_, + frameIt->symbolName_, frameIt->vaddrInFile_, sample.data_.period); + item.ToDebugString().c_str(); + HLOGV("%s", item.ToDebugString().c_str()); + HLOG_ASSERT(!item.func_.empty()); + } + } + configs_[configIndex].sampleCount_++; + configs_[configIndex].eventCount_ += sample.data_.period; +} + +void Report::AddReportItemBranch(const PerfRecordSample &sample) +{ + size_t configIndex = GetConfigIndex(sample.data_.id); + HLOG_ASSERT(configs_.size() > configIndex); + VirtualThread &thread = virtualRuntime_.GetThread(sample.data_.pid, sample.data_.tid); + for (u64 i = 0; i < sample.data_.bnr; i++) { + Symbol symbol_to = + virtualRuntime_.GetSymbol(sample.data_.lbr[i].to, sample.data_.pid, sample.data_.tid); + Symbol symbol_from = + virtualRuntime_.GetSymbol(sample.data_.lbr[i].from, sample.data_.pid, sample.data_.tid); + + // branch only have 1 time only for period + ReportItem &item = configs_[configIndex].reportItems_.emplace_back( + sample.data_.pid, sample.data_.tid, thread.name_, symbol_to.module_, symbol_to.Name(), + symbol_to.funcVaddr_, 1u); + + item.fromDso_ = symbol_from.module_; + item.fromFunc_ = symbol_from.Name(); + + HLOGV("%s 0x%" PRIx64 "", item.ToDebugString().c_str(), symbol_to.taskVaddr_); + } + configs_[configIndex].sampleCount_++; + configs_[configIndex].eventCount_ += sample.data_.bnr; +} + +void Report::StatisticsRecords() +{ + for (auto &config : configs_) { + size_t duplicates = 0; + size_t totalReportCount = config.reportItems_.size(); + // merge duplicate + HLOGD("uniquing %zu", totalReportCount); + auto last = std::unique(config.reportItems_.begin(), config.reportItems_.end(), + std::bind(&Report::MultiLevelSameAndUpdateCount, this, _1, _2)); + + config.reportItems_.erase(last, config.reportItems_.end()); + + duplicates = totalReportCount - config.reportItems_.size(); + HLOGD("duplicates %zu, %zu -> %zu", duplicates, totalReportCount, + config.reportItems_.size()); + } +} + +void Report::FilterDisplayRecords() +{ + // remove the item with not in fliter + for (auto &config : configs_) { + size_t filterOuts = 0; +#ifndef NDEBUG + size_t totalReportCount = config.reportItems_.size(); +#endif + for (auto &reportKeyPair : reportKeyMap_) { + auto reportKey = reportKeyPair.second; + if (reportKey.displayFilter_.size() != 0) { + auto itemIt = config.reportItems_.begin(); + while (itemIt != config.reportItems_.end()) { + if (!reportKey.ShouldDisplay(*itemIt)) { + HLOGM("filter out %s", itemIt->ToDebugString().c_str()); + + // we need recalc the heating ,so also remove in total count + config.eventCount_ -= itemIt->eventCount_; + + // after update total eventCount remove this + itemIt = config.reportItems_.erase(itemIt); + filterOuts++; + } else { + itemIt++; + } + } + } + } +#ifndef NDEBUG + HLOGD("filter out %zu, %zu -> %zu", filterOuts, totalReportCount, + config.reportItems_.size()); +#endif + } +} + +void Report::UpdateReportItemsAfterAdjust() +{ + for (auto &config : configs_) { + HLOGV("percentage %zu items", config.reportItems_.size()); + uint64_t totalEventCount = 0; // just for debug check + for (auto &item : config.reportItems_) { + item.heat = Percentage(item.eventCount_, config.eventCount_); + totalEventCount += item.eventCount_; + HLOGM("%s percentage from %5.2f%% %" PRIu64 "/ %" PRIu64 "", + item.ToDebugString().c_str(), item.heat, item.eventCount_, config.eventCount_); + for (auto keyPair : reportKeyMap_) { + reportKeyMap_.at(keyPair.first).UpdateValueMaxLen(keyPair.second.GetValue(item)); + } + } + // check again + HLOGV("recalc totalEventCount is %" PRIu64 " old totalEventCount is %" PRIu64 "", + totalEventCount, config.eventCount_); + HLOG_ASSERT(totalEventCount == config.eventCount_); + } +} + +void Report::AdjustReportItems() +{ + HLOGD("Adjust Record Order ...."); + for (auto &config : configs_) { +#ifndef NDEBUG + uint64_t totalReportCount = config.reportItems_.size(); + if (option_.debug_) { + for (auto &reportItem : config.reportItems_) { + HLOGV("reportItem %s", reportItem.ToDebugString().c_str()); + } + } + // sort first. + HLOGD("MultiLevelSorting %" PRIu64 "", totalReportCount); +#endif + std::sort(config.reportItems_.begin(), config.reportItems_.end(), + std::bind(&Report::MultiLevelSorting, this, _1, _2)); + HLOGD("MultiLevelSorting %" PRIu64 " done", totalReportCount); + // reorder the callstack +#ifndef NDEBUG + if (option_.debug_) { + for (auto &reportItem : config.reportItems_) { + HLOGV("reportItem %s", reportItem.ToDebugString().c_str()); + } + } +#endif + StatisticsRecords(); + FilterDisplayRecords(); + + // reorder by count + std::sort(config.reportItems_.begin(), config.reportItems_.end(), + &ReportItem::CompareSortingEventCount); + + // reorder the callstack + for (auto &reportItem : config.reportItems_) { + ReportItemCallFrame::OrderCallFrames(reportItem.callStacks_); + } + HLOGD("afater sorting and unique, we have %zu report items,", config.reportItems_.size()); + } + // udpate percentage + UpdateReportItemsAfterAdjust(); +} + +int Report::MultiLevelCompare(const ReportItem &a, const ReportItem &b) +{ + HLOGM("MultiLevelCompare %s vs %s sort order %s", a.ToDebugString().c_str(), + b.ToDebugString().c_str(), VectorToString(option_.sortKeys_).c_str()); + + // check each key user care + for (auto it = option_.sortKeys_.begin(); it != option_.sortKeys_.end(); ++it) { + int result = reportKeyMap_.at(*it).compareFunction_(a, b); + if (result == 0) { + // this key is same , check the next one + continue; + } else { + // if onekey is not same , returl as not same + HLOGM("not same because %s %d : %s vs %s", it->c_str(), result, + reportKeyMap_.at(*it).GetValue(a).c_str(), + reportKeyMap_.at(*it).GetValue(b).c_str()); + return result; + } + } + // all the key is same + return 0; +} + +bool Report::MultiLevelSame(const ReportItem &a, const ReportItem &b) +{ + return MultiLevelCompare(a, b) == 0; +} + +void Report::MergeCallFrameCount(ReportItem &leftItem, ReportItem &rightItem) +{ + // add to left (right to left) + std::vector *leftCallFrames = &leftItem.callStacks_; + const std::vector *rightCallFrames = &rightItem.callStacks_; + uint64_t maxEventCount = leftItem.eventCount_; + // right should only have one call stack + int level = 0; + while (rightCallFrames->size() != 0) { + HLOG_ASSERT(rightCallFrames->size() == 1u); + const ReportItemCallFrame &rightFrame = rightCallFrames->at(0); + auto leftFrameIt = std::find(leftCallFrames->begin(), leftCallFrames->end(), rightFrame); + if (leftFrameIt == leftCallFrames->end()) { + // new callfames +#ifndef NDEBUG + auto &leftCallFrame = leftCallFrames->emplace_back(rightFrame); + HLOGV("%*s create frame %s in %s", level, "", leftCallFrame.ToDebugString().c_str(), + leftItem.ToDebugString().c_str()); + HLOG_ASSERT(leftCallFrame.eventCount_ <= maxEventCount); +#endif + // this is a new call stack , + // all the child in rightFrame has been copy to left. + break; + } else { + // already have , add count + leftFrameIt->eventCount_ += rightFrame.eventCount_; + leftFrameIt->selfEventCount_ += rightFrame.selfEventCount_; + // left move to next + leftCallFrames = &(leftFrameIt->childs); + HLOGM("%*s udpate frame +%" PRIu64 " %s in %s", level, "", rightFrame.eventCount_, + leftFrameIt->ToDebugString().c_str(), leftItem.ToDebugString().c_str()); + HLOG_ASSERT_MESSAGE(leftFrameIt->eventCount_ <= maxEventCount, + " maxEventCount is %" PRIu64 "", maxEventCount); + maxEventCount = leftFrameIt->eventCount_; + } + // move to next level + rightCallFrames = &(rightFrame.childs); + level++; + } +} + +bool Report::MultiLevelSameAndUpdateCount(ReportItem &l, ReportItem &r) +{ + if (MultiLevelCompare(l, r) == 0) { + l.eventCount_ += r.eventCount_; + HLOGM("l %" PRIu64 " %s c:%zu vs r %" PRIu64 " %s c:%zu", l.eventCount_, l.func_.data(), + l.callStacks_.size(), r.eventCount_, r.func_.data(), r.callStacks_.size()); + // if it have call stack? + if (r.callStacks_.size() != 0) { + // add to left (right to left) + MergeCallFrameCount(l, r); + } + return true; + } else { + return false; + } +} + +bool Report::MultiLevelSorting(const ReportItem &a, const ReportItem &b) +{ + /* + The value returned indicates whether the element passed as first argument is + considered to go before the second in the specific strict weak ordering it defines. + */ + bool result = MultiLevelCompare(a, b) > 0; +#ifdef HIPERF_DEBUG + if (DebugLogger::GetInstance()->GetLogLevel() <= LEVEL_VERBOSE) { + bool result2 = MultiLevelCompare(b, a) > 0; + if (result and result == result2) { + HLOGE("MultiLevelSorting a->b %d vs b->a %d", result, result2); + HLOGE("left %s", a.ToDebugString().c_str()); + HLOGE("right %s", b.ToDebugString().c_str()); + HLOG_ASSERT(false); + } + } +#endif + return result; +} + +void Report::OutputStdStatistics(ReportEventConfigItem &config) +{ + if (fprintf(output_, "\n") < 0) { + return; + } // make a blank line for new event + if (fprintf(output_, "Event: %s (type %" PRIu32 " id %" PRIu64 ")\n", config.eventName_.c_str(), + config.type_, config.config_) < 0) { + return; + } + if (fprintf(output_, "Samples Count: %" PRIu64 "\n", config.sampleCount_) < 0) { + return; + } + if (!config.coutMode_) { + fprintf(output_, "Time in ns: "); + } else { + fprintf(output_, "Event Count: "); + } + fprintf(output_, "%" PRIu64 "\n", config.eventCount_); +} + +bool Report::OutputStdStatistics(ReportEventConfigItem &config, ReportEventConfigItem &otherConfig) +{ + if (config != otherConfig) { + fprintf(output_, "diff config unable compare\n"); + return false; + } + fprintf(output_, "Event: %s (type %" PRIu32 " id %" PRIu64 ")", config.eventName_.c_str(), + config.type_, config.config_); + fprintf(output_, "Samples Count: %" PRIu64 " vs %" PRIu64 "\n", config.sampleCount_, + otherConfig.sampleCount_); + if (config.coutMode_) { + fprintf(output_, "Time in ns: "); + } else { + fprintf(output_, "Event Count: "); + } + fprintf(output_, "%" PRIu64 " vs %" PRIu64 "\n", config.eventCount_, otherConfig.eventCount_); + return true; +} + +void Report::OutputStdHead(ReportEventConfigItem &config, bool diffMode) +{ + // head print + const std::string head = "Heating"; + if (fprintf(output_, "%-*s ", FULL_PERCENTAGE_LEN, head.c_str()) < 0) { + return; + } + + if (diffMode) { + const std::string diff = "Diff"; + fprintf(output_, "%-*s ", FULL_PERCENTAGE_DIFF_LEN, diff.c_str()); + } + + // merge sort key and no-sort key (like count) + + displayKeyNames_ = option_.sortKeys_; + if (!option_.hideCount_) { + displayKeyNames_.insert(displayKeyNames_.begin(), "count"); + } + + int remainingWidth = consoleWidth_; + // sort key head + for (auto &keyName : displayKeyNames_) { + auto &key = reportKeyMap_.at(keyName); + remainingWidth -= key.maxLen_; + if (remainingWidth <= 0) { + key.maxLen_ = 0; + } + if (fprintf(output_, "%-*s ", (remainingWidth > 0) ? static_cast(key.maxLen_) : 0, + key.keyName_.c_str()) < 0) { + return; + } + HLOGD("'%s' max len %zu(from '%s') console width %d", key.keyName_.c_str(), key.maxLen_, + key.maxValue_.c_str(), remainingWidth); + } + if (fprintf(output_, "\n") < 0) { + return; + } +} + +bool Report::OutputStdCallFrame(int indent, const std::string_view &funcName, uint64_t eventCount, + uint64_t totalEventCount) +{ + float heat = Percentage(eventCount, totalEventCount); + float num = 100.0; + HLOGV("frame %f indent %d at %s", heat, indent, funcName.data()); + + if (heat < option_.callStackHeatLimit_) { + // don't print this three anymore + return false; + } + + if (heat == num) { + fprintf(output_, "%*s", indent, " "); + fprintf(output_, "%*s ", FULL_PERCENTAGE_NUM_LEN, " "); + } else { + fprintf(output_, "%*s", indent, "|- "); + fprintf(output_, "%*.2f%% ", FULL_PERCENTAGE_NUM_LEN, heat); + } + if (option_.debug_) { + fprintf(output_, "%" PRIu64 "/%" PRIu64 " %s\n", eventCount, totalEventCount, + funcName.data()); + } else { + fprintf(output_, "%s\n", funcName.data()); + } + return true; +} + +void Report::PrepareConsole() +{ +} + +void Report::OutputStdCallFrames(int indent, const ReportItemCallFrame &callFrame, + uint64_t totalEventCount) +{ + /* + 90% a + |- 80% b + c + d + |- 50% e + |- 50% f + g + */ + // this is the first call frame + if (!OutputStdCallFrame(indent, callFrame.func_, callFrame.eventCount_, totalEventCount)) { + // this tree will skipped. + return; + } + + // print it self + if (callFrame.selfEventCount_ != 0 and callFrame.selfEventCount_ != callFrame.eventCount_) { + OutputStdCallFrame(indent + CALLSTACK_INDENT, "[run in self function]", + callFrame.selfEventCount_, callFrame.eventCount_); + } + + // printf children + // if only one children + if (callFrame.childs.size() == 1u and + callFrame.childs[0].eventCount_ == callFrame.eventCount_) { + HLOGV("childCallFream %*c %s", indent, ' ', callFrame.childs[0].func_.data()); + // don't indent if same count (only one 100% children) + OutputStdCallFrames(indent, callFrame.childs[0], callFrame.eventCount_); + } else { + // else a lot children + for (const ReportItemCallFrame &childCallFrame : callFrame.childs) { + HLOGV("childCallFream %*c %s", indent, ' ', childCallFrame.func_.data()); + OutputStdCallFrames(indent + CALLSTACK_INDENT, childCallFrame, callFrame.eventCount_); + } + } +} + +void Report::OutputStdContent(ReportEventConfigItem &config) +{ + // content print + auto it = config.reportItems_.begin(); + while (it != config.reportItems_.end()) { + const ReportItem &reportItem = it.operator*(); + // if we need skip it ? + if (reportItem.heat < option_.heatLimit_) { + it++; + continue; // below limit + } else { + fprintf(output_, "%*.2f%% ", FULL_PERCENTAGE_NUM_LEN, reportItem.heat); + } + OutputStdContentItem(reportItem); + if (reportItem.callStacks_.size() != 0) { + HLOGV("reportItem.callStacks_ %zu %s", reportItem.callStacks_.size(), + reportItem.ToDebugString().c_str()); + HLOG_ASSERT(reportItem.callStacks_.size() == 1u); + for (auto &callFrame : reportItem.callStacks_) { + OutputStdCallFrames(CALLSTACK_INDENT, callFrame, reportItem.eventCount_); + } + } + it++; + } +} + +void Report::OutputStdContentItem(const ReportItem &reportItem) +{ + // output by sort keys + for (auto sortKey : displayKeyNames_) { + ReportKey &reportKey = Report::reportKeyMap_.at(sortKey); + if (fprintf(output_, "%s ", reportKey.GetValue(reportItem).c_str()) < 0) { + return; + } + } + if (fprintf(output_, "\n") < 0) { + return; + } +} + +void Report::OutputStdItemHeating(float heat, float heat2) +{ + if (heat == heat2 and heat == 0.0f) { + fprintf(output_, "something error , all it is end.\n"); + } else if (heat2 == 0) { + // only have first + fprintf(output_, "%*.2f%% ", FULL_PERCENTAGE_NUM_LEN, heat); + fprintf(output_, "%*s ", FULL_PERCENTAGE_DIFF_LEN, ""); + } else if (heat == 0) { + // only have second + fprintf(output_, "%*s ", FULL_PERCENTAGE_LEN, ""); + fprintf(output_, "%+*.2f%% ", FULL_PERCENTAGE_DIFF_NUM_LEN, heat2); + } else if (heat2 > heat) { + fprintf(output_, "%s%*.2f%%%s ", TEXT_RED.c_str(), FULL_PERCENTAGE_NUM_LEN, heat, + TEXT_RESET.c_str()); + fprintf(output_, "%s%+*.2f%%%s ", TEXT_GREEN.c_str(), FULL_PERCENTAGE_DIFF_NUM_LEN, + heat2 - heat, TEXT_RESET.c_str()); + } else if (heat2 < heat) { + fprintf(output_, "%s%*.2f%%%s ", TEXT_GREEN.c_str(), FULL_PERCENTAGE_NUM_LEN, heat, + TEXT_RESET.c_str()); + fprintf(output_, "%s%+*.2f%%%s ", TEXT_RED.c_str(), FULL_PERCENTAGE_DIFF_NUM_LEN, + heat2 - heat, TEXT_RESET.c_str()); + } else { + // same heating + fprintf(output_, "%*.2f%% ", FULL_PERCENTAGE_NUM_LEN, heat); + fprintf(output_, "%+*.2f%% ", FULL_PERCENTAGE_DIFF_NUM_LEN, heat2 - heat); + } +} + +void Report::OutputStdContentDiff(ReportEventConfigItem &left, ReportEventConfigItem &right) +{ + // first we need found the match config + HLOGD("first count %zu second count %zu", left.reportItems_.size(), right.reportItems_.size()); + ReportItemsConstIt it = left.reportItems_.begin(); + ReportItemsConstIt it2 = right.reportItems_.begin(); + while (it != left.reportItems_.end()) { + // still have it2 ? + if (it2 != right.reportItems_.end()) { + // find the same item in it2 by same sort key + while (it2 != right.reportItems_.end()) { + if (MultiLevelSame(*it, *it2)) { + // we found the same item + // output the diff heating + if (it->heat > option_.heatLimit_ and it2->heat > option_.heatLimit_) { + OutputStdItemHeating(it->heat, it2->heat); + OutputStdContentItem(*it); + } + it++; + it2++; + break; // next it + } else { + // only print it2 item + if (it2->heat > option_.heatLimit_) { + OutputStdItemHeating(0.0f, it2->heat); + OutputStdContentItem(*it2); + } + it2++; + continue; // next it2 + } + } + } else { + // no more it2, go on print all the it + if (it->heat > option_.heatLimit_) { + OutputStdItemHeating(it->heat, 0.0f); + OutputStdContentItem(*it); + } + it++; + continue; // next it + } + } + while (it2 != right.reportItems_.end()) { + // if diff still have some item in it2 ,print it + OutputStdItemHeating(0, it2->heat); + OutputStdContentItem(*it2); + it2++; + continue; // next it2 + } +} + +void Report::OutputStdContentDiffOneSide(bool leftOnly, ReportItem &reportItem) +{ + if (reportItem.heat > option_.heatLimit_) { + if (leftOnly) { + OutputStdItemHeating(reportItem.heat, 0.0f); + } else { + OutputStdItemHeating(0.0f, reportItem.heat); + } + OutputStdContentItem(reportItem); + } +} + +void Report::OutputStd(FILE *output) +{ + output_ = output; + PrepareConsole(); + + for (auto &config : configs_) { + OutputStdStatistics(config); + OutputStdHead(config); + OutputStdContent(config); + } +} + +void Report::OutputStdDiff(FILE *output, Report &other) +{ + output_ = output; + PrepareConsole(); + + auto left = configs_.begin(); + while (left != configs_.end()) { + auto right = other.configs_.begin(); + while (right != other.configs_.end()) { + if (*left == *right) { + OutputStdStatistics(*left); + OutputStdHead(*left, true); + OutputStdContentDiff(*left, *right); + break; // check next left + } + right++; + } + left++; // go on left + } +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/ring_buffer.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/ring_buffer.cpp new file mode 100755 index 0000000000000000000000000000000000000000..4aa2dbcc056ee193bde521bab1a244fbd9096e04 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/ring_buffer.cpp @@ -0,0 +1,112 @@ +/* + * 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. + */ +#define HILOG_TAG "RingBuffer" + +#include "ring_buffer.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +RingBuffer::RingBuffer(size_t size) : size_(size) +{ + if (size > 0) { + buf_ = std::make_unique(size); + } +} + +RingBuffer::~RingBuffer() {} + +// get size of the writable space +size_t RingBuffer::GetFreeSize() const +{ + return size_ - (head_.load(std::memory_order_relaxed) - tail_.load(std::memory_order_relaxed)); +} + +uint8_t *RingBuffer::AllocForWrite(size_t writeSize) +{ + size_t writeHead = head_.load(std::memory_order_relaxed); + size_t readHead = tail_.load(std::memory_order_acquire); + size_t writePos = writeHead % size_; + size_t readPos = readHead % size_; + writeSize_ = writeSize; + if (writePos < readPos) { + // |---writePos<---writeSize--->readPos---| + if (writePos + writeSize > readPos) { + return nullptr; + } + } else if (writePos == readPos and writeHead != readHead) { + // writePos catch up with readPos, but buffer is full + return nullptr; + } else { + // two cases: 1, writePos catch up with readPos, but buffer is empty + // 2, |---readPos---writePos<---writeSize--->| + if (writePos + writeSize > size_) { + // no enough space at the end + if (readPos < writeSize) { + return nullptr; + } + // wrap to the start, set mark byte + buf_.get()[writePos] = MARGIN_BYTE; + writeSize_ += (size_ - writePos); + writePos = 0; + } + } + + return buf_.get() + writePos; +} + +void RingBuffer::EndWrite() +{ + size_t head = head_.load(std::memory_order_relaxed); + head += writeSize_; + head_.store(head, std::memory_order_release); +} + +uint8_t *RingBuffer::GetReadData() +{ + size_t writeHead = head_.load(std::memory_order_acquire); + size_t readHead = tail_.load(std::memory_order_relaxed); + if (writeHead == readHead) { + return nullptr; + } + + readSize_ = 0; + size_t writePos = writeHead % size_; + size_t readPos = readHead % size_; + if (writePos <= readPos) { + // |<---data2--->writePos---readPos<---data1--->| + if (buf_.get()[readPos] == MARGIN_BYTE) { + if (writePos == 0) { + return nullptr; + } + readSize_ = (size_ - readPos); + readPos = 0; + } + } + // else |---readPos<---data--->writePos---| + perf_event_header *header = reinterpret_cast(buf_.get() + readPos); + readSize_ += header->size; + return buf_.get() + readPos; +} + +void RingBuffer::EndRead() +{ + size_t tail = tail_.load(std::memory_order_relaxed); + tail += readSize_; + tail_.store(tail, std::memory_order_release); +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/section_header.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/section_header.cpp new file mode 100755 index 0000000000000000000000000000000000000000..1e5d67ccd4f67fd322b9d360c027f9a868d7c58d --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/section_header.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2021-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. + */ + +#include + +using namespace OHOS::Developtools::HiPerf::ELF; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +enum class NUMBER : int { + NUMBER_ZERO = 0, + NUMBER_ONE = 1, + NUMBER_TWO = 2, + NUMBER_THREE = 3, + NUMBER_FOUR = 4, + NUMBER_FIVE = 5, + NUMBER_SIX = 6, + NUMBER_SEVEN = 7, + NUMBER_EIGHT = 8, + NUMBER_NINE = 9, + NUMBER_TEN = 10, + NUMBER_ELEVEN = 11, + NUMBER_TWELVE = 12, +}; + +std::unique_ptr SectionHeader::MakeUnique(char * const shdrBuf, const size_t bufSize, + const size_t index) +{ + std::unique_ptr shdr {new (std::nothrow) SectionHeader()}; + if (shdr == nullptr) { + return nullptr; + } + if (!shdr->Init(shdrBuf, bufSize, index)) { + HLOGE("SectionHeader::Init(shdrBuf, bufSize, index) failed"); + DumpShdrBuf(shdrBuf, bufSize); + return nullptr; + } + return shdr; +} + +bool SectionHeader::ParseSecHeader32(char * const shdrBuf) +{ + uint32_t *u4Buf = reinterpret_cast(shdrBuf); + int index {0}; + nameIndex_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_ONE); + secType_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_TWO); + secFlags_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_SIX); + link_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_SEVEN); + info_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_THREE); + secVaddr_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_FOUR); + fileOffset_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_FIVE); + secSize_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_EIGHT); + secAddrAlign_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_NINE); + secEntrySize_ = u4Buf[index]; + return true; +} + +bool SectionHeader::ParseSecHeader64(char * const shdrBuf) +{ + uint64_t *u8Buf = reinterpret_cast(shdrBuf); + uint32_t *u4Buf = reinterpret_cast(shdrBuf); + size_t index {0}; + nameIndex_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_ONE); + secType_ = u4Buf[index]; + secFlags_ = u8Buf[index]; + index = static_cast(NUMBER::NUMBER_TEN); + link_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_ELEVEN); + info_ = u4Buf[index]; + index = static_cast(NUMBER::NUMBER_TWO); + secVaddr_ = u8Buf[index]; + index = static_cast(NUMBER::NUMBER_THREE); + fileOffset_ = u8Buf[index]; + index = static_cast(NUMBER::NUMBER_FOUR); + secSize_ = u8Buf[index]; + index = static_cast(NUMBER::NUMBER_SIX); + secAddrAlign_ = u8Buf[index]; + index = static_cast(NUMBER::NUMBER_SEVEN); + secEntrySize_ = u8Buf[index]; + return true; +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/subcommand.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/subcommand.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de86194ab8b34823dee549859236219f56de034c --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/subcommand.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2021-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. + */ + +#include "subcommand.h" + +#include "debug_logger.h" +#include "option.h" +#include "subcommand_help.h" +#include "utilities.h" + +using namespace std; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +static std::map> g_SubCommandsMap; + +// parse option first +bool SubCommand::OnSubCommandOptions(std::vector args) +{ + // parse common first + if (!Option::GetOptionValue(args, "--dumpoptions", dumpOptions_)) { + return false; + } + if (!Option::GetOptionValue(args, "--help", showHelp_) + || !Option::GetOptionValue(args, "-h", showHelp_)) { + return false; + } + + if (showHelp_) { + if (!args.empty()) { + printf("unknown option '%s'\n", args.front().c_str()); + return false; + } + if (OnPreSubCommand()) { + return false; + } + } + + if (ParseOption(args)) { + if (dumpOptions_) { + DumpOptions(); + } + HLOGD(" args left over: (%zu): %s", args.size(), VectorToString(args).c_str()); + if (!args.empty()) { + printf("unknown option '%s'\n", args.front().c_str()); + return false; + } + } else { + HLOGD("incorrect option(s)\n"); + return false; + } + return true; +} + +bool SubCommand::RegisterSubCommand(std::string cmdName, std::unique_ptr subCommand) +{ + HLOGV("%s", cmdName.c_str()); + if (cmdName.empty()) { + HLOGE("unable to register empty subcommand!"); + return false; + } + if (cmdName.front() == '-') { + HLOGE("unable use '-' at the begin of subcommand '%s'", cmdName.c_str()); + return false; + } + + if (g_SubCommandsMap.count(cmdName) == 0) { + g_SubCommandsMap.insert(std::make_pair(cmdName, std::move(subCommand))); + return true; + } else { + HLOGE("subcommand '%s' already registered!", cmdName.c_str()); + return false; + } +} + +void SubCommand::ClearSubCommands() +{ + g_SubCommandsMap.clear(); +} + +const std::map> &SubCommand::GetSubCommands() +{ + HLOGV("enter"); + return g_SubCommandsMap; +} + +SubCommand *SubCommand::FindSubCommand(std::string cmdName) +{ + HLOGV("%s", cmdName.c_str()); + auto found = g_SubCommandsMap.find(cmdName); + if (found != g_SubCommandsMap.end()) { + // remove the subcmd itself + return found->second.get(); + } else { + return nullptr; + } +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/subcommand.h b/host/trace_streamer/src/parser/hiperf_parser/hiperf/subcommand.h new file mode 100644 index 0000000000000000000000000000000000000000..5f5a683b57a83d90671f363fc21407f88e5822b3 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/subcommand.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2021-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. + */ +#ifndef HIPERF_SUBCOMMAND_H_ +#define HIPERF_SUBCOMMAND_H_ + +#include +#include +#include "utilities.h" + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +class SubCommand { +public: + SubCommand(const std::string &name, const std::string &brief, const std::string &help) + : name_(name), brief_(brief), help_(help) + { + } + + virtual ~SubCommand() {} + + const std::string &Name() const + { + return name_; + } + const std::string &Brief() const + { + return brief_; + } + const std::string &Help() const + { + return help_; + } + + // parse option first + bool OnSubCommandOptions(std::vector args); + + // some help cmd + bool OnPreSubCommand() + { + if (showHelp_) { + printf("%s\n", Help().c_str()); + return true; + } + return false; + }; + + virtual void DumpOptions() const {} + + // args should be empty after all the args processed + virtual bool ParseOption(std::vector &args) + { + args.clear(); // all the args is processed + return true; + } + + // return false means cmd failed + virtual bool OnSubCommand(std::vector &args) = 0; + // some test code will use this for simple + bool OnSubCommand(std::string stringArgs) + { + auto args = StringSplit(stringArgs, " "); + return OnSubCommand(args); + }; + + // called from main + static bool RegisterSubCommand(std::string, std::unique_ptr); + + // get some cmd + static const std::map> &GetSubCommands(); + static SubCommand *FindSubCommand(std::string); + + // for test code + static void ClearSubCommands(); + +protected: + const std::string name_; + const std::string brief_; + std::string help_; + bool dumpOptions_ = false; + bool showHelp_ = false; +}; +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS +#endif // HIPERF_SUBCOMMAND_H_ diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/subcommand_help.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/subcommand_help.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0bb4ceb2a5f13c807da35041b35520f3534862e4 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/subcommand_help.cpp @@ -0,0 +1,73 @@ +/* + * 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. + */ + +#include "subcommand_help.h" +#include "debug_logger.h" +#include "utilities.h" + +using namespace std; + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +bool SubCommandHelp::OnSubCommand(std::vector &args) +{ + HLOGV("enter"); + OnHelp(args); + return true; +} + +void SubCommandHelp::RegisterSubCommandHelp() +{ + HLOGV("enter"); + SubCommand::RegisterSubCommand("help", std::make_unique()); +} + +bool SubCommandHelp::OnHelp(std::vector &args) +{ + if (args.empty()) { + const auto &mainOptions = Option::GetMainOptions(); + HLOGD("%zu options found:", mainOptions.size()); + printf("Usage: hiperf [options] command [args for command]\n"); + + printf("options:\n"); + for (const auto &commandOption : mainOptions) { + printf("\t%-20s\t%s\n", commandOption.first.c_str(), + commandOption.second->help.c_str()); + } + + auto &commands = SubCommand::GetSubCommands(); + HLOGD("%zu cmds found:", commands.size()); + printf("command:\n"); + for (const auto &command : commands) { + printf("\t%s:\t%s\n", command.second->Name().c_str(), command.second->Brief().c_str()); + } + printf("\nSee 'hiperf help [command]' for more information on a specific command.\n\n"); + } else { + auto command = SubCommand::FindSubCommand(args.front()); + if (command != nullptr) { + args.clear(); + printf("%s\n", command->Help().c_str()); + } else { + printf("Unknown command: '%s'\n", args.front().c_str()); + return false; + } + } + + return true; +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/symbols_file.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/symbols_file.cpp new file mode 100755 index 0000000000000000000000000000000000000000..082e6834b809a6fa9efe8d6a7d0c6720cc2b6702 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/symbols_file.cpp @@ -0,0 +1,1348 @@ +/* + * Copyright (c) 2021-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. + */ + +#define HILOG_TAG "Symbols" + +#include "symbols_file.h" + +#include +#include +#include +#include +#include + +#if is_mingw +#include +#else +#include +#include +#endif + +#include +#include + +#include "dwarf_encoding.h" +#include "elf_parser.h" +#include "utilities.h" + +using namespace OHOS::Developtools::HiPerf::ELF; +using namespace std::chrono; + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +bool SymbolsFile::onRecording_ = false; +const std::string SymbolsFile::GetBuildId() const +{ + return buildId_; +} + +bool SymbolsFile::UpdateBuildIdIfMatch(std::string buildId) +{ + /* + here we have two case + 1 buildId_ is empty + a) always return match + 2 buildId_ is not empty + a) really check if the same one + */ + + if (buildId_.empty()) { + // we have new empty build + if (buildId.empty()) { + // both empty , no build id provided + HLOGD("build id is empty."); + return true; + } else { + buildId_ = buildId; + HLOGD("new buildId %s", buildId_.c_str()); + return true; + } + } else { + // we already have a build id + // so this is not the first time load symbol + // we need check if it match + HLOGV("expected buildid: %s vs %s", buildId_.c_str(), buildId.c_str()); + + if (buildId_ != buildId) { + HLOGW("id not match"); + return false; + } else { + HLOGD("id match"); + return true; + } + } +} + +std::string SymbolsFile::SearchReadableFile(const std::vector &searchPaths, + const std::string &filePath) const +{ + if (filePath.empty()) { + HLOGW("nothing to found"); + return filePath; + } + for (auto searchPath : searchPaths) { + if (searchPath.back() != PATH_SEPARATOR) { + searchPath += PATH_SEPARATOR; + } + std::string PossibleFilePath = searchPath + filePath; + if (CheckPathReadable(PossibleFilePath)) { + return PossibleFilePath; + } + HLOGW("have not found '%s' in search paths %s", filePath.c_str(), searchPath.c_str()); + } + return EMPTY_STRING; +} + +const std::string SymbolsFile::FindSymbolFile( + const std::vector &symbolsFileSearchPaths, std::string symboleFilePath) const +{ + /* + this function do 2 things: + find by name: + 1 find dso path + 2 find search path + a) search path + dso path + b) search path + dso name + + show we should return filePath_ as default ? + */ + if (symboleFilePath.empty()) { + symboleFilePath = filePath_; + HLOGD("use default filename: %s ", symboleFilePath.c_str()); + } + symboleFilePath = PlatformPathConvert(symboleFilePath); + std::string foundPath; + // search first if we have path + if (symbolsFileSearchPaths.size() != 0) { + foundPath = SearchReadableFile(symbolsFileSearchPaths, symboleFilePath); + if (foundPath.empty()) { + HLOGV("try base name for: %s split with %s", symboleFilePath.c_str(), + PATH_SEPARATOR_STR.c_str()); + auto pathSplit = StringSplit(symboleFilePath, PATH_SEPARATOR_STR); + if (pathSplit.size() > 1) { + HLOGV("base name is: %s ", pathSplit.back().c_str()); + // found it again with base name , split it and get last name + foundPath = SearchReadableFile(symbolsFileSearchPaths, pathSplit.back()); + } + } + } + + // only access the patch in onRecording_ + // in report mode we don't load any thing in runtime path + if (foundPath.empty() and onRecording_) { + // try access direct at last + if (CheckPathReadable(symboleFilePath)) { + // found direct folder + HLOGD("find %s in current work dir", symboleFilePath.c_str()); + return symboleFilePath; + } + } + return foundPath; +} + +class ElfFileSymbols : public SymbolsFile { +public: + explicit ElfFileSymbols(const std::string &symbolFilePath, + const SymbolsFileType symbolsFileType = SYMBOL_ELF_FILE) + : SymbolsFile(symbolsFileType, symbolFilePath) + { + } + + virtual ~ElfFileSymbols() + { + if (mmap_ != MMAP_FAILED) { + if (munmap(mmap_, mmapSize_) != 0) { + HLOGE("munmap failed with %p", munmap); + } + } + } + + bool LoadSymbols(const std::string &symbolFilePath) override + { + symbolsLoaded_ = true; + std::string findPath = FindSymbolFile(symbolsFileSearchPaths_, symbolFilePath); + if (findPath.empty()) { + HLOGW("elf found failed (belong to %s)", filePath_.c_str()); + return false; + } + if (LoadElfSymbols(findPath)) { + return true; + } else { + HLOGW("elf open failed with '%s'", findPath.c_str()); + return false; + } + return false; + } + + size_t ReadRoMemory(uint64_t addr, uint8_t * const data, size_t size) const override + { + size_t readSize = 0; + + if (mmap_ != MMAP_FAILED) { + if ((addr + size) <= mmapSize_) { + std::copy_n(static_cast(mmap_) + addr, size, data); + readSize = size; + } else { + HLOGW("read out of range."); + HLOGW("try read 0x%" PRIx64 "(elf offset)+%zu max is 0x%" PRIx64 "", addr, size, + mmapSize_); + } + } else { + if (readFd_ != nullptr) { + if (fseek(readFd_.get(), addr, SEEK_SET) != 0) { + return 0; + } + if (fread(data, size, 1u, readFd_.get())) { + readSize = size; + } else { + HLOGEP("read at %" PRIx64 " failed for %s", addr, filePath_.c_str()); + } + } + HLOGM("no mmap files loaded"); + } + + HLOGM("read %zu/%zu bytes at %" PRIx64 "(elf offset)", readSize, size, addr); + + return readSize; + } + +protected: + std::string CovertByteBufferToHexString(const unsigned char *buffer, size_t size) const + { + if (buffer == nullptr) { + HLOGE("param is null"); + return ""; + } + std::string descString; + size_t i = 0; + while (i < size) { + descString.append(ToHex(buffer[i])); + i++; // move to next char + } + return descString; + } + + std::string ElfGetBuildId(const unsigned char *buffer, size_t size) const + { + if (buffer == nullptr) { + HLOGE("param is null"); + return ""; + } + const unsigned char *end = buffer + size; + HLOGV("size:%zu", size); + + /* + Note Section + A vendor or system engineer might need to mark an object file with special + information that other programs can check for conformance or compatibility. Sections + of type SHT_NOTE and program header elements of type PT_NOTE can be used for this + purpose. + + The note information in sections and program header elements holds any number of + entries, as shown in the following figure. For 64–bit objects and 32–bit objects, + each entry is an array of 4-byte words in the format of the target processor. Labels + are shown in Figure 12-6 to help explain note information organization, but are not + part of the specification. + + Figure 12-5 Note Information + + image:ELF note section information. + namesz and name + The first namesz bytes in name contain a null-terminated character representation of + the entry's owner or originator. No formal mechanism exists for avoiding name + conflicts. By convention, vendors use their own name, such as “XYZ Computer + Company,” as the identifier. If no name is present, namesz contains the value zero. + Padding is present, if necessary, to ensure 4-byte alignment for the descriptor. + Such padding is not included in namesz. + + descsz and desc + The first descsz bytes in desc hold the note descriptor. If no descriptor is + present, descsz contains the value zero. Padding is present, if necessary, to ensure + 4-byte alignment for the next note entry. Such padding is not included in descsz. + + type + Provides the interpretation of the descriptor. Each originator controls its own + types. Multiple interpretations of a single type value can exist. A program must + recognize both the name and the type to understand a descriptor. Types currently + must be nonnegative. + + The note segment that is shown in the following figure holds two entries. + */ + + // namesz + descsz + type + static constexpr const int elfNoteSectionLens = sizeof(uint32_t) * 3; + + while (end - buffer >= elfNoteSectionLens) { + uint32_t namesz; + uint32_t descsz; + uint32_t type; + CopyFromBufferAndMove(buffer, &namesz); + CopyFromBufferAndMove(buffer, &descsz); + CopyFromBufferAndMove(buffer, &type); + + // to ensure 4-byte alignment for the descriptor. + constexpr const int elfNoteSectionNameAlign = 4; + + namesz = RoundUp(namesz, elfNoteSectionNameAlign); + descsz = RoundUp(descsz, elfNoteSectionNameAlign); + HLOGM("namesz:%u descsz:%u type:%u", namesz, descsz, type); + + // size enough ? + if (buffer >= end) { + return EMPTY_STRING; + } + if (type == NT_GNU_BUILD_ID) { + char name[namesz + 1]; + CopyFromBufferAndMove(buffer, &name[0], namesz); + name[namesz] = 0; + HLOGM("found buildid name:%s", name); + if (strcmp(name, ELF_NOTE_GNU) == 0) { + std::string descString = CovertByteBufferToHexString(buffer, descsz); + HLOGD("found buildid:%s", descString.c_str()); + return descString; + } else { + // next + buffer += descsz; + } + } else { + // next + buffer += namesz + descsz; + } + } + return EMPTY_STRING; // found nothing + } + + bool LoadDebugInfo(const std::string &symbolFilePath) override + { + if (debugInfoLoaded_) { + return true; + } else { + debugInfoLoaded_ = true; + } + std::string elfPath = FindSymbolFile(symbolsFileSearchPaths_, symbolFilePath); + if (elfPath.empty()) { + HLOGW("elf found failed (belong to %s)", filePath_.c_str()); + return false; + } + std::unique_ptr elfFile = LoadElfFile(elfPath); + if (elfFile == nullptr) { + HLOGD("elf load failed"); + return false; + } else { + HLOGD("loaded elf %s", elfPath.c_str()); + } + for (auto &phdr : elfFile->phdrs_) { + if ((phdr->type_ == PT_LOAD) && (phdr->flags_ & PF_X)) { + // find the min addr + if (textExecVaddr_ != std::min(textExecVaddr_, phdr->vaddr_)) { + textExecVaddr_ = std::min(textExecVaddr_, phdr->vaddr_); + textExecVaddrFileOffset_ = phdr->offset_; + } + } + } + + HLOGD("textExecVaddr_ 0x%016" PRIx64 " file offset 0x%016" PRIx64 "", textExecVaddr_, + textExecVaddrFileOffset_); + + if (!ParseShdr(std::move(elfFile))) { + return false; + } + + // mmap it for later use + LoadFileToMemory(elfPath); + return true; + } + +private: + bool EhFrameHDRValid_ {false}; + uint64_t ehFrameHDRElfOffset_ {0}; + uint64_t ehFrameHDRFdeCount_ {0}; + uint64_t ehFrameHDRFdeTableItemSize_ {0}; + uint64_t ehFrameHDRFdeTableElfOffset_ {0}; + OHOS::UniqueFd fd_ {-1}; + std::unique_ptr readFd_ {nullptr, &fclose}; + struct ShdrInfo { + uint64_t sectionVaddr_; + uint64_t sectionSize_; + uint64_t sectionFileOffset_; + ShdrInfo(uint64_t sectionVaddr, uint64_t sectionSize, uint64_t sectionFileOffset) + : sectionVaddr_(sectionVaddr), + sectionSize_(sectionSize), + sectionFileOffset_(sectionFileOffset) + { + } + }; + std::map shdrMap_ {}; + void *mmap_ {MMAP_FAILED}; + uint64_t mmapSize_ = {0}; + + const std::string GetReadableName(const std::string &name) const + { + int status = 0; + const char *nameStart = name.c_str(); + bool linkerName = false; + if (StringStartsWith(name, LINKER_PREFIX)) { + nameStart += LINKER_PREFIX.size(); + linkerName = true; + } + + char *demangle = abi::__cxa_demangle(nameStart, nullptr, nullptr, &status); + if (status == 0) { + std::string demangleName = demangle; + free(static_cast(demangle)); + return linkerName ? (LINKER_PREFIX_NAME + demangleName) : demangleName; + } else { + return linkerName ? (LINKER_PREFIX_NAME + nameStart) : nameStart; + } + } + + const std::string ElfStTypeName(unsigned char stt) const + { + switch (stt) { + case STT_FUNC: + return "function"; + case STT_GNU_IFUNC: + return "gun_func"; + case STT_OBJECT: + return " object"; + default: + return " unknown"; + } + } + + bool GetSectionInfo(const std::string &name, uint64_t §ionVaddr, uint64_t §ionSize, + uint64_t §ionFileOffset) const override + { + HLOGM("Section '%s' found in %zu", name.c_str(), shdrMap_.size()); + if (shdrMap_.count(name) > 0) { + HLOGM("Section '%s' found", name.c_str()); + const auto &shdrInfo = shdrMap_.at(name); + sectionVaddr = shdrInfo.sectionVaddr_; + sectionSize = shdrInfo.sectionSize_; + sectionFileOffset = shdrInfo.sectionFileOffset_; + HLOGM("Get Section '%s' %" PRIx64 " - %" PRIx64 "", name.c_str(), sectionVaddr, + sectionSize); + return true; + } else { + HLOGW("Section '%s' not found", name.c_str()); + return false; + } + } + +#ifndef target_cpu_arm + bool GetHDRSectionInfo(uint64_t &ehFrameHdrElfOffset, uint64_t &fdeTableElfOffset, + uint64_t &fdeTableSize) const override + { + if (EhFrameHDRValid_) { + ehFrameHdrElfOffset = ehFrameHDRElfOffset_; + fdeTableElfOffset = ehFrameHDRFdeTableElfOffset_; + fdeTableSize = ehFrameHDRFdeCount_ * ehFrameHDRFdeTableItemSize_; + return true; + } else { + HLOGW("!EhFrameHDRValid_"); + return false; + } + } +#endif + + void DumpEhFrameHDR() const + { + HLOGD(" ehFrameHDRElfOffset_: 0x%" PRIx64 "", ehFrameHDRElfOffset_); + HLOGD(" ehFrameHDRFdeCount_: 0x%" PRIx64 "", ehFrameHDRFdeCount_); + HLOGD(" ehFrameHDRFdeTableElfOffset_: 0x%" PRIx64 "", ehFrameHDRFdeTableElfOffset_); + HLOGD(" ehFrameHDRFdeTableItemSize_: 0x%" PRIx64 "", ehFrameHDRFdeTableItemSize_); + } + + bool LoadEhFrameHDR(const unsigned char *buffer, size_t bufferSize, uint64_t shdrOffset) + { + eh_frame_hdr *ehFrameHdr = (eh_frame_hdr *)buffer; + const uint8_t *dataPtr = ehFrameHdr->encode_data; + DwarfEncoding dwEhFramePtr(ehFrameHdr->eh_frame_ptr_enc, dataPtr); + DwarfEncoding dwFdeCount(ehFrameHdr->fde_count_enc, dataPtr); + DwarfEncoding dwTable(ehFrameHdr->table_enc, dataPtr); + DwarfEncoding dwTableValue(ehFrameHdr->table_enc, dataPtr); + + HLOGD("eh_frame_hdr:"); + HexDump(ehFrameHdr, BITS_OF_FOUR_BYTE, bufferSize); + unsigned char version = ehFrameHdr->version; + HLOGD(" version: %02x:%s", version, (version == 1) ? "valid" : "invalid"); + HLOGD(" eh_frame_ptr_enc: %s", dwEhFramePtr.ToString().c_str()); + HLOGD(" fde_count_enc: %s", dwFdeCount.ToString().c_str()); + HLOGD(" table_enc: %s", dwTable.ToString().c_str()); + HLOGD(" table_enc: %s", dwTable.ToString().c_str()); + HLOGD(" table_value_enc: %s", dwTableValue.ToString().c_str()); + HLOGD(" table_iteam_size: %zd", dwTable.GetSize() + dwTableValue.GetSize()); + HLOGD(" table_offset_in_hdr: %zu", dwTable.GetData() - buffer); + + if (version != 1) { + HLOGD("eh_frame_hdr version is invalid"); + return false; + } + EhFrameHDRValid_ = true; + ehFrameHDRElfOffset_ = shdrOffset; + ehFrameHDRFdeCount_ = dwFdeCount.GetAppliedValue(); + ehFrameHDRFdeTableElfOffset_ = dwTable.GetData() - buffer + shdrOffset; + ehFrameHDRFdeTableItemSize_ = dwTable.GetSize() + dwTableValue.GetSize(); + DumpEhFrameHDR(); + + if (!dwFdeCount.IsOmit() && dwFdeCount.GetValue() > 0) { + return true; + } else { + HLOGW("fde table not found."); + } + return false; + } + + void LoadFileToMemory(const std::string &loadElfPath) + { +#ifndef HIPERF_ELF_READ_USE_MMAP + if (readFd_ == nullptr) { + std::string resolvedPath = CanonicalizeSpecPath(loadElfPath.c_str()); + FILE *fp = fopen(resolvedPath.c_str(), "rb"); + if (fp == nullptr) { + return; + } + readFd_ = + std::unique_ptr(fp, &fclose); + fclose(fp); + return; + } +#else + if (fd_ != -1) { + return; + } +#if is_mingw + std::string resolvedPath = CanonicalizeSpecPath(loadElfPath.c_str()); + fd_ = OHOS::UniqueFd(open(resolvedPath.c_str(), O_RDONLY | O_BINARY)); +#else + std::string resolvedPath = CanonicalizeSpecPath(loadElfPath.c_str()); + fd_ = OHOS::UniqueFd(open(resolvedPath.c_str(), O_RDONLY)); +#endif + if (fd_ != -1) { + struct stat sb = {}; + + if (fstat(fd_, &sb) == -1) { + HLOGE("unable to check the file size"); + } else { + HLOGV("file stat size %" PRIu64 "", sb.st_size); + + // unmap it first + if (mmap_ != MMAP_FAILED) { + munmap(mmap_, mmapSize_); + } + + mmap_ = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd_, 0); + if (mmap_ == MMAP_FAILED) { + HLOGE("unable to map the file size %" PRIu64 " ", sb.st_size); + mmapSize_ = 0; + } else { + mmapSize_ = sb.st_size; + HLOGD("mmap build with size %" PRIu64 " ", mmapSize_); + } + } + } else { + HLOGD("elf file open failed with %s by %d", loadElfPath.c_str(), errno); + return; + } +#endif + } + + bool ReadSymTab(const std::unique_ptr &elfFile, const ELF::SectionHeader *shdr, + std::vector &symbolsTable) const + { + if (shdr == nullptr) { + HLOGE("param is null"); + return false; + } + HLOGV("ParseSymTable"); + if (!elfFile->ParseSymTable(shdr)) { + return false; + } + + HLOGV("Symbol Table:%s", shdr->secTypeName_.c_str()); + HLOGM("%*s|%16s|%4s|%s", MAX_SYMBOLS_TYPE_NAME_LEN, "type", "addr", "size", "name"); + + for (const std::unique_ptr &symbol : elfFile->symTable_->symbols_) { + if (ELF64_ST_TYPE(symbol->symInfo_) == STT_FUNC or + ELF64_ST_TYPE(symbol->symInfo_) == STT_GNU_IFUNC) { + /* + name| addr|size|name + function|00000000c0102b8c| 56|__lookup_processor_type + function|00000000c0102bd4| 0|__error_p + function|00000000c0008224| 64|__vet_atags + function|00000000c0008144| 128|__fixup_smp + function|00000000c00081d0| 64|__fixup_pv_table + function|00000000c000808c| 168|__create_page_tables + function|00000000c0b002e0| 68|__mmap_switched + function|00000000c0102acc| 20|__enable_mmu + object|00000000c0102ac0| 0|__secondary_data + function|00000000c0102ae0| 20|__do_fixup_smp_on_up + */ + + std::string name = elfFile->GetStrPtr(shdr->link_, symbol->nameIndex_); + std::string type = ElfStTypeName(ELF64_ST_TYPE(symbol->symInfo_)); + // this will cause malloc , maybe need do this in report ? + std::string demangle = GetReadableName(name); + HLOGV("%10s|%016" PRIx64 "|%4" PRIu64 "|%s", type.c_str(), symbol->symValue_, + symbol->symSize_, demangle.c_str()); + + if (symbol->symValue_ == 0) { + continue; // we don't need 0 addr symbol + } + symbolsTable.emplace_back(symbol->symValue_, symbol->symSize_, name, demangle, + filePath_); + } else { + continue; + } + } // for symbols + return true; + } + + bool ParseShdr(const std::unique_ptr elfFile) + { + // only save the section info , not actually read any file content + for (const auto &shdrPair : elfFile->shdrs_) { + const auto &shdr = shdrPair.second; + const char *sh_name = + elfFile->GetStrPtr(elfFile->ehdr_->shdrStrTabIdx_, shdr->nameIndex_); + const unsigned char *data = elfFile->GetSectionData(shdr->secIndex_); + + if (sh_name == nullptr || data == nullptr) { + HLOGE("name %p or data %p get failed.", sh_name, data); + return false; + } + + HLOGV("shdr name '%s' vaddr 0x%" PRIx64 " offset 0x%" PRIx64 " size 0x%" PRIx64 + " type 0x%" PRIx64 "(%s) index %u link 0x%u entry 0x%" PRIx64 "", + sh_name, shdr->secVaddr_, shdr->fileOffset_, shdr->secSize_, shdr->secType_, + shdr->secTypeName_.c_str(), shdr->secIndex_, shdr->link_, shdr->secEntrySize_); + + shdrMap_.emplace(sh_name, ShdrInfo(shdr->secVaddr_, shdr->secSize_, shdr->fileOffset_)); + } + return true; + } + + void AddSectionAsSymbol(const std::unique_ptr &shdr, const char *name, + std::vector &symbolsTable) const + { + HLOGV("add section %s as function symbol from 0x%" PRIx64 " size 0x%" PRIx64 "", name, + shdr->secVaddr_, shdr->secSize_); + symbolsTable.emplace_back(shdr->secVaddr_, shdr->secSize_, name, name, filePath_); + } + + bool ParseShdr(const std::unique_ptr elfFile, std::vector &symbolsTable, + std::string &buildIdFound) + { + const ELF::SectionHeader *symTableShdr = nullptr; + // walkthough + for (const auto &shdrPair : elfFile->shdrs_) { + const auto &shdr = shdrPair.second; + const char *sh_name = + elfFile->GetStrPtr(elfFile->ehdr_->shdrStrTabIdx_, shdr->nameIndex_); + const unsigned char *data = elfFile->GetSectionData(shdr->secIndex_); + + if (sh_name == nullptr || data == nullptr) { + HLOGE("name %p or data %p get failed.", sh_name, data); + return false; + } + + HLOGVVV("shdr name '%s' vaddr 0x%" PRIx64 " offset 0x%" PRIx64 " size 0x%" PRIx64 + " type 0x%" PRIx64 "(%s) index %u link 0x%u entry 0x%" PRIx64 "", + sh_name, shdr->secVaddr_, shdr->fileOffset_, shdr->secSize_, shdr->secType_, + shdr->secTypeName_.c_str(), shdr->secIndex_, shdr->link_, shdr->secEntrySize_); + + shdrMap_.emplace(sh_name, ShdrInfo(shdr->secVaddr_, shdr->secSize_, shdr->fileOffset_)); + switch (shdr->secType_) { + case SHT_SYMTAB: + symTableShdr = shdr.get(); + break; + case SHT_DYNSYM: + // if we already have SHT_SYMTAB ? + if (symTableShdr == nullptr) { + symTableShdr = shdr.get(); + } + break; + case SHT_NOTE: + // notes + if (buildIdFound.empty()) { + // we use our function, not from gelf_getnote + HLOGM("found NOTE_GNU_BUILD_ID size: %" PRIu64 "", shdr->secSize_); + + // there will be a log of note sh , we just need the right one + buildIdFound = ElfGetBuildId(data, shdr->secSize_); + } + break; + case SHT_PROGBITS: +#ifndef target_cpu_arm + if (EH_FRAME_HR == sh_name) { + LoadEhFrameHDR(data, shdr->secSize_, shdr->fileOffset_); + break; + } +#endif + if (PLT == sh_name) { + // this is a plt section, PLT table will put here + // we make it as named PLT function + AddSectionAsSymbol(shdr, sh_name, symbolsTable); + } + break; + default: + HLOGM("skip shdr.sh_type %" PRIx64 "", shdr->secType_); + break; + } // for shdr + } // for each shdrs_ + // load symtab + if (symTableShdr != nullptr) { + if (!ReadSymTab(elfFile, symTableShdr, symbolsTable)) { + return false; + } + } + return true; + } + + std::unique_ptr LoadElfFile(std::string &elfPath) const + { + HLOGD("try load elf %s", elfPath.c_str()); + if (elfPath.empty()) { + elfPath = filePath_; + HLOGD("use default elf path %s\n", elfPath.c_str()); + } + return ElfFile::MakeUnique(elfPath); + } + + void UpdateSymbols(std::vector &symbolsTable, const std::string &elfPath) + { + symbols_.clear(); + HLOGD("%zu symbols loadded from symbolsTable.", symbolsTable.size()); + + symbols_.swap(symbolsTable); + + AdjustSymbols(); + HLOGD("%zu symbols loadded from elf '%s'.", symbols_.size(), elfPath.c_str()); + if (buildId_.empty()) { + HLOGD("buildId not found from elf '%s'.", elfPath.c_str()); + // don't failed. some time the lib have not got the build id + // buildId not found from elf '/system/bin/ld-musl-arm.so.1'. + } + } + + bool LoadElfSymbols(std::string elfPath) + { +#ifdef HIPERF_DEBUG_TIME + const auto startTime = steady_clock::now(); +#endif + std::unique_ptr elfFile = LoadElfFile(elfPath); + if (elfFile == nullptr) { + HLOGD("elf load failed"); + return false; + } else { + HLOGD("loaded elf %s", elfPath.c_str()); + } + // we prepare two table here + // only one we will push in to symbols_ + // or both drop if build id is not same + std::vector symbolsTable; + std::string buildIdFound; + for (auto &phdr : elfFile->phdrs_) { + if ((phdr->type_ == PT_LOAD) && (phdr->flags_ & PF_X)) { + // find the min addr + if (textExecVaddr_ != std::min(textExecVaddr_, phdr->vaddr_)) { + textExecVaddr_ = std::min(textExecVaddr_, phdr->vaddr_); + textExecVaddrFileOffset_ = phdr->offset_; + } + } + } + + HLOGD("textExecVaddr_ 0x%016" PRIx64 " file offset 0x%016" PRIx64 "", textExecVaddr_, + textExecVaddrFileOffset_); + + if (!ParseShdr(std::move(elfFile), symbolsTable, buildIdFound)) { + return false; + } + + if (UpdateBuildIdIfMatch(buildIdFound)) { + UpdateSymbols(symbolsTable, elfPath); + } else { + HLOGW("symbols will not update for '%s' because buildId is not match.", + elfPath.c_str()); + // this mean failed . we don't goon for this. + return false; + } + + // mmap it for later use + LoadFileToMemory(elfPath); +#ifdef HIPERF_DEBUG_TIME + auto usedTime = duration_cast(steady_clock::now() - startTime); + if (usedTime.count() != 0) { + HLOGV("cost %0.3f ms to load symbols '%s'", + usedTime.count() / static_cast(milliseconds::duration::period::den), + elfPath.c_str()); + } +#endif + return true; + } + + uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, + uint64_t mapPageOffset) const override + { + /* + 00200000-002c5000 r--p 00000000 08:02 46400311 + 002c5000-00490000 r-xp 000c5000 08:02 4640031 + + [14] .text PROGBITS 00000000002c5000 000c5000 + + if ip is 0x46e6ab + 1. find the map range is 002c5000-00490000 + 2. ip - map start(002c5000) = map section offset + 3. map section offset + map page offset(000c5000) = elf file offset + 4. elf file offset - exec file offset(000c5000) + = ip offset (ip always in exec file offset) + 5. ip offset + exec begin vaddr(2c5000) = virtual ip in elf + */ + uint64_t vaddr = ip - mapStart + mapPageOffset - textExecVaddrFileOffset_ + textExecVaddr_; + HLOGM(" ip :0x%016" PRIx64 " -> elf offset :0x%016" PRIx64 " -> vaddr :0x%016" PRIx64 " ", + ip, ip - mapStart + mapPageOffset, vaddr); + HLOGM("(minExecAddrFileOffset_ is 0x%" PRIx64 " textExecVaddr_ is 0x%" PRIx64 ")", + textExecVaddrFileOffset_, textExecVaddr_); + return vaddr; + } +}; + +class KernelSymbols : public ElfFileSymbols { +public: + explicit KernelSymbols(const std::string &symbolFilePath) + : ElfFileSymbols(symbolFilePath, SYMBOL_KERNEL_FILE) + { + } + + static constexpr const int KSYM_MIN_TOKENS = 3; + static constexpr const int KSYM_DEFAULT_LINE = 35000; + static constexpr const int KSYM_DEFAULT_SIZE = 1024 * 1024 * 1; // 1MB + + bool ParseKallsymsLine() + { +#ifdef HIPERF_DEBUG_SYMBOLS_TIME + const auto startTime = steady_clock::now(); + std::chrono::microseconds parseLineTime = std::chrono::microseconds::zero(); + std::chrono::microseconds sscanfTime = std::chrono::microseconds::zero(); + std::chrono::microseconds newTime = std::chrono::microseconds::zero(); + std::chrono::microseconds readFileTime = std::chrono::microseconds::zero(); +#endif + size_t lines = 0; +#ifdef HIPERF_DEBUG_SYMBOLS_TIME + const auto eachFileStartTime = steady_clock::now(); +#endif + std::string kallsym; + if (!ReadFileToString("/proc/kallsyms", kallsym, KSYM_DEFAULT_SIZE)) { + HLOGW("/proc/kallsyms load failed."); + return false; + } +#ifdef HIPERF_DEBUG_SYMBOLS_TIME + // any way we finish the line scan + readFileTime += duration_cast(steady_clock::now() - eachFileStartTime); +#endif + // reduce the mem alloc + symbols_.reserve(KSYM_DEFAULT_LINE); + + char *lineBegin = kallsym.data(); + char *dataEnd = lineBegin + kallsym.size(); + while (lineBegin < dataEnd) { + char *lineEnd = strchr(lineBegin, '\n'); + if (lineEnd != nullptr) { + *lineEnd = '\0'; + } + size_t lineSize = (lineEnd != nullptr) ? (lineEnd - lineBegin) : (dataEnd - lineBegin); + +#ifdef HIPERF_DEBUG_SYMBOLS_TIME + const auto eachLineStartTime = steady_clock::now(); +#endif + lines++; + uint64_t addr = 0; + char type = '\0'; + + char nameRaw[lineSize]; + char moduleRaw[lineSize]; + int ret = sscanf_s(lineBegin, "%" PRIx64 " %c %s%s", &addr, &type, sizeof(type), + nameRaw, sizeof(nameRaw), moduleRaw, sizeof(moduleRaw)); + + lineBegin = lineEnd + 1; +#ifdef HIPERF_DEBUG_SYMBOLS_TIME + // any way we finish the line scan + sscanfTime += duration_cast(steady_clock::now() - eachLineStartTime); +#endif + if (ret >= KSYM_MIN_TOKENS) { + if (ret == KSYM_MIN_TOKENS) { + moduleRaw[0] = '\0'; + } + HLOGM(" 0x%016" PRIx64 " %c '%s' '%s'", addr, type, nameRaw, moduleRaw); + } else { + HLOGW("unknown line %d: '%s'", ret, lineBegin); + continue; + } + std::string name = nameRaw; + std::string module = moduleRaw; + + /* + T + The symbol is in the text (code) section. + + W + The symbol is a weak symbol that has not been specifically + tagged as a weak object symbol. When a weak defined symbol is + linked with a normal defined symbol, the normal defined symbol + is used with no error. When a weak undefined symbol is linked + and the symbol is not defined, the value of the weak symbol + becomes zero with no error. + */ + if (addr != 0 && strchr("TtWw", type)) { +#ifdef HIPERF_DEBUG_SYMBOLS_TIME + const auto eachNewSymbolTime = steady_clock::now(); +#endif + // we only need text symbols + symbols_.emplace_back(addr, name, module.empty() ? filePath_ : module); +#ifdef HIPERF_DEBUG_SYMBOLS_TIME + newTime += duration_cast(steady_clock::now() - eachNewSymbolTime); +#endif + } +#ifdef HIPERF_DEBUG_SYMBOLS_TIME + parseLineTime += duration_cast(steady_clock::now() - eachLineStartTime); +#endif + } +#ifdef HIPERF_DEBUG_SYMBOLS_TIME + std::chrono::microseconds usedTime = + duration_cast(steady_clock::now() - startTime); + printf("parse kernel symbols use : %0.3f ms\n", usedTime.count() / MS_DUARTION); + printf("parse line use : %0.3f ms\n", parseLineTime.count() / MS_DUARTION); + printf("sscanf line use : %0.3f ms\n", sscanfTime.count() / MS_DUARTION); + printf("new symbols use : %0.3f ms\n", newTime.count() / MS_DUARTION); + printf("read file use : %0.3f ms\n", readFileTime.count() / MS_DUARTION); +#endif + HLOGD("%zu line processed(%zu symbols)", lines, symbols_.size()); + return true; + } + + const std::string KPTR_RESTRICT = "/proc/sys/kernel/kptr_restrict"; + + bool LoadKernelSyms() + { + HLOGD("try read /proc/kallsyms"); + if (access("/proc/kallsyms", R_OK) != 0) { + printf("No vmlinux path is given, and kallsyms cannot be opened\n"); + return false; + } + + if (ReadFileToString(KPTR_RESTRICT).front() != '0') { + printf("/proc/sys/kernel/kptr_restrict is NOT 0, will try set it to 0.\n"); + if (!WriteStringToFile(KPTR_RESTRICT, "0")) { + printf("/proc/sys/kernel/kptr_restrict write failed and we can't not change it.\n"); + } + } + + // getline end + if (!ParseKallsymsLine()) { + return false; + } + + if (symbols_.empty()) { + printf("The symbol table addresses in /proc/kallsyms are all 0.\n" + "Please check the value of /proc/sys/kernel/kptr_restrict, it " + "should be 0.\n" + "Or provide a separate vmlinux path.\n"); + + if (buildId_.size() != 0) { + // but we got the buildid , so we make a dummpy symbols + HLOGD("kallsyms not found. but we have the buildid"); + return true; + } else { + // we got nothing + return false; + } + } else { + AdjustSymbols(); + HLOGV("%zu symbols_ loadded from kallsyms.\n", symbols_.size()); + return true; + } + } + bool LoadSymbols(const std::string &symbolFilePath) override + { + symbolsLoaded_ = true; + HLOGV("KernelSymbols try read '%s' search paths size %zu, inDeviceRecord %d", + symbolFilePath.c_str(), symbolsFileSearchPaths_.size(), onRecording_); + + if (onRecording_) { + // try read + HLOGD("try read /sys/kernel/notes"); + std::string notes = ReadFileToString("/sys/kernel/notes"); + if (notes.empty()) { + printf("notes cannot be opened, unable get buildid\n"); + return false; + } else { + HLOGD("kernel notes size: %zu", notes.size()); + buildId_ = ElfGetBuildId((const unsigned char *)notes.data(), notes.size()); + } + + const auto startTime = std::chrono::steady_clock::now(); + if (!LoadKernelSyms()) { + printf("parse kalsyms failed.\n"); + return false; + } else { + const auto thisTime = std::chrono::steady_clock::now(); + const auto usedTimeMsTick = + std::chrono::duration_cast(thisTime - startTime); + HLOGV("Load kernel symbols (total %" PRId64 " ms)\n", (int64_t)usedTimeMsTick.count()); + // load complete + return true; + } + } // no search path + + // try vmlinux + return ElfFileSymbols::LoadSymbols(KERNEL_ELF_NAME); + } + uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t) const override + { + // ip is vaddr in /proc/kallsyms + return ip; + } + ~KernelSymbols() override {} +}; + +class KernelModuleSymbols : public ElfFileSymbols { +public: + explicit KernelModuleSymbols(const std::string &symbolFilePath) : ElfFileSymbols(symbolFilePath) + { + HLOGV("create %s", symbolFilePath.c_str()); + symbolFileType_ = SYMBOL_KERNEL_MODULE_FILE; + module_ = symbolFilePath; + } + ~KernelModuleSymbols() override {}; + + bool LoadSymbols(const std::string &symbolFilePath) override + { + symbolsLoaded_ = true; + if (module_ == filePath_ and onRecording_) { + // file name still not convert to ko file path + // this is in record mode + HLOGV("find ko name %s", module_.c_str()); + for (const std::string &path : kernelModulePaths) { + if (access(path.c_str(), R_OK) == 0) { + std::string koPath = path + module_ + KERNEL_MODULES_EXT_NAME; + HLOGV("found ko in %s", koPath.c_str()); + if (access(koPath.c_str(), R_OK) == 0) { + // create symbol + filePath_ = koPath; + break; // find next ko + } + } + } + LoadBuildId(); + } else { + HLOGV("we have file path, load with %s", filePath_.c_str()); + return ElfFileSymbols::LoadSymbols(filePath_); + } + return false; + } + uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, uint64_t) const override + { + return ip - mapStart; + } + +private: + bool LoadBuildId() + { + std::string sysFile = "/sys/module/" + module_ + "/notes/.note.gnu.build-id"; + std::string buildIdRaw = ReadFileToString(sysFile); + if (!buildIdRaw.empty()) { + buildId_ = ElfGetBuildId((const unsigned char *)buildIdRaw.data(), buildIdRaw.size()); + HLOGD("kerne module %s(%s) build id %s", module_.c_str(), filePath_.c_str(), + buildId_.c_str()); + return buildId_.empty() ? false : true; + } + return false; + } + + const std::vector kernelModulePaths = {"/vendor/modules/"}; + std::string module_ = ""; +}; + +class JavaFileSymbols : public ElfFileSymbols { +public: + explicit JavaFileSymbols(const std::string &symbolFilePath) : ElfFileSymbols(symbolFilePath) + { + symbolFileType_ = SYMBOL_KERNEL_FILE; + } + bool LoadSymbols(const std::string &symbolFilePath) override + { + symbolsLoaded_ = true; + return false; + } + ~JavaFileSymbols() override {} + + uint64_t GetVaddrInSymbols(uint64_t ip, uint64_t mapStart, + uint64_t mapPageOffset) const override + { + // this is different with elf + // elf use ip - mapStart + mapPageOffset - minExecAddrFileOffset_ + textExecVaddr_ + return ip - mapStart + mapPageOffset; + } +}; + +class JSFileSymbols : public ElfFileSymbols { +public: + explicit JSFileSymbols(const std::string &symbolFilePath) : ElfFileSymbols(symbolFilePath) + { + symbolFileType_ = SYMBOL_KERNEL_FILE; + } + bool LoadSymbols(const std::string &symbolFilePath) override + { + symbolsLoaded_ = true; + return false; + } + ~JSFileSymbols() override {} +}; + +class UnknowFileSymbols : public SymbolsFile { +public: + explicit UnknowFileSymbols(const std::string &symbolFilePath) + : SymbolsFile(SYMBOL_UNKNOW_FILE, symbolFilePath) + { + } + bool LoadSymbols(const std::string &symbolFilePath) override + { + symbolsLoaded_ = true; + return false; + } + ~UnknowFileSymbols() override {} +}; + +SymbolsFile::~SymbolsFile() {} + +std::unique_ptr SymbolsFile::CreateSymbolsFile(SymbolsFileType symbolType, + const std::string symbolFilePath) +{ + switch (symbolType) { + case SYMBOL_KERNEL_FILE: + return std::make_unique(symbolFilePath.empty() ? KERNEL_MMAP_NAME + : symbolFilePath); + case SYMBOL_KERNEL_MODULE_FILE: + return std::make_unique(symbolFilePath); + case SYMBOL_ELF_FILE: + return std::make_unique(symbolFilePath); + case SYMBOL_JAVA_FILE: + return std::make_unique(symbolFilePath); + case SYMBOL_JS_FILE: + return std::make_unique(symbolFilePath); + default: + return std::make_unique(SYMBOL_UNKNOW_FILE, symbolFilePath); + } +} + +std::unique_ptr SymbolsFile::CreateSymbolsFile(const std::string &symbolFilePath) +{ + // we need check file name here + if (symbolFilePath == KERNEL_MMAP_NAME) { + return SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_FILE, symbolFilePath); + } else if (StringEndsWith(symbolFilePath, KERNEL_MODULES_EXT_NAME)) { + return SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_MODULE_FILE, symbolFilePath); + } else { + // default is elf + return SymbolsFile::CreateSymbolsFile(SYMBOL_ELF_FILE, symbolFilePath); + } +} + +void SymbolsFile::AdjustSymbols() +{ + if (symbols_.size() <= 1u) { + return; + } + + // order + sort(symbols_.begin(), symbols_.end(), Symbol::CompareLessThen); + HLOGV("sort completed"); + + size_t fullSize = symbols_.size(); + size_t erased = 0; + + // Check for duplicate vaddr + auto last = std::unique(symbols_.begin(), symbols_.end(), &Symbol::SameVaddr); + symbols_.erase(last, symbols_.end()); + erased = fullSize - symbols_.size(); + HLOGV("uniqued completed"); + auto it = symbols_.begin(); + while (it != symbols_.end()) { + it->index_ = it - symbols_.begin(); + it++; + } + HLOGV("indexed completed"); + + HLOG_ASSERT(symbols_.size() != 0); + + if (textExecVaddrRange_ == maxVaddr) { + textExecVaddrRange_ = symbols_.back().funcVaddr_ - symbols_.front().funcVaddr_; + } + + HLOGDDD("%zu symbols after adjust (%zu erased) 0x%016" PRIx64 " - 0x%016" PRIx64 + " @0x%016" PRIx64 " ", + symbols_.size(), erased, symbols_.front().funcVaddr_, symbols_.back().funcVaddr_, + textExecVaddrFileOffset_); +} + +void SymbolsFile::SortMatchedSymbols() +{ + if (matchedSymbols_.size() <= 1u) { + return; + } + sort(matchedSymbols_.begin(), matchedSymbols_.end(), Symbol::CompareByPointer); +} + +const std::vector &SymbolsFile::GetSymbols() +{ + return symbols_; +} + +const std::vector &SymbolsFile::GetMatchedSymbols() +{ + return matchedSymbols_; +} + +const Symbol SymbolsFile::GetSymbolWithVaddr(uint64_t vaddrInFile) +{ +#ifdef HIPERF_DEBUG_TIME + const auto startTime = steady_clock::now(); +#endif + Symbol symbol; + // it should be already order from small to large + auto found = + std::upper_bound(symbols_.begin(), symbols_.end(), vaddrInFile, Symbol::ValueLessThen); + /* + if data is { 1, 2, 4, 5, 5, 6 }; + upper_bound for each val : + 0 < 1 at index 0 + 1 < 2 at index 1 + 2 < 4 at index 2 + 3 < 4 at index 2 + 4 < 5 at index 3 + 5 < 6 at index 5 + 6 < not found + if key symbol vaddr is { 1, 2, 4, 5, 5, 6 }; + check ip vaddr for each val : + ip sym + 0 not found + 1 1 + 1 1 + 2 2 + 3 3 + 4 4 + 5 5 + 6 6 + 7 7 + */ + if (found != symbols_.begin()) { + found = std::prev(found); + if (found->Contain(vaddrInFile)) { + if (!found->HasMatched()) { + found->SetMatchFlag(); + matchedSymbols_.push_back(&(*found)); + } + symbol = *found; // copy + HLOGV("found '%s' for vaddr 0x%016" PRIx64 "", symbol.ToString().c_str(), vaddrInFile); + } + } + + if (!symbol.isValid()) { + HLOGV("NOT found vaddr 0x%" PRIx64 " in symbole file %s(%zu)", vaddrInFile, + filePath_.c_str(), symbols_.size()); + } + symbol.fileVaddr_ = vaddrInFile; + +#ifdef HIPERF_DEBUG_TIME + auto usedTime = duration_cast(steady_clock::now() - startTime); + if (usedTime > 1ms) { + HLOGW("cost %" PRId64 "ms to search ", usedTime.count()); + } +#endif + return symbol; +} + +bool SymbolsFile::CheckPathReadable(const std::string &path) const +{ + if (access(path.c_str(), R_OK) == 0) { + return true; + } else { + HLOGM("'%s' is unable read", path.c_str()); + return false; + } +} + +bool SymbolsFile::setSymbolsFilePath(const std::vector &symbolsSearchPaths) +{ + symbolsFileSearchPaths_.clear(); + for (auto &symbolsSearchPath : symbolsSearchPaths) { + if (CheckPathReadable(symbolsSearchPath)) { + symbolsFileSearchPaths_.emplace_back(symbolsSearchPath); + HLOGV("'%s' is add to symbolsSearchPath", symbolsSearchPath.c_str()); + } + } + return (symbolsFileSearchPaths_.size() > 0); +} + +std::unique_ptr SymbolsFile::LoadSymbolsFromSaved( + const SymbolFileStruct &symbolFileStruct) +{ + auto symbolsFile = CreateSymbolsFile(symbolFileStruct.filePath_); + symbolsFile->filePath_ = symbolFileStruct.filePath_; + symbolsFile->symbolFileType_ = (SymbolsFileType)symbolFileStruct.symbolType_; + symbolsFile->textExecVaddr_ = symbolFileStruct.textExecVaddr_; + symbolsFile->textExecVaddrFileOffset_ = symbolFileStruct.textExecVaddrFileOffset_; + symbolsFile->buildId_ = symbolFileStruct.buildId_; + for (auto &symbolStruct : symbolFileStruct.symbolStructs_) { + symbolsFile->symbols_.emplace_back(symbolStruct.vaddr_, symbolStruct.len_, + symbolStruct.symbolName_, symbolFileStruct.filePath_); + } + symbolsFile->AdjustSymbols(); // reorder + HLOGV("load %zu symbol from SymbolFileStruct for file '%s'", symbolsFile->symbols_.size(), + symbolsFile->filePath_.c_str()); + return symbolsFile; +} + +void SymbolsFile::ExportSymbolToFileFormat(SymbolFileStruct &symbolFileStruct) +{ + symbolFileStruct.filePath_ = filePath_; + symbolFileStruct.symbolType_ = symbolFileType_; + symbolFileStruct.textExecVaddr_ = textExecVaddr_; + symbolFileStruct.textExecVaddrFileOffset_ = textExecVaddrFileOffset_; + symbolFileStruct.buildId_ = buildId_; + + SortMatchedSymbols(); + auto symbols = GetMatchedSymbols(); + symbolFileStruct.symbolStructs_.reserve(symbols.size()); + for (auto symbol : symbols) { + auto &symbolStruct = symbolFileStruct.symbolStructs_.emplace_back(); + symbolStruct.vaddr_ = symbol->funcVaddr_; + symbolStruct.len_ = symbol->len_; + symbolStruct.symbolName_ = symbol->Name(); + } + + HLOGV("export %zu symbol to SymbolFileStruct from %s", symbolFileStruct.symbolStructs_.size(), + filePath_.c_str()); +} + +uint64_t SymbolsFile::GetVaddrInSymbols(uint64_t ip, uint64_t, uint64_t) const +{ + // no convert + return ip; +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/utilities.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/utilities.cpp new file mode 100755 index 0000000000000000000000000000000000000000..4f118d7e548e6d257283824cb2ffe241298889fc --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/utilities.cpp @@ -0,0 +1,541 @@ +/* + * Copyright (c) 2021-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. + */ +#include "utilities.h" +#if is_mingw +#include +#endif + +namespace OHOS { +namespace Developtools { +namespace HiPerf { +const char *MemoryHold::HoldStringView(std::string_view view) +{ + if (view.size() == 0) { + return ""; + } + char *p = new char[view.size() + 1]; + if (p == nullptr) { + return ""; + } + p[view.size()] = '\0'; + std::copy(view.data(), view.data() + view.size(), p); + holder_.emplace_back(p); + return p; +} + +std::string CanonicalizeSpecPath(const char* src) +{ + if (src == nullptr || strlen(src) >= PATH_MAX) { + fprintf(stderr, "Error: CanonicalizeSpecPath failed, src is NULL"); + return ""; + } + char resolvedPath[PATH_MAX] = { 0 }; +#if defined(_WIN32) + if (!_fullpath(resolvedPath, src, PATH_MAX)) { + fprintf(stderr, "Error: _fullpath %s failed", src); + return ""; + } +#else + if (access(src, F_OK) == 0) { + if (realpath(src, resolvedPath) == nullptr) { + fprintf(stderr, "Error: realpath %s failed", src); + return ""; + } + } else { + std::string fileName(src); + if (fileName.find("..") == std::string::npos) { + if (sprintf_s(resolvedPath, PATH_MAX, "%s", src) == -1) { + fprintf(stderr, "Error: sprintf_s %s failed", src); + return ""; + } + } else { + fprintf(stderr, "Error: find .. %s failed", src); + return ""; + } + } +#endif + std::string res(resolvedPath); + return res; +} + +uint32_t RoundUp(uint32_t x, const int align) +{ + return (((x) + (align)-1) / (align)) * (align); +} + +std::string StringReplace(std::string source, const std::string &from, const std::string &to) +{ + size_t pos = 0; + std::string result; + // find + while ((pos = source.find(from)) != std::string::npos) { + // replace + result.append(source.substr(0, pos) + to); + source.erase(0, pos + from.length()); + } + // add last token + result.append(source); + return result; +} + +size_t SubStringCount(const std::string &source, const std::string &sub) +{ + size_t count(0); + size_t pos(0); + if (sub.empty()) { + return source.size(); + } + while ((pos = source.find(sub, pos)) != std::string::npos) { + pos += sub.size(); + count++; + } + return count; +} + +std::vector StringSplit(std::string source, std::string split) +{ + std::vector result; + + // find + if (!split.empty()) { + size_t pos = 0; + while ((pos = source.find(split)) != std::string::npos) { + // split + std::string token = source.substr(0, pos); + if (!token.empty()) { + result.push_back(token); + } + source.erase(0, pos + split.length()); + } + } + // add last token + if (!source.empty()) { + result.push_back(source); + } + return result; +} +StdoutRecord::StdoutRecord(const std::string &tempFile, const std::string &mode) +{ + if (!tempFile.empty()) { + std::string resolvedPath = CanonicalizeSpecPath(tempFile.c_str()); + recordFile_ = fopen(resolvedPath.c_str(), mode.c_str()); + if (recordFile_ == nullptr) { + HLOGE("tmpfile create failed '%s' with mode '%s'", tempFile.c_str(), mode.c_str()); + } else { + // auto start it + Start(); + } + } +} +bool StdoutRecord::Start() +{ + content_ = EMPTY_STRING; + fflush(stdout); + + // we will save output here + if (recordFile_ == nullptr) { + recordFile_ = std::tmpfile(); + } + if (recordFile_ == nullptr) { + // try second way + std::string fileName = "temp.stdout"; + std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str()); + recordFile_ = fopen(resolvedPath.c_str(), "w+"); + if (recordFile_ == nullptr) { + HLOGF("tmpfile create failed '%s'", fileName.c_str()); + return false; + } + } + + // we save the stdout + stdoutFile_ = OHOS::UniqueFd(dup(STDOUT_FILENO)); + if (stdoutFile_ == -1) { + HLOGF("std dup failed"); + return false; + } + + // setup temp file as stdout + if (dup2(fileno(recordFile_), STDOUT_FILENO) != -1) { + stop_ = false; + return true; + } else { + HLOGF("std dup2 failed"); + return false; + } +} + +std::string StdoutRecord::Stop() +{ + if (stop_) + return content_; + fflush(stdout); + // restore fd + dup2(stdoutFile_, STDOUT_FILENO); + + // return file content + if (recordFile_ != nullptr) { + const long fileLength = lseek(fileno(recordFile_), 0, SEEK_END); + content_.resize(fileLength); + lseek(fileno(recordFile_), 0, SEEK_SET); + const long len = read(fileno(recordFile_), content_.data(), fileLength); + std::fclose(recordFile_); + recordFile_ = nullptr; + if (len < 0) { + HLOGE("tmp file read failed (try read %ld)", fileLength); + } else if (len < fileLength) { + HLOGE("not all the data is read, lost %ld/%ld bytes", fileLength - len, fileLength); + } + } else { + HLOGE("recordFile_ is nullptr"); + } + stop_ = true; + return content_; +} + +bool IsDigits(const std::string &str) +{ + if (str.empty()) { + return false; + } else { + return std::all_of(str.begin(), str.end(), ::isdigit); + } +} + +bool IsHexDigits(const std::string &str) +{ + if (str.empty()) { + return false; + } + const std::string prefix {"0x"}; + std::string effectStr {str}; + if (prefix.compare(0, prefix.size(), effectStr.substr(0, prefix.size())) == 0) { + effectStr = effectStr.substr(prefix.size(), effectStr.size() - prefix.size()); + } + if (effectStr.empty()) { + return false; + } + std::size_t start {0}; + for (; start < effectStr.size(); ++start) { + if (effectStr[start] == '0') { + continue; + } + break; + } + if (start == effectStr.size()) { + effectStr = "0"; + } + return std::all_of(effectStr.begin(), effectStr.end(), ::isxdigit); +} + +bool IsDir(const std::string &path) +{ + struct stat st; + if (stat(path.c_str(), &st) == 0) { + return S_ISDIR(st.st_mode); + } + return false; +} + +bool IsPath(const std::string &fileName) +{ + HLOG_ASSERT(!fileName.empty()); + if (fileName[0] == PATH_SEPARATOR) { + return true; + } + const int prefixPathLen = 2; + if (fileName.substr(0, prefixPathLen) == "./") { + return true; + } + return false; +} + +std::string PlatformPathConvert(const std::string &path) +{ +#if is_mingw + return StringReplace(path, "/", "\\"); +#else + return path; +#endif +} + +std::string ReadFileToString(const std::string &fileName) +{ + std::ifstream inputString(fileName, std::ios::in); + if (!inputString or !inputString.is_open()) { + return EMPTY_STRING; + } + std::istreambuf_iterator firstIt = {inputString}; + std::istreambuf_iterator lastIt = {}; + + std::string content(firstIt, lastIt); + return content; +} + +bool ReadFileToString(const std::string &fileName, std::string &fileData, size_t fileSize) +{ + fileData.clear(); + std::string resolvedPath = CanonicalizeSpecPath(fileName.c_str()); + OHOS::UniqueFd fd(open(resolvedPath.c_str(), O_RDONLY | O_BINARY)); + if (fileSize == 0) { + struct stat fileStat; + if (fstat(fd.Get(), &fileStat) != -1 && fileStat.st_size > 0) { + fileData.reserve(fileStat.st_size); + } + } else { + fileData.reserve(fileSize); + } + + char buf[BUFSIZ] __attribute__((__uninitialized__)); + ssize_t readSize; + while ((readSize = read(fd.Get(), &buf[0], sizeof(buf))) > 0) { + fileData.append(buf, readSize); + } + return (readSize == 0) ? true : false; +} + +bool WriteStringToFile(const std::string &fileName, const std::string &value) +{ + std::ofstream output(fileName, std::ios::out); + if (!output) { + return false; + } + output << value; + + return output.good(); +} + +bool IsRoot() +{ +#if is_linux || is_ohos + static bool isRoot = (getuid() == 0); + return isRoot; +#else + return true; +#endif +} + +bool PowerOfTwo(uint64_t n) +{ + return n && (!(n & (n - 1))); +} + +bool ReadIntFromProcFile(const std::string &path, int &value) +{ + std::string s = ReadFileToString(path); + if (s.empty()) { + return false; + } + value = std::stoi(s); + return true; +} + +bool WriteIntToProcFile(const std::string &path, int value) +{ + std::string s = std::to_string(value); + + return WriteStringToFile(path, s); +} + +// compress specified dataFile into gzip file +bool CompressFile(const std::string &dataFile, const std::string &destFile) +{ + return true; +} + +// uncompress specified gzip file into dataFile +bool UncompressFile(const std::string &gzipFile, const std::string &dataFile) +{ + return true; +} + +std::string &StringTrim(std::string &string) +{ + if (!string.empty()) { + string.erase(0, string.find_first_not_of(" ")); + string.erase(string.find_last_not_of(" ") + 1); + } + return string; +} + +std::vector GetEntriesInDir(const std::string &basePath) +{ + std::vector result; + DIR *dir = opendir(basePath.c_str()); + if (dir == nullptr) { + return result; + } + dirent *entry; + while ((entry = readdir(dir)) != nullptr) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + result.push_back(entry->d_name); + } + closedir(dir); + return result; +} + +std::vector GetSubDirs(const std::string &basePath) +{ + std::vector entries = GetEntriesInDir(basePath); + std::vector result = {}; + for (std::size_t index = 0; index < entries.size(); ++index) { + if (IsDir(basePath + "/" + entries[index])) { + result.push_back(std::move(entries[index])); + } + } + return result; +} + +bool IsSameCommand(const std::string &cmdLine, const std::string &cmdName) +{ + std::vector cmdpaths = StringSplit(cmdLine, "/"); + if (!cmdpaths.empty()) { + if (strcmp(cmdpaths.back().c_str(), cmdName.c_str()) == 0) { + return true; + } + } + return false; +} + +std::vector GetSubthreadIDs(const pid_t pid) +{ + std::string path {"/proc/"}; + path += std::to_string(pid); + path += "/task/"; + auto tids = GetSubDirs(path); + std::vector res {}; + for (auto tidStr : tids) { + pid_t tid = static_cast(std::stoul(tidStr, nullptr)); + if (tid == pid) { + continue; + } + res.push_back(tid); + } + return res; +} + +bool StringStartsWith(const std::string &string, const std::string &with) +{ + return string.find(with) == 0; +} + +bool StringEndsWith(const std::string &string, const std::string &with) +{ + if (string.empty()) { + // empty string only end with empty string + if (with.empty()) { + return true; + } else { + return false; + } + } + return string.rfind(with) == (string.length() - with.length()); +} + +void HexDump(const void *buf, size_t size, size_t maxSize) +{ + const unsigned char *byteBuf = static_cast(buf); + const size_t dumpByteEachLine = 8; + size_t outputBytes = 0; + if (!maxSize) { + outputBytes = size; + } else { + outputBytes = std::min(size, maxSize); + } + + for (size_t i = 0; i <= outputBytes; i += dumpByteEachLine) { + HLOGM(" %02zu: %s ", i, BufferToHexString(byteBuf, dumpByteEachLine).c_str()); + byteBuf += dumpByteEachLine; + } +} + +std::string BufferToHexString(const std::vector &vec) +{ + return BufferToHexString(vec.data(), vec.size()); +} + +std::string BufferToHexString(const unsigned char buf[], size_t size) +{ + std::stringstream ss; + ss << size << ":"; + for (size_t i = 0; i < size; i++) { + ss << " 0x" << std::setfill('0') << std::setw(BYTE_PRINT_WIDTH) << std::hex + << (unsigned short)buf[i]; + } + return ss.str(); +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS + +// this will also used for libunwind head (out of namespace) +#if is_mingw +using namespace OHOS::Developtools::HiPerf; +std::string GetLastErrorString() +{ + LPVOID lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), 0, (LPTSTR)&lpMsgBuf, 0, NULL); + std::string error((LPTSTR)lpMsgBuf); + LocalFree(lpMsgBuf); + return error; +} + +void *mmap(void *addr, size_t length, int prot, int flags, int fd, size_t offset) +{ + HANDLE FileHandle = reinterpret_cast(_get_osfhandle(fd)); + if (FileHandle == INVALID_HANDLE_VALUE) { + return MMAP_FAILED; + } + + HLOGV("fd is %d", fd); + + HANDLE FileMappingHandle = ::CreateFileMappingW(FileHandle, 0, PAGE_READONLY, 0, 0, 0); + if (FileMappingHandle == nullptr) { + HLOGE("CreateFileMappingW %zu Failed with %ld:%s", length, GetLastError(), + GetLastErrorString().c_str()); + return MMAP_FAILED; + } + + void *mapAddr = ::MapViewOfFile(FileMappingHandle, FILE_MAP_READ, 0, 0, 0); + if (mapAddr == nullptr) { + HLOGE("MapViewOfFile %zu Failed with %ld:%s", length, GetLastError(), + GetLastErrorString().c_str()); + return MMAP_FAILED; + } + + // Close all the handles except for the view. It will keep the other handles + // alive. + ::CloseHandle(FileMappingHandle); + return mapAddr; +} + +int munmap(void *addr, size_t) +{ + /* + On success, munmap() returns 0. On failure, it returns -1, and + errno is set to indicate the error (probably to EINVAL). + + UnmapViewOfFile function (memoryapi.h) + + If the function succeeds, the return value is nonzero. + If the function fails, the return value is zero. To get extended error information, call + GetLastError. + */ + return !UnmapViewOfFile(addr); +} +#endif diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/virtual_runtime.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/virtual_runtime.cpp new file mode 100755 index 0000000000000000000000000000000000000000..4b1ec2b59ad65f7ea94dd4ff6db89b6f5766995b --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/virtual_runtime.cpp @@ -0,0 +1,706 @@ +/* + * Copyright (c) 2021-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. + */ +#define HILOG_TAG "Runtime" + +#include "virtual_runtime.h" + +#include +#include +#include +#include +#if !is_mingw +#include +#endif + +#include "register.h" +#include "symbols_file.h" +#include "utilities.h" + +using namespace std::chrono; +namespace OHOS { +namespace Developtools { +namespace HiPerf { +// we unable to access 'swapper' from /proc/0/ +VirtualRuntime::VirtualRuntime(bool onDevice) +{ + UpdateThread(0, 0, "swapper"); +} + +std::string VirtualRuntime::ReadThreadName(pid_t tid) +{ + std::string comm = ReadFileToString(StringPrintf("/proc/%d/comm", tid)).c_str(); + comm.erase(std::remove(comm.begin(), comm.end(), '\r'), comm.end()); + comm.erase(std::remove(comm.begin(), comm.end(), '\n'), comm.end()); + return comm; +} + +VirtualThread &VirtualRuntime::UpdateThread(pid_t pid, pid_t tid, const std::string name) +{ +#ifdef HIPERF_DEBUG_TIME + const auto startTime = steady_clock::now(); +#endif + VirtualThread &thread = GetThread(pid, tid); + if (!name.empty()) { + thread.name_ = name; + } +#ifdef HIPERF_DEBUG_TIME + updateThreadTimes_ += duration_cast(steady_clock::now() - startTime); +#endif + return thread; +} + +VirtualThread &VirtualRuntime::CreateThread(pid_t pid, pid_t tid) +{ + // make a new one + if (pid == tid) { + userSpaceThreadMap_.emplace(std::piecewise_construct, std::forward_as_tuple(tid), + std::forward_as_tuple(pid, symbolsFiles_)); + } else { + // for thread we need give it process info( for same mmap) + userSpaceThreadMap_.emplace( + std::piecewise_construct, std::forward_as_tuple(tid), + std::forward_as_tuple(pid, tid, GetThread(pid, pid), symbolsFiles_)); + } + VirtualThread &thread = userSpaceThreadMap_.at(tid); + if (recordCallBack_) { + if (pid == tid) { +#ifdef HIPERF_DEBUG_TIME + const auto startTime = steady_clock::now(); +#endif + thread.ParseMap(); +#ifdef HIPERF_DEBUG_TIME + threadParseMapsTimes_ += duration_cast(steady_clock::now() - startTime); +#endif + } +#ifdef HIPERF_DEBUG_TIME + const auto startCreateMmapTime = steady_clock::now(); +#endif + thread.name_ = ReadThreadName(pid); + HLOGD("create a new thread record for %u:%u:%s with %zu dso", pid, tid, + thread.name_.c_str(), thread.GetMaps().size()); + // we need make a PerfRecordComm + auto commRecord = std::make_unique(false, pid, tid, thread.name_); + recordCallBack_(std::move(commRecord)); + // only work for pid + if (pid == tid) { + for (auto &memMapItem : thread.GetMaps()) { + auto mmapRecord = + std::make_unique(false, thread.pid_, thread.tid_, memMapItem); + HLOGD("make PerfRecordMmap2 %d:%d:%s:%s(0x%" PRIx64 "-0x%" PRIx64 ")@%" PRIx64 " ", + thread.pid_, thread.tid_, thread.name_.c_str(), memMapItem.name_.c_str(), + memMapItem.begin_, memMapItem.end_, memMapItem.pageoffset_); + recordCallBack_(std::move(mmapRecord)); + UpdateSymbols(memMapItem.name_); + } + } + HLOGV("thread created"); +#ifdef HIPERF_DEBUG_TIME + threadCreateMmapTimes_ += + duration_cast(steady_clock::now() - startCreateMmapTime); +#endif + } + return thread; +} + +VirtualThread &VirtualRuntime::GetThread(pid_t pid, pid_t tid) +{ + if (userSpaceThreadMap_.find(pid) == userSpaceThreadMap_.end()) { + // no pid found + // create process first + CreateThread(pid, pid); + } + + auto it = userSpaceThreadMap_.find(tid); + if (it == userSpaceThreadMap_.end()) { + // we also need thread + return CreateThread(pid, tid); + } else { + return it->second; + } +} + +void VirtualRuntime::UpdateThreadMaps(pid_t pid, pid_t tid, const std::string filename, + uint64_t begin, uint64_t len, uint64_t offset) +{ + VirtualThread &thread = GetThread(pid, tid); + thread.CreateMapItem(filename, begin, len, offset); +} + +void VirtualRuntime::UpdateKernelModulesSpaceMaps() +{ + // found the kernel modules + std::vector koMaps; + std::ifstream ifs("/proc/modules", std::ifstream::in); + if (!ifs.is_open()) { + perror("kernel modules read failed(/proc/modules)\n"); + return; + } + std::string line; + while (getline(ifs, line)) { + uint64_t addr = 0; + uint64_t size = 0; + char module[line.size()]; + /* + name size load map + hi_mipi_rx 53248 0 - Live 0xbf109000 (O) + hi3516cv500_hdmi 237568 0 - Live 0xbf0bb000 (O) + hifb 143360 0 - Live 0xbf089000 (O) + hi3516cv500_vo_dev 98304 0 - Live 0xbf070000 (O) + hi3516cv500_tde 110592 0 - Live 0xbf04a000 (O) + hi3516cv500_sys 36864 0 - Live 0xbf03a000 (O) + hi3516cv500_base 20480 5 + hi_mipi_rx,hi3516cv500_hdmi,hifb,hi3516cv500_vo_dev,hi3516cv500_tde,hi3516cv500_sys, + hi3516cv500_base,sys_config,hi_proc,hi_irq,Live 0xbf000000 (O) + */ + int ret = sscanf_s(line.c_str(), "%s%" PRIu64 "%*u%*s%*s 0x%" PRIx64 "", module, + sizeof(module), &size, &addr, sizeof(addr)); + constexpr int numSlices {3}; + if (ret == numSlices) { + MemMapItem &map = koMaps.emplace_back(addr, addr + size, 0, std::string(module)); + HLOGV("add ko map %s", map.ToString().c_str()); + } else { + HLOGE("unknown line %d: '%s'", ret, line.c_str()); + } + } + + if (std::all_of(koMaps.begin(), koMaps.end(), + [](const MemMapItem &item) { return item.begin_ == 0; })) { + koMaps.clear(); + HLOGW("no addr found in /proc/modules. remove all the ko"); + } + if (recordCallBack_) { + for (MemMapItem &map : koMaps) { + auto record = std::make_unique(true, 0, 0, map.begin_, + map.end_ - map.begin_, 0, map.name_); + recordCallBack_(std::move(record)); + } + } + std::move(koMaps.begin(), koMaps.end(), std::back_inserter(kernelSpaceMemMaps_)); +} + +void VirtualRuntime::UpdateKernelSpaceMaps() +{ + // add kernel first + auto &map = kernelSpaceMemMaps_.emplace_back(0, std::numeric_limits::max(), 0, + KERNEL_MMAP_NAME); + if (recordCallBack_) { + auto record = std::make_unique(true, 0, 0, map.begin_, + map.end_ - map.begin_, 0, map.name_); + recordCallBack_(std::move(record)); + } +} + +void VirtualRuntime::UpdateKernelModulesSymbols() +{ + HLOGD("load ko symbol and build id"); + for (MemMapItem &map : kernelSpaceMemMaps_) { + if (map.name_ == KERNEL_MMAP_NAME) { + continue; + } + auto kernelModuleFile = + SymbolsFile::CreateSymbolsFile(SYMBOL_KERNEL_MODULE_FILE, map.name_); + if (symbolsPaths_.size() > 0) { + kernelModuleFile->setSymbolsFilePath(symbolsPaths_); // also load from search path + } + kernelModuleFile->LoadSymbols(); + symbolsFiles_.emplace_back(std::move(kernelModuleFile)); + } +} + +void VirtualRuntime::UpdateKernelSymbols() +{ + HLOGD("create a kernel mmap record"); + // found kernel source + auto kernelFile = SymbolsFile::CreateSymbolsFile(KERNEL_MMAP_NAME); + // set sybol path If it exists + if (symbolsPaths_.size() > 0) { + kernelFile->setSymbolsFilePath(symbolsPaths_); // also load from search path + } + if (kernelFile->LoadSymbols()) { + auto record = std::make_unique( + true, 0, 0, kernelFile->textExecVaddr_, kernelFile->textExecVaddrRange_, + kernelFile->textExecVaddrFileOffset_, KERNEL_MMAP_NAME); + + if (recordCallBack_) { + recordCallBack_(std::move(record)); + } + symbolsFiles_.emplace_back(std::move(kernelFile)); + } else { + HLOGW("kernel symbol not found.\n"); + } +} + +void VirtualRuntime::UpdatekernelMap(uint64_t begin, uint64_t end, uint64_t offset, + std::string filename) +{ + HLOGV("update kernel map name:'%s' 0x%" PRIx64 " - 0x%" PRIx64 "@0x%08" PRIx64 "", + filename.c_str(), begin, end, offset); + + HLOG_ASSERT(!filename.empty()); + auto it = find(kernelSpaceMemMaps_.begin(), kernelSpaceMemMaps_.end(), filename); + if (it == kernelSpaceMemMaps_.end()) { + kernelSpaceMemMaps_.emplace_back(begin, end, offset, filename); + } else { + it->begin_ = begin; + it->end_ = end; + it->pageoffset_ = offset; + it->name_ = filename; + } +} + +void VirtualRuntime::UpdateFromRecord(PerfEventRecord &record) +{ +#ifdef HIPERF_DEBUG_TIME + const auto startTime = steady_clock::now(); +#endif + if (record.GetType() == PERF_RECORD_SAMPLE) { + auto recordSample = static_cast(&record); + UpdateFromRecord(*recordSample); +#ifdef HIPERF_DEBUG_TIME + prcessSampleRecordTimes_ += duration_cast(steady_clock::now() - startTime); +#endif + } else if (record.GetType() == PERF_RECORD_MMAP) { + auto recordMmap = static_cast(&record); + UpdateFromRecord(*recordMmap); +#ifdef HIPERF_DEBUG_TIME + prcessMmapRecordTimes_ += duration_cast(steady_clock::now() - startTime); +#endif + } else if (record.GetType() == PERF_RECORD_MMAP2) { + auto recordMmap2 = static_cast(&record); + UpdateFromRecord(*recordMmap2); +#ifdef HIPERF_DEBUG_TIME + prcessMmap2RecordTimes_ += duration_cast(steady_clock::now() - startTime); +#endif + } else if (record.GetType() == PERF_RECORD_COMM) { + auto recordCommp = static_cast(&record); + UpdateFromRecord(*recordCommp); +#ifdef HIPERF_DEBUG_TIME + prcessCommRecordTimes_ += duration_cast(steady_clock::now() - startTime); +#endif + } else { + HLOGW("skip record type %d", record.GetType()); + } +} + +void VirtualRuntime::MakeCallFrame(Symbol &symbol, CallFrame &callFrame) +{ + callFrame.vaddrInFile_ = symbol.funcVaddr_; + callFrame.symbolName_ = symbol.Name(); + callFrame.symbolIndex_ = symbol.index_; + callFrame.filePath_ = symbol.module_.empty() ? symbol.comm_ : symbol.module_; + HLOG_ASSERT_MESSAGE(!callFrame.symbolName_.empty(), "%s", symbol.ToDebugString().c_str()); +} + +void VirtualRuntime::SymbolicCallFrame(PerfRecordSample &recordSample, uint64_t ip, + perf_callchain_context context) +{ + auto symbol = GetSymbol(ip, recordSample.data_.pid, recordSample.data_.tid, context); + MakeCallFrame(symbol, recordSample.callFrames_.emplace_back(ip, 0)); + HLOGV(" (%zu)unwind symbol: %*s%s", recordSample.callFrames_.size(), + static_cast(recordSample.callFrames_.size()), "", + recordSample.callFrames_.back().ToSymbolString().c_str()); +} + +void VirtualRuntime::SymbolicRecord(PerfRecordSample &recordSample) +{ +#ifdef HIPERF_DEBUG_TIME + const auto startTime = steady_clock::now(); +#endif + // Symbolic the Call Stack + recordSample.callFrames_.clear(); + perf_callchain_context context = PERF_CONTEXT_MAX; + if (recordSample.data_.nr == 0) { + SymbolicCallFrame(recordSample, recordSample.data_.ip, PERF_CONTEXT_MAX); + } + for (u64 i = 0; i < recordSample.data_.nr; i++) { + uint64_t ip = recordSample.data_.ips[i]; + if (ip >= PERF_CONTEXT_MAX) { + std::string contextName = UpdatePerfContext(ip, context); + HLOGV("context switch to %s", contextName.c_str()); + continue; + } else if (ip < BAD_IP_ADDRESS) { + // ip 0 or 1 or less than 0 + continue; + } + SymbolicCallFrame(recordSample, ip, context); + } +#ifdef HIPERF_DEBUG_TIME + auto usedTime = duration_cast(steady_clock::now() - startTime); + if (usedTime.count() != 0) { + HLOGV("cost %0.3f ms to symbolic ", usedTime.count() / MS_DUARTION); + } + symbolicRecordTimes_ += usedTime; +#endif +} + +void VirtualRuntime::UnwindFromRecord(PerfRecordSample &recordSample) +{ +#ifdef HIPERF_DEBUG_TIME + const auto startTime = steady_clock::now(); +#endif + HLOGV("unwind record (time:%llu)", recordSample.data_.time); + // if we have userstack ? + if (recordSample.data_.stack_size > 0) { + auto &thread = UpdateThread(recordSample.data_.pid, recordSample.data_.tid); + callstack_.UnwindCallStack(thread, recordSample.data_.user_abi == PERF_SAMPLE_REGS_ABI_32, + recordSample.data_.user_regs, recordSample.data_.reg_nr, + recordSample.data_.stack_data, recordSample.data_.dyn_size, + recordSample.callFrames_); +#ifdef HIPERF_DEBUG_TIME + unwindCallStackTimes_ += duration_cast(steady_clock::now() - startTime); +#endif + size_t oldSize = recordSample.callFrames_.size(); + HLOGV("unwind %zu", recordSample.callFrames_.size()); + callstack_.ExpandCallStack(thread.tid_, recordSample.callFrames_, callstackMergeLevel_); + HLOGV("expand %zu (+%zu)", recordSample.callFrames_.size(), + recordSample.callFrames_.size() - oldSize); + + recordSample.ReplaceWithCallStack(oldSize); + } + +#ifdef HIPERF_DEBUG_TIME + unwindFromRecordTimes_ += duration_cast(steady_clock::now() - startTime); +#endif + + // we will not do this in record mode + if (recordCallBack_ == nullptr) { + // find the symbols , reabuild frame info + SymbolicRecord(recordSample); + } +} + +void VirtualRuntime::UpdateFromRecord(PerfRecordSample &recordSample) +{ + UpdateThread(recordSample.data_.pid, recordSample.data_.tid); + // unwind + if (disableUnwind_) { + return; + } else { + UnwindFromRecord(recordSample); + } +} + +void VirtualRuntime::UpdateFromRecord(PerfRecordMmap &recordMmap) +{ + HLOGV(" MMAP: size %d pid %u tid %u", recordMmap.header.size, recordMmap.data_.pid, + recordMmap.data_.tid); + HLOGV(" MMAP: %s dso '%s' (0x%llx-0x%llx)@0x%llx", recordMmap.inKernel() ? "kernel" : "user", + recordMmap.data_.filename, recordMmap.data_.addr, + recordMmap.data_.addr + recordMmap.data_.len, recordMmap.data_.pgoff); + // kernel mmap + // don't overwrite the vailed mmap , so we also check the recordMmap.data_.len + if (recordMmap.inKernel()) { + UpdatekernelMap(recordMmap.data_.addr, recordMmap.data_.addr + recordMmap.data_.len, + recordMmap.data_.pgoff, recordMmap.data_.filename); + } else { + UpdateThreadMaps(recordMmap.data_.pid, recordMmap.data_.tid, recordMmap.data_.filename, + recordMmap.data_.addr, recordMmap.data_.len, recordMmap.data_.pgoff); + UpdateSymbols(recordMmap.data_.filename); + } +} + +void VirtualRuntime::UpdateFromRecord(PerfRecordMmap2 &recordMmap2) +{ + if (!VirtualThread::IsLegalFileName(recordMmap2.data_.filename)) { + return; + } + HLOGV(" MMAP2: size %d pid %u tid %u", recordMmap2.header.size, recordMmap2.data_.pid, + recordMmap2.data_.tid); + HLOGV(" MMAP2: %s dso '%s' (0x%llx-0x%llx)@0x%llx", recordMmap2.inKernel() ? "kernel" : "user", + recordMmap2.data_.filename, recordMmap2.data_.addr, + recordMmap2.data_.addr + recordMmap2.data_.len, recordMmap2.data_.pgoff); + UpdateThreadMaps(recordMmap2.data_.pid, recordMmap2.data_.tid, recordMmap2.data_.filename, + recordMmap2.data_.addr, recordMmap2.data_.len, recordMmap2.data_.pgoff); + UpdateSymbols(recordMmap2.data_.filename); +} + +void VirtualRuntime::UpdateFromRecord(PerfRecordComm &recordComm) +{ + recordComm.DumpLog(__FUNCTION__); + UpdateThread(recordComm.data_.pid, recordComm.data_.tid, recordComm.data_.comm); +} + +void VirtualRuntime::SetRecordMode(RecordCallBack recordCallBack) +{ + recordCallBack_ = recordCallBack; +} + +void VirtualRuntime::UpdateSymbols(std::string fileName) +{ + HLOGD("try to find symbols for file: %s", fileName.c_str()); +#ifdef HIPERF_DEBUG_TIME + const auto startTime = steady_clock::now(); +#endif + for (auto &symbolsFile : symbolsFiles_) { + if (symbolsFile->filePath_ == fileName) { + HLOGV("already have '%s'", fileName.c_str()); + return; + } + } + // found it by name + auto symbolsFile = SymbolsFile::CreateSymbolsFile(fileName); + + // set sybol path If it exists + if (symbolsPaths_.size() > 0) { + symbolsFile->setSymbolsFilePath(symbolsPaths_); // also load from search path + } + if (loadSymboleWhenNeeded_) { + // load it when we need it + symbolsFiles_.emplace_back(std::move(symbolsFile)); + } else if (symbolsFile->LoadSymbols()) { + symbolsFiles_.emplace_back(std::move(symbolsFile)); + } else { + HLOGW("symbols file for '%s' not found.", fileName.c_str()); + } +#ifdef HIPERF_DEBUG_TIME + auto usedTime = duration_cast(steady_clock::now() - startTime); + if (usedTime.count() != 0) { + HLOGV("cost %0.3f ms to load '%s'", usedTime.count() / MS_DUARTION, fileName.c_str()); + } + updateSymbolsTimes_ += usedTime; +#endif +} + +const Symbol VirtualRuntime::GetKernelSymbol(uint64_t ip, const std::vector &memMaps, + const VirtualThread &thread) +{ + Symbol vaddrSymbol(ip, thread.name_); + for (auto &map : memMaps) { + if (ip > map.begin_ && ip < map.end_) { + HLOGM("found addr 0x%" PRIx64 " in kernel map 0x%" PRIx64 " - 0x%" PRIx64 " from %s", + ip, map.begin_, map.end_, map.name_.c_str()); + vaddrSymbol.module_ = map.name_; + // found symbols by file name + for (auto &symbolsFile : symbolsFiles_) { + if (symbolsFile->filePath_ == map.name_) { + vaddrSymbol.fileVaddr_ = + symbolsFile->GetVaddrInSymbols(ip, map.begin_, map.pageoffset_); + HLOGV("found symbol vaddr 0x%" PRIx64 " for runtime vaddr 0x%" PRIx64 + " at '%s'", + vaddrSymbol.fileVaddr_, ip, map.name_.c_str()); + if (!symbolsFile->SymbolsLoaded()) { + symbolsFile->LoadSymbols(); + } + Symbol foundSymbols = symbolsFile->GetSymbolWithVaddr(vaddrSymbol.fileVaddr_); + foundSymbols.taskVaddr_ = ip; + if (!foundSymbols.isValid()) { + HLOGW("addr 0x%" PRIx64 " vaddr 0x%" PRIx64 " NOT found in symbol file %s", + ip, vaddrSymbol.fileVaddr_, map.name_.c_str()); + return vaddrSymbol; + } else { + return foundSymbols; + } + } + } + HLOGW("addr 0x%" PRIx64 " in map but NOT found the symbol file %s", ip, + map.name_.c_str()); + } else { + HLOGM("addr 0x%" PRIx64 " not in map 0x%" PRIx64 " - 0x%" PRIx64 " from %s", ip, + map.begin_, map.end_, map.name_.c_str()); + } + } + return vaddrSymbol; +} + +const Symbol VirtualRuntime::GetUserSymbol(uint64_t ip, const VirtualThread &thread) +{ + Symbol vaddrSymbol(ip, thread.name_); + const MemMapItem *mmap = thread.FindMapByAddr(ip); + if (mmap != nullptr) { + SymbolsFile *symbolsFile = thread.FindSymbolsFileByMap(*mmap); + if (symbolsFile != nullptr) { + vaddrSymbol.fileVaddr_ = + symbolsFile->GetVaddrInSymbols(ip, mmap->begin_, mmap->pageoffset_); + vaddrSymbol.module_ = mmap->nameHold_; + HLOGV("found symbol vaddr 0x%" PRIx64 " for runtime vaddr 0x%" PRIx64 " at '%s'", + vaddrSymbol.fileVaddr_, ip, mmap->name_.c_str()); + if (!symbolsFile->SymbolsLoaded()) { + symbolsFile->LoadSymbols(); + } + Symbol foundSymbols = symbolsFile->GetSymbolWithVaddr(vaddrSymbol.fileVaddr_); + foundSymbols.taskVaddr_ = ip; + if (!foundSymbols.isValid()) { + HLOGW("addr 0x%" PRIx64 " vaddr 0x%" PRIx64 " NOT found in symbol file %s", ip, + vaddrSymbol.fileVaddr_, mmap->name_.c_str()); + return vaddrSymbol; + } else { + return foundSymbols; + } + } else { + HLOGW("addr 0x%" PRIx64 " in map but NOT found the symbol file %s", ip, + mmap->name_.c_str()); + } + } else { +#ifdef HIPERF_DEBUG + thread.ReportVaddrMapMiss(ip); +#endif + } + return vaddrSymbol; +} + +bool VirtualRuntime::GetSymbolCache(uint64_t ip, pid_t pid, pid_t tid, Symbol &symbol, + const perf_callchain_context &context) +{ + if (context != PERF_CONTEXT_USER and kernelSymbolCache_.count(ip)) { + if (kernelSymbolCache_.find(ip) == kernelSymbolCache_.end()) { + return false; + } + Symbol &foundSymbol = kernelSymbolCache_[ip]; + foundSymbol.hit_++; + HLOGV("hit kernel cache 0x%" PRIx64 " %d", ip, foundSymbol.hit_); + symbol = foundSymbol; + return true; + } else if (threadSymbolCache_[tid].count(ip) != 0) { + Symbol &foundSymbol = threadSymbolCache_[tid][ip]; + foundSymbol.hit_++; + HLOGV("hit user cache 0x%" PRIx64 " %d %s", ip, foundSymbol.hit_, + foundSymbol.ToDebugString().c_str()); + symbol = foundSymbol; + return true; + } else { + HLOGM("cache miss k %zu u %zu", kernelSymbolCache_.size(), threadSymbolCache_[tid].size()); + } + return false; +} + +const Symbol VirtualRuntime::GetSymbol(uint64_t ip, pid_t pid, pid_t tid, + const perf_callchain_context &context) +{ + HLOGV("try find tid %u ip 0x%" PRIx64 " in %zu symbolsFiles", tid, ip, symbolsFiles_.size()); + Symbol symbol; + if (threadSymbolCache_.find(tid) == threadSymbolCache_.end()) { + threadSymbolCache_[tid].reserve(THREAD_SYMBOL_CACHE_LIMIT); + } + if (GetSymbolCache(ip, pid, tid, symbol, context)) { + return symbol; + } + if (context == PERF_CONTEXT_USER or (context == PERF_CONTEXT_MAX and !symbol.isValid())) { + // check userspace memmap + symbol = GetUserSymbol(ip, GetThread(pid, tid)); + threadSymbolCache_[tid][ip] = symbol; + HLOGV("cache ip 0x%" PRIx64 " to %s", ip, + threadSymbolCache_[tid][ip].ToDebugString().c_str()); + } + + if (context == PERF_CONTEXT_KERNEL or (context == PERF_CONTEXT_MAX and !symbol.isValid())) { + // check kernelspace + HLOGM("try found addr in kernelspace %zu maps", kernelSpaceMemMaps_.size()); + symbol = GetKernelSymbol(ip, kernelSpaceMemMaps_, GetThread(pid, tid)); + HLOGM("add addr to kernel cache 0x%" PRIx64 " cache size %zu", ip, + kernelSymbolCache_.size()); + kernelSymbolCache_[ip] = symbol; + } + return symbol; +} + +bool VirtualRuntime::SetSymbolsPaths(const std::vector &symbolsPaths) +{ + std::unique_ptr symbolsFile = SymbolsFile::CreateSymbolsFile(SYMBOL_UNKNOW_FILE); + // we need check if the path is accessible + bool accessible = symbolsFile->setSymbolsFilePath(symbolsPaths); + if (accessible) { + symbolsPaths_ = symbolsPaths; + } else { + if (!symbolsPaths.empty()) { + printf("some symbols path unable access\n"); + } + } + return accessible; +} + +void VirtualRuntime::UpdateFromPerfData(const std::vector &symbolFileStructs) +{ + // review: if we need move to some other place ? + HLOG_ASSERT_MESSAGE(symbolsFiles_.size() == 0, " symbolsFiles_ size is %zu", + symbolsFiles_.size()); + for (const auto &symbolFileStruct : symbolFileStructs) { + HLOGV("symbolFileStruct.filePath_:'%s'", symbolFileStruct.filePath_.c_str()); + HLOGV("symbolFileStruct.buildId_:'%s'", symbolFileStruct.buildId_.c_str()); + HLOGV("process symbols file:'%s':'%s'", symbolFileStruct.filePath_.c_str(), + symbolFileStruct.buildId_.c_str()); + + // load from symbolFileStruct (perf.data) + std::unique_ptr symbolsFile = + SymbolsFile::LoadSymbolsFromSaved(symbolFileStruct); + + // reaload from sybol path If it exists + if (symbolsPaths_.size() > 0) { + HLOGV("try again with symbolsPaths setup"); + symbolsFile->setSymbolsFilePath(symbolsPaths_); // also load from search path + // use give us path ,we must reload it. + symbolsFile->LoadSymbols(); + } + symbolsFiles_.emplace_back(std::move(symbolsFile)); + } +} + +/* + ARM functions + The table below lists the symbols exported by the vDSO. + + symbol version + ──────────────────────────────────────────────────────────── + __vdso_gettimeofday LINUX_2.6 (exported since Linux 4.1) + __vdso_clock_gettime LINUX_2.6 (exported since Linux 4.1) + + Additionally, the ARM port has a code page full of utility + functions. Since it's just a raw page of code, there is no ELF + information for doing symbol lookups or versioning. It does + provide support for different versions though. + + For information on this code page, it's best to refer to the + kernel documentation as it's extremely detailed and covers + everything you need to know: + Documentation/arm/kernel_user_helpers.txt. + + aarch64 functions + The table below lists the symbols exported by the vDSO. + + symbol version + ────────────────────────────────────── + __kernel_rt_sigreturn LINUX_2.6.39 + __kernel_gettimeofday LINUX_2.6.39 + __kernel_clock_gettime LINUX_2.6.39 + __kernel_clock_getres LINUX_2.6.39 +*/ +void VirtualRuntime::LoadVdso() +{ +#if !is_mingw + VirtualThread myThread(getpid(), symbolsFiles_); + myThread.ParseMap(); + for (const auto &map : myThread.GetMaps()) { + if (map.name_ == MMAP_VDSO_NAME) { + std::string memory(map.end_ - map.begin_, '\0'); + std::copy(reinterpret_cast((map.begin_)), reinterpret_cast((map.end_)), + &memory[0]); + std::string tempPath("/data/local/tmp/"); + std::string tempFileName = tempPath + MMAP_VDSO_NAME; + if (!WriteStringToFile(tempFileName, memory)) { + printf("vdso temp file create fail at %s\n", tempFileName.c_str()); + } else { + HLOGD("vdso temp file create at %s:%zu", tempFileName.c_str(), memory.size()); + auto symbolsFile = SymbolsFile::CreateSymbolsFile(MMAP_VDSO_NAME); + symbolsFile->setSymbolsFilePath(tempPath); // also load from search path + symbolsFiles_.emplace_back(std::move(symbolsFile)); + return; + } + } + } + HLOGD("no vdso found"); +#endif +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/hiperf/virtual_thread.cpp b/host/trace_streamer/src/parser/hiperf_parser/hiperf/virtual_thread.cpp new file mode 100755 index 0000000000000000000000000000000000000000..0b0e570c2dfcbd826989bcf8727849eeedb55710 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/hiperf/virtual_thread.cpp @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2021-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. + */ +#define HILOG_TAG "RuntimeThread" + +#include "virtual_thread.h" + +#include +#include +#include +#if !is_mingw +#include +#endif + +#include "symbols_file.h" +#include "utilities.h" +#include "virtual_runtime.h" +namespace OHOS { +namespace Developtools { +namespace HiPerf { +#ifdef DEBUG_TIME +bool VirtualThread::IsSorted() const +{ + for (std::size_t index = 1; index < memMaps_.size(); ++index) { + if (memMaps_[index - 1].end_ > memMaps_[index].begin_) { + std::cout << "memMaps_ order error:\n" + << " " << memMaps_[index - 1].begin_ << "-" << memMaps_[index - 1].end_ + << " " << memMaps_[index].begin_ << "-" << memMaps_[index].end_; + return false; + } + } + return true; +} +#endif + +const MemMapItem *VirtualThread::FindMapByAddr2(uint64_t addr) const +{ + HLOGM("try found vaddr 0x%" PRIx64 " in maps %zu ", addr, memMaps_.size()); + if (memMaps_.size() == 0) { + return nullptr; + } + auto foundIt = + std::upper_bound(memMaps_.begin(), memMaps_.end(), addr, MemMapItem::ValueLessThan); + if (foundIt == memMaps_.begin()) { + // have map 2 3 4 5 + // find 1 , will return 2 (index 0, begin elem) + // this same as not found any thins + } else { + // include memMaps_.end() + foundIt = std::prev(foundIt); + if (foundIt->Contain(addr)) { + HLOGM("found '%s' for vaddr 0x%016" PRIx64 "", foundIt->ToString().c_str(), addr); + return &(*foundIt); + } + } + return nullptr; +} + +const MemMapItem *VirtualThread::FindMapByAddr(uint64_t addr) const +{ + HLOGM("try found vaddr 0x%" PRIx64 " in maps %zu ", addr, memMaps_.size()); + if (memMaps_.size() == 0) { + return nullptr; + } + if (memMaps_.front().begin_ > addr) { + return nullptr; + } + if (memMaps_.back().end_ <= addr) { + return nullptr; + } + constexpr int two {2}; + std::size_t left {0}; + std::size_t right {memMaps_.size()}; + std::size_t mid = (right - left) / two + left; + while (left < right) { + if (addr < memMaps_[mid].end_) { + right = mid; + mid = (right - left) / two + left; + continue; + } + if (addr >= memMaps_[mid].end_) { + left = mid + 1; + mid = (right - left) / two + left; + continue; + } + } + if (addr >= memMaps_[left].begin_ and addr < memMaps_[left].end_) { + return &memMaps_[left]; + } + return nullptr; +} + +const MemMapItem *VirtualThread::FindMapByFileInfo(const std::string name, uint64_t offset) const +{ + for (auto &map : memMaps_) { + if (name != map.name_) { + continue; + } + // check begin and length + if (offset >= map.pageoffset_ && (offset - map.pageoffset_) < (map.end_ - map.begin_)) { + HLOGMMM("found fileoffset 0x%" PRIx64 " in map (0x%" PRIx64 " - 0x%" PRIx64 + " pageoffset 0x%" PRIx64 ") from %s", + offset, map.begin_, map.end_, map.pageoffset_, map.name_.c_str()); + return ↦ + } + } + HLOGM("NOT found offset 0x%" PRIx64 " in maps %zu ", offset, memMaps_.size()); + return nullptr; +} + +SymbolsFile *VirtualThread::FindSymbolsFileByMap(const MemMapItem &inMap) const +{ + for (auto &symbolsFile : symbolsFiles_) { + if (symbolsFile->filePath_ == inMap.name_) { + HLOGM("found symbol for map '%s'", inMap.name_.c_str()); + symbolsFile->LoadDebugInfo(); + return symbolsFile.get(); + } + } +#ifdef DEBUG_MISS_SYMBOL + if (find(missedSymbolFile_.begin(), missedSymbolFile_.end(), inMap.name_) == + missedSymbolFile_.end()) { + missedSymbolFile_.emplace_back(inMap.name_); + HLOGW("NOT found symbol for map '%s'", inMap.name_.c_str()); + for (auto &file : symbolsFiles_) { + HLOGW(" we have '%s'", file->filePath_.c_str()); + } + } +#endif + return nullptr; +} +void VirtualThread::ReportVaddrMapMiss(uint64_t vaddr) const +{ +#ifdef HIPERF_DEBUG + if (DebugLogger::GetInstance()->GetLogLevel() <= LEVEL_VERBOSE) { + if (missedRuntimeVaddr_.find(vaddr) == missedRuntimeVaddr_.end()) { + missedRuntimeVaddr_.insert(vaddr); + HLOGV("vaddr %" PRIx64 " not found in any map", vaddr); + for (auto &map : memMaps_) { + HLOGV("map %s ", map.ToString().c_str()); + } + } + } +#endif +} + +bool VirtualThread::ReadRoMemory(uint64_t vaddr, uint8_t *data, size_t size) const +{ + const MemMapItem *map = FindMapByAddr(vaddr); + if (map != nullptr) { + // found symbols by file name + SymbolsFile *symbolsFile = FindSymbolsFileByMap(*map); + if (symbolsFile != nullptr) { + HLOGM("read vaddr from addr is 0x%" PRIx64 " at '%s'", vaddr - map->begin_, + map->name_.c_str()); + if (size == symbolsFile->ReadRoMemory(map->FileOffsetFromAddr(vaddr), data, size)) { + return true; + } else { + return false; + } + } else { + HLOGW("found addr %" PRIx64 " in map but not loaded symbole %s", vaddr, + map->name_.c_str()); + } + } else { +#ifdef HIPERF_DEBUG + ReportVaddrMapMiss(vaddr); +#endif + } + return false; +} + +bool VirtualThread::IsLegalFileName(const std::string &fileName) +{ + // some special + if (fileName == "[vdso]") { + return true; + } + if (fileName.empty() or fileName.find(':') != std::string::npos or fileName.front() == '[' or + fileName.back() == ']' or std::strncmp(fileName.c_str(), "/dev/", sizeof("/dev/")) == 0 or + std::strncmp(fileName.c_str(), "/memfd:", sizeof("/memfd:")) == 0 or + std::strncmp(fileName.c_str(), "//anon", sizeof("//anon")) == 0 or + StringEndsWith(fileName, ".ttf")) { + return false; + } + return true; +} + +#if is_mingw +void VirtualThread::ParseMap() +{ + // only linux support read maps in runtime + return; +} +#else +constexpr const int MMAP_LINE_MIN_TOKEN = 5; +constexpr const int MMAP_LINE_TOKEN_INDEX_FLAG = 1; +constexpr const int MMAP_LINE_TOKEN_INDEX_OFFSET = 2; +constexpr const int MMAP_LINE_TOKEN_INDEX_MM = 3; +constexpr const int MMAP_LINE_TOKEN_INDEX_INODE = 4; +constexpr const int MMAP_LINE_TOKEN_INDEX_NAME = 5; +constexpr const int MMAP_LINE_MAX_TOKEN = 6; + +void VirtualThread::ParseMap() +{ + std::string mapPath = StringPrintf("/proc/%d/maps", pid_); + std::string mapContent = ReadFileToString(mapPath); + if (mapContent.size() > 0) { + std::istringstream s(mapContent); + std::string line; + while (std::getline(s, line)) { + HLOGM("map line: %s", line.c_str()); + // b0023000-b0024000 r--p 00000000 b3:05 959 /system/lib/libdl.so + // 0 1 2 3 4 5 + MemMapItem memMapItem; + std::vector mapTokens = StringSplit(line, " "); + + if (mapTokens.size() < MMAP_LINE_MIN_TOKEN) { + // maybe file name is empty + continue; + } + + // b0023000-b0024000 + constexpr const int MMAP_ADDR_RANGE_TOKEN = 2; + std::vector addrRanges = StringSplit(mapTokens[0], "-"); + if (addrRanges.size() != MMAP_ADDR_RANGE_TOKEN) { + continue; + } + + // b0023000 / b0024000 + memMapItem.begin_ = std::stoull(addrRanges[0], nullptr, NUMBER_FORMAT_HEX_BASE); + memMapItem.end_ = std::stoull(addrRanges[1], nullptr, NUMBER_FORMAT_HEX_BASE); + + constexpr const int MMAP_PROT_CHARS = 4; + int index = 0; + // rwxp + memMapItem.type_ = 0; + if (mapTokens[MMAP_LINE_TOKEN_INDEX_FLAG].size() != MMAP_PROT_CHARS) { + continue; + } + if (mapTokens[MMAP_LINE_TOKEN_INDEX_FLAG][index++] == 'r') { + memMapItem.type_ |= PROT_READ; + } + if (mapTokens[MMAP_LINE_TOKEN_INDEX_FLAG][index++] == 'w') { + memMapItem.type_ |= PROT_WRITE; + } + if (mapTokens[MMAP_LINE_TOKEN_INDEX_FLAG][index++] == 'x') { + memMapItem.type_ |= PROT_EXEC; + } + + if ((memMapItem.type_ & PROT_EXEC) or (memMapItem.type_ == PROT_READ)) { + /* + we need record the read hen exec map address + callstackk need r map to check the ehframe addrssss + Section Headers: + [Nr] Name Type Address Offset + Size EntSize Flags Link Info Align + + [12] .eh_frame_hdr PROGBITS 00000000002929a0 000929a0 + 00000000000071fc 0000000000000000 A 0 0 4 + [13] .eh_frame PROGBITS 0000000000299ba0 00099ba0 + 000000000002a8f4 0000000000000000 A 0 0 8 + [14] .text PROGBITS 00000000002c5000 000c5000 + 00000000001caa4a 0000000000000000 AX 0 0 16 + + 00200000-002c5000 r--p 00000000 08:02 46400311 + 002c5000-00490000 r-xp 000c5000 08:02 46400311 + */ + } else { + continue; + } + + // MAP_PRIVATE or MAP_SHARED + constexpr const int MAP_FLAG_ATTR_INDEX = 3; + if (mapTokens[MMAP_LINE_TOKEN_INDEX_FLAG][MAP_FLAG_ATTR_INDEX] == 'p') { + memMapItem.flags = MAP_PRIVATE; + } else if (mapTokens[MMAP_LINE_TOKEN_INDEX_FLAG][MAP_FLAG_ATTR_INDEX] == 's') { + memMapItem.flags = MAP_SHARED; + } + + memMapItem.pageoffset_ = + std::stoull(mapTokens[MMAP_LINE_TOKEN_INDEX_OFFSET], nullptr, NUMBER_FORMAT_HEX_BASE); + + // major:minor + std::vector mm = StringSplit(mapTokens[MMAP_LINE_TOKEN_INDEX_MM], ":"); + + // b3:05 + memMapItem.major_ = std::stoull(mm.at(0), nullptr, NUMBER_FORMAT_HEX_BASE); + memMapItem.minor_ = std::stoull(mm.at(1), nullptr, NUMBER_FORMAT_HEX_BASE); + + // 959 + memMapItem.inode = std::stoull(mapTokens[MMAP_LINE_TOKEN_INDEX_INODE], nullptr, NUMBER_FORMAT_HEX_BASE); + + // system/lib/libdl.so + if (mapTokens.size() == MMAP_LINE_MAX_TOKEN) { + memMapItem.name_ = mapTokens[MMAP_LINE_TOKEN_INDEX_NAME]; + } + if (!IsLegalFileName(memMapItem.name_)) { + continue; + } + HLOGD("%d %d memMap add '%s'", pid_, tid_, memMapItem.name_.c_str()); + memMaps_.emplace_back(std::move(memMapItem)); + } + } + SortMemMaps(); +} +#endif + +void VirtualThread::SortMemMaps() +{ + for (int currPos = 1; currPos < static_cast(memMaps_.size()); ++currPos) { + int targetPos = currPos - 1; + while (targetPos >= 0 and memMaps_[currPos].end_ < memMaps_[targetPos].end_) { + --targetPos; + } + if (targetPos < currPos - 1) { + auto target = memMaps_[currPos]; + for (int k = currPos - 1; k > targetPos; --k) { + memMaps_[k + 1] = memMaps_[k]; + } + memMaps_[targetPos + 1] = target; + } + } + return; +} + +void VirtualThread::CreateMapItem(const std::string filename, uint64_t begin, uint64_t len, + uint64_t offset) +{ + if (!IsLegalFileName(filename)) { + return; // skip some memmap + } + MemMapItem &map = memMaps_.emplace_back(begin, begin + len, offset, filename); + HLOGD(" %u:%u create a new map(total %zu) at '%s' (0x%" PRIx64 "-0x%" PRIx64 ")@0x%" PRIx64 " ", + pid_, tid_, memMaps_.size(), map.name_.c_str(), map.begin_, map.end_, map.pageoffset_); + SortMemMaps(); +} +} // namespace HiPerf +} // namespace Developtools +} // namespace OHOS diff --git a/host/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp b/host/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp new file mode 100755 index 0000000000000000000000000000000000000000..c53a5d02c0a9a06d2381509c90256662afe2d11a --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/perf_data_parser.cpp @@ -0,0 +1,292 @@ +/* + * 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. + */ +#include "perf_data_parser.h" +#include "perf_data_filter.h" +#include "stat_filter.h" + +namespace SysTuning { +namespace TraceStreamer { +PerfDataParser::PerfDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : HtracePluginTimeParser(dataCache, ctx), frameToCallChainId_(INVALID_UINT64), + configNameIndex_(traceDataCache_->dataDict_.GetStringIndex("config_name")), + workloaderIndex_(traceDataCache_->dataDict_.GetStringIndex("workload_cmd")), + cmdlineIndex_(traceDataCache_->dataDict_.GetStringIndex("cmdline")), + runingStateIndex_(traceDataCache_->dataDict_.GetStringIndex("Running")), + suspendStatIndex_(traceDataCache_->dataDict_.GetStringIndex("Suspend")), + unkonwnStateIndex_(traceDataCache_->dataDict_.GetStringIndex("-")) +{ +} +void PerfDataParser::InitPerfDataAndLoad(const std::deque& dequeBuffer, uint64_t size) +{ + bufferSize_ = size; + buffer_ = std::make_unique(size); + std::copy(dequeBuffer.begin(), dequeBuffer.begin() + size, buffer_.get()); + LoadPerfData(); +} +PerfDataParser::~PerfDataParser() +{ + TS_LOGI("perf data ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); +} + +bool PerfDataParser::LoadPerfData() +{ + TS_LOGI("enter"); + // try load the perf data + recordDataReader_ = PerfFileReader::Instance(buffer_.get(), bufferSize_); + buffer_.release(); + if (recordDataReader_ == nullptr) { + return false; + } + + if (!recordDataReader_->ReadFeatureSection()) { + printf("record format error.\n"); + return false; + } + // update perf report table + UpdateEventConfigInfo(); + UpdateReportWorkloadInfo(); + UpdateCmdlineInfo(); + + // update perf Files table + UpdateSymbolAndFilesData(); + + TS_LOGD("process record"); + UpdateClockType(); + recordDataReader_->ReadDataSection(std::bind(&PerfDataParser::RecordCallBack, this, std::placeholders::_1)); + TS_LOGD("process record completed"); + TS_LOGI("load perf data done"); + return true; +} + +void PerfDataParser::UpdateEventConfigInfo() +{ + auto features = recordDataReader_->GetFeatures(); + cpuOffMode_ = find(features.begin(), features.end(), FEATURE::HIPERF_CPU_OFF) != features.end(); + if (cpuOffMode_) { + TS_LOGD("this is cpuOffMode "); + } + const PerfFileSection* featureSection = recordDataReader_->GetFeatureSection(FEATURE::EVENT_DESC); + if (featureSection) { + TS_LOGI("have EVENT_DESC"); + LoadEventDesc(); + } else { + TS_LOGE("Do not have EVENT_DESC !!!"); + } +} + +void PerfDataParser::LoadEventDesc() +{ + const auto featureSection = recordDataReader_->GetFeatureSection(FEATURE::EVENT_DESC); + const auto& sectionEventdesc = *static_cast(featureSection); + TS_LOGI("Event descriptions: %zu", sectionEventdesc.eventDesces_.size()); + for (size_t i = 0; i < sectionEventdesc.eventDesces_.size(); i++) { + const auto& fileAttr = sectionEventdesc.eventDesces_[i]; + TS_LOGI("event name[%zu]: %s ids: %s", i, fileAttr.name.c_str(), VectorToString(fileAttr.ids).c_str()); + for (uint64_t id : fileAttr.ids) { + report_.configIdIndexMaps_[id] = report_.configs_.size(); // setup index + TS_LOGI("add config id map %" PRIu64 " to %zu", id, report_.configs_.size()); + } + // when cpuOffMode_ , don't use count mode , use time mode. + auto& config = report_.configs_.emplace_back(fileAttr.name, fileAttr.attr.type, fileAttr.attr.config, + cpuOffMode_ ? false : true); + config.ids_ = fileAttr.ids; + TS_ASSERT(config.ids_.size() > 0); + + auto perfReportData = traceDataCache_->GetPerfReportData(); + auto configValueIndex = traceDataCache_->dataDict_.GetStringIndex(fileAttr.name.c_str()); + perfReportData->AppendNewPerfReport(configNameIndex_, configValueIndex); + } +} + +void PerfDataParser::UpdateReportWorkloadInfo() const +{ + // workload + auto featureSection = recordDataReader_->GetFeatureSection(FEATURE::HIPERF_WORKLOAD_CMD); + std::string workloader = ""; + if (featureSection) { + TS_LOGI("found HIPERF_META_WORKLOAD_CMD"); + auto sectionString = static_cast(featureSection); + workloader = sectionString->toString(); + } else { + TS_LOGW("NOT found HIPERF_META_WORKLOAD_CMD"); + } + if (workloader.empty()) { + TS_LOGW("NOT found HIPERF_META_WORKLOAD_CMD"); + return; + } + auto perfReportData = traceDataCache_->GetPerfReportData(); + auto workloaderValueIndex = traceDataCache_->dataDict_.GetStringIndex(workloader.c_str()); + perfReportData->AppendNewPerfReport(workloaderIndex_, workloaderValueIndex); +} + +void PerfDataParser::UpdateCmdlineInfo() const +{ + auto cmdline = recordDataReader_->GetFeatureString(FEATURE::CMDLINE); + auto perfReportData = traceDataCache_->GetPerfReportData(); + auto cmdlineValueIndex = traceDataCache_->dataDict_.GetStringIndex(cmdline.c_str()); + perfReportData->AppendNewPerfReport(cmdlineIndex_, cmdlineValueIndex); +} + +void PerfDataParser::UpdateSymbolAndFilesData() +{ + // we need unwind it (for function name match) even not give us path + report_.virtualRuntime_.SetDisableUnwind(false); + + // found symbols in file + const auto featureSection = recordDataReader_->GetFeatureSection(FEATURE::HIPERF_FILES_SYMBOL); + if (featureSection != nullptr) { + const PerfFileSectionSymbolsFiles* sectionSymbolsFiles = + static_cast(featureSection); + report_.virtualRuntime_.UpdateFromPerfData(sectionSymbolsFiles->symbolFileStructs_); + } + uint64_t fileId = 0; + for (auto& symbolsFile : report_.virtualRuntime_.GetSymbolsFiles()) { + auto filePathIndex = traceDataCache_->dataDict_.GetStringIndex(symbolsFile->filePath_.c_str()); + uint32_t serial = 0; + for (auto& symbol : symbolsFile->GetSymbols()) { + auto symbolIndex = traceDataCache_->dataDict_.GetStringIndex(symbol.Name().data()); + streamFilters_->statFilter_->IncreaseStat(TRACE_PERF, STAT_EVENT_RECEIVED); + streamFilters_->perfDataFilter_->AppendPerfFiles(fileId, serial++, symbolIndex, filePathIndex); + } + fileDataDictIdToFileId_.insert(std::make_pair(filePathIndex, fileId)); + ++fileId; + } +} +void PerfDataParser::UpdateClockType() +{ + const auto& attrIds_ = recordDataReader_->GetAttrSection(); + if (attrIds_.size() > 0) { + useClockId_ = attrIds_[0].attr.use_clockid; + clockId_ = attrIds_[0].attr.clockid; + TS_LOGE("useClockId_ = %u, clockId_ = %u", useClockId_, clockId_); + } +} +bool PerfDataParser::RecordCallBack(std::unique_ptr record) +{ + // tell process tree what happend for rebuild symbols + report_.virtualRuntime_.UpdateFromRecord(*record); + + if (record->GetType() == PERF_RECORD_SAMPLE) { + std::unique_ptr sample(static_cast(record.release())); + auto callChainId = UpdatePerfCallChainData(sample); + UpdatePerfSampleData(callChainId, sample); + } else if (record->GetType() == PERF_RECORD_COMM) { + auto recordComm = static_cast(record.get()); + auto range = tidToPid_.equal_range(recordComm->data_.tid); + for (auto it = range.first; it != range.second; it++) { + if (it->second == recordComm->data_.pid) { + return true; + } + } + tidToPid_.insert(std::make_pair(recordComm->data_.tid, recordComm->data_.pid)); + auto perfThreadData = traceDataCache_->GetPerfThreadData(); + auto threadNameIndex = traceDataCache_->dataDict_.GetStringIndex(recordComm->data_.comm); + perfThreadData->AppendNewPerfThread(recordComm->data_.pid, recordComm->data_.tid, threadNameIndex); + } + return true; +} + +uint64_t PerfDataParser::UpdatePerfCallChainData(std::unique_ptr& sample) +{ + uint64_t depth = 0; + bool callStackNotExist = false; + uint64_t callChainId = INVALID_UINT64; + std::vector> callStackTemp = {}; + // Filter callstack unuse data + for (auto frame = sample->callFrames_.rbegin(); frame != sample->callFrames_.rend(); ++frame) { + auto symbolId = frame->symbolIndex_; + if (symbolId == -1 && frame->vaddrInFile_ == 0) { + continue; + } + auto fileDataIndex = traceDataCache_->dataDict_.GetStringIndex(frame->filePath_); + auto itor = fileDataDictIdToFileId_.find(fileDataIndex); + if (itor == fileDataDictIdToFileId_.end()) { + continue; + } + auto fileId = itor->second; + callStackTemp.emplace_back( + std::move(std::make_unique(depth, frame->vaddrInFile_, fileId, symbolId))); + depth++; + } + // Determine whether to write callstack data to cache + auto size = callStackTemp.size(); + for (auto itor = callStackTemp.begin(); itor != callStackTemp.end(); itor++) { + auto callstack = itor->get(); + auto ret = frameToCallChainId_.Find(callstack->fileId_, callstack->symbolId_, callstack->depth_, size); + if (ret != INVALID_UINT64) { // find it + if (callChainId == INVALID_UINT64) { + callChainId = ret; + } else if (callChainId != ret) { + callStackNotExist = true; + break; + } + } else { // not find it + callStackNotExist = true; + break; + } + } + // write callstack data to cache + if (callStackNotExist) { + callChainId = ++callChainId_; + for (auto itor = callStackTemp.begin(); itor != callStackTemp.end(); itor++) { + auto callstack = itor->get(); + frameToCallChainId_.Insert(callstack->fileId_, callstack->symbolId_, callstack->depth_, + callStackTemp.size(), callChainId); + streamFilters_->perfDataFilter_->AppendPerfCallChain( + callChainId, callstack->depth_, callstack->vaddrInFile_, callstack->fileId_, callstack->symbolId_); + } + } + callStackTemp.clear(); + return callChainId; +} + +void PerfDataParser::UpdatePerfSampleData(uint64_t callChainId, std::unique_ptr& sample) +{ + auto perfSampleData = traceDataCache_->GetPerfSampleData(); + uint64_t newTimeStamp = 0; + if (useClockId_ == 0) { + newTimeStamp = sample->data_.time; + } else { + newTimeStamp = + streamFilters_->clockFilter_->ToPrimaryTraceTime(perfToTSClockType_.at(clockId_), sample->data_.time); + } + UpdatePluginTimeRange(perfToTSClockType_.at(clockId_), sample->data_.time, newTimeStamp); + + DataIndex threadStatIndex = unkonwnStateIndex_; + auto threadState = report_.GetConfigName(sample->data_.id); + if (threadState.compare(wakingEventName_) == 0) { + threadStatIndex = runingStateIndex_; + } else if (threadState.compare(cpuOffEventName_) == 0) { + threadStatIndex = suspendStatIndex_; + } + auto configIndex = report_.GetConfigIndex(sample->data_.id); + perfSampleData->AppendNewPerfSample(callChainId, sample->data_.time, sample->data_.tid, sample->data_.period, + configIndex, newTimeStamp, sample->data_.cpu, threadStatIndex); +} + +void PerfDataParser::Finish() +{ + streamFilters_->perfDataFilter_->Finish(); + // Update trace_range when there is only perf data in the trace file + if (traceDataCache_->traceStartTime_ == INVALID_UINT64 || traceDataCache_->traceEndTime_ == 0) { + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); + } else { + TS_LOGI("perfData time is not updated, maybe this trace file has other data"); + } + frameToCallChainId_.Clear(); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/hiperf_parser/perf_data_parser.h b/host/trace_streamer/src/parser/hiperf_parser/perf_data_parser.h new file mode 100755 index 0000000000000000000000000000000000000000..7cb102f620bd0cf657b4dcbf0c688c9c6aa12ab6 --- /dev/null +++ b/host/trace_streamer/src/parser/hiperf_parser/perf_data_parser.h @@ -0,0 +1,103 @@ +/* + * 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. + */ +#ifndef PERF_DATA_PARSER_H +#define PERF_DATA_PARSER_H +#include +#include +#include +#include +#include +#include "htrace_plugin_time_parser.h" +#include "log.h" +#include "perf_events.h" +#include "perf_file_format.h" +#include "perf_file_reader.h" +#include "quatra_map.h" +#include "report.h" +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace OHOS::Developtools::HiPerf; +class PerfDataParser : public HtracePluginTimeParser { +public: + PerfDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~PerfDataParser(); + void InitPerfDataAndLoad(const std::deque& dequeBuffer, uint64_t size); + void Finish(); + +private: + bool LoadPerfData(); + void UpdateEventConfigInfo(); + void UpdateCmdlineInfo() const; + void LoadEventDesc(); + void UpdateReportWorkloadInfo() const; + void UpdateSymbolAndFilesData(); + void UpdateClockType(); + bool RecordCallBack(std::unique_ptr record); + void UpdatePerfSampleData(uint64_t callChainId, std::unique_ptr& sample); + uint64_t UpdatePerfCallChainData(std::unique_ptr& sample); + + class CallStackTemp { + public: + CallStackTemp() {} + CallStackTemp(uint32_t depth, uint64_t vaddr, uint64_t fileId, uint64_t symbolId) + : depth_(depth), vaddrInFile_(vaddr), fileId_(fileId), symbolId_(symbolId) + { + } + ~CallStackTemp() {} + uint32_t depth_ = 0; + uint64_t vaddrInFile_ = 0; + uint64_t fileId_ = 0; + uint64_t symbolId_ = 0; + }; + uint64_t callChainId_ = 0; + std::unique_ptr recordDataReader_ = nullptr; + const std::string cpuOffEventName_ = "sched:sched_switch"; + const std::string wakingEventName_ = "sched:sched_waking"; + std::unique_ptr buffer_ = {}; + size_t bufferSize_ = 0; + bool cpuOffMode_ = false; + std::set cpuOffids_ = {}; + std::map> prevSampleCache_ = {}; + Report report_; + uint32_t useClockId_ = 0; + uint32_t clockId_ = 0; + enum PerfClockType { + PERF_CLOCK_REALTIME = 0, + PERF_CLOCK_MONOTONIC, + PERF_CLOCK_MONOTONIC_RAW = 4, + PERF_CLOCK_BOOTTIME = 7, + }; + DataIndex configNameIndex_ = 0; + DataIndex workloaderIndex_ = 0; + DataIndex cmdlineIndex_ = 0; + DataIndex runingStateIndex_ = 0; + DataIndex suspendStatIndex_ = 0; + DataIndex unkonwnStateIndex_ = 0; + std::unordered_multimap tidToPid_ = {}; + const std::map perfToTSClockType_ = { + {PERF_CLOCK_REALTIME, TS_CLOCK_REALTIME}, + {PERF_CLOCK_MONOTONIC, TS_MONOTONIC}, + {PERF_CLOCK_MONOTONIC_RAW, TS_MONOTONIC_RAW}, + {PERF_CLOCK_BOOTTIME, TS_CLOCK_BOOTTIME} + }; + std::map fileDataDictIdToFileId_ = {}; + QuatraMap frameToCallChainId_; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PERF_DATA_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/BUILD.gn b/host/trace_streamer/src/parser/htrace_parser/BUILD.gn old mode 100644 new mode 100755 index 17f81c4ca59502ee62eaccedc4ab5850fa51c7af..e2e58dd3751c2b5259501d0d00e48b2f5e78fb49 --- a/host/trace_streamer/src/parser/htrace_parser/BUILD.gn +++ b/host/trace_streamer/src/parser/htrace_parser/BUILD.gn @@ -17,32 +17,50 @@ ohos_source_set("htrace_parser_src") { "../parser_base.cpp", "htrace_clock_detail_parser.cpp", "htrace_clock_detail_parser.h", + "htrace_cpu_data_parser.cpp", + "htrace_cpu_data_parser.h", "htrace_cpu_parser/htrace_cpu_detail_parser.cpp", "htrace_cpu_parser/htrace_cpu_detail_parser.h", + "htrace_disk_io_parser.cpp", + "htrace_disk_io_parser.h", "htrace_event_parser/htrace_event_parser.cpp", "htrace_event_parser/htrace_event_parser.h", + "htrace_file_header.h", "htrace_hidump_parser.cpp", "htrace_hidump_parser.h", "htrace_hilog_parser.cpp", "htrace_hilog_parser.h", + "htrace_hisysevent_parser.cpp", + "htrace_hisysevent_parser.h", "htrace_mem_parser.cpp", "htrace_mem_parser.h", "htrace_native_hook_parser.cpp", "htrace_native_hook_parser.h", + "htrace_network_parser.cpp", + "htrace_network_parser.h", "htrace_parser.cpp", + "htrace_plugin_time_parser.cpp", + "htrace_plugin_time_parser.h", + "htrace_process_parser.cpp", + "htrace_process_parser.h", "htrace_symbols_detail_parser.cpp", "htrace_symbols_detail_parser.h", ] include_dirs = [ + ".", "htrace_event_parser", "htrace_cpu_parser", - ".", "${OHOS_PROTO_GEN}", "${OHOS_PROTO_GEN}/types/plugins/memory_data", - "${OHOS_PROTO_GEN}/types/plugins/ftrace_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/${kernel_version}", "${OHOS_PROTO_GEN}/types/plugins/hilog_data", "${OHOS_PROTO_GEN}/types/plugins/native_hook", "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}/types/plugins/network_data", + "${OHOS_PROTO_GEN}/types/plugins/cpu_data", + "${OHOS_PROTO_GEN}/types/plugins/diskio_data", + "${OHOS_PROTO_GEN}/types/plugins/process_data", + "${OHOS_PROTO_GEN}/types/plugins/hisysevent_data", "../../include", "../../", "../", @@ -51,9 +69,31 @@ ohos_source_set("htrace_parser_src") { "../../trace_streamer", "//third_party/protobuf/src", "//third_party/sqlite/include", + "//third_party/json-master/include", + "//third_party/json-master/include/nlohmann", "../../filter", "../../base", + "../ebpf_parser", ] + include_dirs += [ + "//third_party/libunwind/include", + "//third_party/libunwind/src", + ] + if (with_perf) { + include_dirs += [ + "../hiperf_parser/hiperf/linux", + "//third_party/perf_include/musl", + "../hiperf_parser/hiperf/include", + "../hiperf_parser/hiperf/include/linux", + "//third_party/perf_include/libbpf", + "../hiperf_parser/hiperf/kernel", + "//third_party/perf_include/include", + "//third_party/perf_include", + "//third_party/perf_include/linux", + "../hiperf_parser", + "../hiperf_parser/include", + ] + } if (enable_ts_utest && !use_wasm) { cflags = [ "-fprofile-arcs", @@ -71,8 +111,13 @@ ohos_source_set("htrace_parser_src") { group("htrace_parser") { deps = [ ":htrace_parser_src", - "//prebuilts/protos:ts_proto_data_cpp", "//third_party/protobuf:protobuf", "//third_party/protobuf:protobuf_lite", ] + if (!use_wasm && !is_win && !is_macx && !is_test) { + deps += [ "//third_party/libunwind:libunwind" ] + } + if (target != "test" && !is_openharmony) { + deps += [ "//prebuilts/protos:ts_proto_data_cpp" ] + } } diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.cpp old mode 100644 new mode 100755 index bc4158b5729945ff9274a810339d437bed092461..32065a3f3d1113ac057681607bb3bcaa46129696 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.cpp +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.cpp @@ -21,8 +21,8 @@ #include "symbols_filter.h" namespace SysTuning { namespace TraceStreamer { -HtraceClockDetailParser::HtraceClockDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) - : streamFilters_(ctx), traceDataCache_(dataCache) +HtraceClockDetailParser::HtraceClockDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters) + : EventParserBase(dataCache, filters) { for (auto i = 0; i < MEM_MAX; i++) { memNameDictMap_.insert(std::make_pair(static_cast(i), @@ -31,22 +31,79 @@ HtraceClockDetailParser::HtraceClockDetailParser(TraceDataCache* dataCache, cons } HtraceClockDetailParser::~HtraceClockDetailParser() = default; -void HtraceClockDetailParser::Parse(TracePluginResult& tracePacket) const +void HtraceClockDetailParser::Parse(TracePluginResult* tracePacket) const { - if (!tracePacket.clocks_detail_size()) { + if (streamFilters_->clockFilter_->HasInitSnapShot()) { + TS_LOGW("already has clock snapshot!!!"); + return; + } + if (!tracePacket->clocks_detail_size()) { + TS_LOGE("!!! no clock snapshot"); return; } std::vector snapShot; TS_LOGI("got clock snapshot"); - for (int i = 0; i < tracePacket.clocks_detail_size(); i++) { - auto clockInfo = tracePacket.mutable_clocks_detail(i); + for (int i = 0; i < tracePacket->clocks_detail_size(); i++) { + auto clockInfo = tracePacket->mutable_clocks_detail(i); TS_LOGI("clockid:%d, ts:%llu", clockInfo->id(), static_cast(clockInfo->time().tv_nsec() + clockInfo->time().tv_sec() * SEC_TO_NS)); snapShot.push_back(SnapShot{static_cast(clockInfo->id()), clockInfo->time().tv_nsec() + clockInfo->time().tv_sec() * SEC_TO_NS}); + } + if (snapShot.size()) { streamFilters_->clockFilter_->AddClockSnapshot(snapShot); } streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_SYNC, STAT_EVENT_RECEIVED); } + +void HtraceClockDetailParser::Parse(const ProfilerTraceFileHeader* profilerTraceFileHeader) const +{ + if (streamFilters_->clockFilter_->HasInitSnapShot()) { + TS_LOGW("already has clock snapshot!!!"); + return; + } + if (!profilerTraceFileHeader->data.boottime) { + TS_LOGW("Profiler header has no clock snapshot!!!"); + return; + } + + std::vector snapShot; + TS_LOGI("got clock snapshot"); + + TS_LOGI("clockid: TS_CLOCK_BOOTTIME, ts:%llu", profilerTraceFileHeader->data.boottime); + if (profilerTraceFileHeader->data.boottime) { + snapShot.push_back(SnapShot{TS_CLOCK_BOOTTIME, profilerTraceFileHeader->data.boottime}); + } + + TS_LOGI("clockid: TS_CLOCK_REALTIME, ts:%llu", profilerTraceFileHeader->data.realtime); + if (profilerTraceFileHeader->data.realtime) { + snapShot.push_back(SnapShot{TS_CLOCK_REALTIME, profilerTraceFileHeader->data.realtime}); + } + + TS_LOGI("clockid: TS_CLOCK_REALTIME_COARSE, ts:%llu", profilerTraceFileHeader->data.realtimeCoarse); + if (profilerTraceFileHeader->data.realtimeCoarse) { + snapShot.push_back(SnapShot{TS_CLOCK_REALTIME_COARSE, profilerTraceFileHeader->data.realtimeCoarse}); + } + + TS_LOGI("clockid: TS_MONOTONIC, ts:%llu", profilerTraceFileHeader->data.monotonic); + if (profilerTraceFileHeader->data.monotonic) { + snapShot.push_back(SnapShot{TS_MONOTONIC, profilerTraceFileHeader->data.monotonic}); + } + + TS_LOGI("clockid: TS_MONOTONIC_COARSE, ts:%llu", profilerTraceFileHeader->data.monotonicCoarse); + if (profilerTraceFileHeader->data.monotonicCoarse) { + snapShot.push_back(SnapShot{TS_MONOTONIC_COARSE, profilerTraceFileHeader->data.monotonicCoarse}); + } + + TS_LOGI("clockid: TS_MONOTONIC_RAW, ts:%llu", profilerTraceFileHeader->data.monotonicRaw); + if (profilerTraceFileHeader->data.monotonicRaw) { + snapShot.push_back(SnapShot{TS_MONOTONIC_RAW, profilerTraceFileHeader->data.monotonicRaw}); + } + + if (snapShot.size()) { + streamFilters_->clockFilter_->AddClockSnapshot(snapShot); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CLOCK_SYNC, STAT_EVENT_RECEIVED); + } +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.h old mode 100644 new mode 100755 index c36c73d675696cef9c455094ee484202513fa391..c26e0638be8b7e3514bbcba76af21dbe5c215a75 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.h +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_clock_detail_parser.h @@ -19,6 +19,9 @@ #include #include #include +#include "event_parser_base.h" +#include "file.h" +#include "htrace_file_header.h" #include "trace_data/trace_data_cache.h" #include "trace_plugin_result.pb.h" #include "trace_streamer_config.h" @@ -26,17 +29,16 @@ namespace SysTuning { namespace TraceStreamer { -class HtraceClockDetailParser { +class HtraceClockDetailParser : public EventParserBase { public: HtraceClockDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters); ~HtraceClockDetailParser(); - void Parse(TracePluginResult& tracePacket) const; + void Parse(TracePluginResult* tracePacket) const; + void Parse(const ProfilerTraceFileHeader* profilerTraceFileHeader) const; private: - const TraceStreamerFilters* streamFilters_; - TraceDataCache* traceDataCache_; - TraceStreamerConfig config_ = {}; std::map memNameDictMap_ = {}; + TraceStreamerConfig config_{}; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_data_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_data_parser.cpp new file mode 100755 index 0000000000000000000000000000000000000000..97987c614c663763e02a2a43b638192a8329a6c3 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_data_parser.cpp @@ -0,0 +1,77 @@ +/* + * 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. + */ +#include "htrace_cpu_data_parser.h" +#include "clock_filter.h" +#include "htrace_event_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceCpuDataParser::HtraceCpuDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : HtracePluginTimeParser(dataCache, ctx) +{ +} + +HtraceCpuDataParser::~HtraceCpuDataParser() +{ + TS_LOGI("cpuData ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); +} +void HtraceCpuDataParser::Parse(CpuData& tracePacket, uint64_t ts) +{ + if (!tracePacket.has_cpu_usage_info() && !tracePacket.thread_info_size()) { + return; + } + if (tracePacket.has_cpu_usage_info()) { + auto cpuInfo = tracePacket.cpu_usage_info(); + auto userLoad = tracePacket.user_load(); + auto sysLoad = tracePacket.sys_load(); + auto process_num = tracePacket.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, cpuInfo); + cpuUsage->SetExtInfo(tracePacket.total_load(), userLoad, sysLoad, process_num); + cpuData_.push_back(std::move(cpuUsage)); + } +} +void HtraceCpuDataParser::Finish() +{ + auto cmp = [](const std::unique_ptr& a, const std::unique_ptr& b) { return a->ts_ < b->ts_; }; + std::sort(cpuData_.begin(), cpuData_.end(), cmp); + bool firstTime = true; + uint64_t lastTs = 0; + for (auto itor = cpuData_.begin(); itor != cpuData_.end(); itor++) { + auto newTimeStamp = (*itor)->ts_; + if (firstTime) { + lastTs = newTimeStamp; + firstTime = false; + continue; + } + auto dur = newTimeStamp - lastTs; + auto durMs = (*itor)->cpuUsageData_->system_boot_time_ms() - (*itor)->cpuUsageData_->prev_system_boot_time_ms(); + durMs = durMs == 0 ? 1 : durMs; + traceDataCache_->GetCpuUsageInfoData()->AppendNewData( + newTimeStamp, dur, + (*itor)->totalLoad_, + (*itor)->userLoad_, (*itor)->sysLoad_, (*itor)->process_num_); + lastTs = newTimeStamp; + } + cpuData_.clear(); + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_data_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_data_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..62e1ca5a4fdc7f298f90a54494962ecbcf347a24 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_data_parser.h @@ -0,0 +1,81 @@ +/* + * 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. + */ +#ifndef HTRACE_CPU_DATA_PARSER_H +#define HTRACE_CPU_DATA_PARSER_H +#include +#include +#include +#include "cpu_plugin_result.pb.h" +#include "hilog_plugin_result.pb.h" +#include "htrace_plugin_time_parser.h" +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +class HtraceCpuDataParser : public HtracePluginTimeParser { +public: + HtraceCpuDataParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceCpuDataParser(); + void Parse(CpuData& tracePacket, uint64_t ts); + void Finish(); + enum TSCpuDataType { TSCpuDataType_Usage, TSCpuDataType_ThreadInfo, TSCpuDataType_Load }; + class TsCpuData { + public: + TsCpuData() + { + ts_ = 0; + cpuDataType_ = TSCpuDataType_Usage; + } + void SetCpuUsage(uint64_t ts, CpuUsageInfo& usage) + { + ts_ = ts; + cpuUsageData_ = std::make_unique(usage); + cpuDataType_ = TSCpuDataType_Usage; + } + void SetThreadInfo(uint64_t ts, ThreadInfo& threadInfo) + { + ts_ = ts; + threadDataData_ = std::make_unique(threadInfo); + cpuDataType_ = TSCpuDataType_ThreadInfo; + } + void SetExtInfo(double totalLoad, double userLoad, double sysLoad, double process_num) + { + totalLoad_ = totalLoad; + userLoad_ = userLoad; + sysLoad_ = sysLoad; + process_num_ = process_num; + cpuDataType_ = TSCpuDataType_Load; + } + uint64_t ts_; + std::unique_ptr cpuUsageData_; + std::unique_ptr threadDataData_; + TSCpuDataType cpuDataType_; + double userLoad_ = 0; + double sysLoad_ = 0; + double process_num_ = 0; + double totalLoad_ = 0; + }; + std::vector> cpuData_; + +private: + std::string threadStateDesc_[THREAD_WAITING + 1] = {"undefined", "Running", "Sleep", "Sloped", "Watting"}; + uint64_t lastLineSeq_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_CPU_DATA_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.cpp index cb37c7c707ad4528c20dd3bbf8cf2364c67203ee..76390aa093ea6ad4ae2eb0e41a81b8b4667c6f2b 100644 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.cpp +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.cpp @@ -23,16 +23,21 @@ HtraceCpuDetailParser::HtraceCpuDetailParser(TraceDataCache* dataCache, const Tr } HtraceCpuDetailParser::~HtraceCpuDetailParser() = default; -void HtraceCpuDetailParser::Parse(TracePluginResult& tracePacket, BuiltinClocks clock) +void HtraceCpuDetailParser::Parse(TracePluginResult* tracePacket, BuiltinClocks clock) { - if (!tracePacket.ftrace_cpu_detail_size()) { + if (!tracePacket->ftrace_cpu_detail_size()) { return; } - for (int i = 0; i < tracePacket.ftrace_cpu_detail_size(); i++) { - FtraceCpuDetailMsg* cpuDetail = tracePacket.mutable_ftrace_cpu_detail(i); + for (int i = 0; i < tracePacket->ftrace_cpu_detail_size(); i++) { + FtraceCpuDetailMsg* cpuDetail = tracePacket->mutable_ftrace_cpu_detail(i); eventParser_->ParseDataItem(cpuDetail, clock); } } +void HtraceCpuDetailParser::FilterAllEvents() +{ + eventParser_->FilterAllEvents(); + eventParser_->Clear(); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.h old mode 100644 new mode 100755 index f422770ff6887a0c8f9ed4baa533b90238d530d4..b7c5cdc9474e70b81cf3ca1f25c91e86fe42dc03 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.h +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.h @@ -33,7 +33,8 @@ class HtraceCpuDetailParser { public: HtraceCpuDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); ~HtraceCpuDetailParser(); - void Parse(TracePluginResult& tracePacket, BuiltinClocks clock); + void Parse(TracePluginResult* tracePacket, BuiltinClocks clock); + void FilterAllEvents(); private: std::unique_ptr eventParser_; diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_disk_io_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_disk_io_parser.cpp new file mode 100755 index 0000000000000000000000000000000000000000..52ccc89d6cc5b6f46a56fdc2c56302350deb6ff1 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_disk_io_parser.cpp @@ -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. + */ +#include "htrace_disk_io_parser.h" +#include "clock_filter.h" +#include "htrace_event_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceDiskIOParser::HtraceDiskIOParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : HtracePluginTimeParser(dataCache, ctx) +{ +} + +HtraceDiskIOParser::~HtraceDiskIOParser() +{ + TS_LOGI("diskio ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); +} +void HtraceDiskIOParser::Parse(DiskioData& tracePacket, uint64_t ts) +{ + auto stat = tracePacket.statsdata(); + if (!stat.statsinfo_size()) { + return; + } + double rdCountPerSec = 0; // The amount of data read from the device per second kB_read/s + double wrCountPerSec = 0; // The amount of data written to the device per second kB_wrtn/s + uint64_t rdCount = 0; // Total amount of data read kB_read + uint64_t wrCount = 0; // The total amount of data written kB_wrtn + for (auto i = 0; i < stat.statsinfo_size(); i++) { + auto statsInfo = stat.statsinfo(i); + rdCountPerSec += statsInfo.rd_per_sec(); + wrCountPerSec += statsInfo.wr_per_sec(); + rdCount += statsInfo.rd_kb(); + wrCount += statsInfo.wr_kb(); + } + + streamFilters_->statFilter_->IncreaseStat(TRACE_DISKIO, STAT_EVENT_RECEIVED); + diskIOData_.push_back(TsDiskIOData{ts, tracePacket.rd_sectors_kb(), tracePacket.wr_sectors_kb(), + tracePacket.prev_rd_sectors_kb(), tracePacket.prev_wr_sectors_kb(), + rdCountPerSec, wrCountPerSec, rdCount, wrCount}); +} +void HtraceDiskIOParser::Finish() +{ + auto cmp = [](const TsDiskIOData& a, const TsDiskIOData& b) { return a.ts < b.ts; }; + std::sort(diskIOData_.begin(), diskIOData_.end(), cmp); + bool first = true; + uint64_t lastTs = 0; + for (auto itor = diskIOData_.begin(); itor != diskIOData_.end(); itor++) { + itor->ts = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, itor->ts); + UpdatePluginTimeRange(TS_CLOCK_REALTIME, itor->ts, itor->ts); + if (first) { + lastTs = itor->ts; + first = false; + continue; + } + auto dur = itor->ts - lastTs; + auto durS = 1.0 * dur / SEC_TO_NS; + traceDataCache_->GetDiskIOData()->AppendNewData( + itor->ts, itor->ts - lastTs, itor->rdSectorsKb, itor->wrSectorsKb, + 1.0 * (itor->rdSectorsKb - itor->prevRdSectorsKb) / durS, + 1.0 * (itor->wrSectorsKb - itor->prevWrSectorsKb) / durS, itor->rdCountPerSec, itor->wrCountPerSec, + itor->rdCount, itor->wrCount); + lastTs = itor->ts; + } + diskIOData_.clear(); + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_disk_io_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_disk_io_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..80ef63f4fc139a7a6f3c23f39bfe96769f50f3e5 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_disk_io_parser.h @@ -0,0 +1,52 @@ +/* + * 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. + */ +#ifndef HTRACE_DISKI0_PARSER_H +#define HTRACE_DISKI0_PARSER_H +#include +#include +#include +#include "diskio_plugin_result.pb.h" +#include "htrace_plugin_time_parser.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" + + +namespace SysTuning { +namespace TraceStreamer { +class HtraceDiskIOParser : public HtracePluginTimeParser { +public: + HtraceDiskIOParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceDiskIOParser(); + void Parse(DiskioData& tracePacket, uint64_t ts); + void Finish(); + +private: + struct TsDiskIOData { + uint64_t ts; + int64_t rdSectorsKb; + int64_t wrSectorsKb; + int64_t prevRdSectorsKb; + int64_t prevWrSectorsKb; + double rdCountPerSec; // 每秒从设备读取的数据量 kB_read/s + double wrCountPerSec; // 每秒向设备写入的数据量 kB_wrtn/s + uint64_t rdCount; // 读取的总数据量 kB_read + uint64_t wrCount; // 写入的总数量数据量 kB_wrtn + }; + std::vector diskIOData_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_DISKI0_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.cpp old mode 100644 new mode 100755 index 20055374ced5ef04fd9bcb4fb57fec5728bb8e45..f5bc69f10729f5e409a56c5f8a423bdc97f673b8 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.cpp +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.cpp @@ -26,6 +26,7 @@ #include "slice_filter.h" #include "stat_filter.h" #include "symbols_filter.h" +#include "system_event_measure_filter.h" #include "thread_state.h" namespace SysTuning { namespace TraceStreamer { @@ -68,6 +69,8 @@ HtraceEventParser::HtraceEventParser(TraceDataCache* dataCache, const TraceStrea std::bind(&HtraceEventParser::CpuIdleEvent, this, std::placeholders::_1)}, {config_.eventNameMap_.at(TRACE_EVENT_CPU_FREQUENCY), std::bind(&HtraceEventParser::CpuFrequencyEvent, this, std::placeholders::_1)}, + {config_.eventNameMap_.at(TRACE_EVENT_CPU_FREQUENCY_LIMITS), + std::bind(&HtraceEventParser::CpuFrequencyLimitsEvent, this, std::placeholders::_1)}, {config_.eventNameMap_.at(TRACE_EVENT_SUSPEND_RESUME), std::bind(&HtraceEventParser::SuspendResumeEvent, this, std::placeholders::_1)}, {config_.eventNameMap_.at(TRACE_EVENT_WORKQUEUE_EXECUTE_START), @@ -101,15 +104,15 @@ HtraceEventParser::HtraceEventParser(TraceDataCache* dataCache, const TraceStrea {config_.eventNameMap_.at(TRACE_EVENT_SYS_EXIT), std::bind(&HtraceEventParser::SysExitEvent, this, std::placeholders::_1)}, {config_.eventNameMap_.at(TRACE_EVENT_OOM_SCORE_ADJ_UPDATE), - std::bind(&HtraceEventParser::OomScoreAdjUdate, this, std::placeholders::_1)}}; + std::bind(&HtraceEventParser::OomScoreAdjUpdate, this, std::placeholders::_1)}}; } HtraceEventParser::~HtraceEventParser() { TS_LOGI("thread count:%u", static_cast(tids_.size())); TS_LOGI("process count:%u", static_cast(pids_.size())); - TS_LOGI("ftrace ts MIN:%llu, MAX:%llu", static_cast(traceStartTime_), - static_cast(traceEndTime_)); + TS_LOGI("ftrace ts MIN:%llu, MAX:%llu", static_cast(ftraceStartTime_), + static_cast(ftraceEndTime_)); } void HtraceEventParser::ParseDataItem(const FtraceCpuDetailMsg* cpuDetail, BuiltinClocks clock) { @@ -132,8 +135,9 @@ void HtraceEventParser::ParseDataItem(const FtraceCpuDetailMsg* cpuDetail, Built for (auto i = 0; i < events.size(); i++) { auto event = cpuDetail->event(i); eventTimestamp_ = event.timestamp(); - traceStartTime_ = std::min(traceStartTime_, eventTimestamp_); - traceEndTime_ = std::max(traceEndTime_, eventTimestamp_); + comm_ = event.comm(); + ftraceStartTime_ = std::min(ftraceStartTime_, eventTimestamp_); + ftraceEndTime_ = std::max(ftraceEndTime_, eventTimestamp_); eventTimestamp_ = streamFilters_->clockFilter_->ToPrimaryTraceTime(clock, eventTimestamp_); traceDataCache_->UpdateTraceTime(eventTimestamp_); if (event.tgid() != INVALID_INT32) { @@ -143,91 +147,111 @@ void HtraceEventParser::ParseDataItem(const FtraceCpuDetailMsg* cpuDetail, Built } streamFilters_->processFilter_->GetOrCreateThreadWithPid(eventPid_, eventPid_); } - if (event.has_sched_switch_format()) { - InvokeFunc(TRACE_EVENT_SCHED_SWITCH, event.sched_switch_format()); - } else if (event.has_task_rename_format()) { - InvokeFunc(TRACE_EVENT_TASK_RENAME, event.task_rename_format()); - } else if (event.has_task_newtask_format()) { - InvokeFunc(TRACE_EVENT_TASK_NEWTASK, event.task_newtask_format()); - } else if (event.has_sched_wakeup_format()) { - InvokeFunc(TRACE_EVENT_SCHED_WAKEUP, event.sched_wakeup_format()); - } else if (event.has_sched_wakeup_new_format()) { - InvokeFunc(TRACE_EVENT_SCHED_WAKEUP, event.sched_wakeup_new_format()); - } else if (event.has_sched_process_exit_format()) { - InvokeFunc(TRACE_EVENT_PROCESS_EXIT, event.sched_process_exit_format()); - } else if (event.has_sched_process_free_format()) { - InvokeFunc(TRACE_EVENT_PROCESS_FREE, event.sched_process_free_format()); - } else if (event.has_sched_waking_format()) { - InvokeFunc(TRACE_EVENT_SCHED_WAKING, event.sched_waking_format()); - } else if (event.has_cpu_idle_format()) { - InvokeFunc(TRACE_EVENT_CPU_IDLE, event.cpu_idle_format()); - } else if (event.has_cpu_frequency_format()) { - InvokeFunc(TRACE_EVENT_CPU_FREQUENCY, event.cpu_frequency_format()); - } else if (event.has_print_format()) { - InvokeFunc(TRACE_EVENT_PRINT, event.print_format()); - } else if (event.has_suspend_resume_format()) { - InvokeFunc(TRACE_EVENT_SUSPEND_RESUME, event.suspend_resume_format()); - } else if (event.has_workqueue_execute_start_format()) { - InvokeFunc(TRACE_EVENT_WORKQUEUE_EXECUTE_START, event.workqueue_execute_start_format()); - } else if (event.has_workqueue_execute_end_format()) { - InvokeFunc(TRACE_EVENT_WORKQUEUE_EXECUTE_END, event.workqueue_execute_end_format()); - } else if (event.has_clock_disable_format()) { - InvokeFunc(TRACE_EVENT_CLOCK_DISABLE, event.clock_disable_format()); - } else if (event.has_clock_enable_format()) { - InvokeFunc(TRACE_EVENT_CLOCK_ENABLE, event.clock_enable_format()); - } else if (event.has_clock_set_rate_format()) { - InvokeFunc(TRACE_EVENT_CLOCK_SET_RATE, event.clock_set_rate_format()); - } else if (event.has_clk_disable_format()) { - InvokeFunc(TRACE_EVENT_CLK_DISABLE, event.clk_disable_format()); - } else if (event.has_clk_enable_format()) { - InvokeFunc(TRACE_EVENT_CLK_ENABLE, event.clk_enable_format()); - } else if (event.has_clk_set_rate_format()) { - InvokeFunc(TRACE_EVENT_CLK_SET_RATE, event.clk_set_rate_format()); - } else if (event.has_sys_enter_format()) { - InvokeFunc(TRACE_EVENT_SYS_ENTRY, event.sys_enter_format()); - } else if (event.has_sys_exit_format()) { - InvokeFunc(TRACE_EVENT_SYS_EXIT, event.sys_exit_format()); - } else if (event.has_binder_transaction_format()) { - InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION, event.binder_transaction_format()); - } else if (event.has_binder_transaction_received_format()) { - InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, event.binder_transaction_received_format()); - } else if (event.has_binder_transaction_alloc_buf_format()) { - InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, event.binder_transaction_alloc_buf_format()); - } else if (event.has_binder_lock_format()) { - InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_LOCK, event.binder_lock_format()); - } else if (event.has_binder_unlock_format()) { - InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, event.binder_unlock_format()); - } else if (event.has_binder_locked_format()) { - InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_LOCKED, event.binder_locked_format()); - } else if (event.has_irq_handler_entry_format()) { - InvokeFunc(TRACE_EVENT_IRQ_HANDLER_ENTRY, event.irq_handler_entry_format()); - } else if (event.has_irq_handler_exit_format()) { - InvokeFunc(TRACE_EVENT_IRQ_HANDLER_EXIT, event.irq_handler_exit_format()); - } else if (event.has_softirq_entry_format()) { - InvokeFunc(TRACE_EVENT_SOFTIRQ_ENTRY, event.softirq_entry_format()); - } else if (event.has_softirq_exit_format()) { - InvokeFunc(TRACE_EVENT_SOFTIRQ_EXIT, event.softirq_exit_format()); - } else if (event.has_oom_score_adj_update_format()) { - InvokeFunc(TRACE_EVENT_OOM_SCORE_ADJ_UPDATE, event.softirq_exit_format()); - } else if (event.has_signal_generate_format()) { - InvokeFunc(TRACE_EVENT_SIGNAL_GENERATE, event.signal_generate_format()); - } else if (event.has_signal_deliver_format()) { - InvokeFunc(TRACE_EVENT_SIGNAL_DELIVER, event.signal_deliver_format()); - } else { - streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, - STAT_EVENT_NOTSUPPORTED); - TS_LOGD("has_rpc_socket_shutdown_format\n"); + if (event.common_fields().pid() != INVALID_INT32) { + eventTid_ = event.common_fields().pid(); + if (!tids_.count(eventTid_)) { + tids_.insert(eventTid_); + } + streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventTid_); + } + if (eventTid_ != INVALID_INT32 && eventPid_ != INVALID_INT32) { + streamFilters_->processFilter_->GetOrCreateThreadWithPid(eventTid_, eventPid_); } + // remember all event + eventList_.push_back(std::move( + std::make_unique(comm_, eventTimestamp_, eventCpu_, eventPid_, eventTid_, std::move(event)))); + // push all events in queue and finally release it, the data may not be released + // this may limit the max size of data, so we parser data periodicity + FilterAllEventsTemp(); + } +} +void HtraceEventParser::DealEvent(const FtraceEvent& event) +{ + streamFilters_->processFilter_->UpdateOrCreateThreadWithPidAndName(event.common_fields().pid(), event.tgid(), + event.comm()); + if (event.has_sched_switch_format()) { + InvokeFunc(TRACE_EVENT_SCHED_SWITCH, event.sched_switch_format()); + } else if (event.has_task_rename_format()) { + InvokeFunc(TRACE_EVENT_TASK_RENAME, event.task_rename_format()); + } else if (event.has_task_newtask_format()) { + InvokeFunc(TRACE_EVENT_TASK_NEWTASK, event.task_newtask_format()); + } else if (event.has_sched_wakeup_format()) { + InvokeFunc(TRACE_EVENT_SCHED_WAKEUP, event.sched_wakeup_format()); + } else if (event.has_sched_wakeup_new_format()) { + InvokeFunc(TRACE_EVENT_SCHED_WAKEUP, event.sched_wakeup_new_format()); + } else if (event.has_sched_process_exit_format()) { + InvokeFunc(TRACE_EVENT_PROCESS_EXIT, event.sched_process_exit_format()); + } else if (event.has_sched_process_free_format()) { + InvokeFunc(TRACE_EVENT_PROCESS_FREE, event.sched_process_free_format()); + } else if (event.has_sched_waking_format()) { + InvokeFunc(TRACE_EVENT_SCHED_WAKING, event.sched_waking_format()); + } else if (event.has_cpu_idle_format()) { + InvokeFunc(TRACE_EVENT_CPU_IDLE, event.cpu_idle_format()); + } else if (event.has_cpu_frequency_format()) { + InvokeFunc(TRACE_EVENT_CPU_FREQUENCY, event.cpu_frequency_format()); + } else if (event.has_cpu_frequency_limits_format()) { + InvokeFunc(TRACE_EVENT_CPU_FREQUENCY_LIMITS, event.cpu_frequency_limits_format()); + } else if (event.has_print_format()) { + InvokeFunc(TRACE_EVENT_PRINT, event.print_format()); + } else if (event.has_suspend_resume_format()) { + InvokeFunc(TRACE_EVENT_SUSPEND_RESUME, event.suspend_resume_format()); + } else if (event.has_workqueue_execute_start_format()) { + InvokeFunc(TRACE_EVENT_WORKQUEUE_EXECUTE_START, event.workqueue_execute_start_format()); + } else if (event.has_workqueue_execute_end_format()) { + InvokeFunc(TRACE_EVENT_WORKQUEUE_EXECUTE_END, event.workqueue_execute_end_format()); + } else if (event.has_clock_disable_format()) { + InvokeFunc(TRACE_EVENT_CLOCK_DISABLE, event.clock_disable_format()); + } else if (event.has_clock_enable_format()) { + InvokeFunc(TRACE_EVENT_CLOCK_ENABLE, event.clock_enable_format()); + } else if (event.has_clock_set_rate_format()) { + InvokeFunc(TRACE_EVENT_CLOCK_SET_RATE, event.clock_set_rate_format()); + } else if (event.has_clk_disable_format()) { + InvokeFunc(TRACE_EVENT_CLK_DISABLE, event.clk_disable_format()); + } else if (event.has_clk_enable_format()) { + InvokeFunc(TRACE_EVENT_CLK_ENABLE, event.clk_enable_format()); + } else if (event.has_clk_set_rate_format()) { + InvokeFunc(TRACE_EVENT_CLK_SET_RATE, event.clk_set_rate_format()); + } else if (event.has_sys_enter_format()) { + InvokeFunc(TRACE_EVENT_SYS_ENTRY, event.sys_enter_format()); + } else if (event.has_sys_exit_format()) { + InvokeFunc(TRACE_EVENT_SYS_EXIT, event.sys_exit_format()); + } else if (event.has_binder_transaction_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION, event.binder_transaction_format()); + } else if (event.has_binder_transaction_received_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, event.binder_transaction_received_format()); + } else if (event.has_binder_transaction_alloc_buf_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, event.binder_transaction_alloc_buf_format()); + } else if (event.has_binder_lock_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_LOCK, event.binder_lock_format()); + } else if (event.has_binder_unlock_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_UNLOCK, event.binder_unlock_format()); + } else if (event.has_binder_locked_format()) { + InvokeFunc(TRACE_EVENT_BINDER_TRANSACTION_LOCKED, event.binder_locked_format()); + } else if (event.has_irq_handler_entry_format()) { + InvokeFunc(TRACE_EVENT_IRQ_HANDLER_ENTRY, event.irq_handler_entry_format()); + } else if (event.has_irq_handler_exit_format()) { + InvokeFunc(TRACE_EVENT_IRQ_HANDLER_EXIT, event.irq_handler_exit_format()); + } else if (event.has_softirq_entry_format()) { + InvokeFunc(TRACE_EVENT_SOFTIRQ_ENTRY, event.softirq_entry_format()); + } else if (event.has_softirq_exit_format()) { + InvokeFunc(TRACE_EVENT_SOFTIRQ_EXIT, event.softirq_exit_format()); + } else if (event.has_oom_score_adj_update_format()) { + InvokeFunc(TRACE_EVENT_OOM_SCORE_ADJ_UPDATE, event.oom_score_adj_update_format()); + } else if (event.has_signal_generate_format()) { + InvokeFunc(TRACE_EVENT_SIGNAL_GENERATE, event.signal_generate_format()); + } else if (event.has_signal_deliver_format()) { + InvokeFunc(TRACE_EVENT_SIGNAL_DELIVER, event.signal_deliver_format()); + } else { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_NOTSUPPORTED); } } - bool HtraceEventParser::BinderTractionAllocBufEvent(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_ALLOC_BUF, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); uint64_t dataSize = msg.data_size(); uint64_t offsetsSize = msg.offsets_size(); - streamFilters_->binderFilter_->TransactionAllocBuf(eventTimestamp_, eventPid_, dataSize, offsetsSize); + streamFilters_->binderFilter_->TransactionAllocBuf(eventTimestamp_, eventTid_, dataSize, offsetsSize); TS_LOGD("dataSize:%lu, offsetSize:%lu", dataSize, offsetsSize); return true; } @@ -243,7 +267,7 @@ bool HtraceEventParser::BinderTractionEvent(const MessageLite& event) const uint32_t flags = msg.flags(); TS_LOGD("destNode:%d, destTgid:%d, destTid:%d, transactionId:%d, isReply:%d flags:%d, code:%d", destNode, destTgid, destTid, transactionId, isReply, flags, msg.code()); - streamFilters_->binderFilter_->SendTraction(eventTimestamp_, eventPid_, transactionId, destNode, destTgid, destTid, + streamFilters_->binderFilter_->SendTraction(eventTimestamp_, eventTid_, transactionId, destNode, destTgid, destTid, isReply, flags, msg.code()); return true; } @@ -252,7 +276,7 @@ bool HtraceEventParser::BinderTractionReceivedEvent(const MessageLite& event) co streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_RECEIVED, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); int32_t transactionId = msg.debug_id(); - streamFilters_->binderFilter_->ReceiveTraction(eventTimestamp_, eventPid_, transactionId); + streamFilters_->binderFilter_->ReceiveTraction(eventTimestamp_, eventTid_, transactionId); TS_LOGD("transactionId:%d", transactionId); return true; } @@ -261,7 +285,7 @@ bool HtraceEventParser::BinderTractionLockEvent(const MessageLite& event) const streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_LOCK, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); std::string tag = msg.tag(); - streamFilters_->binderFilter_->TractionLock(eventTimestamp_, eventPid_, tag); + streamFilters_->binderFilter_->TractionLock(eventTimestamp_, eventTid_, tag); TS_LOGD("tag:%s", tag.c_str()); return true; } @@ -270,7 +294,7 @@ bool HtraceEventParser::BinderTractionLockedEvent(const MessageLite& event) cons streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BINDER_TRANSACTION_LOCKED, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); std::string tag = msg.tag(); - streamFilters_->binderFilter_->TractionLocked(eventTimestamp_, eventPid_, tag); + streamFilters_->binderFilter_->TractionLocked(eventTimestamp_, eventTid_, tag); return true; } bool HtraceEventParser::BinderTractionUnLockEvent(const MessageLite& event) const @@ -279,7 +303,7 @@ bool HtraceEventParser::BinderTractionUnLockEvent(const MessageLite& event) cons const auto msg = static_cast(event); std::string tag = msg.tag(); TS_LOGD("tag:%s", tag.c_str()); - streamFilters_->binderFilter_->TractionUnlock(eventTimestamp_, eventPid_, tag); + streamFilters_->binderFilter_->TractionUnlock(eventTimestamp_, eventTid_, tag); return true; } bool HtraceEventParser::SchedSwitchEvent(const MessageLite& event) @@ -343,38 +367,23 @@ bool HtraceEventParser::TaskRenameEvent(const MessageLite& event) const const auto msg = static_cast(event); auto prevCommStr = msg.newcomm(); auto pidValue = msg.pid(); - streamFilters_->processFilter_->UpdateOrCreateProcessWithName(pidValue, prevCommStr); return true; } bool HtraceEventParser::TaskNewtaskEvent(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TASK_NEWTASK, STAT_EVENT_RECEIVED); - const auto msg = static_cast(event); - auto commonStr = msg.comm(); - auto pidValue = msg.pid(); - - uint32_t ftracePid = 0; - if (eventPid_ != INVALID_UINT32) { - ftracePid = eventPid_; - } - - static const uint32_t threadPid = 2; - static const uint32_t cloneThread = 0x00010000; - auto cloneFlags = msg.clone_flags(); - if ((cloneFlags & cloneThread) == 0 && ftracePid != threadPid) { - streamFilters_->processFilter_->UpdateOrCreateProcessWithName(pidValue, commonStr); - } else if (ftracePid == threadPid) { - streamFilters_->processFilter_->GetOrCreateThreadWithPid(pidValue, threadPid); - } + // the clone flag from txt trace from kernel original is HEX, but when it is converted from proto + // based trace, it will be OCT number, it is not stable, so we decide to ignore it + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TASK_NEWTASK, STAT_EVENT_NOTSUPPORTED); return true; } bool HtraceEventParser::ParsePrintEvent(const MessageLite& event) { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_PRINT, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); - printEventParser_.ParsePrintEvent(eventTimestamp_, eventPid_, msg.buf().c_str()); - if (!pids_.count(eventPid_)) { - pids_.insert(eventPid_); + printEventParser_.ParsePrintEvent(comm_, eventTimestamp_, eventTid_, msg.buf().c_str()); + if (!tids_.count(eventTid_)) { + tids_.insert(eventTid_); } return true; } @@ -382,12 +391,11 @@ bool HtraceEventParser::SchedWakeupEvent(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); - DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_wakeup")); auto instants = traceDataCache_->GetInstantsData(); InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, msg.pid()); - instants->AppendInstantEventData(eventTimestamp_, name, internalTid); - + InternalTid wakeupFromPid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventTid_); + instants->AppendInstantEventData(eventTimestamp_, schedWakeupName_, internalTid, wakeupFromPid); std::optional targetCpu = msg.target_cpu(); if (targetCpu.has_value()) { traceDataCache_->GetRawData()->AppendRawData(0, eventTimestamp_, RAW_SCHED_WAKEUP, targetCpu.value(), @@ -401,12 +409,11 @@ bool HtraceEventParser::SchedWakeupNewEvent(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKEUP_NEW, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); - DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_wakeup_new")); auto instants = traceDataCache_->GetInstantsData(); InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, msg.pid()); - instants->AppendInstantEventData(eventTimestamp_, name, internalTid); - + InternalTid wakeupFromPid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventTid_); + instants->AppendInstantEventData(eventTimestamp_, schedWakeupNewName_, internalTid, wakeupFromPid); std::optional targetCpu = msg.target_cpu(); if (targetCpu.has_value()) { traceDataCache_->GetRawData()->AppendRawData(0, eventTimestamp_, RAW_SCHED_WAKEUP, targetCpu.value(), @@ -426,15 +433,16 @@ bool HtraceEventParser::SchedWakingEvent(const MessageLite& event) const streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_DATA_INVALID); return false; } - DataIndex name = traceDataCache_->GetDataIndex(std::string_view("sched_waking")); auto instants = traceDataCache_->GetInstantsData(); - InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventPid_); - instants->AppendInstantEventData(eventTimestamp_, name, internalTid); + InternalTid internalTid = + streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, wakePidValue.value()); + InternalTid wakeupFromPid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventTid_); + instants->AppendInstantEventData(eventTimestamp_, schedWakingName_, internalTid, wakeupFromPid); streamFilters_->cpuFilter_->InsertWakeupEvent(eventTimestamp_, internalTid); std::optional targetCpu = msg.target_cpu(); if (targetCpu.has_value()) { traceDataCache_->GetRawData()->AppendRawData(0, eventTimestamp_, RAW_SCHED_WAKING, targetCpu.value(), - internalTid); + wakeupFromPid); } return true; } @@ -454,10 +462,9 @@ bool HtraceEventParser::CpuIdleEvent(const MessageLite& event) const streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_IDLE, STAT_EVENT_DATA_INVALID); return false; } - auto cpuIdleNameIndex = traceDataCache_->GetDataIndex(std::string_view("cpu_idle")); - streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuIdleNameIndex, eventTimestamp_, - newStateValue.value()); + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuIdleName_, eventTimestamp_, + config_.GetStateValue(newStateValue.value())); // Add cpu_idle event to raw_data_table traceDataCache_->GetRawData()->AppendRawData(0, eventTimestamp_, RAW_CPU_IDLE, eventCpuValue.value(), 0); @@ -480,12 +487,24 @@ bool HtraceEventParser::CpuFrequencyEvent(const MessageLite& event) const streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_DATA_INVALID); return false; } - auto cpuidleNameIndex = traceDataCache_->GetDataIndex(std::string_view("cpu_frequency")); - streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuidleNameIndex, eventTimestamp_, + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue.value(), cpuFrequencyName_, eventTimestamp_, newStateValue.value()); return true; } +bool HtraceEventParser::CpuFrequencyLimitsEvent(const MessageLite& event) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_CPU_FREQUENCY_LIMITS, STAT_EVENT_RECEIVED); + const auto msg = static_cast(event); + uint32_t maxFreq = msg.max_freq(); + uint32_t minFreq = msg.min_freq(); + uint32_t eventCpuValue = msg.cpu_id(); + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue, cpuFrequencyLimitMaxNameId, eventTimestamp_, + maxFreq); + streamFilters_->cpuMeasureFilter_->AppendNewMeasureData(eventCpuValue, cpuFrequencyLimitMinNameId, eventTimestamp_, + minFreq); + return true; +} bool HtraceEventParser::SuspendResumeEvent(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SUSPEND_RESUME, STAT_EVENT_RECEIVED); @@ -503,18 +522,29 @@ bool HtraceEventParser::WorkqueueExecuteStartEvent(const MessageLite& event) con { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_START, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); - auto result = streamFilters_->sliceFilter_->BeginSlice(eventTimestamp_, eventPid_, eventPid_, workQueueId_, - streamFilters_->symbolsFilter_->GetFunc(msg.function())); + auto funcNameIndex = streamFilters_->symbolsFilter_->GetFunc(msg.function()); + size_t result = INVALID_UINT32; + if (funcNameIndex == INVALID_UINT64) { + std::string addrStr = "0x" + base::number(msg.function(), base::INTEGER_RADIX_TYPE_HEX); + auto addStrIndex = traceDataCache_->GetDataIndex(addrStr); + result = streamFilters_->sliceFilter_->BeginSlice(comm_, eventTimestamp_, eventPid_, eventPid_, + workQueueId_, addStrIndex); + } else { + result = streamFilters_->sliceFilter_->BeginSlice(comm_, eventTimestamp_, eventPid_, eventPid_, + workQueueId_, funcNameIndex); + } traceDataCache_->GetInternalSlicesData()->AppendDistributeInfo(); - UNUSED(result); + if (result == INVALID_UINT32) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST); + } return true; } bool HtraceEventParser::WorkqueueExecuteEndEvent(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_END, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); - if (streamFilters_->sliceFilter_->EndSlice(eventTimestamp_, eventPid_, eventPid_)) { + if (streamFilters_->sliceFilter_->EndSlice(eventTimestamp_, eventPid_, eventPid_, workQueueId_)) { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_WORKQUEUE_EXECUTE_END, STAT_EVENT_NOTMATCH); } return true; @@ -607,27 +637,24 @@ bool HtraceEventParser::SysEnterEvent(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); - DataIndex nameIndex = traceDataCache_->GetDataIndex("sys_enter"); auto ipid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventPid_); - traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), nameIndex, ipid, eventTimestamp_, 0); + traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), sysEnterName_, ipid, eventTimestamp_, 0); return true; } bool HtraceEventParser::SysExitEvent(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_EXIT, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); - DataIndex nameIndex = traceDataCache_->GetDataIndex("sys_exit"); auto ipid = streamFilters_->processFilter_->UpdateOrCreateThread(eventTimestamp_, eventPid_); - traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), nameIndex, ipid, eventTimestamp_, msg.ret()); + traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), sysExitName_, ipid, eventTimestamp_, msg.ret()); return true; } -bool HtraceEventParser::OomScoreAdjUdate(const MessageLite& event) const +bool HtraceEventParser::OomScoreAdjUpdate(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OOM_SCORE_ADJ_UPDATE, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); - DataIndex nameIndex = traceDataCache_->GetDataIndex("oom_score_adj"); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(msg.pid(), nameIndex, eventTimestamp_, + streamFilters_->processMeasureFilter_->AppendNewMeasureData(msg.pid(), oomScoreAdjName_, eventTimestamp_, msg.oom_score_adj()); return true; } @@ -636,8 +663,8 @@ bool HtraceEventParser::SignalGenerateEvent(const MessageLite& event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_BLOCK_BIO_BACKMERGE, STAT_EVENT_RECEIVED); const auto msg = static_cast(event); - InternalTid internalTid = streamFilters_->processFilter_->UpdateOrCreateThreadWithName(eventTimestamp_, msg.pid(), - msg.comm()); + InternalTid internalTid = + streamFilters_->processFilter_->UpdateOrCreateThreadWithName(eventTimestamp_, msg.pid(), msg.comm()); streamFilters_->threadFilter_->AppendNewMeasureData(internalTid, signalGenerateId_, eventTimestamp_, msg.sig()); return true; } @@ -649,8 +676,7 @@ bool HtraceEventParser::SignalDeleverEvent(const MessageLite& event) const streamFilters_->threadFilter_->AppendNewMeasureData(internalTid, signalDeliverId_, eventTimestamp_, msg.sig()); return true; } -bool HtraceEventParser::InvokeFunc(const SupportedTraceEventType& eventType, - const MessageLite& msgBase) +bool HtraceEventParser::InvokeFunc(const SupportedTraceEventType& eventType, const MessageLite& msgBase) { auto eventName = config_.eventNameMap_.find(eventType); if (eventName == config_.eventNameMap_.end()) { @@ -667,5 +693,78 @@ bool HtraceEventParser::InvokeFunc(const SupportedTraceEventType& eventType, it->second(msgBase); return true; } +void HtraceEventParser::FilterAllEventsTemp() +{ + size_t maxBuffSize = 1000 * 1000; + size_t maxQueue = 2; + if (eventList_.size() < maxBuffSize * maxQueue) { + return; + } + auto cmp = [](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->eventTimestamp_ < b->eventTimestamp_; + }; + std::sort(eventList_.begin(), eventList_.end(), cmp); + + auto endOfList = eventList_.begin() + maxBuffSize; + for (auto itor = eventList_.begin(); itor != endOfList; itor++) { + EventInfo* event = itor->get(); + eventTimestamp_ = event->eventTimestamp_; + eventCpu_ = event->eventCpu_; + eventPid_ = event->eventPid_; + eventTid_ = event->eventTid_; + comm_ = event->common_; + DealEvent(event->cpuDetail_); + itor->reset(); + } + eventList_.erase(eventList_.begin(), endOfList); +} +void HtraceEventParser::FilterAllEvents() +{ + auto cmp = [](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->eventTimestamp_ < b->eventTimestamp_; + }; + std::sort(eventList_.begin(), eventList_.end(), cmp); + size_t maxBuffSize = 1000 * 1000; + + while (eventList_.size()) { + int size = std::min(maxBuffSize, eventList_.size()); + auto endOfList = eventList_.begin() + size; + for (auto itor = eventList_.begin(); itor != endOfList; itor++) { + EventInfo* event = itor->get(); + eventTimestamp_ = event->eventTimestamp_; + eventCpu_ = event->eventCpu_; + eventPid_ = event->eventPid_; + eventTid_ = event->eventTid_; + comm_ = event->common_; + DealEvent(event->cpuDetail_); + itor->reset(); + } + eventList_.erase(eventList_.begin(), endOfList); + } + eventList_.clear(); + streamFilters_->cpuFilter_->Finish(); + traceDataCache_->dataDict_.Finish(); + traceDataCache_->UpdataZeroThreadInfo(); +} +void HtraceEventParser::Clear() const +{ + streamFilters_->binderFilter_->Clear(); + streamFilters_->sliceFilter_->Clear(); + streamFilters_->cpuFilter_->Clear(); + streamFilters_->irqFilter_->Clear(); + streamFilters_->cpuMeasureFilter_->Clear(); + streamFilters_->threadMeasureFilter_->Clear(); + streamFilters_->threadFilter_->Clear(); + streamFilters_->processMeasureFilter_->Clear(); + streamFilters_->processFilterFilter_->Clear(); + streamFilters_->symbolsFilter_->Clear(); + streamFilters_->clockEnableFilter_->Clear(); + streamFilters_->clockDisableFilter_->Clear(); + streamFilters_->clkRateFilter_->Clear(); + streamFilters_->clkDisableFilter_->Clear(); + streamFilters_->binderFilter_->Clear(); + streamFilters_->sysEventMemMeasureFilter_->Clear(); + streamFilters_->sysEventVMemMeasureFilter_->Clear(); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.h old mode 100644 new mode 100755 index 05ca103a2ed079c563f8d4073c08d36a94b32e7d..8f71a0e7211cd9e45d390101b3f425e3b1de5ef1 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.h +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_event_parser/htrace_event_parser.h @@ -17,10 +17,10 @@ #include #include #include -#include #include #include #include +#include #include "event_parser_base.h" #include "google/protobuf/message_lite.h" @@ -28,6 +28,7 @@ #include "print_event_parser.h" #include "trace_data/trace_data_cache.h" #include "trace_plugin_result.pb.h" +#include "trace_streamer_config.h" #include "trace_streamer_filters.h" #include "ts_common.h" @@ -39,7 +40,11 @@ public: HtraceEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter); ~HtraceEventParser(); void ParseDataItem(const FtraceCpuDetailMsg* cpuDetail, BuiltinClocks clock); + void FilterAllEventsTemp(); + void FilterAllEvents(); + void Clear() const; private: + void DealEvent(const FtraceEvent& event); bool BinderTractionEvent(const MessageLite& event) const; bool BinderTractionReceivedEvent(const MessageLite& event) const; bool BinderTractionAllocBufEvent(const MessageLite& event) const; @@ -57,6 +62,7 @@ private: bool SchedWakingEvent(const MessageLite& event) const; bool CpuIdleEvent(const MessageLite& event) const; bool CpuFrequencyEvent(const MessageLite& event) const; + bool CpuFrequencyLimitsEvent(const MessageLite& event) const; bool SuspendResumeEvent(const MessageLite& event) const; bool WorkqueueExecuteStartEvent(const MessageLite& event) const; bool WorkqueueExecuteEndEvent(const MessageLite& event) const; @@ -73,24 +79,61 @@ private: bool SoftIrqExitEvent(const MessageLite& event) const; bool SysEnterEvent(const MessageLite& event) const; bool SysExitEvent(const MessageLite& event) const; - bool OomScoreAdjUdate(const MessageLite& event) const; + bool OomScoreAdjUpdate(const MessageLite& event) const; bool SignalGenerateEvent(const MessageLite& event) const; bool SignalDeleverEvent(const MessageLite& event) const; bool InvokeFunc(const SupportedTraceEventType& eventType, const MessageLite& msgBase); + class EventInfo { + public: + EventInfo(const std::string& common, + uint64_t eventTimestamp, + uint32_t eventCpu, + uint32_t eventPid, + uint32_t eventTid, + const FtraceEvent& cpuDetail) + : common_(common), + eventTimestamp_(eventTimestamp), + eventCpu_(eventCpu), + eventPid_(eventPid), + eventTid_(eventTid), + cpuDetail_(std::move(cpuDetail)) + { + } + std::string common_; + uint64_t eventTimestamp_; + uint32_t eventCpu_; + uint32_t eventPid_; + uint32_t eventTid_; + FtraceEvent cpuDetail_; + }; using FuncCall = std::function; uint32_t eventCpu_ = INVALID_UINT32; uint64_t eventTimestamp_ = INVALID_UINT64; + std::string comm_ = ""; uint32_t eventPid_ = INVALID_UINT32; + uint32_t eventTid_ = INVALID_UINT32; std::map eventToFunctionMap_ = {}; std::unordered_set tids_ = {}; std::unordered_set pids_ = {}; DataIndex workQueueId_ = 0; PrintEventParser printEventParser_; uint64_t lastOverwrite_ = 0; - DataIndex signalGenerateId_ = traceDataCache_->GetDataIndex("signal_generate"); - DataIndex signalDeliverId_ = traceDataCache_->GetDataIndex("signal_deliver"); - uint64_t traceStartTime_ = std::numeric_limits::max(); - uint64_t traceEndTime_ = 0; + uint64_t ftraceStartTime_ = std::numeric_limits::max(); + uint64_t ftraceEndTime_ = 0; + std::vector> eventList_ = {}; + const DataIndex signalGenerateId_ = traceDataCache_->GetDataIndex("signal_generate"); + const DataIndex signalDeliverId_ = traceDataCache_->GetDataIndex("signal_deliver"); + const DataIndex schedWakeupName_ = traceDataCache_->GetDataIndex("sched_wakeup"); + const DataIndex schedWakingName_ = traceDataCache_->GetDataIndex("sched_waking"); + const DataIndex schedWakeupNewName_ = traceDataCache_->GetDataIndex("sched_wakeup_new"); + const DataIndex cpuIdleName_ = traceDataCache_->GetDataIndex("cpu_idle"); + const DataIndex cpuFrequencyName_ = traceDataCache_->GetDataIndex("cpu_frequency"); + const DataIndex cpuFrequencyLimitMaxNameId = traceDataCache_->GetDataIndex("cpu_frequency_limits_max"); + const DataIndex cpuFrequencyLimitMinNameId = traceDataCache_->GetDataIndex("cpu_frequency_limits_min"); + const DataIndex sysEnterName_ = traceDataCache_->GetDataIndex("sys_enter"); + const DataIndex sysExitName_ = traceDataCache_->GetDataIndex("sys_exit"); + const DataIndex oomScoreAdjName_ = traceDataCache_->GetDataIndex("oom_score_adj"); + TraceStreamerConfig config_{}; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_file_header.h b/host/trace_streamer/src/parser/htrace_parser/htrace_file_header.h new file mode 100644 index 0000000000000000000000000000000000000000..b0069afcd2be421c65be63ae9cd071b48f48631a --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_file_header.h @@ -0,0 +1,64 @@ +/* + * 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. + */ +#ifndef HTRACE_FILE_HEADER_H +#define HTRACE_FILE_HEADER_H +namespace SysTuning { +namespace TraceStreamer { +struct ProfilerTraceFileHeader { + // Some space is reserved to facilitate the subsequent addition of fields in the header + static constexpr uint32_t HEADER_SIZE = 1024; + static constexpr uint32_t SHA256_SIZE = 256 / 8; + static constexpr uint64_t HEADER_MAGIC = 0x464F5250534F484FuLL; + static constexpr uint32_t V_MAJOR = 0x0001; + static constexpr uint32_t V_MAJOR_BITS = 16; + static constexpr uint32_t V_MINOR = 0x0000; + static constexpr uint32_t TRACE_VERSION = (V_MAJOR << V_MAJOR_BITS) | V_MINOR; + static constexpr uint8_t PLUGIN_MODULE_NAME_MAX = 127; + static constexpr uint8_t PLUGIN_MODULE_VERSION_MAX = 7; + enum DataType { + HIPROFILER_PROTOBUF_BIN = 0, + HIPERF_DATA, + STANDALONE_DATA = 1000, + UNKNOW_TYPE = 1024, + }; + struct HeaderData { + // Magic number, used to distinguish offline files + uint64_t magic = HEADER_MAGIC; + // Total length, which can be used to check whether the document is truncated; + uint64_t length = HEADER_SIZE; + uint32_t version = TRACE_VERSION; + // The number of segments in the load data. The number of segments is even. One describes the length L and the + // other describes the next data v + uint32_t segments = 0; + // Sha256 of load data is used to verify whether the load data is complete; + uint8_t sha256[SHA256_SIZE] = {}; + uint32_t dataType = UNKNOW_TYPE; + // clock + uint64_t boottime = 0; + uint64_t realtime = 0; + uint64_t realtimeCoarse = 0; + uint64_t monotonic = 0; + uint64_t monotonicCoarse = 0; + uint64_t monotonicRaw = 0; + char standalonePluginName[PLUGIN_MODULE_NAME_MAX + 1] = ""; + char pluginVersion[PLUGIN_MODULE_VERSION_MAX +1] = ""; + } __attribute__((packed)); + HeaderData data = {}; + uint8_t padding_[HEADER_SIZE - sizeof(data)] = {}; +}; +const std::string EBPF_PLUGIN_NAME = "hiebpf-plugin"; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // HTRACE_FILE_HEADER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.cpp old mode 100644 new mode 100755 index 7742db963bfbc788ad21ede638179e6c67cc4e69..dcf0edc3caffd6710e29e911811a6d08690ee5ff --- a/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.cpp +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.cpp @@ -12,63 +12,42 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "htrace_hidump_parser.h" #include "clock_filter.h" -#include "hidump_plugin_result.pb.h" #include "htrace_event_parser.h" #include "process_filter.h" #include "stat_filter.h" -#include "htrace_hidump_parser.h" namespace SysTuning { namespace TraceStreamer { HtraceHidumpParser::HtraceHidumpParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) - : streamFilters_(ctx), traceDataCache_(dataCache) -{ - if (!traceDataCache_) { - TS_LOGE("traceDataCache_ should not be null"); - return; - } - if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); - return; - } -} + : HtracePluginTimeParser(dataCache, ctx), + clockId_(0) + {} HtraceHidumpParser::~HtraceHidumpParser() { - TS_LOGI("FPS data ts MIN:%llu, MAX:%llu", - static_cast(traceStartTime_), static_cast(traceEndTime_)); + TS_LOGI("Fps data ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); } void HtraceHidumpParser::Parse(HidumpInfo& tracePacket) { if (!tracePacket.fps_event_size()) { return; } - if (!traceDataCache_) { - TS_LOGE("traceDataCache_ should not be null"); - return; - } - if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); - return; - } for (int i = 0; i < tracePacket.fps_event_size(); i++) { streamFilters_->statFilter_->IncreaseStat(TRACE_HIDUMP_FPS, STAT_EVENT_RECEIVED); auto hidumpData = tracePacket.mutable_fps_event(i); auto timeStamp = hidumpData->time().tv_nsec() + hidumpData->time().tv_sec() * SEC_TO_NS; auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(hidumpData->id(), timeStamp); - if (newTimeStamp != timeStamp) { // record the time only when the time is valid - traceStartTime_ = std::min(traceStartTime_, newTimeStamp); - traceEndTime_ = std::max(traceEndTime_, newTimeStamp); - } else { - streamFilters_->statFilter_->IncreaseStat(TRACE_HIDUMP_FPS, STAT_EVENT_DATA_INVALID); - } + UpdatePluginTimeRange(hidumpData->id(), timeStamp, newTimeStamp); + clockId_ = hidumpData->id(); auto fps = hidumpData->fps(); traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(newTimeStamp, fps); } } void HtraceHidumpParser::Finish() { - traceDataCache_->MixTraceTime(traceStartTime_, traceEndTime_); + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.h index dc4cf21e82d2033d587efc75532c02ab76b4575b..48a6c5ffadd3bc538827ddbc0ee9b177ad43a315 100644 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.h +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hidump_parser.h @@ -17,6 +17,8 @@ #include #include #include +#include "hidump_plugin_result.pb.h" +#include "htrace_plugin_time_parser.h" #include "trace_data/trace_data_cache.h" #include "trace_streamer_config.h" #include "trace_streamer_filters.h" @@ -24,19 +26,19 @@ namespace SysTuning { namespace TraceStreamer { -class HtraceHidumpParser { +class HtraceHidumpParser : public HtracePluginTimeParser { public: HtraceHidumpParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); ~HtraceHidumpParser(); void Parse(HidumpInfo& tracePacket); void Finish(); + uint8_t ClockId() + { + return clockId_; + } private: - const TraceStreamerFilters* streamFilters_; - TraceDataCache* traceDataCache_; - TraceStreamerConfig config_ = {}; - uint64_t traceStartTime_ = std::numeric_limits::max(); - uint64_t traceEndTime_ = 0; + uint8_t clockId_; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.cpp old mode 100644 new mode 100755 index ad3e12f4d73b27139517ea4c31cd4756434708ed..bc5378e7eb875e5889835fa55f5c88d5c4a34338 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.cpp +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.cpp @@ -20,36 +20,18 @@ namespace SysTuning { namespace TraceStreamer { HtraceHiLogParser::HtraceHiLogParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) - : streamFilters_(ctx), traceDataCache_(dataCache) -{ - if (!traceDataCache_) { - TS_LOGE("traceDataCache_ should not be null"); - return; - } - if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); - return; - } -} + : HtracePluginTimeParser(dataCache, ctx) {} HtraceHiLogParser::~HtraceHiLogParser() { - TS_LOGI("hilog ts MIN:%llu, MAX:%llu", - static_cast(traceStartTime_), static_cast(traceEndTime_)); + TS_LOGI("hilog ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); } void HtraceHiLogParser::Parse(HilogInfo& tracePacket) { if (!tracePacket.info_size()) { return; } - if (!traceDataCache_) { - TS_LOGE("traceDataCache_ should not be null"); - return; - } - if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); - return; - } for (int i = 0; i < tracePacket.info_size(); i++) { auto hilogLine = tracePacket.mutable_info(i); uint64_t curLineSeq = hilogLine->id(); @@ -70,16 +52,9 @@ void HtraceHiLogParser::Parse(HilogInfo& tracePacket) TS_LOGD("log level do not exit!!!"); continue; } - auto timeStamp = logDetails.tv_nsec() + logDetails.tv_sec() * SEC_TO_NS; auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, timeStamp); - if (newTimeStamp != timeStamp) { // record the time only when the time is valid - traceStartTime_ = std::min(traceStartTime_, newTimeStamp); - traceEndTime_ = std::max(traceEndTime_, newTimeStamp); - } else { - streamFilters_->statFilter_->IncreaseStat(TRACE_HILOG, STAT_EVENT_DATA_INVALID); - } - + UpdatePluginTimeRange(TS_CLOCK_REALTIME, timeStamp, newTimeStamp); DataIndex levelData = traceDataCache_->dataDict_.GetStringIndex(iter->second.c_str()); DataIndex logTag = traceDataCache_->dataDict_.GetStringIndex(logDetails.tag().c_str()); traceDataCache_->GetHilogData()->AppendNewLogInfo(curLineSeq, newTimeStamp, logDetails.pid(), logDetails.tid(), @@ -88,7 +63,7 @@ void HtraceHiLogParser::Parse(HilogInfo& tracePacket) } void HtraceHiLogParser::Finish() { - traceDataCache_->MixTraceTime(traceStartTime_, traceEndTime_); + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.h index e889f9554848f802dd9004b93adad2832766184d..e0e5f2803265ab4376bdf9deefab99e998b8f71d 100644 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.h +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hilog_parser.h @@ -19,13 +19,14 @@ #include #include "trace_data/trace_data_cache.h" #include "hilog_plugin_result.pb.h" +#include "htrace_plugin_time_parser.h" #include "trace_streamer_config.h" #include "trace_streamer_filters.h" namespace SysTuning { namespace TraceStreamer { -class HtraceHiLogParser { +class HtraceHiLogParser : public HtracePluginTimeParser { public: HtraceHiLogParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); ~HtraceHiLogParser(); @@ -38,12 +39,7 @@ public: void Finish(); private: - const TraceStreamerFilters* streamFilters_; - TraceDataCache* traceDataCache_; - TraceStreamerConfig config_ = {}; uint64_t lastLineSeq_ = 0; - uint64_t traceStartTime_ = std::numeric_limits::max(); - uint64_t traceEndTime_ = 0; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hisysevent_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_hisysevent_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3029d9c5017763ca20961d1692c346a2774131fa --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hisysevent_parser.cpp @@ -0,0 +1,210 @@ +/* + * 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. + */ +#include "clock_filter.h" +#include "hi_sysevent_measure_filter.h" +#include "htrace_event_parser.h" +#include "htrace_hisysevent_parser.h" +#include "htrace_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceHisyseventParser::HtraceHisyseventParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : HtracePluginTimeParser(dataCache, ctx) +{ +} +HtraceHisyseventParser::~HtraceHisyseventParser() +{ + TS_LOGI("hisysevent ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); + TS_LOGI("hisysevent real ts MIN:%llu, MAX:%llu", static_cast(MinTs()), + static_cast(MaxTs())); +} + +int32_t HtraceHisyseventParser::JGetData(json& jMessage, + JsonData& jData, + size_t& maxArraySize, + std::vector& noArrayIndex, + std::vector& arrayIndex) +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_HISYSEVENT, STAT_EVENT_RECEIVED); + for (auto i = jMessage.begin(); i != jMessage.end(); i++) { + if (i.key() == "name_") { + if (find(eventsAccordingAppNames.begin(), eventsAccordingAppNames.end(), i.value()) == + eventsAccordingAppNames.end()) { + streamFilters_->statFilter_->IncreaseStat(TRACE_HISYSEVENT, STAT_EVENT_NOTMATCH); + TS_LOGW("event source:%s not supported for hisysevent", i.value().c_str()); + return -1; + } + jData.eventSource = i.value(); + continue; + } + if (i.key() == "time_") { + jData.timestamp = i.value(); + continue; + } + if (i.key() == "tag_" && i.value() != "PowerStats") { + streamFilters_->statFilter_->IncreaseStat(TRACE_HISYSEVENT, STAT_EVENT_DATA_INVALID); + return -1; + } + if (i.key() == "APPNAME") { + jData.appName.assign(i.value().begin(), i.value().end()); + } + if (i.value().is_array()) { + maxArraySize = std::max(maxArraySize, i.value().size()); + arrayIndex.push_back(jData.key.size()); + } else { + noArrayIndex.push_back(jData.key.size()); + } + jData.key.push_back(i.key()); + jData.value.push_back(i.value()); + } + return 0; +} + +void HtraceHisyseventParser::NoArrayDataParse(JsonData jData, + std::vector noArrayIndex, + DataIndex eventSourceIndex, + uint64_t serial) +{ + for (auto itor = noArrayIndex.begin(); itor != noArrayIndex.end(); itor++) { + auto value = jData.value[*itor]; + auto key = jData.key[*itor]; + streamFilters_->hiSysEventMeasureFilter_->GetOrCreateFilterId(eventSourceIndex); + DataIndex keyIndex = traceDataCache_->GetDataIndex(key); + if (value.is_string()) { + std::string strValue = value; + DataIndex valueIndex = traceDataCache_->GetDataIndex(strValue); + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(serial, jData.timestamp, eventSourceIndex, keyIndex, 1, 0, + valueIndex); + } else { + double valueIndex = value; + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(serial, jData.timestamp, eventSourceIndex, keyIndex, 0, + valueIndex, 0); + } + } +} +void HtraceHisyseventParser::ArrayDataParse(JsonData jData, + std::vector arrayIndex, + DataIndex eventSourceIndex, + size_t maxArraySize, + uint64_t serial) +{ + for (int j = 0; j < maxArraySize; j++) { + for (auto itor = arrayIndex.begin(); itor != arrayIndex.end(); itor++) { + auto value = jData.value[*itor][j]; + std::string key = jData.key[*itor]; + DataIndex keyIndex = traceDataCache_->GetDataIndex(key); + streamFilters_->hiSysEventMeasureFilter_->GetOrCreateFilterId(eventSourceIndex); + if (value.is_number()) { + double valueIndex = value; + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(serial, jData.timestamp, eventSourceIndex, keyIndex, 0, + valueIndex, 0); + } else if (value.is_string()) { + std::string strValue = value; + DataIndex valueIndex = traceDataCache_->GetDataIndex(strValue); + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(serial, jData.timestamp, eventSourceIndex, keyIndex, 1, + 0, valueIndex); + } + } + } +} +void HtraceHisyseventParser::CommonDataParser(JsonData jData, DataIndex eventSourceIndex, uint64_t serial) +{ + for (int j = 0; j < jData.key.size(); j++) { + std::string key = jData.key[j]; + auto value = jData.value[j]; + DataIndex keyIndex = traceDataCache_->GetDataIndex(key); + streamFilters_->hiSysEventMeasureFilter_->GetOrCreateFilterId(eventSourceIndex); + if (value.is_string()) { + std::string strValue = value; + DataIndex valueIndex = traceDataCache_->GetDataIndex(strValue); + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(serial, jData.timestamp, eventSourceIndex, keyIndex, 1, 0, + valueIndex); + } else { + double valueIndex = value; + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue(serial, jData.timestamp, eventSourceIndex, keyIndex, 0, + valueIndex, 0); + } + } +} +void HtraceHisyseventParser::Finish() +{ + if (GetPluginStartTime() != GetPluginEndTime()) { + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); + } else { + TS_LOGI("hisysevent time is not updated, maybe this trace file only has one piece of hisysevent data"); + } + TS_LOGI("--------Parse end--------"); +} + +static std::stringstream ss; +void HtraceHisyseventParser::Parse(HisyseventInfo& tracePacket, uint64_t ts) +{ + if (isDeviceState) { + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue( + tracePacket.device_state().brightness_state(), tracePacket.device_state().bt_state(), + tracePacket.device_state().location_state(), tracePacket.device_state().wifi_state(), + tracePacket.device_state().volume_state().stream_default(), + tracePacket.device_state().volume_state().voice_call(), tracePacket.device_state().volume_state().music(), + tracePacket.device_state().volume_state().stream_ring(), tracePacket.device_state().volume_state().media(), + tracePacket.device_state().volume_state().voice_assistant(), + tracePacket.device_state().volume_state().system(), tracePacket.device_state().volume_state().alarm(), + tracePacket.device_state().volume_state().notification(), + tracePacket.device_state().volume_state().bluetoolth_sco(), + tracePacket.device_state().volume_state().enforced_audible(), + tracePacket.device_state().volume_state().stream_dtmf(), + tracePacket.device_state().volume_state().stream_tts(), + tracePacket.device_state().volume_state().accessibility(), + tracePacket.device_state().volume_state().recording(), + tracePacket.device_state().volume_state().stream_all()); + isDeviceState = false; + } + json jMessage; + for (int i = 0; i < tracePacket.info_size(); i++) { + if (tracePacket.info(i).raw_content().front() != '{' || tracePacket.info(i).raw_content().back() != '}') { + continue; + } + ss << tracePacket.info(i).raw_content(); + ss >> jMessage; + size_t maxArraySize = 0; + JsonData jData; + std::vector noArrayIndex = {}; + std::vector arrayIndex = {}; + if (JGetData(jMessage, jData, maxArraySize, noArrayIndex, arrayIndex) < 0) { + continue; + } + uint64_t serial = tracePacket.info(i).id(); + DataIndex eventSourceIndex = traceDataCache_->GetDataIndex(jData.eventSource); + jData.timestamp *= MSEC_TO_NS; + auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, jData.timestamp); + UpdatePluginTimeRange(TS_CLOCK_BOOTTIME, jData.timestamp, newTimeStamp); + jData.timestamp = newTimeStamp; + if (maxArraySize) { + NoArrayDataParse(jData, noArrayIndex, eventSourceIndex, serial); + ArrayDataParse(jData, arrayIndex, eventSourceIndex, maxArraySize, serial); + } else { + CommonDataParser(jData, eventSourceIndex, serial); + } + } +} +void HtraceHisyseventParser::Parse(HisyseventConfig& tracePacket, uint64_t ts) +{ + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue("message", tracePacket.msg()); + streamFilters_->hiSysEventMeasureFilter_->AppendNewValue("process_name", tracePacket.process_name()); + return; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_hisysevent_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_hisysevent_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..d2588e3719bea2e2d4dcaca987298372d004bd13 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_hisysevent_parser.h @@ -0,0 +1,106 @@ + +/* + * 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. + */ + +#ifndef HTRACE_HISYSEVENT_PARSER_H +#define HTRACE_HISYSEVENT_PARSER_H + +#include "clock_filter.h" +#include "hisysevent_plugin_config.pb.h" +#include "hisysevent_plugin_result.pb.h" +#include "htrace_plugin_time_parser.h" +#include "json.hpp" +#include "trace_data/trace_data_cache.h" +#include "trace_streamer_filters.h" +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +class HtraceHisyseventParser : public HtracePluginTimeParser { +public: + HtraceHisyseventParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceHisyseventParser(); + void Finish(); + void Parse(HisyseventInfo& tracePacket, uint64_t ts); + void Parse(HisyseventConfig& tracePacket, uint64_t ts); + +private: + using json = nlohmann::json; + typedef struct { + std::string eventSource; + uint64_t timestamp; + std::vector appName; + std::vector appVersions; + std::vector key; + std::vector value; + } JsonData; + +private: + void + NoArrayDataParse(JsonData jData, std::vector noArrayIndex, DataIndex eventSourceIndex, uint64_t serial); + void ArrayDataParse(JsonData jData, + std::vector arrayIndex, + DataIndex eventSourceIndex, + size_t maxArraySize, + uint64_t serial); + void CommonDataParser(JsonData jData, DataIndex eventSourceIndex, uint64_t serial); + int32_t JGetData(json& jMessage, + JsonData& jData, + size_t& maxArraySize, + std::vector& noArrayIndex, + std::vector& arrayIndex); + + std::vector eventsAccordingAppNames = {"POWER_IDE_BATTERY", + "POWER_IDE_CPU", + "POWER_IDE_LOCATION", + "POWER_IDE_GPU", + "POWER_IDE_DISPLAY", + "POWER_IDE_CAMERA", + "POWER_IDE_BLUETOOTH", + "POWER_IDE_FLASHLIGHT", + "POWER_IDE_AUDIO", + "POWER_IDE_WIFISCAN", + "BRIGHTNESS_NIT", + "SIGNAL_LEVEL", + "WIFI_EVENT_RECEIVED", + "AUDIO_STREAM_CHANGE", + "AUDIO_VOLUME_CHANGE", + "WIFI_STATE", + "BLUETOOTH_BR_SWITCH_STATE", + "LOCATION_SWITCH_STATE", + "ENABLE_SENSOR", + "DISABLE_SENSOR", + "WORK_REMOVE", + "WORK_START", + "WORK_STOP", + "WORK_ADD", + "POWER_RUNNINGLOCK", + "GNSS_STATE", + "ANOMALY_SCREEN_OFF_ENERGY", + "ANOMALY_ALARM_WAKEUP", + "ANOMALY_KERNEL_WAKELOCK", + "ANOMALY_RUNNINGLOCK", + "ANORMALY_APP_ENERGY", + "ANOMALY_GNSS_ENERGY", + "ANOMALY_CPU_HIGH_FREQUENCY", + "ANOMALY_CPU_ENERGY", + "ANOMALY_WAKEUP"}; + const uint64_t MSEC_TO_NS = 1000 * 1000; + std::vector hisyseventTS_; + bool isDeviceState = true; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // HTRACE_HISYSEVENT_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.cpp old mode 100644 new mode 100755 index 55ebfb07c295a260997cbbb4f6edecd1c3cd0cdb..686a03965cbe7b5cb109d47e7070f3c96d6ee64c --- a/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.cpp +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.cpp @@ -23,22 +23,14 @@ namespace SysTuning { namespace TraceStreamer { HtraceMemParser::HtraceMemParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) - : streamFilters_(ctx), traceDataCache_(dataCache) + : HtracePluginTimeParser(dataCache, ctx) { - if (!traceDataCache_) { - TS_LOGE("traceDataCache_ should not be null"); - return; - } - if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); - return; - } for (auto i = 0; i < MEM_MAX; i++) { memNameDictMap_.insert( std::make_pair(static_cast(i), traceDataCache_->GetDataIndex(config_.memNameMap_.at(static_cast(i))))); } - for (auto i = 0; i < SysMeminfoType::PMEM_CMA_FREE + 1; i++) { + for (auto i = 0; i < SysMeminfoType::PMEM_KERNEL_RECLAIMABLE + 1; i++) { sysMemNameDictMap_.insert( std::make_pair(static_cast(i), traceDataCache_->GetDataIndex(config_.sysMemNameMap_.at(static_cast(i))))); @@ -52,24 +44,14 @@ HtraceMemParser::HtraceMemParser(TraceDataCache* dataCache, const TraceStreamerF HtraceMemParser::~HtraceMemParser() { - TS_LOGI("mem ts MIN:%llu, MAX:%llu", static_cast(traceStartTime_), - static_cast(traceEndTime_)); + TS_LOGI("mem ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); } void HtraceMemParser::Parse(const MemoryData& tracePacket, uint64_t timeStamp, BuiltinClocks clock) { - if (!traceDataCache_) { - TS_LOGE("traceDataCache_ should not be null"); - return; - } - if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); - return; - } auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(clock, timeStamp); - if (newTimeStamp != timeStamp) { // record the time only when the time is valid - traceStartTime_ = std::min(traceStartTime_, newTimeStamp); - traceEndTime_ = std::max(traceEndTime_, newTimeStamp); - } + UpdatePluginTimeRange(clock, timeStamp, newTimeStamp); + zram_ = tracePacket.zram(); if (tracePacket.processesinfo_size()) { ParseProcessInfo(tracePacket, newTimeStamp); } @@ -88,24 +70,50 @@ void HtraceMemParser::ParseProcessInfo(const MemoryData& tracePacket, uint64_t t for (int i = 0; i < tracePacket.processesinfo_size(); i++) { auto memInfo = tracePacket.processesinfo(i); auto ipid = streamFilters_->processFilter_->UpdateOrCreateProcessWithName(memInfo.pid(), memInfo.name()); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_SIZE), timeStamp, - memInfo.vm_size_kb()); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_RSS), timeStamp, - memInfo.vm_rss_kb()); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_ANON), timeStamp, - memInfo.rss_anon_kb()); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_RSS_FILE), timeStamp, - memInfo.rss_file_kb()); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_RSS_SHMEM), timeStamp, - memInfo.rss_shmem_kb()); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_SWAP), timeStamp, - memInfo.vm_swap_kb()); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_LOCKED), timeStamp, - memInfo.vm_locked_kb()); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_HWM), timeStamp, - memInfo.vm_hwm_kb()); - streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_OOM_SCORE_ADJ), - timeStamp, memInfo.oom_score_adj()); + uint32_t hasValue = 0; + hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_SIZE), + timeStamp, memInfo.vm_size_kb()); + hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_RSS), + timeStamp, memInfo.vm_rss_kb()); + hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_ANON), + timeStamp, memInfo.rss_anon_kb()); + hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_RSS_FILE), + timeStamp, memInfo.rss_file_kb()); + hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_RSS_SHMEM), + timeStamp, memInfo.rss_shmem_kb()); + hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_SWAP), + timeStamp, memInfo.vm_swap_kb()); + hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_LOCKED), + timeStamp, memInfo.vm_locked_kb()); + hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData(ipid, memNameDictMap_.at(MEM_VM_HWM), + timeStamp, memInfo.vm_hwm_kb()); + hasValue += streamFilters_->processMeasureFilter_->AppendNewMeasureData( + ipid, memNameDictMap_.at(MEM_OOM_SCORE_ADJ), timeStamp, memInfo.oom_score_adj()); + if (hasValue) { + streamFilters_->processFilter_->AddProcessMemory(ipid); + } + if (memInfo.smapinfo_size()) { + ParseSmapsInfoEasy(memInfo, timeStamp); + } + } +} + +void HtraceMemParser::ParseSmapsInfoEasy(const ProcessMemoryInfo& memInfo, uint64_t timeStamp) const +{ + streamFilters_->statFilter_->IncreaseStat(TRACE_SMAPS, STAT_EVENT_RECEIVED); + for (auto itor = memInfo.smapinfo().begin(); itor != memInfo.smapinfo().end(); itor++) { + auto startAddr = "0x" + itor->start_addr(); + auto endAddr = "0x" + itor->end_addr(); + uint64_t dirty = itor->dirty(); + uint64_t swapper = itor->swapper(); + uint64_t rss = itor->rss(); + uint64_t pss = itor->pss(); + uint64_t size = itor->size(); + double reside = itor->reside(); + DataIndex protection = traceDataCache_->GetDataIndex(itor->permission()); + DataIndex path = traceDataCache_->GetDataIndex(itor->path()); + traceDataCache_->GetSmapsData()->AppendNewData(timeStamp, startAddr, endAddr, dirty, swapper, rss, pss, size, + reside, protection, path); } } @@ -284,6 +292,10 @@ void HtraceMemParser::ParseMemInfo(const MemoryData& tracePacket, uint64_t timeS streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( sysMemNameDictMap_.at(SysMeminfoType::PMEM_CMA_FREE), timeStamp, vMemInfo.value()); break; + case SysMeminfoType::PMEM_KERNEL_RECLAIMABLE: + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData( + sysMemNameDictMap_.at(SysMeminfoType::PMEM_KERNEL_RECLAIMABLE), timeStamp, vMemInfo.value()); + break; case SysMeminfoType_INT_MIN_SENTINEL_DO_NOT_USE_: case SysMeminfoType_INT_MAX_SENTINEL_DO_NOT_USE_: default: @@ -291,6 +303,7 @@ void HtraceMemParser::ParseMemInfo(const MemoryData& tracePacket, uint64_t timeS break; } } + streamFilters_->sysEventMemMeasureFilter_->AppendNewMeasureData(zramIndex_, timeStamp, zram_); } void HtraceMemParser::ParseVMemInfo(const MemoryData& tracePacket, uint64_t timeStamp) const { @@ -857,7 +870,11 @@ void HtraceMemParser::ParseVMemInfo(const MemoryData& tracePacket, uint64_t time } void HtraceMemParser::Finish() { - traceDataCache_->MixTraceTime(traceStartTime_, traceEndTime_); + if (traceDataCache_->traceStartTime_ == INVALID_UINT64 || traceDataCache_->traceEndTime_ == 0) { + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); + } else { + TS_LOGI("mem data time is not updated, maybe this trace file has other data"); + } } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.h old mode 100644 new mode 100755 index a5d762beb043935bc3d4fc3792c2556452721e73..c71acc01c75c834ca391b1f915b7f3351399e1e1 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.h +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_mem_parser.h @@ -20,13 +20,14 @@ #include #include #include +#include "htrace_plugin_time_parser.h" #include "memory_plugin_result.pb.h" #include "trace_data/trace_data_cache.h" #include "trace_streamer_config.h" #include "trace_streamer_filters.h" namespace SysTuning { namespace TraceStreamer { -class HtraceMemParser { +class HtraceMemParser : public HtracePluginTimeParser { public: HtraceMemParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); ~HtraceMemParser(); @@ -38,14 +39,13 @@ private: void ParseMemInfoEasy(const MemoryData& tracePacket, uint64_t timeStamp) const; void ParseVMemInfo(const MemoryData& tracePacket, uint64_t timeStamp) const; void ParseVMemInfoEasy(const MemoryData& tracePacket, uint64_t timeStamp) const; - const TraceStreamerFilters* streamFilters_; - TraceDataCache* traceDataCache_; - TraceStreamerConfig config_ = {}; + void ParseSmapsInfoEasy(const ProcessMemoryInfo& memInfo, uint64_t timeStamp) const; std::map memNameDictMap_ = {}; std::map sysMemNameDictMap_ = {}; std::map sysVMemNameDictMap_ = {}; - uint64_t traceStartTime_ = std::numeric_limits::max(); - uint64_t traceEndTime_ = 0; + uint64_t zram_ = 0; + const DataIndex zramIndex_ = traceDataCache_->GetDataIndex("sys.mem.zram"); + TraceStreamerConfig config_{}; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.cpp old mode 100644 new mode 100755 index ef8098758805b9505c8acd908f73d10b3927b061..13377e893ec1e9a392d7b25e9d7dfcaa9bf533c7 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.cpp +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.cpp @@ -12,121 +12,421 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "htrace_native_hook_parser.h" #include "clock_filter.h" -#include "htrace_event_parser.h" -#include "native_hook_result.pb.h" #include "process_filter.h" #include "stat_filter.h" -#include "htrace_native_hook_parser.h" namespace SysTuning { namespace TraceStreamer { -uint64_t HtraceNativeHookParser::eventId_ = 0; HtraceNativeHookParser::HtraceNativeHookParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) - : streamFilters_(ctx), traceDataCache_(dataCache), addrToAllocEventRow_(INVALID_UINT64) + : HtracePluginTimeParser(dataCache, ctx), + addrToAllocEventRow_(INVALID_UINT64), + addrToMmapEventRow_(INVALID_UINT64), + frameToFrameId_(INVALID_UINT64) { - if (!traceDataCache_) { - TS_LOGE("traceDataCache_ should not be null"); - return; + invalidLibPathIndexs_.insert(traceDataCache_->dataDict_.GetStringIndex("/system/lib/libc++.so")); + 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")); +} + +HtraceNativeHookParser::~HtraceNativeHookParser() +{ + TS_LOGI("native hook data ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); + TS_LOGI("native real ts MIN:%llu, MAX:%llu", static_cast(MinTs()), + static_cast(MaxTs())); +} +// In order to improve the accuracy of data, it is necessary to sort the original data. +// Data sorting will be reduced by 5% to 10% Speed of parsing data. +void HtraceNativeHookParser::SortNativeHookData(BatchNativeHookData& tracePacket) +{ + for (auto i = 0; i < tracePacket.events_size(); i++) { + auto nativeHookData = std::make_unique(*tracePacket.mutable_events(i)); + auto timeStamp = nativeHookData->tv_nsec() + nativeHookData->tv_sec() * SEC_TO_NS; + tsNativeHookQueue_.insert(std::make_pair(timeStamp, std::move(nativeHookData))); + MaybeParseNativeHookData(); } - if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); + return; +} +template +void HtraceNativeHookParser::UpdateMap(std::unordered_map& sourceMap, T1 key, T2 value) +{ + auto itor = sourceMap.find(key); + if (itor != sourceMap.end()) { + itor->second = value; + } else { + sourceMap.insert(std::make_pair(key, value)); + } +} +void HtraceNativeHookParser::MaybeParseNativeHookData() +{ + if (tsNativeHookQueue_.size() > MAX_CACHE_SIZE) { + ParseNativeHookData(tsNativeHookQueue_.begin()->first, tsNativeHookQueue_.begin()->second.get()); + tsNativeHookQueue_.erase(tsNativeHookQueue_.begin()); + } +} +void HtraceNativeHookParser::FinishParseNativeHookData() +{ + for (auto it = tsNativeHookQueue_.begin(); it != tsNativeHookQueue_.end(); it++) { + ParseNativeHookData(it->first, it->second.get()); + } + if (traceDataCache_->GetNativeHookData()->Size() == 0) { return; } + traceDataCache_->GetNativeHookData()->UpdateMemMapSubType(); + // update function name index + traceDataCache_->GetNativeHookFrameData()->UpdateSymbolId(); + // update file path index + traceDataCache_->GetNativeHookFrameData()->UpdateFileId(filePathIdToFilePathName_); + // update instractions vaddr + GetNativeHookFrameVaddrs(); + traceDataCache_->GetNativeHookFrameData()->UpdateVaddrs(vaddrs_); + // update last lib id + GetCallIdToLastLibId(); + if (callIdToLastCallerPathIndex_.size()) { + traceDataCache_->GetNativeHookData()->UpdateLastCallerPathIndexs(callIdToLastCallerPathIndex_); + } + + UpdateThreadNameWithNativeHookData(); + tsNativeHookQueue_.clear(); + threadNameIdToThreadName_.clear(); + itidToThreadNameId_.clear(); + callIdToLastCallerPathIndex_.clear(); + functionNameIndexToVaddr_.clear(); + vaddrs_.clear(); } +void HtraceNativeHookParser::GetCallIdToLastLibId() +{ + auto size = static_cast(traceDataCache_->GetNativeHookFrameData()->Size()); + uint32_t lastCallChainId = INVALID_UINT32; + bool foundLast = false; + for (auto i = size - 1; i > -1; i--) { + auto callChainId = traceDataCache_->GetNativeHookFrameData()->CallChainIds()[i]; + if (callChainId == lastCallChainId) { + if (foundLast) { + continue; + } + } + if (callChainId != lastCallChainId) { + lastCallChainId = callChainId; + foundLast = false; + } + auto filePathIndex = traceDataCache_->GetNativeHookFrameData()->FilePaths()[i]; + if (!traceDataCache_->GetNativeHookFrameData()->Depths()[i]) { + callIdToLastCallerPathIndex_.insert(std::make_pair(callChainId, filePathIndex)); + foundLast = true; + continue; + } -HtraceNativeHookParser::~HtraceNativeHookParser() + auto lower = std::lower_bound(invalidLibPathIndexs_.begin(), invalidLibPathIndexs_.end(), filePathIndex); + if (lower == invalidLibPathIndexs_.end() || *lower != filePathIndex) { // found + auto filePath = traceDataCache_->dataDict_.GetDataFromDict(filePathIndex); + auto ret = filePath.find("libc++_shared.so"); + if (ret == filePath.npos) { + callIdToLastCallerPathIndex_.insert(std::make_pair(callChainId, filePathIndex)); + foundLast = true; + } + } + } +} + +void HtraceNativeHookParser::GetNativeHookFrameVaddrs() { - TS_LOGI("native hook data ts MIN:%llu, MAX:%llu", - static_cast(traceStartTime_), static_cast(traceEndTime_)); + auto size = traceDataCache_->GetNativeHookFrameData()->Size(); + // Traverse every piece of native_hook frame data + for (auto i = 0; i < size; i++) { + auto symbolOffset = traceDataCache_->GetNativeHookFrameData()->SymbolOffsets()[i]; + // When the symbol offset is not 0, vaddr=offset+symbol offset + if (symbolOffset) { + auto fileOffset = traceDataCache_->GetNativeHookFrameData()->Offsets()[i]; + auto vaddr = base::Uint64ToHexText(fileOffset + symbolOffset); + vaddrs_.emplace_back(vaddr); + continue; + } + // When the symbol offset is 0, vaddr takes the string after the plus sign in the function name + auto functionNameIndex = traceDataCache_->GetNativeHookFrameData()->SymbolNames()[i]; + std::string vaddr = ""; + auto itor = functionNameIndexToVaddr_.find(functionNameIndex); + if (itor == functionNameIndexToVaddr_.end()) { + auto functionName = traceDataCache_->dataDict_.GetDataFromDict(functionNameIndex); + auto pos = functionName.rfind("+"); + if (pos != functionName.npos && pos != functionName.length() - 1) { + vaddr = functionName.substr(++pos); + } + // Vaddr keeps "" when lookup failed + functionNameIndexToVaddr_.emplace(std::make_pair(functionNameIndex, vaddr)); + } else { + vaddr = itor->second; + } + vaddrs_.emplace_back(vaddr); + } } -void HtraceNativeHookParser::Parse(BatchNativeHookData& tracePacket) +void HtraceNativeHookParser::ParseAllocEvent(uint64_t newTimeStamp, const NativeHookData* nativeHookData) { - if (!tracePacket.events_size()) { - return; + auto allocEvent = nativeHookData->alloc_event(); + auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(allocEvent.tid(), allocEvent.pid()); + auto ipid = streamFilters_->processFilter_->GetInternalPid(allocEvent.pid()); + if (allocEvent.thread_name_id() != 0) { + UpdateMap(itidToThreadNameId_, itid, allocEvent.thread_name_id()); } - if (!traceDataCache_) { - TS_LOGE("traceDataCache_ should not be null"); + auto callChainId = ParseNativeHookFrame(allocEvent.frame_info()); + auto row = traceDataCache_->GetNativeHookData()->AppendNewNativeHookData( + callChainId, ipid, itid, allocEvent.GetTypeName(), INVALID_UINT64, newTimeStamp, 0, 0, allocEvent.addr(), + allocEvent.size(), allocEvent.size()); + addrToAllocEventRow_.Insert(ipid, allocEvent.addr(), static_cast(row)); + MaybeUpdateCurrentSizeDur(row, newTimeStamp, true); +} +void HtraceNativeHookParser::ParseFreeEvent(uint64_t newTimeStamp, const NativeHookData* nativeHookData) +{ + auto freeEvent = nativeHookData->free_event(); + auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(freeEvent.tid(), freeEvent.pid()); + auto ipid = streamFilters_->processFilter_->GetInternalPid(freeEvent.pid()); + if (freeEvent.thread_name_id() != 0) { + UpdateMap(itidToThreadNameId_, itid, freeEvent.thread_name_id()); + } + int64_t freeHeapSize = 0; + auto row = addrToAllocEventRow_.Find(ipid, freeEvent.addr()); + if (row != INVALID_UINT64 && newTimeStamp > traceDataCache_->GetNativeHookData()->TimeStamData()[row]) { + addrToAllocEventRow_.Erase(ipid, freeEvent.addr()); + traceDataCache_->GetNativeHookData()->UpdateHeapDuration(row, newTimeStamp); + freeHeapSize = traceDataCache_->GetNativeHookData()->MemSizes()[row]; + } else if (row == INVALID_UINT64) { + TS_LOGW("func addr:%lu is empty", freeEvent.addr()); + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_DATA_INVALID); return; } - if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); + auto callChainId = ParseNativeHookFrame(freeEvent.frame_info()); + row = traceDataCache_->GetNativeHookData()->AppendNewNativeHookData( + callChainId, ipid, itid, freeEvent.GetTypeName(), INVALID_UINT64, newTimeStamp, 0, 0, freeEvent.addr(), + freeHeapSize, (-1) * freeHeapSize); + if (freeHeapSize != 0) { + MaybeUpdateCurrentSizeDur(row, newTimeStamp, true); + } +} +void HtraceNativeHookParser::ParseMmapEvent(uint64_t newTimeStamp, const NativeHookData* nativeHookData) +{ + auto mMapEvent = nativeHookData->mmap_event(); + auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(mMapEvent.tid(), mMapEvent.pid()); + auto ipid = streamFilters_->processFilter_->GetInternalPid(mMapEvent.pid()); + if (mMapEvent.thread_name_id() != 0) { + UpdateMap(itidToThreadNameId_, itid, mMapEvent.thread_name_id()); + } + DataIndex subType = INVALID_UINT64; + if (!mMapEvent.type().empty()) { + subType = traceDataCache_->dataDict_.GetStringIndex(mMapEvent.type()); + traceDataCache_->GetNativeHookData()->UpdateAddrToMemMapSubType(mMapEvent.addr(), mMapEvent.size(), subType); + } + auto callChainId = ParseNativeHookFrame(mMapEvent.frame_info()); + auto row = traceDataCache_->GetNativeHookData()->AppendNewNativeHookData( + callChainId, ipid, itid, mMapEvent.GetTypeName(), subType, newTimeStamp, 0, 0, mMapEvent.addr(), + mMapEvent.size(), mMapEvent.size()); + addrToMmapEventRow_.Insert(ipid, mMapEvent.addr(), static_cast(row)); + MaybeUpdateCurrentSizeDur(row, newTimeStamp, false); +} +void HtraceNativeHookParser::ParseMunmapEvent(uint64_t newTimeStamp, const NativeHookData* nativeHookData) +{ + auto mUnMapEvent = nativeHookData->munmap_event(); + auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(mUnMapEvent.tid(), mUnMapEvent.pid()); + auto ipid = streamFilters_->processFilter_->GetInternalPid(mUnMapEvent.pid()); + if (mUnMapEvent.thread_name_id() != 0) { + UpdateMap(itidToThreadNameId_, itid, mUnMapEvent.thread_name_id()); + } + auto row = addrToMmapEventRow_.Find(ipid, mUnMapEvent.addr()); + int64_t effectiveMUnMapSize = 0; + if (row != INVALID_UINT64 && newTimeStamp > traceDataCache_->GetNativeHookData()->TimeStamData()[row]) { + addrToMmapEventRow_.Erase(ipid, mUnMapEvent.addr()); + traceDataCache_->GetNativeHookData()->UpdateHeapDuration(row, newTimeStamp); + effectiveMUnMapSize = static_cast(mUnMapEvent.size()); + } else if (row == INVALID_UINT64) { + TS_LOGW("func addr:%lu is empty", mUnMapEvent.addr()); + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_DATA_INVALID); return; } - for (auto i = 0; i < tracePacket.events_size(); i++) { - auto nativeHookData = tracePacket.mutable_events(i); - auto timeStamp = nativeHookData->tv_nsec() + nativeHookData->tv_sec() * SEC_TO_NS; - auto newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, timeStamp); - if (newTimeStamp != timeStamp) { // record the time only when the time is valid - traceStartTime_ = std::min(traceStartTime_, newTimeStamp); - traceEndTime_ = std::max(traceEndTime_, newTimeStamp); + auto callChainId = ParseNativeHookFrame(mUnMapEvent.frame_info()); + row = traceDataCache_->GetNativeHookData()->AppendNewNativeHookData( + callChainId, ipid, itid, mUnMapEvent.GetTypeName(), INVALID_UINT64, newTimeStamp, 0, 0, mUnMapEvent.addr(), + mUnMapEvent.size(), (-1) * effectiveMUnMapSize); + if (effectiveMUnMapSize != 0) { + MaybeUpdateCurrentSizeDur(row, newTimeStamp, false); + } +} +void HtraceNativeHookParser::ParseTagEvent(const NativeHookData* nativeHookData) +{ + auto memMapTagEvent = nativeHookData->tag_event(); + auto addr = memMapTagEvent.addr(); + auto size = memMapTagEvent.size(); + auto tagIndex = traceDataCache_->dataDict_.GetStringIndex(memMapTagEvent.tag()); + traceDataCache_->GetNativeHookData()->UpdateAddrToMemMapSubType(addr, static_cast(size), tagIndex); +} +void HtraceNativeHookParser::ParseFileEvent(const NativeHookData* nativeHookData) +{ + auto filePathMapMessage = nativeHookData->file_path(); + auto id = filePathMapMessage.id(); + auto nameIndex = traceDataCache_->dataDict_.GetStringIndex(filePathMapMessage.name()); + filePathIdToFilePathName_.insert(std::make_pair(id, nameIndex)); +} +void HtraceNativeHookParser::ParseSymbolEvent(const NativeHookData* nativeHookData) +{ + auto symbolMapMessage = nativeHookData->symbol_name(); + auto id = symbolMapMessage.id(); + auto nameIndex = traceDataCache_->dataDict_.GetStringIndex(symbolMapMessage.name()); + traceDataCache_->GetNativeHookFrameData()->UpdateSymbolIdToNameMap(id, nameIndex); +} +void HtraceNativeHookParser::ParseThreadEvent(const NativeHookData* nativeHookData) +{ + auto threadNameMapMessage = nativeHookData->thread_name_map(); + auto id = threadNameMapMessage.id(); + auto nameIndex = traceDataCache_->dataDict_.GetStringIndex(threadNameMapMessage.name()); + UpdateMap(threadNameIdToThreadName_, id, nameIndex); +} + +void HtraceNativeHookParser::ParseNativeHookData(const uint64_t timeStamp, const NativeHookData* nativeHookData) +{ + auto eventCase = nativeHookData->event_case(); + if (eventCase >= NativeHookData::kAllocEvent && eventCase <= NativeHookData::kMunmapEvent) { + uint64_t newTimeStamp = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, timeStamp); + UpdatePluginTimeRange(TS_CLOCK_REALTIME, timeStamp, newTimeStamp); + switch (eventCase) { + case NativeHookData::kAllocEvent: + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED); + if (newTimeStamp == timeStamp) { + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_DATA_INVALID); + } + ParseAllocEvent(newTimeStamp, nativeHookData); + break; + case NativeHookData::kFreeEvent: + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); + if (newTimeStamp == timeStamp) { + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_DATA_INVALID); + } + ParseFreeEvent(newTimeStamp, nativeHookData); + break; + case NativeHookData::kMmapEvent: + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED); + if (newTimeStamp == timeStamp) { + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_DATA_INVALID); + } + ParseMmapEvent(newTimeStamp, nativeHookData); + break; + case NativeHookData::kMunmapEvent: + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED); + if (newTimeStamp == timeStamp) { + streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_DATA_INVALID); + } + ParseMunmapEvent(newTimeStamp, nativeHookData); + break; + default: + TS_LOGE("An unknown type of data was received!"); + break; } - // kAllocEvent = 3 kFreeEvent = 4 EVENT_NOT_SET = 0 - auto eventCase = nativeHookData->event_case(); - if (eventCase == NativeHookData::kAllocEvent) { - streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED); - if (newTimeStamp == timeStamp) { - streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_DATA_INVALID); - } - auto allocEvent = nativeHookData->alloc_event(); - DataIndex allocIndex = traceDataCache_->dataDict_.GetStringIndex("AllocEvent"); - auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(allocEvent.tid(), allocEvent.pid()); - auto ipid = streamFilters_->processFilter_->GetInternalPid(allocEvent.pid()); - auto row = traceDataCache_->GetHeapData()->AppendNewHeapInfo(eventId_, ipid, itid, allocIndex, newTimeStamp, - 0, 0, allocEvent.addr(), allocEvent.size(), - allocEvent.size(), 0); - addrToAllocEventRow_.Insert(ipid, allocEvent.addr(), static_cast(row)); - traceDataCache_->GetHeapData()->UpdateCurrentSizeDur(row, newTimeStamp); - for (auto depth = 0; depth < allocEvent.frame_info_size(); depth++) { - auto allocEventFrame = allocEvent.frame_info(depth); - DataIndex symbolNameIndex = - traceDataCache_->dataDict_.GetStringIndex(allocEventFrame.symbol_name().c_str()); - DataIndex filePathIndex = - traceDataCache_->dataDict_.GetStringIndex(allocEventFrame.file_path().c_str()); - traceDataCache_->GetHeapFrameData()->AppendNewHeapFrameInfo( - eventId_, depth, allocEventFrame.ip(), allocEventFrame.sp(), symbolNameIndex, filePathIndex, - allocEventFrame.offset(), allocEventFrame.symbol_offset()); - } - eventId_++; - } else if (eventCase == NativeHookData::kFreeEvent) { - streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); - if (newTimeStamp == timeStamp) { - streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_DATA_INVALID); - } - auto freeEvent = nativeHookData->free_event(); - DataIndex freeIndex = traceDataCache_->dataDict_.GetStringIndex("FreeEvent"); - auto itid = streamFilters_->processFilter_->GetOrCreateThreadWithPid(freeEvent.tid(), freeEvent.pid()); - auto ipid = streamFilters_->processFilter_->GetInternalPid(freeEvent.pid()); - int64_t freeHeapSize = 0; - auto row = addrToAllocEventRow_.Find(ipid, freeEvent.addr()); - if (row != INVALID_UINT64 && newTimeStamp > traceDataCache_->GetHeapData()->TimeStamData()[row]) { - addrToAllocEventRow_.Erase(ipid, freeEvent.addr()); - traceDataCache_->GetHeapData()->UpdateHeapDuration(row, newTimeStamp); - freeHeapSize = traceDataCache_->GetHeapData()->HeapSizes()[row]; - } else if (row == INVALID_UINT64) { - TS_LOGW("func addr:%lu is empty", freeEvent.addr()); - streamFilters_->statFilter_->IncreaseStat(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_DATA_INVALID); + } else { + switch (eventCase) { + case NativeHookData::kTagEvent: + ParseTagEvent(nativeHookData); + break; + case NativeHookData::kFilePath: + ParseFileEvent(nativeHookData); + break; + case NativeHookData::kSymbolName: + ParseSymbolEvent(nativeHookData); + break; + case NativeHookData::kThreadNameMap: + ParseThreadEvent(nativeHookData); + break; + default: + TS_LOGE("An unknown type of data was received!"); + break; + } + } +} +void HtraceNativeHookParser::MaybeUpdateCurrentSizeDur(uint64_t row, uint64_t timeStamp, bool isMalloc) +{ + auto& lastAnyEventRaw = isMalloc ? lastMallocEventRaw_ : lastMmapEventRaw_; + if (lastAnyEventRaw != INVALID_UINT64) { + traceDataCache_->GetNativeHookData()->UpdateCurrentSizeDur(lastAnyEventRaw, timeStamp); + } + lastAnyEventRaw = row; +} +uint64_t HtraceNativeHookParser::ParseNativeHookFrame(const RepeatedPtrField<::Frame>& repeatedFrame) +{ + // the callstack from nativehook of sourcedata is reverse order + // we need to show the last frame firstly + std::vector> callStackTemp = {}; + auto depth = 0; + for (auto i = repeatedFrame.size() - 1; i >= 0; i--) { + auto frame = repeatedFrame.Get(i); + DataIndex symbolNameIndex = INVALID_UINT64; + DataIndex filePathIndex = INVALID_UINT64; + if (!frame.symbol_name().empty()) { + symbolNameIndex = traceDataCache_->dataDict_.GetStringIndex(frame.symbol_name().c_str()); + traceDataCache_->GetNativeHookFrameData()->UpdateSymbolIdToNameMap(symbolNameIndex, symbolNameIndex); + } else if (frame.symbol_name_id()) { + symbolNameIndex = frame.symbol_name_id(); + } + if (!frame.file_path().empty()) { + filePathIndex = traceDataCache_->dataDict_.GetStringIndex(frame.file_path().c_str()); + filePathIdToFilePathName_.insert(std::make_pair(filePathIndex, filePathIndex)); + } else if (frame.file_path_id()) { + filePathIndex = frame.file_path_id(); + } + callStackTemp.emplace_back(std::move(std::make_unique( + filePathIndex, symbolNameIndex, depth, frame.offset(), frame.symbol_offset()))); + depth++; + } + + // Determine whether to write callstack data to cache + auto callChainId = INVALID_UINT64; + bool callStackNotExist = false; + auto size = callStackTemp.size(); + for (auto itor = callStackTemp.begin(); itor != callStackTemp.end(); itor++) { + auto callstack = itor->get(); + auto ret = frameToFrameId_.Find(callstack->fileId_, callstack->symbolId_, callstack->depth_, size); + if (ret != INVALID_UINT64) { // find it + if (callChainId == INVALID_UINT64) { + callChainId = ret; + } else if (callChainId != ret) { + callStackNotExist = true; + break; } - row = traceDataCache_->GetHeapData()->AppendNewHeapInfo(eventId_, ipid, itid, freeIndex, newTimeStamp, 0, 0, - freeEvent.addr(), freeHeapSize, -freeHeapSize, 0); - traceDataCache_->GetHeapData()->UpdateCurrentSizeDur(row, newTimeStamp); - for (auto depth = 0; depth < freeEvent.frame_info_size(); depth++) { - auto freeEventFrame = freeEvent.frame_info(depth); - DataIndex symbolNameIndex = - traceDataCache_->dataDict_.GetStringIndex(freeEventFrame.symbol_name().c_str()); - DataIndex filePathIndex = traceDataCache_->dataDict_.GetStringIndex(freeEventFrame.file_path().c_str()); - traceDataCache_->GetHeapFrameData()->AppendNewHeapFrameInfo( - eventId_, depth, freeEventFrame.ip(), freeEventFrame.sp(), symbolNameIndex, filePathIndex, - freeEventFrame.offset(), freeEventFrame.symbol_offset()); + } else { // not find it + callStackNotExist = true; + break; + } + } + // write callstack data to cache + if (callStackNotExist) { + callChainId = ++callChainId_; + for (auto itor = callStackTemp.begin(); itor != callStackTemp.end(); itor++) { + auto callstack = itor->get(); + frameToFrameId_.Insert(callstack->fileId_, callstack->symbolId_, callstack->depth_, callStackTemp.size(), + callChainId); + traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame( + callChainId, callstack->depth_, callstack->ip_, callstack->sp_, callstack->symbolId_, callstack->fileId_, callstack->offset_, + callstack->symbolOffset_); + } + } + callStackTemp.clear(); + return callChainId; +} +void HtraceNativeHookParser::UpdateThreadNameWithNativeHookData() const +{ + if (itidToThreadNameId_.empty() || threadNameIdToThreadName_.empty()) { + return; + } + for (auto itor = itidToThreadNameId_.begin(); itor != itidToThreadNameId_.end(); ++itor) { + auto thread = traceDataCache_->GetThreadData(itor->first); + if (thread->nameIndex_ == 0) { + auto threadNameMapItor = threadNameIdToThreadName_.find(itor->second); + if (threadNameMapItor != threadNameIdToThreadName_.end()) { + thread->nameIndex_ = threadNameMapItor->second; } - eventId_++; - } else { - TS_LOGE("An unknown type of data was received!"); } } } void HtraceNativeHookParser::Finish() { - traceDataCache_->MixTraceTime(traceStartTime_, traceEndTime_); + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.h index 6e1cfa949152e6e57fb9bdd3e4e2e5323e0edda7..fd8ae3972ff7bfe90196a66bd94e27aeb8542845 100644 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.h +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_native_hook_parser.h @@ -16,30 +16,76 @@ #define HTRACE_NATIVE_HOOK_PARSER_H #include #include +#include #include #include "double_map.h" -#include "trace_data/trace_data_cache.h" +#include "htrace_event_parser.h" +#include "htrace_plugin_time_parser.h" +#include "native_hook_result.pb.h" +#include "numerical_to_string.h" +#include "quatra_map.h" #include "trace_streamer_config.h" #include "trace_streamer_filters.h" - namespace SysTuning { namespace TraceStreamer { -class HtraceNativeHookParser { +class HtraceNativeHookParser : public HtracePluginTimeParser { public: HtraceNativeHookParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); ~HtraceNativeHookParser(); - void Parse(BatchNativeHookData& tracePacket); + void SortNativeHookData(BatchNativeHookData& tracePacket); + void FinishParseNativeHookData(); void Finish(); private: - const TraceStreamerFilters* streamFilters_; - TraceDataCache* traceDataCache_; - TraceStreamerConfig config_ = {}; - uint64_t traceStartTime_ = std::numeric_limits::max(); - uint64_t traceEndTime_ = 0; - static uint64_t eventId_; + class NativeHookFrameTemp { + public: + NativeHookFrameTemp() {} + NativeHookFrameTemp(uint64_t fileId, uint64_t symbolId, uint32_t depth, uint64_t offset, uint64_t symbolOffset) + : fileId_(fileId), symbolId_(symbolId), depth_(depth), offset_(offset), symbolOffset_(symbolOffset) + { + } + ~NativeHookFrameTemp() {} + uint64_t fileId_ = 0; + uint64_t symbolId_ = 0; + uint32_t depth_ = 0; + uint32_t ip_ = 0; + uint32_t sp_ = 0; + uint64_t offset_ = 0; + uint64_t symbolOffset_ = 0; + }; + template + void UpdateMap(std::unordered_map& sourceMap, T1 key, T2 value); + void MaybeParseNativeHookData(); + void ParseNativeHookData(const uint64_t timeStamp, const NativeHookData* nativeHookData); + uint64_t ParseNativeHookFrame(const RepeatedPtrField<::Frame>& repeatedFrame); + void MaybeUpdateCurrentSizeDur(uint64_t row, uint64_t timeStamp, bool isMalloc); + void UpdateThreadNameWithNativeHookData() const; + void ParseAllocEvent(uint64_t newTimeStamp, const NativeHookData* nativeHookData); + void ParseFreeEvent(uint64_t newTimeStamp, const NativeHookData* nativeHookData); + void ParseMmapEvent(uint64_t newTimeStamp, const NativeHookData* nativeHookData); + void ParseMunmapEvent(uint64_t newTimeStamp, const NativeHookData* nativeHookData); + void ParseTagEvent(const NativeHookData* nativeHookData); + void ParseFileEvent(const NativeHookData* nativeHookData); + void ParseSymbolEvent(const NativeHookData* nativeHookData); + void ParseThreadEvent(const NativeHookData* nativeHookData); + void GetCallIdToLastLibId(); + void GetNativeHookFrameVaddrs(); + uint64_t callChainId_ = 0; DoubleMap addrToAllocEventRow_; + DoubleMap addrToMmapEventRow_; + uint64_t lastMallocEventRaw_ = INVALID_UINT64; + uint64_t lastMmapEventRaw_ = INVALID_UINT64; + std::multimap> tsNativeHookQueue_ = {}; + std::unordered_map threadNameIdToThreadName_ = {}; + std::unordered_map itidToThreadNameId_ = {}; + QuatraMap frameToFrameId_; + std::set invalidLibPathIndexs_ = {}; + std::map filePathIdToFilePathName_ = {}; + std::map callIdToLastCallerPathIndex_ = {}; + std::map functionNameIndexToVaddr_ = {}; + std::deque vaddrs_ = {}; + const size_t MAX_CACHE_SIZE = 200000; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_network_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_network_parser.cpp new file mode 100755 index 0000000000000000000000000000000000000000..df663c417962231b5f992fe25e97218a417f6a8d --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_network_parser.cpp @@ -0,0 +1,80 @@ +/* + * 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. + */ +#include "htrace_network_parser.h" +#include "clock_filter.h" +#include "htrace_event_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceNetworkParser::HtraceNetworkParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : HtracePluginTimeParser(dataCache, ctx) +{ +} + +HtraceNetworkParser::~HtraceNetworkParser() +{ + TS_LOGI("network ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); +} + +void HtraceNetworkParser::Parse(NetworkDatas& tracePacket, uint64_t ts) +{ + auto netSysInfo = tracePacket.network_system_info(); + ts = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, ts); + streamFilters_->statFilter_->IncreaseStat(TRACE_NETWORK, STAT_EVENT_RECEIVED); + networkData_.push_back(std::move(TsNetworkData{ts, netSysInfo})); +} +void HtraceNetworkParser::Finish() +{ + auto cmp = [](const TsNetworkData& a, const TsNetworkData& b) { return a.ts < b.ts; }; + std::sort(networkData_.begin(), networkData_.end(), cmp); + bool firstTime = true; + uint64_t lastTs = 0; + uint64_t lastRx = 0; + uint64_t lastTx = 0; + uint64_t lastPacketIn = 0.0; + uint64_t lastPacketOut = 0.0; + for (auto itor = networkData_.begin(); itor != networkData_.end(); itor++) { + auto networkSysData = itor->networkSysData; + auto newTimeStamp = itor->ts; + UpdatePluginTimeRange(TS_CLOCK_REALTIME, itor->ts, newTimeStamp); + if (firstTime) { + lastTs = newTimeStamp; + lastRx = networkSysData.rx_bytes(); + lastTx = networkSysData.tx_bytes(); + lastPacketIn = networkSysData.rx_packets(); + lastPacketOut = networkSysData.tx_packets(); + firstTime = false; + continue; + } + auto dur = newTimeStamp - lastTs; + auto durS = 1.0 * dur / SEC_TO_NS; + traceDataCache_->GetNetworkData()->AppendNewNetData( + newTimeStamp, networkSysData.tx_bytes(), networkSysData.rx_bytes(), dur, + 1.0 * (networkSysData.rx_bytes() - lastRx) / durS, 1.0 * (networkSysData.tx_bytes() - lastTx) / durS, + networkSysData.rx_packets(), 1.0 * (networkSysData.rx_packets() - lastPacketIn) / durS, + networkSysData.tx_packets(), 1.0 * (networkSysData.tx_packets() - lastPacketOut) / durS, "undefined"); + lastTs = newTimeStamp; + lastRx = networkSysData.rx_bytes(); + lastTx = networkSysData.tx_bytes(); + lastPacketIn = networkSysData.rx_packets(); + lastPacketOut = networkSysData.tx_packets(); + } + networkData_.clear(); + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_network_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_network_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..b5c4ab57dbbc41861cdc8e9b7079343007a3ccb7 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_network_parser.h @@ -0,0 +1,51 @@ +/* + * 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. + */ +#ifndef HTRACE_NETWORK_PARSER_H +#define HTRACE_NETWORK_PARSER_H +#include +#include +#include +#include +#include "htrace_plugin_time_parser.h" +#include "network_plugin_result.pb.h" +#include "trace_streamer_config.h" +#include "trace_streamer_filters.h" +namespace SysTuning { +namespace TraceStreamer { +class HtraceNetworkParser : public HtracePluginTimeParser { +public: + HtraceNetworkParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceNetworkParser(); + void Parse(NetworkDatas& tracePacket, uint64_t ts); + void Finish(); + struct TsNetworkData { + uint64_t ts; + NetworkSystemData networkSysData; + }; + std::vector networkData_; +private: + uint64_t lastLineSeq_ = 0; + struct LastNetWorkDetail { + uint64_t rx; + uint64_t tx; + uint64_t ts; + }; + + std::unordered_map lastNetworkDetail_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_NETWORK_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_parser.cpp old mode 100644 new mode 100755 index 9893c5dac298224915acef962c754409b1f104f4..a6c308627ec92f481e3fe56a95caf9cf4b18ecf7 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_parser.cpp +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_parser.cpp @@ -22,12 +22,15 @@ #include "memory_plugin_result.pb.h" #include "services/common_types.pb.h" #include "stat_filter.h" -#include "trace_plugin_config.pb.h" #include "trace_plugin_result.pb.h" +#if IS_WASM +#include "../rpc/wasm_func.h" +#endif namespace SysTuning { namespace TraceStreamer { HtraceParser::HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters) : ParserBase(filters), + traceDataCache_(dataCache), htraceCpuDetailParser_(std::make_unique(dataCache, filters)), htraceSymbolsDetailParser_(std::make_unique(dataCache, filters)), htraceMemParser_(std::make_unique(dataCache, filters)), @@ -35,11 +38,22 @@ HtraceParser::HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters htraceHiLogParser_(std::make_unique(dataCache, filters)), htraceNativeHookParser_(std::make_unique(dataCache, filters)), htraceHidumpParser_(std::make_unique(dataCache, filters)), - dataSegArray(new HtraceDataSegment[MAX_SEG_ARRAY_SIZE]) -{ + cpuUsageParser_(std::make_unique(dataCache, filters)), + networkParser_(std::make_unique(dataCache, filters)), + diskIOParser_(std::make_unique(dataCache, filters)), + processParser_(std::make_unique(dataCache, filters)), + ebpfDataParser_(std::make_unique(dataCache, filters)), + hisyseventParser_(std::make_unique(dataCache, filters)), +#if WITH_PERF + perfDataParser_(std::make_unique(dataCache, filters)), +#endif #ifdef SUPPORTTHREAD - noThread_ = false; + supportThread_(true), + dataSegArray_(std::make_unique(MAX_SEG_ARRAY_SIZE)) +#else + dataSegArray_(std::make_unique(1)) #endif +{ } HtraceParser::~HtraceParser() @@ -55,86 +69,130 @@ void HtraceParser::WaitForParserEnd() usleep(sleepDur_ * sleepDur_); } } - streamFilters_->cpuFilter_->FinishCpuEvent(); - streamFilters_->binderFilter_->FinishBinderEvent(); + htraceCpuDetailParser_->FilterAllEvents(); + htraceNativeHookParser_->FinishParseNativeHookData(); htraceHiLogParser_->Finish(); - htraceMemParser_->Finish(); htraceNativeHookParser_->Finish(); htraceHidumpParser_->Finish(); + cpuUsageParser_->Finish(); + networkParser_->Finish(); + processParser_->Finish(); + diskIOParser_->Finish(); + hisyseventParser_->Finish(); + // keep final upate perf and ebpf data time range + ebpfDataParser_->Finish(); +#if WITH_PERF + perfDataParser_->Finish(); +#endif + htraceMemParser_->Finish(); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_TRACE, + dataSourceTypeTraceClockid_); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_MEM, dataSourceTypeMemClockid_); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HILOG, + dataSourceTypeHilogClockid_); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_ALLOCATION, + dataSourceTypeAllocationClockid_); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_FPS, dataSourceTypeFpsClockid_); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_NETWORK, + dataSourceTypeNetworkClockid_); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_DISKIO, + dataSourceTypeDiskioClockid_); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_CPU, dataSourceTypeCpuClockid_); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_PROCESS, + dataSourceTypeProcessClockid_); + traceDataCache_->GetDataSourceClockIdData()->SetDataSourceClockId(DATA_SOURCE_TYPE_HISYSEVENT, + dataSourceTypeHisyseventClockid_); + traceDataCache_->GetDataSourceClockIdData()->Finish(); + dataSegArray_.reset(); } void HtraceParser::ParseTraceDataItem(const std::string& buffer) { int head = rawDataHead_; + if (!supportThread_) { + dataSegArray_[head].seg = std::move(buffer); + dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED; + ParserData(dataSegArray_[head]); + return; + } while (!toExit_) { - if (!noThread_ && dataSegArray[head].status.load() != TS_PARSE_STATUS_INIT) { + if (dataSegArray_[head].status.load() != TS_PARSE_STATUS_INIT) { usleep(sleepDur_); continue; } - dataSegArray[head].seg = std::move(buffer); - dataSegArray[head].status = TS_PARSE_STATUS_SEPRATED; - if (!noThread_) { - rawDataHead_ = (rawDataHead_ + 1) % MAX_SEG_ARRAY_SIZE; - } + dataSegArray_[head].seg = std::move(buffer); + dataSegArray_[head].status = TS_PARSE_STATUS_SEPRATED; + rawDataHead_ = (rawDataHead_ + 1) % MAX_SEG_ARRAY_SIZE; break; } - if (!parseThreadStarted_ && !noThread_) { + if (!parseThreadStarted_) { parseThreadStarted_ = true; int tmp = maxThread_; while (tmp--) { parserThreadCount_++; std::thread ParseTypeThread(&HtraceParser::ParseThread, this); ParseTypeThread.detach(); - TS_LOGI("parser Thread:%d/%d start working ...\n", maxThread_ - tmp, maxThread_); + TS_LOGD("parser Thread:%d/%d start working ...\n", maxThread_ - tmp, maxThread_); } } - if (noThread_) { - ParserData(dataSegArray[head]); - } } void HtraceParser::FilterData(HtraceDataSegment& seg) { if (seg.dataType == DATA_SOURCE_TYPE_TRACE) { - if (seg.traceData.ftrace_cpu_detail_size()) { - htraceCpuDetailParser_->Parse(seg.traceData, clock_); // has Event + if (seg.traceData->ftrace_cpu_detail_size()) { + htraceCpuDetailParser_->Parse(seg.traceData.get(), seg.clockId); // has Event } - if (seg.traceData.symbols_detail_size()) { - htraceSymbolsDetailParser_->Parse(seg.traceData); // has Event + if (seg.traceData->symbols_detail_size()) { + htraceSymbolsDetailParser_->Parse(seg.traceData.get()); // has Event } - if (seg.traceData.clocks_detail_size()) { - htraceClockDetailParser_->Parse(seg.traceData); // has Event + if (seg.traceData->clocks_detail_size()) { + htraceClockDetailParser_->Parse(seg.traceData.get()); // has Event } } else if (seg.dataType == DATA_SOURCE_TYPE_MEM) { htraceMemParser_->Parse(seg.memData, seg.timeStamp, seg.clockId); } else if (seg.dataType == DATA_SOURCE_TYPE_HILOG) { htraceHiLogParser_->Parse(seg.logData); - } else if (seg.dataType == DATA_SOURCE_TYPE_HEAP) { - htraceNativeHookParser_->Parse(seg.batchNativeHookData); + } else if (seg.dataType == DATA_SOURCE_TYPE_ALLOCATION) { + htraceNativeHookParser_->SortNativeHookData(seg.batchNativeHookData); } else if (seg.dataType == DATA_SOURCE_TYPE_FPS) { htraceHidumpParser_->Parse(seg.hidumpInfo); + dataSourceTypeFpsClockid_ = htraceHidumpParser_->ClockId(); + } else if (seg.dataType == DATA_SOURCE_TYPE_NETWORK) { + networkParser_->Parse(seg.networkInfo, seg.timeStamp); + } else if (seg.dataType == DATA_SOURCE_TYPE_CPU) { + cpuUsageParser_->Parse(seg.cpuInfo, seg.timeStamp); + } else if (seg.dataType == DATA_SOURCE_TYPE_PROCESS) { + processParser_->Parse(seg.processInfo, seg.timeStamp); + } else if (seg.dataType == DATA_SOURCE_TYPE_DISKIO) { + diskIOParser_->Parse(seg.diskIOInfo, seg.timeStamp); + } else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT) { + hisyseventParser_->Parse(seg.hisyseventInfo, seg.timeStamp); + } else if (seg.dataType == DATA_SOURCE_TYPE_HISYSEVENT_CONFIG) { + hisyseventParser_->Parse(seg.hisyseventConfig, seg.timeStamp); } - if (!noThread_) { + if (supportThread_) { filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; } seg.status = TS_PARSE_STATUS_INIT; } void HtraceParser::FilterThread() { + TS_LOGI("filter thread start work!"); while (1) { - HtraceDataSegment& seg = dataSegArray[filterHead_]; + HtraceDataSegment& seg = dataSegArray_[filterHead_]; if (seg.status.load() == TS_PARSE_STATUS_INVALID) { seg.status = TS_PARSE_STATUS_INIT; filterHead_ = (filterHead_ + 1) % MAX_SEG_ARRAY_SIZE; streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); - TS_LOGI("seprateHead_d:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_); + TS_LOGD("seprateHead_d:\t%d, parseHead_:\t%d, filterHead_:\t%d\n", rawDataHead_, parseHead_, filterHead_); continue; } if (seg.status.load() != TS_PARSE_STATUS_PARSED) { if (toExit_ && !parserThreadCount_) { - TS_LOGI("exiting ParseLine Thread"); + TS_LOGI("exiting Filter Thread"); exited_ = true; filterThreadStarted_ = false; - TS_LOGD("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_, + TS_LOGI("seprateHead:\t%d, parseHead_:\t%d, filterHead_:\t%d, status:%d\n", rawDataHead_, parseHead_, filterHead_, seg.status.load()); return; } @@ -155,6 +213,7 @@ void HtraceParser::ParserData(HtraceDataSegment& dataSeg) dataSeg.status = TS_PARSE_STATUS_INVALID; return; } + dataSeg.timeStamp = pluginData.tv_nsec() + pluginData.tv_sec() * SEC_TO_NS; if (pluginData.name() == "memory-plugin") { ParseMemory(pluginData, dataSeg); } else if (pluginData.name() == "hilog-plugin" || pluginData.name() == "/data/local/tmp/libhilogplugin.z.so") { @@ -165,30 +224,54 @@ void HtraceParser::ParserData(HtraceDataSegment& dataSeg) ParseNativeHook(pluginData, dataSeg); } else if (pluginData.name() == "hidump-plugin" || pluginData.name() == "/data/local/tmp/libhidumpplugin.z.so") { ParseFPS(pluginData, dataSeg); + } else if (pluginData.name() == "cpu-plugin") { + ParseCpuUsage(pluginData, dataSeg); + } else if (pluginData.name() == "network-plugin") { + ParseNetwork(pluginData, dataSeg); + } else if (pluginData.name() == "diskio-plugin") { + ParseDiskIO(pluginData, dataSeg); + } else if (pluginData.name() == "process-plugin") { + ParseProcess(pluginData, dataSeg); + } else if (pluginData.name() == "hisysevent-plugin") { + ParseHisysevent(pluginData, dataSeg); + } else if (pluginData.name() == "hisysevent-plugin_config") { + ParseHisyseventConfig(pluginData, dataSeg); } else { - TS_LOGW("unrecognized pluginData.name():%s", pluginData.name().c_str()); +#if IS_WASM + TraceStreamer_Plugin_Out_Filter(pluginData.data().data(), pluginData.data().length(), pluginData.name()); +#endif + dataSeg.status = TS_PARSE_STATUS_INVALID; + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); + return; } - if (noThread_) { // do it only in wasm mode, wasm noThead_ will be true + if (!supportThread_) { // do it only in wasm mode, wasm noThead_ will be true + if (dataSeg.status == STAT_EVENT_DATA_INVALID) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_OTHER, STAT_EVENT_DATA_INVALID); + return; + } FilterData(dataSeg); } } void HtraceParser::ParseThread() { + TS_LOGI("parser thread start work!\n"); while (1) { - if (!filterThreadStarted_ && !noThread_) { + if (supportThread_ && !filterThreadStarted_) { filterThreadStarted_ = true; std::thread ParserThread(&HtraceParser::FilterThread, this); + TS_LOGD("FilterThread start working ...\n"); ParserThread.detach(); } int head = GetNextSegment(); if (head < 0) { if (head == ERROR_CODE_EXIT) { + TS_LOGI("parse thread exit\n"); return; } else if (head == ERROR_CODE_NODATA) { continue; } } - HtraceDataSegment& dataSeg = dataSegArray[head]; + HtraceDataSegment& dataSeg = dataSegArray_[head]; ParserData(dataSeg); } } @@ -196,12 +279,12 @@ void HtraceParser::ParseThread() void HtraceParser::ParseMemory(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) { dataSeg.dataType = DATA_SOURCE_TYPE_MEM; - auto timeStamp = pluginData.tv_nsec() + pluginData.tv_sec() * SEC_TO_NS; BuiltinClocks clockId = TS_CLOCK_REALTIME; auto clockIdTemp = pluginData.clock_id(); if (clockIdTemp == ProfilerPluginData_ClockId_CLOCKID_REALTIME) { clockId = TS_CLOCK_REALTIME; } + dataSourceTypeMemClockid_ = clockId; dataSeg.memData.Clear(); if (!dataSeg.memData.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { TS_LOGW("tracePacketParseFromArray failed\n"); @@ -210,17 +293,14 @@ void HtraceParser::ParseMemory(const ProfilerPluginData& pluginData, HtraceDataS } if (dataSeg.memData.processesinfo_size()) { dataSeg.dataType = DATA_SOURCE_TYPE_MEM; - dataSeg.timeStamp = timeStamp; dataSeg.clockId = clockId; dataSeg.status = TS_PARSE_STATUS_PARSED; } else if (dataSeg.memData.meminfo_size()) { dataSeg.dataType = DATA_SOURCE_TYPE_MEM; - dataSeg.timeStamp = timeStamp; dataSeg.clockId = clockId; dataSeg.status = TS_PARSE_STATUS_PARSED; } else if (dataSeg.memData.vmeminfo_size()) { dataSeg.dataType = DATA_SOURCE_TYPE_MEM; - dataSeg.timeStamp = timeStamp; dataSeg.clockId = clockId; dataSeg.status = TS_PARSE_STATUS_PARSED; } else { @@ -230,7 +310,7 @@ void HtraceParser::ParseMemory(const ProfilerPluginData& pluginData, HtraceDataS void HtraceParser::ParseHilog(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) { dataSeg.dataType = DATA_SOURCE_TYPE_HILOG; - dataSeg.traceData.Clear(); + dataSourceTypeHilogClockid_ = TS_CLOCK_REALTIME; if (!dataSeg.logData.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { TS_LOGW("tracePacketParseFromArray failed\n"); dataSeg.status = TS_PARSE_STATUS_PARSED; @@ -245,27 +325,34 @@ void HtraceParser::ParseHilog(const ProfilerPluginData& pluginData, HtraceDataSe void HtraceParser::ParseFtrace(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) { dataSeg.dataType = DATA_SOURCE_TYPE_TRACE; - dataSeg.traceData.Clear(); - if (!dataSeg.traceData.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + dataSeg.traceData = std::make_unique(); + if (!dataSeg.traceData->ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { TS_LOGW("tracePacketParseFromArray failed\n"); dataSeg.status = TS_PARSE_STATUS_INVALID; return; } - if (dataSeg.traceData.ftrace_cpu_stats_size()) { - auto cpuStats = dataSeg.traceData.ftrace_cpu_stats(0); + if (dataSeg.traceData->ftrace_cpu_stats_size()) { + auto cpuStats = dataSeg.traceData->ftrace_cpu_stats(0); auto s = cpuStats.per_cpu_stats(0); TS_LOGD("s.overrun():%lu", s.overrun()); TS_LOGD("s.dropped_events():%lu", s.dropped_events()); auto clock = cpuStats.trace_clock(); if (clock == "boot") { clock_ = TS_CLOCK_BOOTTIME; + } else if (clock == "mono"){ + clock_ = TS_MONOTONIC; + } else { + TS_LOGI("invalid clock:%s", clock.c_str()); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; } - dataSeg.clockId = clock_; dataSeg.status = TS_PARSE_STATUS_PARSED; return; } - if (dataSeg.traceData.clocks_detail_size() || dataSeg.traceData.ftrace_cpu_detail_size() || - dataSeg.traceData.symbols_detail_size()) { + dataSeg.clockId = clock_; + dataSourceTypeTraceClockid_ = clock_; + if (dataSeg.traceData->clocks_detail_size() || dataSeg.traceData->ftrace_cpu_detail_size() || + dataSeg.traceData->symbols_detail_size()) { dataSeg.status = TS_PARSE_STATUS_PARSED; return; } @@ -274,8 +361,8 @@ void HtraceParser::ParseFtrace(const ProfilerPluginData& pluginData, HtraceDataS void HtraceParser::ParseNativeHook(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) { - dataSeg.dataType = DATA_SOURCE_TYPE_HEAP; - dataSeg.traceData.Clear(); + dataSourceTypeAllocationClockid_ = TS_CLOCK_REALTIME; + dataSeg.dataType = DATA_SOURCE_TYPE_ALLOCATION; if (!dataSeg.batchNativeHookData.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { TS_LOGW("tracePacketParseFromArray failed\n"); @@ -292,7 +379,6 @@ void HtraceParser::ParseNativeHook(const ProfilerPluginData& pluginData, HtraceD void HtraceParser::ParseFPS(const ProfilerPluginData& pluginData, HtraceDataSegment& dataSeg) { dataSeg.dataType = DATA_SOURCE_TYPE_FPS; - dataSeg.traceData.Clear(); if (!dataSeg.hidumpInfo.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { TS_LOGW("tracePacketParseFromArray failed\n"); dataSeg.status = TS_PARSE_STATUS_INVALID; @@ -304,12 +390,93 @@ void HtraceParser::ParseFPS(const ProfilerPluginData& pluginData, HtraceDataSegm } dataSeg.status = TS_PARSE_STATUS_INVALID; } + +void HtraceParser::ParseCpuUsage(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg) +{ + dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME; + dataSeg.dataType = DATA_SOURCE_TYPE_CPU; + if (!dataSeg.cpuInfo.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + streamFilters_->statFilter_->IncreaseStat(TRACE_CPU_USAGE, STAT_EVENT_DATA_INVALID); + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + if (dataSeg.cpuInfo.has_cpu_usage_info() || dataSeg.cpuInfo.thread_info_size()) { + dataSeg.status = TS_PARSE_STATUS_PARSED; + return; + } + dataSeg.status = TS_PARSE_STATUS_INVALID; +} +void HtraceParser::ParseNetwork(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg) +{ + dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME; + dataSeg.dataType = DATA_SOURCE_TYPE_NETWORK; + if (!dataSeg.networkInfo.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + streamFilters_->statFilter_->IncreaseStat(TRACE_NETWORK, STAT_EVENT_DATA_INVALID); + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + dataSeg.status = TS_PARSE_STATUS_PARSED; +} +void HtraceParser::ParseDiskIO(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg) +{ + dataSourceTypeProcessClockid_ = TS_CLOCK_REALTIME; + dataSeg.dataType = DATA_SOURCE_TYPE_DISKIO; + if (!dataSeg.diskIOInfo.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + streamFilters_->statFilter_->IncreaseStat(TRACE_DISKIO, STAT_EVENT_DATA_INVALID); + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + dataSeg.status = TS_PARSE_STATUS_PARSED; +} + +void HtraceParser::ParseProcess(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg) +{ + dataSourceTypeProcessClockid_ = TS_CLOCK_BOOTTIME; + dataSeg.dataType = DATA_SOURCE_TYPE_PROCESS; + if (!dataSeg.processInfo.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + streamFilters_->statFilter_->IncreaseStat(TRACE_PROCESS, STAT_EVENT_DATA_INVALID); + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + dataSeg.timeStamp = pluginData.tv_nsec() + pluginData.tv_sec() * SEC_TO_NS; + dataSeg.status = TS_PARSE_STATUS_PARSED; +} + +void HtraceParser::ParseHisysevent(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg) +{ + dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME; + dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT; + if (!dataSeg.hisyseventInfo.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + streamFilters_->statFilter_->IncreaseStat(TRACE_HISYSEVENT, STAT_EVENT_DATA_INVALID); + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + dataSeg.status = TS_PARSE_STATUS_PARSED; +} +void HtraceParser::ParseHisyseventConfig(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg) +{ + dataSourceTypeHisyseventClockid_ = TS_CLOCK_REALTIME; + dataSeg.dataType = DATA_SOURCE_TYPE_HISYSEVENT_CONFIG; + if (!dataSeg.hisyseventConfig.ParseFromArray(pluginData.data().data(), static_cast(pluginData.data().size()))) { + streamFilters_->statFilter_->IncreaseStat(TRACE_HISYSEVENT, STAT_EVENT_DATA_INVALID); + TS_LOGW("tracePacketParseFromArray failed\n"); + dataSeg.status = TS_PARSE_STATUS_INVALID; + return; + } + dataSeg.status = TS_PARSE_STATUS_PARSED; +} + int HtraceParser::GetNextSegment() { int head; dataSegMux_.lock(); head = parseHead_; - HtraceDataSegment& seg = dataSegArray[head]; + HtraceDataSegment& seg = dataSegArray_[head]; if (seg.status.load() != TS_PARSE_STATUS_SEPRATED) { if (toExit_) { parserThreadCount_--; @@ -336,18 +503,60 @@ int HtraceParser::GetNextSegment() dataSegMux_.unlock(); return head; } -void HtraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, size_t size) +bool HtraceParser::ParseDataRecursively(std::deque::iterator& packagesBegin, size_t& currentLength) { - packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]); - auto packagesBegin = packagesBuffer_.begin(); - auto currentLength = packagesBuffer_.size(); - if (!hasGotHeader) { - std::string start(reinterpret_cast(bufferStr.get()), std::min(size, 20)); - if (start.compare(0, std::string("OHOSPROF").length(), "OHOSPROF") == 0) { + if (!hasGotHeader_) { + if (InitProfilerTraceFileHeader()) { + packagesBuffer_.erase(packagesBuffer_.begin(), packagesBuffer_.begin() + PACKET_HEADER_LENGTH); currentLength -= PACKET_HEADER_LENGTH; packagesBegin += PACKET_HEADER_LENGTH; + htraceCurentLength_ = profilerTraceFileHeader_.data.length; + htraceCurentLength_ -= PACKET_HEADER_LENGTH; + hasGotHeader_ = true; + if (!currentLength) { + return false; + } + } else { + TS_LOGE("get profiler trace file header failed"); + return false; + } + } + if (profilerTraceFileHeader_.data.dataType == ProfilerTraceFileHeader::HIPERF_DATA) { + if (packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) { +#if WITH_PERF + auto size = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH; + perfDataParser_->InitPerfDataAndLoad(packagesBuffer_, size); + currentLength -= size; + packagesBegin += size; + profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE; + hasGotHeader_ = false; + return true; +#endif + } + return false; + } + if (profilerTraceFileHeader_.data.dataType == ProfilerTraceFileHeader::STANDALONE_DATA) { + if (EBPF_PLUGIN_NAME.compare(profilerTraceFileHeader_.data.standalonePluginName) == 0 && + packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) { + auto size = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH; + ebpfDataParser_->InitAndParseEbpfData(packagesBuffer_, size); + currentLength -= size; + packagesBegin += size; + profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE; + hasGotHeader_ = false; + return true; } - hasGotHeader = true; +#if IS_WASM + if (packagesBuffer_.size() >= profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH) { + auto thirdPartySize = profilerTraceFileHeader_.data.length - PACKET_HEADER_LENGTH; + auto buffer = std::make_unique(thirdPartySize).get(); + std::copy(packagesBuffer_.begin(), packagesBuffer_.begin() + thirdPartySize, buffer); + TraceStreamer_Plugin_Out_Filter(reinterpret_cast(buffer), thirdPartySize, + profilerTraceFileHeader_.data.standalonePluginName); + return true; + } +#endif + return false; } while (1) { if (!hasGotSegLength_) { @@ -357,9 +566,11 @@ void HtraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, s std::string bufferLine(packagesBegin, packagesBegin + PACKET_SEG_LENGTH); const uint32_t* len = reinterpret_cast(bufferLine.data()); nextLength_ = *len; + htraceLength_ += nextLength_ + PACKET_SEG_LENGTH; hasGotSegLength_ = true; currentLength -= PACKET_SEG_LENGTH; packagesBegin += PACKET_SEG_LENGTH; + htraceCurentLength_ -= PACKET_SEG_LENGTH; } if (currentLength < nextLength_) { break; @@ -369,9 +580,62 @@ void HtraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, s hasGotSegLength_ = false; packagesBegin += nextLength_; currentLength -= nextLength_; + if (nextLength_ > htraceCurentLength_) { + TS_LOGE("fatal error, data length not match nextLength_:%u, htraceCurentLength_:%llu", nextLength_, + htraceCurentLength_); + } + htraceCurentLength_ -= nextLength_; + if (htraceCurentLength_ == 0) { + hasGotHeader_ = false; + packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin); + profilerTraceFileHeader_.data.dataType = ProfilerTraceFileHeader::UNKNOW_TYPE; + TS_LOGW("read proto finished!"); + return ParseDataRecursively(packagesBegin, currentLength); + } + } + return true; +} +void HtraceParser::ParseTraceDataSegment(std::unique_ptr bufferStr, size_t size) +{ + packagesBuffer_.insert(packagesBuffer_.end(), &bufferStr[0], &bufferStr[size]); + auto packagesBegin = packagesBuffer_.begin(); + auto currentLength = packagesBuffer_.size(); + if (ParseDataRecursively(packagesBegin, currentLength)) { + packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin); } - packagesBuffer_.erase(packagesBuffer_.begin(), packagesBegin); return; } + +bool HtraceParser::InitProfilerTraceFileHeader() +{ + if (packagesBuffer_.size() < PACKET_HEADER_LENGTH) { + TS_LOGE("buffer size less than profiler trace file header"); + return false; + } + uint8_t buffer[PACKET_HEADER_LENGTH]; + memset_s(buffer, PACKET_HEADER_LENGTH, 0, PACKET_HEADER_LENGTH); + int i = 0; + for (auto it = packagesBuffer_.begin(); it != packagesBuffer_.begin() + PACKET_HEADER_LENGTH; ++it, ++i) { + buffer[i] = *it; + } + auto ret = memcpy_s(&profilerTraceFileHeader_, sizeof(profilerTraceFileHeader_), buffer, PACKET_HEADER_LENGTH); + if (ret == -1 || profilerTraceFileHeader_.data.magic != ProfilerTraceFileHeader::HEADER_MAGIC) { + TS_LOGE("Get profiler trace file header failed! ret = %d, magic = %lx", ret, + profilerTraceFileHeader_.data.magic); + return false; + } + if (profilerTraceFileHeader_.data.length <= PACKET_HEADER_LENGTH) { + TS_LOGE("Profiler Trace data is truncated!!!"); + return false; + } + TS_LOGI("magic = %llx, length = %llx, dataType = %llx, boottime = %llx", profilerTraceFileHeader_.data.magic, + profilerTraceFileHeader_.data.length, profilerTraceFileHeader_.data.dataType, profilerTraceFileHeader_.data.boottime); +#if IS_WASM + const int DATA_TYPE_CLOCK = 100; + TraceStreamer_Plugin_Out_SendData(reinterpret_cast(&profilerTraceFileHeader_), sizeof(profilerTraceFileHeader_), DATA_TYPE_CLOCK); +#endif + htraceClockDetailParser_->Parse(&profilerTraceFileHeader_); + return true; +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_parser.h old mode 100644 new mode 100755 index 3b0e6a6c8b1704e86406a931d75a26a63cdc6da2..0e696cc6212389b01404cd870d02e13e457ed2b3 --- a/host/trace_streamer/src/parser/htrace_parser/htrace_parser.h +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_parser.h @@ -22,20 +22,37 @@ #include #include #include "common_types.h" +#include "ebpf_data_parser.h" +#include "file.h" #include "htrace_clock_detail_parser.h" #include "htrace_cpu_detail_parser.h" +#include "htrace_cpu_data_parser.h" +#include "htrace_disk_io_parser.h" +#include "htrace_file_header.h" #include "htrace_hidump_parser.h" #include "htrace_hilog_parser.h" +#include "htrace_hisysevent_parser.h" #include "htrace_mem_parser.h" #include "htrace_native_hook_parser.h" +#include "htrace_network_parser.h" +#include "htrace_process_parser.h" #include "htrace_symbols_detail_parser.h" #include "log.h" #include "parser_base.h" +#if WITH_PERF +#include "perf_data_parser.h" +#endif +#include "string_help.h" #include "trace_data/trace_data_cache.h" #include "trace_streamer_filters.h" +#include "ts_common.h" namespace SysTuning { namespace TraceStreamer { +using namespace SysTuning::base; +#if WITH_PERF +using namespace OHOS::Developtools::HiPerf; +#endif class HtraceParser : public ParserBase { public: HtraceParser(TraceDataCache* dataCache, const TraceStreamerFilters* filters); @@ -43,8 +60,9 @@ public: void ParseTraceDataSegment(std::unique_ptr bufferStr, size_t size) override; void WaitForParserEnd(); private: + bool ParseDataRecursively(std::deque::iterator& packagesBegin, size_t& currentLength); void ParseTraceDataItem(const std::string& buffer) override; - void FilterData(HtraceDataSegment& dataSeg); + void FilterData(HtraceDataSegment& seg); void ParserData(HtraceDataSegment& dataSeg); private: void ParseMemory(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); @@ -52,6 +70,12 @@ private: void ParseFtrace(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); void ParseNativeHook(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); void ParseFPS(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseCpuUsage(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseNetwork(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseDiskIO(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseProcess(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseHisysevent(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); + void ParseHisyseventConfig(const ProfilerPluginData& pluginData, HtraceDataSegment &dataSeg); void ParseThread(); int GetNextSegment(); void FilterThread(); @@ -59,11 +83,15 @@ private: ERROR_CODE_EXIT = -2, ERROR_CODE_NODATA = -1 }; + bool InitProfilerTraceFileHeader(); + ProfilerTraceFileHeader profilerTraceFileHeader_; + uint64_t htraceCurentLength_ = 0; bool hasGotSegLength_ = false; - bool hasGotHeader = false; + bool hasGotHeader_ = false; uint32_t nextLength_ = 0; const size_t PACKET_SEG_LENGTH = 4; const size_t PACKET_HEADER_LENGTH = 1024; + TraceDataCache* traceDataCache_; std::unique_ptr htraceCpuDetailParser_; std::unique_ptr htraceSymbolsDetailParser_; std::unique_ptr htraceMemParser_; @@ -71,20 +99,41 @@ private: std::unique_ptr htraceHiLogParser_; std::unique_ptr htraceNativeHookParser_; std::unique_ptr htraceHidumpParser_; + std::unique_ptr cpuUsageParser_; + std::unique_ptr networkParser_; + std::unique_ptr diskIOParser_; + std::unique_ptr processParser_; + std::unique_ptr hisyseventParser_; +#if WITH_PERF + std::unique_ptr perfDataParser_; +#endif + std::unique_ptr ebpfDataParser_; std::atomic filterThreadStarted_{false}; const int MAX_SEG_ARRAY_SIZE = 10000; - std::unique_ptr dataSegArray; + std::unique_ptr dataSegArray_; int rawDataHead_ = 0; bool toExit_ = false; bool exited_ = false; int filterHead_ = 0; int parseHead_ = 0; + size_t sizeAll_ = 0; + size_t htraceLength_ = 1024; const int sleepDur_ = 100; bool parseThreadStarted_ = false; const int maxThread_ = 4; // 4 is the best on ubuntu 113MB/s, max 138MB/s, 6 is best on mac m1 21MB/s, int parserThreadCount_ = 0; - std::mutex dataSegMux_; - bool noThread_ = true; + std::mutex dataSegMux_ = {}; + bool supportThread_ = false; + ClockId dataSourceTypeTraceClockid_ = TS_CLOCK_UNKNOW; + ClockId dataSourceTypeMemClockid_ = TS_CLOCK_UNKNOW; + ClockId dataSourceTypeHilogClockid_ = TS_CLOCK_UNKNOW; + ClockId dataSourceTypeAllocationClockid_ = TS_CLOCK_UNKNOW; + ClockId dataSourceTypeFpsClockid_ = TS_CLOCK_UNKNOW; + ClockId dataSourceTypeNetworkClockid_ = TS_CLOCK_UNKNOW; + ClockId dataSourceTypeDiskioClockid_ = TS_CLOCK_UNKNOW; + ClockId dataSourceTypeCpuClockid_ = TS_CLOCK_UNKNOW; + ClockId dataSourceTypeProcessClockid_ = TS_CLOCK_UNKNOW; + ClockId dataSourceTypeHisyseventClockid_ = TS_CLOCK_UNKNOW; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_plugin_time_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_plugin_time_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec3e143ad48656051674401c1f9a7486db9bf30f --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_plugin_time_parser.cpp @@ -0,0 +1,67 @@ +/* + * 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. + */ +#include "htrace_plugin_time_parser.h" +namespace SysTuning { +namespace TraceStreamer { +HtracePluginTimeParser::HtracePluginTimeParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : EventParserBase(dataCache, ctx) +{ + if (!streamFilters_) { + TS_LOGF("streamFilters_ should not be null"); + return; + } + if (!traceDataCache_) { + TS_LOGF("traceDataCache_ should not be null"); + return; + } +} +void HtracePluginTimeParser::UpdatePluginTimeRange(ClockId clockId, uint64_t asyncTimestamp, uint64_t syncTimestamp) +{ + minTs_ = std::min(minTs_, asyncTimestamp); + maxTs_ = std::max(maxTs_, asyncTimestamp); + if (clockId == streamFilters_->clockFilter_->GetPrimaryClock()) { + syncHtracePluginStartTime_ = std::min(syncHtracePluginStartTime_, syncTimestamp); + syncHtracePluginEndTime_ = std::max(syncHtracePluginEndTime_, syncTimestamp); + return; + } + if (syncTimestamp != asyncTimestamp) { + syncHtracePluginStartTime_ = std::min(syncHtracePluginStartTime_, syncTimestamp); + syncHtracePluginEndTime_ = std::max(syncHtracePluginEndTime_, syncTimestamp); + } else { + asyncHtracePluginStartTime_ = std::min(asyncHtracePluginStartTime_, syncTimestamp); + asyncHtracePluginEndTime_ = std::max(asyncHtracePluginEndTime_, syncTimestamp); + } +} +uint64_t HtracePluginTimeParser::GetPluginStartTime() +{ + if (syncHtracePluginStartTime_ != std::numeric_limits::max()) { + return syncHtracePluginStartTime_; + } else if (asyncHtracePluginStartTime_ != std::numeric_limits::max()) { + return asyncHtracePluginStartTime_; + } + return std::numeric_limits::max(); +} + +uint64_t HtracePluginTimeParser::GetPluginEndTime() +{ + if (syncHtracePluginEndTime_ != 0) { + return syncHtracePluginEndTime_; + } else if (asyncHtracePluginEndTime_ != 0) { + return asyncHtracePluginEndTime_; + } + return 0; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_plugin_time_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_plugin_time_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..a0874ea0a34cc5356c7fdc6e1086ac74c5a28af8 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_plugin_time_parser.h @@ -0,0 +1,52 @@ +/* + * 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. + */ +#ifndef HTRACE_PLUGIN_TIME_PARSER_H +#define HTRACE_PLUGIN_TIME_PARSER_H +#include "clock_filter.h" +#include "event_parser_base.h" +#include "trace_data/trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class HtracePluginTimeParser : public EventParserBase { +public: + HtracePluginTimeParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + HtracePluginTimeParser(const HtracePluginTimeParser&) = delete; + HtracePluginTimeParser& operator=(const HtracePluginTimeParser&) = delete; + ~HtracePluginTimeParser() = default; + void UpdatePluginTimeRange(ClockId clockId, uint64_t asyncTimestamp, uint64_t syncTimestamp); + uint64_t GetPluginStartTime(); + uint64_t GetPluginEndTime(); + uint64_t MinTs() + { + return minTs_; + } + uint64_t MaxTs() + { + return maxTs_; + } + +private: + uint64_t syncHtracePluginStartTime_ = std::numeric_limits::max(); + uint64_t syncHtracePluginEndTime_ = 0; + uint64_t asyncHtracePluginStartTime_ = std::numeric_limits::max(); + uint64_t asyncHtracePluginEndTime_ = 0; + uint64_t minTs_ = std::numeric_limits::max(); + uint64_t maxTs_ = 0; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_PLUGIN_TIME_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_process_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_process_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..461870cd20e3dee70199002a6f353e8657ef8eac --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_process_parser.cpp @@ -0,0 +1,86 @@ +/* + * 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. + */ +#include "htrace_process_parser.h" +#include "clock_filter.h" +#include "htrace_event_parser.h" +#include "process_filter.h" +#include "stat_filter.h" +namespace SysTuning { +namespace TraceStreamer { +HtraceProcessParser::HtraceProcessParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx) + : HtracePluginTimeParser(dataCache, ctx) +{ +} + +HtraceProcessParser::~HtraceProcessParser() +{ + TS_LOGI("process ts MIN:%llu, MAX:%llu", static_cast(GetPluginStartTime()), + static_cast(GetPluginEndTime())); + TS_LOGI("process real ts MIN:%llu, MAX:%llu", static_cast(MinTs()), + static_cast(MaxTs())); +} +void HtraceProcessParser::Parse(ProcessData& tracePacket, uint64_t ts) +{ + for (int i = 0; i < tracePacket.processesinfo_size(); ++i) { + streamFilters_->statFilter_->IncreaseStat(TRACE_PROCESS, STAT_EVENT_START); + auto processesInfo = tracePacket.processesinfo(i); + auto pssInfo = processesInfo.pssinfo(); + auto cpuInfo = CpuInfo(); + if (processesInfo.has_cpuinfo()) { + cpuInfo = processesInfo.cpuinfo(); + } + auto liveProcess = std::make_unique(); + auto diskio = processesInfo.diskinfo(); + liveProcess->SetLiveProcess(ts, processesInfo, cpuInfo, pssInfo, diskio); + liveProcessData_.push_back(std::move(liveProcess)); + } +} +void HtraceProcessParser::Finish() +{ + if (!liveProcessData_.size()) { + TS_LOGW("process no data"); + return; + } + auto cmp = [](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->ts_ < b->ts_; + }; + std::sort(liveProcessData_.begin(), liveProcessData_.end(), cmp); + bool first = true; + uint64_t lastTs = 0; + for (auto itor = liveProcessData_.begin(); itor != liveProcessData_.end(); itor++) { + auto tsOld = (*itor)->ts_; + (*itor)->ts_ = streamFilters_->clockFilter_->ToPrimaryTraceTime(TS_CLOCK_REALTIME, (*itor)->ts_); + UpdatePluginTimeRange(TS_CLOCK_REALTIME, tsOld, (*itor)->ts_); + if (first) { + lastTs = (*itor)->ts_; + first = false; + continue; + } + auto dur = (*itor)->ts_ - lastTs; + lastTs = (*itor)->ts_; + if (!(*itor)->processInfo_->pid()) { + continue; + } + traceDataCache_->GetLiveProcessData()->AppendNewData( + (*itor)->ts_, dur, (*itor)->processInfo_->pid(), (*itor)->processInfo_->name(), + (*itor)->processInfo_->ppid(), (*itor)->processInfo_->uid(), std::to_string((*itor)->processInfo_->uid()), + (*itor)->cpuUsageData_->cpu_usage(), (*itor)->pssInfo_->pss_info(), (*itor)->cpuUsageData_->cpu_time_ms(), + (*itor)->cpuUsageData_->thread_sum(), (*itor)->diskio_->wbytes(), (*itor)->diskio_->rbytes()); + } + liveProcessData_.clear(); + traceDataCache_->MixTraceTime(GetPluginStartTime(), GetPluginEndTime()); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_process_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_process_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..103781d693a4d8cf31bc1a87962cda54fb997989 --- /dev/null +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_process_parser.h @@ -0,0 +1,58 @@ +/* + * 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. + */ +#ifndef HTRACE_PROCESS_PARSER_H +#define HTRACE_PROCESS_PARSER_H +#include +#include +#include +#include "htrace_plugin_time_parser.h" +#include "process_plugin_result.pb.h" +#include "trace_streamer_filters.h" +#include "cpu_plugin_result.pb.h" + + +namespace SysTuning { +namespace TraceStreamer { +class HtraceProcessParser : public HtracePluginTimeParser { +public: + HtraceProcessParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); + ~HtraceProcessParser(); + void Parse(ProcessData& tracePacket, uint64_t ts); + void Finish(); + struct TsLiveProcessData { + void SetLiveProcess(uint64_t ts, + ProcessInfo& liveProcessInfo, + CpuInfo& cpuUsageData, + PssInfo& pssInfo, + DiskioInfo& diskio) + { + ts_ = ts; + processInfo_ = std::make_unique(liveProcessInfo); + cpuUsageData_ = std::make_unique(cpuUsageData); + pssInfo_ = std::make_unique(pssInfo); + diskio_ = std::make_unique(diskio); + } + uint64_t ts_; + std::unique_ptr processInfo_; + std::unique_ptr cpuUsageData_; + std::unique_ptr pssInfo_; + std::unique_ptr diskio_; + }; + std::vector> liveProcessData_; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // HTRACE_PROCESS_PARSER_H diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.cpp b/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.cpp old mode 100644 new mode 100755 index 63f22e8bcebf6f493e10c3ec81cc85dc6c98ed61..db1c352f4ac63f62b8a6b63019f796c5b44e8bed --- a/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.cpp +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.cpp @@ -22,24 +22,19 @@ HtraceSymbolsDetailParser::HtraceSymbolsDetailParser(TraceDataCache* dataCache, { UNUSED(traceDataCache_); if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); + TS_LOGF("streamFilters_ should not be null"); return; } } HtraceSymbolsDetailParser::~HtraceSymbolsDetailParser() = default; -void HtraceSymbolsDetailParser::Parse(const TracePluginResult& tracePacket) +void HtraceSymbolsDetailParser::Parse(const TracePluginResult* tracePacket) { - if (!tracePacket.symbols_detail_size()) { + if (!tracePacket->symbols_detail_size()) { return; } - if (!streamFilters_) { - TS_LOGE("streamFilters_ should not be null"); - return; - } - for (int i = 0; i < tracePacket.symbols_detail_size(); i++) { - auto symbol = const_cast(tracePacket).mutable_symbols_detail(i); - TS_LOGD("symbol_name:%s, symbol_addr:%lu", symbol->symbol_name().c_str(), symbol->symbol_addr()); + for (int i = 0; i < tracePacket->symbols_detail_size(); i++) { + auto symbol = const_cast(tracePacket)->mutable_symbols_detail(i); // symbol streamFilters_->symbolsFilter_->RegisterFunc(symbol->symbol_addr(), traceDataCache_->GetDataIndex(symbol->symbol_name())); diff --git a/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.h b/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.h old mode 100644 new mode 100755 index 5af70f96844f17c1db064ba7d264ac8c6e67327d..34bc1128afbb2c4689e2f9e96674903e84ce189d --- a/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.h +++ b/host/trace_streamer/src/parser/htrace_parser/htrace_symbols_detail_parser.h @@ -29,7 +29,7 @@ class HtraceSymbolsDetailParser { public: HtraceSymbolsDetailParser(TraceDataCache* dataCache, const TraceStreamerFilters* ctx); ~HtraceSymbolsDetailParser(); - void Parse(const TracePluginResult& tracePacket); + void Parse(const TracePluginResult* tracePacket); private: const TraceStreamerFilters* streamFilters_; @@ -37,5 +37,4 @@ private: }; } // namespace TraceStreamer } // namespace SysTuning - #endif // HTRACE_SYMBOLS_DETAIL_PARSER_H diff --git a/host/trace_streamer/src/parser/parser.pri b/host/trace_streamer/src/parser/parser.pri deleted file mode 100644 index 47f8a891137b9175e8356249abaa32f6e5222d2e..0000000000000000000000000000000000000000 --- a/host/trace_streamer/src/parser/parser.pri +++ /dev/null @@ -1,51 +0,0 @@ -# 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. -INCLUDEPATH += $$PWD \ - $$PWD/bytrace_parser \ - $$PWD/htrace_parser/htrace_cpu_parser \ - $$PWD/htrace_parser/htrace_event_parser \ - $$PWD/htrace_parser/htrace_symbol_parser -HEADERS += \ - $$PWD/common_types.h \ - $$PWD/event_parser_base.h \ - $$PWD/thread_state.h \ - $$PWD/print_event_parser.h \ - $$PWD/bytrace_parser/bytrace_parser.h \ - $$PWD/bytrace_parser/bytrace_event_parser.h \ - $$PWD/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.h \ - $$PWD/htrace_parser/htrace_event_parser/htrace_event_parser.h \ - $$PWD/htrace_parser/htrace_parser.h \ - $$PWD/htrace_parser/htrace_mem_parser.h \ - $$PWD/htrace_parser/htrace_hilog_parser.h \ - $$PWD/htrace_parser/htrace_native_hook_parser.h \ - $$PWD/htrace_parser/htrace_hidump_parser.h \ - $$PWD/htrace_parser/htrace_clock_detail_parser.h \ - $$PWD/htrace_parser/htrace_symbols_detail_parser.h - - -SOURCES += \ - $$PWD/parser_base.cpp \ - $$PWD/event_parser_base.cpp \ - $$PWD/thread_state.cpp \ - $$PWD/print_event_parser.cpp \ - $$PWD/bytrace_parser/bytrace_parser.cpp \ - $$PWD/bytrace_parser/bytrace_event_parser.cpp \ - $$PWD/htrace_parser/htrace_cpu_parser/htrace_cpu_detail_parser.cpp \ - $$PWD/htrace_parser/htrace_event_parser/htrace_event_parser.cpp \ - $$PWD/htrace_parser/htrace_parser.cpp \ - $$PWD/htrace_parser/htrace_mem_parser.cpp \ - $$PWD/htrace_parser/htrace_hilog_parser.cpp \ - $$PWD/htrace_parser/htrace_native_hook_parser.cpp \ - $$PWD/htrace_parser/htrace_hidump_parser.cpp \ - $$PWD/htrace_parser/htrace_clock_detail_parser.cpp \ - $$PWD/htrace_parser/htrace_symbols_detail_parser.cpp diff --git a/host/trace_streamer/src/parser/print_event_parser.cpp b/host/trace_streamer/src/parser/print_event_parser.cpp old mode 100644 new mode 100755 index 8773bbb7d5eca086e187ed2726809bab375a7dfe..38668545dafab7aa5559a8ff1bd0cc6bbb44b5ba --- a/host/trace_streamer/src/parser/print_event_parser.cpp +++ b/host/trace_streamer/src/parser/print_event_parser.cpp @@ -24,29 +24,25 @@ PrintEventParser::PrintEventParser(TraceDataCache* dataCache, const TraceStreame { } -void PrintEventParser::ParsePrintEvent(uint64_t ts, uint32_t pid, std::string_view event) const +bool PrintEventParser::ParsePrintEvent(const std::string& comm, uint64_t ts, uint32_t pid, std::string_view event) { + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_RECEIVED); TracePoint point; - if (GetTracePoint(event, point) == SUCCESS) { - ParseTracePoint(ts, pid, point); - streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_RECEIVED); - } else { + if (GetTracePoint(event, point) != SUCCESS) { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID); + return false; } -} - -void PrintEventParser::ParseTracePoint(uint64_t ts, uint32_t pid, TracePoint point) const -{ if (point.tgid_) { streamFilters_->processFilter_->GetOrCreateInternalPid(ts, point.tgid_); } switch (point.phase_) { case 'B': { - if (streamFilters_->sliceFilter_->BeginSlice(ts, pid, point.tgid_, 0, - traceDataCache_->GetDataIndex(point.name_))) { + uint32_t index = streamFilters_->sliceFilter_->BeginSlice(comm, ts, pid, point.tgid_, INVALID_DATAINDEX, + traceDataCache_->GetDataIndex(point.name_)); + if (index != INVALID_UINT32) { // add distributed data - traceDataCache_->GetInternalSlicesData()->AppendDistributeInfo( - point.chainId_, point.spanId_, point.parentSpanId_, point.flag_, point.args_); + traceDataCache_->GetInternalSlicesData()->SetDistributeInfo( + index, point.chainId_, point.spanId_, point.parentSpanId_, point.flag_, point.args_); } else { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST); } @@ -57,13 +53,13 @@ void PrintEventParser::ParseTracePoint(uint64_t ts, uint32_t pid, TracePoint poi break; } case 'S': { - auto cookie = static_cast(point.value_); + auto cookie = static_cast(point.value_); streamFilters_->sliceFilter_->StartAsyncSlice(ts, pid, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_)); break; } case 'F': { - auto cookie = static_cast(point.value_); + auto cookie = static_cast(point.value_); streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_)); break; @@ -80,8 +76,9 @@ void PrintEventParser::ParseTracePoint(uint64_t ts, uint32_t pid, TracePoint poi } default: TS_LOGD("point missing!"); - break; + return false; } + return true; } ParseResult PrintEventParser::CheckTracePoint(std::string_view pointStr) const @@ -139,6 +136,10 @@ ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint& ou return SUCCESS; } // Resolve distributed calls + // the normal data mybe like: + // system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|[8b00e96b2,2,1]:C$#decodeFrame$#" + // "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \ + // system - 1298(1298)[001]... 1 174330.287622 : tracing_mark_write : E | 1298 \n const std::regex distributeMatcher = std::regex(R"((?:^\[([a-z0-9]+),(\d+),(\d+)\]:?([CS]?)\$#)?(.*)\$#(.*)$)"); std::smatch matcheLine; @@ -155,15 +156,18 @@ ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint& ou return SUCCESS; } -ParseResult PrintEventParser::HandlerE(void) const +ParseResult PrintEventParser::HandlerE(void) { return SUCCESS; } -size_t PrintEventParser::GetNameLength(std::string_view pointStr, size_t nameIndex) const +size_t PrintEventParser::GetNameLength(std::string_view pointStr, size_t nameIndex) { size_t namelength = 0; for (size_t i = nameIndex; i < pointStr.size(); i++) { + if (pointStr[i] == ' ') { + namelength = i - nameIndex; + } if (pointStr[i] == '|') { namelength = i - nameIndex; break; @@ -241,7 +245,9 @@ ParseResult PrintEventParser::GetTracePoint(std::string_view pointStr, TracePoin } size_t tGidlength = 0; - + // we may get wrong format data like tracing_mark_write: E + // while the format data must be E|call-tid + // please use a regular-format to get all the data outPoint.phase_ = pointStr.front(); outPoint.tgid_ = GetThreadGroupId(pointStr, tGidlength); diff --git a/host/trace_streamer/src/parser/print_event_parser.h b/host/trace_streamer/src/parser/print_event_parser.h old mode 100644 new mode 100755 index 71311215407a7e9388436576e764d820d1102d26..459360068952df7b96298889149557a481017cc4 --- a/host/trace_streamer/src/parser/print_event_parser.h +++ b/host/trace_streamer/src/parser/print_event_parser.h @@ -22,26 +22,27 @@ #include "filter/process_filter.h" #include "filter/slice_filter.h" #include "string_to_numerical.h" +#include "trace_streamer_config.h" namespace SysTuning { namespace TraceStreamer { class PrintEventParser : private EventParserBase { public: PrintEventParser(TraceDataCache* dataCache, const TraceStreamerFilters* filter); - void ParsePrintEvent(uint64_t ts, uint32_t pid, std::string_view event) const; + bool ParsePrintEvent(const std::string& comm, uint64_t ts, uint32_t pid, std::string_view event); private: - void ParseTracePoint(uint64_t ts, uint32_t pid, TracePoint point) const; - ParseResult GetTracePoint(std::string_view str, TracePoint& out) const; + ParseResult GetTracePoint(std::string_view pointStr, TracePoint& outPoint) const; ParseResult CheckTracePoint(std::string_view pointStr) const; uint32_t GetThreadGroupId(std::string_view pointStr, size_t& length) const; std::string_view GetPointNameForBegin(std::string_view pointStr, size_t tGidlength) const; ParseResult HandlerB(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const; - ParseResult HandlerE(void) const; + static ParseResult HandlerE(void); ParseResult HandlerCSF(std::string_view pointStr, TracePoint& outPoint, size_t tGidlength) const; - size_t GetNameLength(std::string_view pointStr, size_t nameIndex) const; + static size_t GetNameLength(std::string_view pointStr, size_t nameIndex); size_t GetValueLength(std::string_view pointStr, size_t valueIndex) const; private: const uint32_t pointLength_; const uint32_t maxPointLength_; + TraceStreamerConfig config_{}; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/parser/thread_state.cpp b/host/trace_streamer/src/parser/thread_state.cpp old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/README_zh.md b/host/trace_streamer/src/protos/README_zh.md index 112aca9fde16f35a2df60912239483812ae69484..6e49694e23aafe5dcfd18c921519b3f5edda1911 100644 --- a/host/trace_streamer/src/protos/README_zh.md +++ b/host/trace_streamer/src/protos/README_zh.md @@ -4,7 +4,7 @@ `services` 目录下存放的是 服务接口定义, -`types` 目录下存放的是 具体插件业务相关的类型定义,主要为配置类型和结果类型定义; +`types` 目录下存放的是 具体插件业务相关的类型定义,主要为配置类型和结果类型定义。 -例如,`types/plugins/cpu_data/` 目录存放CPU数据插件的配置类型和结果类型; +例如,`types/plugins/cpu_data/` 目录存放CPU数据插件的配置类型和结果类型。 diff --git a/host/trace_streamer/src/protos/protogen.sh b/host/trace_streamer/src/protos/protogen.sh old mode 100644 new mode 100755 index c35b0515d89492c2de6a9266ab5c36913943aba7..f13acb2738be1a01e9f801072efb6ff2637d223d --- a/host/trace_streamer/src/protos/protogen.sh +++ b/host/trace_streamer/src/protos/protogen.sh @@ -11,18 +11,38 @@ # 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. +set -e +protoc='protoc' +proto_dir='.' +case "$OSTYPE" in + msys*) out='../../out/windows' protoc='protoc.exe' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; + darwin*) out='../../out/macx' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; + linux*) out='../../out/linux' proto_dir=$( cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) ;; + *) echo "other: $OSTYPE" ;; +esac +echo $proto_dir SOURCE="${BASH_SOURCE[0]}" cd $(dirname ${SOURCE}) +if [ ! -f $out/$protoc ];then + echo "no $out/$protoc found, you need to run \"./build.sh protoc\" at root folder, and copy protoc.exe to $out/$protoc" + exit +fi echo "begin to generate proto based files" SOURCE=$(dirname ${SOURCE}) -proto_dir="." services_dir="$proto_dir/services" -ftrace_data_dir="$proto_dir/types/plugins/ftrace_data" +# kernel_version="5.10.79_aarch64" +kernel_version="." +ftrace_data_dir="$proto_dir/types/plugins/ftrace_data/$kernel_version" memory_data_dir="$proto_dir/types/plugins/memory_data" hilog_data_dir="$proto_dir/types/plugins/hilog_data" native_hook_dir="$proto_dir/types/plugins/native_hook" hidump_data_dir="$proto_dir/types/plugins/hidump_data" -arrayWen=("${services_dir}/common_types.proto" +network_data_dir="$proto_dir/types/plugins/network_data" +cpu_data_dir="$proto_dir/types/plugins/cpu_data" +diskio_data_dir="$proto_dir/types/plugins/diskio_data" +process_data_dir="$proto_dir/types/plugins/process_data" +hisysevent_data_dir="$proto_dir/types/plugins/hisysevent_data" +proto_array=("${services_dir}/common_types.proto" "$ftrace_data_dir/trace_plugin_result.proto" "$ftrace_data_dir/ftrace_event.proto" "$ftrace_data_dir/irq.proto" @@ -64,15 +84,21 @@ arrayWen=("${services_dir}/common_types.proto" "$native_hook_dir/native_hook_result.proto" "$native_hook_dir/native_hook_config.proto" "$hidump_data_dir/hidump_plugin_result.proto" - "$hidump_data_dir/hidump_plugin_config.proto") + "$network_data_dir/network_plugin_result.proto" + "$cpu_data_dir/cpu_plugin_result.proto" + "$diskio_data_dir/diskio_plugin_result.proto" + "$hisysevent_data_dir/hisysevent_plugin_config.proto" + "$process_data_dir/process_plugin_result.proto" + "$hisysevent_data_dir/hisysevent_plugin_result.proto") -export LD_LIBRARY_PATH=../../out/linux -for ((i = 0; i < ${#arrayWen[@]}; i ++)) +export LD_LIBRARY_PATH=$out +for ((i = 0; i < ${#proto_array[@]}; i ++)) do - newpath=$(dirname ${arrayWen[$i]}) - newpath=${newpath:2} + newpath=$(dirname ${proto_array[$i]}) + tailpath='\'${newpath#$proto_dir} + newpath=${tailpath:2} cppout=../../third_party/protogen/$newpath mkdir -p $cppout - ../../out/linux/protoc --proto_path=$memory_data_dir:$native_hook_dir:$hidump_data_dir:$hilog_data_dir:$ftrace_data_dir:$services_dir --cpp_out=$cppout ${arrayWen[$i]} + $out/$protoc --proto_path=$memory_data_dir:$native_hook_dir:$hidump_data_dir:$hilog_data_dir:$ftrace_data_dir:$services_dir:$network_data_dir:$cpu_data_dir:$diskio_data_dir:$process_data_dir:$hisysevent_data_dir --cpp_out=$cppout ${proto_array[$i]} done echo "generate proto based files over" \ No newline at end of file diff --git a/host/trace_streamer/src/protos/protos.gni b/host/trace_streamer/src/protos/protos.gni old mode 100644 new mode 100755 index 59b67bb4b515a7fbc307e19b3349aad8ee5e25c2..f8582402a8b542f4435fdeda2e18278b1bd725e7 --- a/host/trace_streamer/src/protos/protos.gni +++ b/host/trace_streamer/src/protos/protos.gni @@ -11,14 +11,26 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("../../../build/config.gni") +import("../build/config.gni") subsys_name = OHOS_PROFILER_SUBSYS_NAME -subsys_x64_out = "clang_x64/$subsys_name/$subsys_name" +part_name = OHOS_PROFILER_PART_NAME +subsys_x64_out = "clang_x64/$subsys_name/$part_name" libc_dir_proto = rebase_path("$asdk_libs_dir", "//") root_output_dir_proto = rebase_path("$root_out_dir", "//") -# print("grpc_cpp_plugin = ", grpc_cpp_plugin) -# print("ipc_cpp_plugin = ", ipc_cpp_plugin) -# print("root_build_dir = ", root_build_dir) -# print("root_out_dir = ", root_out_dir) -# print("root_gen_dir = ", root_gen_dir) + +#host:clang_x64 default:arm mingw:mingw_x86_64 +if (current_toolchain != host_toolchain) { + if (current_toolchain == default_toolchain) { + root_output_dir_proto = "$root_output_dir_proto/clang_x64" + } else { + root_output_dir_proto = + get_path_info("$root_output_dir_proto", "dir") + "/clang_x64" + } +} +protoc = root_output_dir_proto +print("default_toolchain = ", default_toolchain) +print("current_toolchain = ", current_toolchain) +print("host_toolchain = ", host_toolchain) +print("root_out_dir = ", root_out_dir) +print("root_output_dir_proto = ", root_output_dir_proto) diff --git a/host/trace_streamer/src/protos/services/BUILD.gn b/host/trace_streamer/src/protos/services/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/services/common_types.proto b/host/trace_streamer/src/protos/services/common_types.proto old mode 100644 new mode 100755 index fa67090edba2d200a1f505316e7df62252f3dd0f..32559daf3b07a34bf9c80c78495bc41adf6e3652 --- a/host/trace_streamer/src/protos/services/common_types.proto +++ b/host/trace_streamer/src/protos/services/common_types.proto @@ -55,4 +55,5 @@ message ProfilerPluginData { ClockId clock_id = 4; uint64 tv_sec = 5; uint64 tv_nsec = 6; + string version = 7; // "1.01" } diff --git a/host/trace_streamer/src/protos/services/plugin_service.proto b/host/trace_streamer/src/protos/services/plugin_service.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/services/plugin_service_types.proto b/host/trace_streamer/src/protos/services/plugin_service_types.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/services/profiler_service.proto b/host/trace_streamer/src/protos/services/profiler_service.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/services/profiler_service_types.proto b/host/trace_streamer/src/protos/services/profiler_service_types.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/agent_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_app_data.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_app_data.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_energy_data.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_energy_data.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_java_heap.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_java_heap.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_network_data.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_network_data.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/agent_data/agent_plugin_result.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/bytrace_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/bytrace_plugin/bytrace_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/cpu_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_result.proto old mode 100644 new mode 100755 index 7b18965564cf2ffdf738b9f346fe16d1a3080175..781a8f521fea4878fc1bf53c040e32ec4d31d829 --- a/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_result.proto +++ b/host/trace_streamer/src/protos/types/plugins/cpu_data/cpu_plugin_result.proto @@ -68,4 +68,8 @@ message ThreadInfo { message CpuData { CpuUsageInfo cpu_usage_info = 1; repeated ThreadInfo thread_info = 2; + int64 process_num = 3; + double user_load = 4; + double sys_load = 5; + double total_load = 6; } diff --git a/host/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/diskio_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_config.proto old mode 100644 new mode 100755 index 4e69f0d051c0268bcd0f6d161701bf214e0e5225..8caac241978ff6910abff7aead9b0e60f22aa649 --- a/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_config.proto +++ b/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_config.proto @@ -16,8 +16,13 @@ syntax = "proto3"; option java_package = "ohos.devtools.datasources.transport.grpc.service"; option optimize_for = LITE_RUNTIME; - // Diskio plug-in configuration, passed to plug-in by plug-in service. message DiskioConfig { int32 unspeci_fied = 1; // Reserved field, not used + enum IoReportType { + UNSPECIFIED = 0; + IO_REPORT = 1; + IO_REPORT_EX = 2; + } + IoReportType report_io_stats = 2; } diff --git a/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_result.proto old mode 100644 new mode 100755 index 742e9a64ffc2f828331fd557fc26cc058df0f038..faabd31436d4dbf58c62c68330367b60b7c97cc4 --- a/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_result.proto +++ b/host/trace_streamer/src/protos/types/plugins/diskio_data/diskio_plugin_result.proto @@ -1,31 +1,88 @@ -// 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. - -syntax = "proto3"; - -option java_package = "ohos.devtools.datasources.transport.grpc.service"; -option optimize_for = LITE_RUNTIME; - -message CollectTimeStamp { - uint64 tv_sec = 1; - uint64 tv_nsec = 2; -} - -message DiskioData { - int64 prev_rd_sectors_kb = 1; - int64 prev_wr_sectors_kb = 2; - CollectTimeStamp prev_timestamp = 3; - int64 rd_sectors_kb = 4; - int64 wr_sectors_kb = 5; - CollectTimeStamp timestamp = 6; +// 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. + +syntax = "proto3"; + +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +message CollectTimeStamp { + uint64 tv_sec = 1; + uint64 tv_nsec = 2; +} + +message CpuStats { + string name = 1; + double cpu_user = 2; + double cpu_nice = 3; + double cpu_sys = 4; + double cpu_idle = 5; + double cpu_iowait = 6; + double cpu_steal = 7; +} + +message IoStatData { + string name = 1; + double ios_per_sec = 2; // 设备每秒的传输次数 + double rd_per_sec = 3; // 每秒从设备读取的数据量 kB_read/s + double wr_per_sec = 4; // 每秒向设备写入的数据量 kB_wrtn/s + double dc_per_sec = 5; // kB_dscd/s + uint64 rd_kb = 6; // 读取的总数据量 kB_read + uint64 wr_kb = 7; // 写入的总数量数据量 kB_wrtn + uint64 dc_kb = 8; // kB_dscd +} + +message IoStatExData { + string name = 1; + uint64 io_rd = 2; // r/s + uint64 io_rsectors = 3; // kB/s, r+w+d + uint64 io_rrqm = 4; // rrqm/s + uint64 io_rrqm_pc = 5; // %rrqm + uint64 io_r_await = 6; // r_await + uint64 io_rarqsz = 7; // rareq-sz + + uint64 io_wr = 8; // w/s + uint64 io_wsectors = 9; // wkB/s , r+w+d + uint64 io_wrqm = 10; // wrqm/s + uint64 io_wrqm_pc = 11; // %wrqm + uint64 io_w_await = 12; // w_await + uint64 io_warqsz = 13; // wareq-sz + + uint64 io_dc = 14; // d/s + uint64 io_dsectors = 15; // dkB/s, r+w+d + uint64 io_drqm = 16; // drqm/s + uint64 io_drqm_pc = 17; // %drqm + uint64 io_d_await = 18; // d_await + uint64 io_darqsz = 19; // dareq-sz + + uint64 io_fd = 20; // f/s + uint64 io_f_await = 21; // f_await + uint64 io_farqsz = 22; // fareq-sz + uint64 disk_util = 23; // fareq-sz +} + +message StatsData { + repeated CpuStats cpuinfo = 1; + repeated IoStatData statsinfo = 2; + repeated IoStatExData estatsinfo = 3; +} + +message DiskioData { + int64 prev_rd_sectors_kb = 1; + int64 prev_wr_sectors_kb = 2; + CollectTimeStamp prev_timestamp = 3; + int64 rd_sectors_kb = 4; + int64 wr_sectors_kb = 5; + CollectTimeStamp timestamp = 6; + StatsData statsData = 7; } \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/ftrace_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/autogenerated.gni b/host/trace_streamer/src/protos/types/plugins/ftrace_data/autogenerated.gni old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/binder.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/binder.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/block.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/block.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/cgroup.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/cgroup.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/clk.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/clk.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/compaction.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/compaction.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/cpuhp.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/cpuhp.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/dma_fence.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/dma_fence.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/ext4.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ext4.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/filelock.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/filelock.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/filemap.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/filemap.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace.proto old mode 100644 new mode 100755 index 6c9429dd63b99dba7aea98a040497e7f72bcf6da..80c23a999c8129916bd7608b0e3c99fe107181b4 --- a/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace.proto +++ b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace.proto @@ -68,7 +68,7 @@ message FunctionFormat { // /sys/kernel/debug/tracing/events/ftrace/kernel_stack/format message KernelStackFormat { int32 size = 1; - uint64 caller = 2; + repeated uint64 caller = 2; } // /sys/kernel/debug/tracing/events/ftrace/mmiotrace_map/format @@ -99,7 +99,7 @@ message PrintFormat { // /sys/kernel/debug/tracing/events/ftrace/user_stack/format message UserStackFormat { uint32 tgid = 1; - string caller = 2; + repeated uint64 caller = 2; } // /sys/kernel/debug/tracing/events/ftrace/wakeup/format diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace_event.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ftrace_event.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/gpio.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/gpio.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/i2c.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/i2c.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/ipi.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/ipi.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/irq.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/irq.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/kmem.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/kmem.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/net.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/net.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/oom.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/oom.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/pagemap.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/pagemap.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/power.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/power.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/printk.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/printk.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/raw_syscalls.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/raw_syscalls.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/rcu.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/rcu.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/sched.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/sched.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/signal.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/signal.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/sunrpc.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/sunrpc.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/task.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/task.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/timer.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/timer.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/v4l2.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/v4l2.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/vmscan.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/vmscan.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/workqueue.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/workqueue.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/ftrace_data/writeback.proto b/host/trace_streamer/src/protos/types/plugins/ftrace_data/writeback.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/hidump_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/hidump_data/hidump_plugin_result.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/hilog_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/hilog_data/hilog_plugin_result.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/hiperf_call_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/hiperf_call_plugin/hiperf_call_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2fb7e74b30699aaa485655d980394167b6618d3a --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hisysevent_data/BUILD.gn @@ -0,0 +1,87 @@ +# 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("//build/ohos.gni") +import("../../../protos.gni") + +hisysevent_data_sources = [ + "./hisysevent_plugin_config.proto", + "./hisysevent_plugin_result.proto", +] + +####################################################### +proto_out_dir = "$root_gen_dir/cpp/" + rebase_path(".", "//") +proto_rel_out_dir = rebase_path(proto_out_dir, root_build_dir) + +hisysevent_data_codegen = [] +hisysevent_data_codegen_standard = [] +hisysevent_data_codegen_all = [] + +foreach(proto, hisysevent_data_sources) { + name = get_path_info(proto, "name") + hisysevent_data_codegen += [ + "$proto_out_dir/$name.pb.h", + "$proto_out_dir/$name.pb.cc", + ] + hisysevent_data_codegen_standard += [ + "$proto_out_dir/${name}_standard.pb.h", + "$proto_out_dir/${name}_standard.pb.cc", + ] +} + +hisysevent_data_codegen_all += hisysevent_data_codegen +hisysevent_data_codegen_all += hisysevent_data_codegen_standard + +config("hisysevent_include_config") { + include_dirs = [ "$proto_out_dir" ] +} + +####################################################### +action("hisysevent_data_cpp_gen") { + script = "${OHOS_PROFILER_DIR}/build/protoc.sh" + sources = hisysevent_data_sources + outputs = hisysevent_data_codegen_all + args = [ + "$libc_dir_proto", + "$root_output_dir_proto", + "$proto_rel_out_dir", + "--cpp_out", + "$proto_rel_out_dir", + "--proto_path", + rebase_path(".", root_build_dir), + ] + args += rebase_path(sources, root_build_dir) + deps = [ "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protoc(${host_toolchain})" ] +} + +ohos_source_set("hisysevent_data_cpp") { + deps = [ ":hisysevent_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":hisysevent_include_config" ] + sources = hisysevent_data_codegen +} + +ohos_source_set("hisysevent_data_cpp_standard") { + deps = [ ":hisysevent_data_cpp_gen" ] + public_deps = [ + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf", + "${OHOS_PROFILER_3RDPARTY_PROTOBUF_DIR}:protobuf_lite", + ] + include_dirs = [ "$proto_out_dir" ] + public_configs = [ ":hisysevent_include_config" ] + sources = hisysevent_data_codegen_standard +} diff --git a/host/trace_streamer/src/protos/types/plugins/hisysevent_data/hisysevent_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/hisysevent_data/hisysevent_plugin_config.proto new file mode 100644 index 0000000000000000000000000000000000000000..9b7a6e5270599141a658551e9e6377e8c291d395 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hisysevent_data/hisysevent_plugin_config.proto @@ -0,0 +1,21 @@ +// 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. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +// TODO Save the fetch data +message HisyseventConfig { + string msg = 1; + string process_name = 2; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/hisysevent_data/hisysevent_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/hisysevent_data/hisysevent_plugin_result.proto new file mode 100644 index 0000000000000000000000000000000000000000..4dba0ff2b16e93fa2b68917d8e10ec619b72efd2 --- /dev/null +++ b/host/trace_streamer/src/protos/types/plugins/hisysevent_data/hisysevent_plugin_result.proto @@ -0,0 +1,55 @@ +// 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. +syntax = "proto3"; +option java_package = "ohos.devtools.datasources.transport.grpc.service"; +option optimize_for = LITE_RUNTIME; + +// For Device Stat all below. +message AudioVolumeInfo { + int32 stream_default = 1; + int32 voice_call = 2; + int32 music = 3; + int32 stream_ring = 4; + int32 media = 5; + int32 voice_assistant = 6; + int32 system = 7; + int32 alarm = 8; + int32 notification = 9; + int32 bluetoolth_sco = 10; + int32 enforced_audible = 11; + int32 stream_dtmf = 12; + int32 stream_tts = 13; + int32 accessibility = 14; + int32 recording = 15; + int32 stream_all = 16; +} + +// NODE Save the Device Stat +message DeviceStat { + uint32 brightness_state = 1; + int32 bt_state = 2; + bool location_state = 3; + int32 wifi_state = 4; + AudioVolumeInfo volume_state = 5; +} + +// NODE Save the captured data +message HisyseventLine { + string raw_content = 1; + uint64 id = 2; +} + +message HisyseventInfo { + repeated HisyseventLine info = 1; + DeviceStat device_state = 2; +} \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/memory_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_common.proto b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_common.proto old mode 100644 new mode 100755 index 1dac1d9a9c82ae6870413051f5c4d02b7fa7b43d..361b65e87016a5e9f253c3529aa9a7437954c380 --- a/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_common.proto +++ b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_common.proto @@ -52,6 +52,7 @@ enum SysMeminfoType { PMEM_VMALLOC_CHUNK = 31; PMEM_CMA_TOTAL = 32; PMEM_CMA_FREE = 33; + PMEM_KERNEL_RECLAIMABLE = 34; } enum SysVMeminfoType { diff --git a/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_result.proto old mode 100644 new mode 100755 index c0e622762d0125ea8e3f99d239153dfb5fe07eb6..f639590d69e8c2e9b64becf19337cdf2c5620a3f --- a/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_result.proto +++ b/host/trace_streamer/src/protos/types/plugins/memory_data/memory_plugin_result.proto @@ -31,11 +31,16 @@ message SysVMeminfo { }; message SmapsInfo { - string mapinfo = 1; - int32 size = 2; - int32 rss = 3; - int32 pss = 4; - int32 anonymous = 5; + string start_addr = 1; + string end_addr = 2; + string permission = 3; + string path = 4; + uint64 size = 5; + uint64 rss = 6; + uint64 pss = 7; + double reside = 8; + uint64 dirty = 9; + uint64 swapper = 10; }; message AppSummary { @@ -70,4 +75,5 @@ message MemoryData { repeated ProcessMemoryInfo processesinfo = 1; repeated SysMeminfo meminfo = 2; repeated SysVMeminfo vmeminfo = 3; + uint64 zram = 4; } diff --git a/host/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/native_hook/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto b/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto old mode 100644 new mode 100755 index 3a93eff3c7b733c04b2adf42a5fc16ff2bc986e8..1727c7acd3e85a0a4b3bf90ce69ecfac907fb278 --- a/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto +++ b/host/trace_streamer/src/protos/types/plugins/native_hook/native_hook_result.proto @@ -23,6 +23,8 @@ message Frame { string file_path = 4; uint64 offset = 5; uint64 symbol_offset = 6; + uint32 symbol_name_id = 7; + uint32 file_path_id = 8; } message AllocEvent { @@ -31,6 +33,7 @@ message AllocEvent { uint64 addr = 3; uint32 size = 4; repeated Frame frame_info = 5; + uint32 thread_name_id = 6; } message FreeEvent { @@ -38,6 +41,47 @@ message FreeEvent { int32 tid = 2; uint64 addr = 3; repeated Frame frame_info = 4; + uint32 thread_name_id = 5; +} + +message MmapEvent { + int32 pid = 1; + int32 tid = 2; + uint64 addr = 3; + string type = 4; + uint32 size = 5; + repeated Frame frame_info = 6; + uint32 thread_name_id = 7; +} + +message MunmapEvent { + int32 pid = 1; + int32 tid = 2; + uint64 addr = 3; + uint32 size = 4; + repeated Frame frame_info = 5; + uint32 thread_name_id = 6; +} + +message MemTagEvent { + uint64 addr = 1; + uint32 size = 2; + string tag = 3; +} + +message FilePathMap { + uint32 id = 1; + string name = 2; +} + +message SymbolMap { + uint32 id = 1; + string name = 2; +} + +message ThreadNameMap { + uint32 id = 1; + string name = 2; } message NativeHookData { @@ -46,6 +90,12 @@ message NativeHookData { oneof event { AllocEvent alloc_event = 3; FreeEvent free_event = 4; + MmapEvent mmap_event = 5; + MunmapEvent munmap_event = 6; + MemTagEvent tag_event = 7; + FilePathMap file_path = 8; + SymbolMap symbol_name = 9; + ThreadNameMap thread_name_map = 10; } } diff --git a/host/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/network_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_result.proto old mode 100644 new mode 100755 index 8df215fb18ff4edf0229e1302ae254008e12980e..2ce759cc660ed0abf3f6c3a42cdbd7e74c5eb68d --- a/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_result.proto +++ b/host/trace_streamer/src/protos/types/plugins/network_data/network_plugin_result.proto @@ -32,6 +32,26 @@ message NetworkData { repeated NetworkDetails details = 6; } +message NetworkSystemDetails { + string type = 1; // e.g. "wlan0", "rmnet0", etc. + uint64 rx_bytes = 2; + uint64 rx_packets = 3; + uint64 tx_bytes = 4; + uint64 tx_packets = 5; +} + +message NetworkSystemData { + // timestamp obtained by CLOCK_REALTIME + uint64 tv_sec = 1; + uint64 tv_nsec = 2; + uint64 rx_bytes = 3; + uint64 rx_packets = 4; + uint64 tx_bytes = 5; + uint64 tx_packets = 6; + repeated NetworkSystemDetails details = 7; +} + message NetworkDatas { repeated NetworkData networkinfo = 1; + NetworkSystemData network_system_info = 2; } \ No newline at end of file diff --git a/host/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/process_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_result.proto old mode 100644 new mode 100755 index 53f586b5feccf678ffb98979fe2cbc098293e7c3..8f790ed024b487fab19cb058da0bfa27c708904b --- a/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_result.proto +++ b/host/trace_streamer/src/protos/types/plugins/process_data/process_plugin_result.proto @@ -16,9 +16,36 @@ syntax = "proto3"; option java_package = "ohos.devtools.datasources.transport.grpc.service"; option optimize_for = LITE_RUNTIME; +message DiskioInfo { + // read /proc/pid/io + uint64 rchar = 1; + uint64 wchar = 2; + uint64 syscr = 3; + uint64 syscw = 4; + uint64 rbytes = 5; + uint64 wbytes = 6; + uint64 cancelled_wbytes = 7; +} + +message PssInfo { + // read /proc/pid/smaps_rollup + int32 pss_info = 1; +} + +message CpuInfo { + double cpu_usage = 1; + int32 thread_sum = 2; + uint64 cpu_time_ms = 3; +} + message ProcessInfo { int32 pid = 1; string name = 2; + int32 ppid = 3; + int32 uid = 4; + CpuInfo cpuinfo = 5; + PssInfo pssinfo = 6; + DiskioInfo diskinfo = 7; } message ProcessData { diff --git a/host/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/sample_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/sample_data/sample_plugin_result.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn b/host/trace_streamer/src/protos/types/plugins/stream_data/BUILD.gn old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_config.proto b/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_config.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_result.proto b/host/trace_streamer/src/protos/types/plugins/stream_data/stream_plugin_result.proto old mode 100644 new mode 100755 diff --git a/host/trace_streamer/src/rpc/http_server.cpp b/host/trace_streamer/src/rpc/http_server.cpp old mode 100644 new mode 100755 index ada95d93e64b71f52b4319a518126a644e8590b0..a6c94471052c868786b1dd0d120f51d63a8d1fa4 --- a/host/trace_streamer/src/rpc/http_server.cpp +++ b/host/trace_streamer/src/rpc/http_server.cpp @@ -17,6 +17,7 @@ #include #include #include +#include // for macx #include #ifdef _WIN32 #include @@ -25,6 +26,7 @@ #include #endif #include "log.h" +#include "string_to_numerical.h" namespace SysTuning { namespace TraceStreamer { void HttpServer::RegisterRpcFunction(RpcServer* rpc) @@ -100,7 +102,7 @@ void HttpServer::Run(int port) } } - for (auto& it : clientThreads_) { + for (const auto& it : clientThreads_) { if (it->thread_.joinable()) { it->sock_.Close(); it->thread_.join(); @@ -113,22 +115,25 @@ void HttpServer::Run(int port) #else void HttpServer::Run(int port) { - signal(SIGPIPE, SIG_IGN); + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { + return; + } if (!CreateSocket(port)) { return; } TS_LOGI("http server running"); - - struct pollfd fds[COUNT_SOCKET] = {{sockets_[0].GetFd(), POLLIN, 0}, {sockets_[1].GetFd(), POLLIN, 0}}; + struct pollfd fds[COUNT_SOCKET]; + for (int i = 0; i < COUNT_SOCKET; i++) { + fds[i] = {sockets_[i].GetFd(), POLLIN, 0}; + } while (!isExit_) { ClearDeadClientThread(); - - if (poll(fds, sizeof(fds)/sizeof(pollfd), pollTimeOut_) <= 0) { + if (poll(fds, sizeof(fds) / sizeof(pollfd), pollTimeOut_) <= 0) { continue; // try again } - for (int i = 0; i < COUNT_SOCKET; i++) { + for (int i = 0; i < 1; i++) { if (fds[i].revents != POLLIN) { continue; } @@ -137,19 +142,22 @@ void HttpServer::Run(int port) client->thread_ = std::thread(&HttpServer::ProcessClient, this, std::ref(client->sock_)); clientThreads_.push_back(std::move(client)); } else { - TS_LOGE("http socket accept error"); std::this_thread::sleep_for(std::chrono::seconds(1)); } } } - for (auto& it : clientThreads_) { + for (const auto& it : clientThreads_) { if (it->thread_.joinable()) { it->sock_.Close(); it->thread_.join(); } } clientThreads_.clear(); + + for (int i = 0; i < COUNT_SOCKET; i++) { + sockets_[i].Close(); + } TS_LOGI("http server exit"); } #endif @@ -164,11 +172,11 @@ void HttpServer::Exit() bool HttpServer::CreateSocket(int port) { - if (!sockets_[0].CreateSocket(AF_INET) || !sockets_[1].CreateSocket(AF_INET6)) { - TS_LOGE("Create http socket error"); - return false; - } for (int i = 0; i < COUNT_SOCKET; i++) { + if (!sockets_[i].CreateSocket(i == 0 ? AF_INET : AF_INET6)) { + TS_LOGE("Create http socket error"); + return false; + } if (!sockets_[i].Bind(port)) { TS_LOGE("bind http socket error"); return false; @@ -260,7 +268,7 @@ void HttpServer::ProcessClient(HttpSocket& client) struct pollfd fd = {client.GetFd(), POLLIN, 0}; while (!isExit_) { - int pollRet = poll(&fd, sizeof(fd)/sizeof(pollfd), pollTimeOut_); + int pollRet = poll(&fd, sizeof(fd) / sizeof(pollfd), pollTimeOut_); if (pollRet < 0) { TS_LOGE("poll client socket(%d) error: %d:%s", client.GetFd(), errno, strerror(errno)); break; @@ -275,6 +283,7 @@ void HttpServer::ProcessClient(HttpSocket& client) continue; } if (!client.Recv(recvBuf.data() + recvPos, recvLen)) { + TS_LOGI("client exit"); break; } recvPos += recvLen; @@ -289,6 +298,7 @@ void HttpServer::ProcessClient(HttpSocket& client) TS_LOGI("recive client thread exit. socket(%d)", client.GetFd()); client.Close(); + TS_LOGI("thread exit"); } #endif @@ -296,18 +306,19 @@ void HttpServer::ProcessRequest(HttpSocket& client, RequestST& request) { if (request.stat == RequstParseStat::RECVING) { TS_LOGE("http request data missing, client %d\n", client.GetFd()); - HttpResponse(client, "408 Request Time-out"); + HttpResponse(client, "408 Request Time-out\r\n"); return; } else if (request.stat != RequstParseStat::OK) { TS_LOGE("bad http request, client %d\n", client.GetFd()); - HttpResponse(client, "400 Bad Request"); + HttpResponse(client, "400 Bad Request\r\n"); return; } if (request.method == "OPTIONS") { - HttpResponse(client, "204 No Content\r\n" - "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n" - "Access-Control-Allow-Headers: *\r\n" - "Access-Control-Max-Age: 86400\r\n"); + HttpResponse(client, + "204 No Content\r\n" + "Access-Control-Allow-Methods: POST, GET, OPTIONS\r\n" + "Access-Control-Allow-Headers: *\r\n" + "Access-Control-Max-Age: 86400\r\n"); return; } else if (request.method != "POST" && request.method != "GET") { TS_LOGE("method(%s) not allowed, client %d", request.method.c_str(), client.GetFd()); @@ -321,7 +332,7 @@ void HttpServer::ProcessRequest(HttpSocket& client, RequestST& request) return; } HttpResponse(client, "200 OK\r\n", true); - auto resultCallback = [&](const std::string result) { + auto resultCallback = [&client](const std::string& result, int) { std::stringstream chunkLenbuff; chunkLenbuff << std::hex << result.size() << "\r\n"; if (!client.Send(chunkLenbuff.str().data(), chunkLenbuff.str().size())) { @@ -366,8 +377,7 @@ void HttpServer::ParseRequest(const uint8_t* requst, size_t& len, RequestST& htt const size_t indexHttpUri = 1; const size_t indexHttpVersion = 2; const size_t countRequestItems = 3; - if (requestItems.size() != countRequestItems || - requestItems[indexHttpVersion] != "HTTP/1.1") { + if (requestItems.size() != countRequestItems || requestItems[indexHttpVersion] != "HTTP/1.1") { len = 0; httpReq.stat = RequstParseStat::BAD; return; @@ -376,16 +386,16 @@ void HttpServer::ParseRequest(const uint8_t* requst, size_t& len, RequestST& htt httpReq.uri = requestItems[indexHttpUri]; for (size_t i = 1; i < headerlines.size(); i++) { - size_t tagPos = headerlines[i].find(": "); + size_t tagPos = headerlines[i].find(":"); if (tagPos == std::string_view::npos) { len = 0; httpReq.stat = RequstParseStat::BAD; return; } std::string_view tag = headerlines[i].substr(0, tagPos); - if (strncasecmp(tag.data(), "content-length", tag.size()) == 0) { - std::string value(headerlines[i].data() + tagPos + strlen(": "), - headerlines[i].size() - tagPos - strlen(": ")); + if (strncasecmp(tag.data(), "Content-Length", tag.size()) == 0) { + std::string value(headerlines[i].data() + tagPos + strlen(":"), + headerlines[i].size() - tagPos - strlen(":")); size_t conterntLen = atoi(value.c_str()); if (conterntLen > httpReq.bodyLen) { httpReq.stat = RequstParseStat::RECVING; @@ -411,16 +421,13 @@ void HttpServer::HttpResponse(HttpSocket& client, const std::string& status, boo res.reserve(maxLenResponse); res += "HTTP/1.1 "; res += status; - res += "\r\n"; res += "Connection: Keep-Alive\r\n"; - if (hasBody) { res += "Content-Type: application/json\r\n"; res += "Transfer-Encoding: chunked\r\n"; } res += "\r\n"; - if (!client.Send(res.data(), res.size())) { TS_LOGE("send client socket(%d) error", client.GetFd()); } diff --git a/host/trace_streamer/src/rpc/http_server.h b/host/trace_streamer/src/rpc/http_server.h old mode 100644 new mode 100755 index e8d4305905ef14bad19fb3fb4e59f8b229d13bc3..e1bd125567c8845c46d721786686d8ea6fc7f56b --- a/host/trace_streamer/src/rpc/http_server.h +++ b/host/trace_streamer/src/rpc/http_server.h @@ -57,12 +57,12 @@ private: bool CreateSocket(int port); void ProcessClient(HttpSocket& client); void ProcessRequest(HttpSocket& client, RequestST& request); - void HttpResponse(HttpSocket& client, const std::string& status, bool hasBody = false); + static void HttpResponse(HttpSocket& client, const std::string& status, bool hasBody = false); void ParseRequest(const uint8_t* requst, size_t& len, RequestST& httpReq); void ClearDeadClientThread(); - std::vector StringSplit(std::string_view source, std::string_view split); + static std::vector StringSplit(std::string_view source, std::string_view split); - static const int COUNT_SOCKET = 2; + static const int COUNT_SOCKET = 1; HttpSocket sockets_[COUNT_SOCKET]; // ipv4 and ipv6 std::atomic_bool isExit_ = {false}; std::vector> clientThreads_; diff --git a/host/trace_streamer/src/rpc/http_socket.cpp b/host/trace_streamer/src/rpc/http_socket.cpp old mode 100644 new mode 100755 index dee3474f34eeabf061b06134071ae432f610a723..e5e9cbe50cec847154d5ba11b5fdd4286dae0d27 --- a/host/trace_streamer/src/rpc/http_socket.cpp +++ b/host/trace_streamer/src/rpc/http_socket.cpp @@ -150,7 +150,7 @@ bool HttpSocket::Send(const void* data, size_t len) TS_LOGE("send to socket(%d) error: %d:%s", sockId_, errno, strerror(errno)); return false; } - TS_LOGD("send to socket(%d) len %zu", sockId_, len); + TS_LOGI("send to socket(%d) len %zu", sockId_, len); return true; } diff --git a/host/trace_streamer/src/rpc/http_socket.h b/host/trace_streamer/src/rpc/http_socket.h old mode 100644 new mode 100755 index f03ccb5e3959a951d4d455908fe2a5b9f8cee5fc..d710f16692caa7791712b5d427b47c137044a7a2 --- a/host/trace_streamer/src/rpc/http_socket.h +++ b/host/trace_streamer/src/rpc/http_socket.h @@ -32,7 +32,11 @@ public: bool Recv(void* data, size_t& len); bool Send(const void* data, size_t len); void Close(); - int GetFd() + bool IsValid() const + { + return sockId_ != INVALID_SOCKET; + } + int GetFd() const { return sockId_; } @@ -40,11 +44,9 @@ public: private: int sockId_ = -1; int domain_ = 0; -#ifndef _WIN32 using SOCKET = int; const int SOCKET_ERROR = -1; const SOCKET INVALID_SOCKET = -1; -#endif }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/rpc/rpc_server.cpp b/host/trace_streamer/src/rpc/rpc_server.cpp index 64a9d96cedc0bcf1cc1d50056f8627be9e90fc49..fe6ad365b1f008c14d0c03612637cc2e56186372 100644 --- a/host/trace_streamer/src/rpc/rpc_server.cpp +++ b/host/trace_streamer/src/rpc/rpc_server.cpp @@ -15,26 +15,30 @@ #include "rpc_server.h" +#include #include #include -#include #include "log.h" +#include "meta.h" +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) namespace SysTuning { namespace TraceStreamer { bool RpcServer::ParseData(const uint8_t* data, size_t len, ResultCallBack resultCallBack) { - TS_LOGI("RPC ParseData, has parsed len %zu + %zu", lenParseData_, len); + g_loadSize += len; + size_t blockSize = 1024 * 1024; do { - constexpr size_t blockSize = 1024 * 1024; size_t parseSize = std::min(len, blockSize); std::unique_ptr buf = std::make_unique(parseSize); std::copy(data, data + parseSize, buf.get()); - if (!ts_->ParseTraceDataSegment(std::move(buf), parseSize)) { if (resultCallBack) { - resultCallBack("formaterror\r\n"); + resultCallBack("formaterror\r\n", SEND_FINISH); } return false; } @@ -43,26 +47,79 @@ bool RpcServer::ParseData(const uint8_t* data, size_t len, ResultCallBack result lenParseData_ += parseSize; } while (len > 0); if (resultCallBack) { - resultCallBack("ok\r\n"); + resultCallBack("ok\r\n", SEND_FINISH); } return true; } +int RpcServer::UpdateTraceTime(const uint8_t* data, int len) +{ + std::unique_ptr buf = std::make_unique(len); + std::copy(data, data + len, buf.get()); + ts_->UpdateTraceRangeTime(buf.get(), len); + return 0; +} + +int RpcServer::TraceStreamer_Init_ThirdParty_Config(const uint8_t* data, int len) +{ + TS_LOGE("TraceStreamer_Init_ThirdParty_Config is comming!"); + std::string thirdPartyConfig = reinterpret_cast(data); + TS_LOGE("thirdPartyConfig = %s", thirdPartyConfig.c_str()); + int size = thirdPartyConfig.size(); + std::vector vTraceRangeStr; + for (int i = 0, pos = 0; i < size; i++) { + pos = thirdPartyConfig.find(";", i); + if (pos == std::string::npos) { + break; + } + if (pos < size) { + std::string s = thirdPartyConfig.substr(i, pos - i); + vTraceRangeStr.push_back(s); + i = pos; + } + } + const int EVENT_COUNT_PAIR = 2; + if (vTraceRangeStr.size() % EVENT_COUNT_PAIR != 0) { + TS_LOGE("thirdPartyConfig is wrong!"); + return -1; + } + for (int m = 0; m < vTraceRangeStr.size(); m += EVENT_COUNT_PAIR) { + int componentId = std::stoi(vTraceRangeStr.at(m)); + std::string componentName = vTraceRangeStr.at(m + 1); + TS_LOGE("vTraceRangeStr[m] = %d, vTraceRangeStr[m + 1] = %s", componentId, componentName.c_str()); + g_thirdPartyConfig.insert((std::map::value_type(componentId, componentName))); + } + return 0; +} + bool RpcServer::ParseDataOver(const uint8_t* data, size_t len, ResultCallBack resultCallBack) { + UNUSED(data); + UNUSED(len); + MetaData* metaData = ts_->GetMetaData(); + metaData->SetSourceFileName("input stream mode"); + metaData->SetOutputFileName("wasm mode"); + metaData->SetParserToolVersion(TRACE_STREAM_VERSION); + metaData->SetParserToolPublishDateTime(TRACE_STREAM_PUBLISHVERSION); + metaData->SetTraceDataSize(g_loadSize); + metaData->SetTraceType((ts_->DataType() == TRACE_FILETYPE_H_TRACE) ? "proto-based-trace" : "txt-based-trace"); TS_LOGI("RPC ParseDataOver, has parsed len %zu", lenParseData_); ts_->WaitForParserEnd(); +#ifndef USE_VTABLE ts_->Clear(); +#endif if (resultCallBack) { - resultCallBack("ok\r\n"); + resultCallBack("ok\r\n", SEND_FINISH); } lenParseData_ = 0; + g_loadSize = 0; return true; } bool RpcServer::SqlOperate(const uint8_t* data, size_t len, ResultCallBack resultCallBack) { + ts_->SetCancel(false); std::string sql(reinterpret_cast(data), len); TS_LOGI("RPC SqlOperate(%s, %zu)", sql.c_str(), len); @@ -72,37 +129,47 @@ bool RpcServer::SqlOperate(const uint8_t* data, size_t len, ResultCallBack resul if (ret != 0) { response = "dberror\r\n"; } - resultCallBack(response); + resultCallBack(response, SEND_FINISH); } return (ret == 0); } bool RpcServer::SqlQuery(const uint8_t* data, size_t len, ResultCallBack resultCallBack) { + ts_->SetCancel(false); std::string sql(reinterpret_cast(data), len); TS_LOGI("RPC SqlQuery %zu:%s", len, sql.c_str()); int ret = ts_->SearchDatabase(sql, resultCallBack); if (resultCallBack && ret != 0) { - resultCallBack("dberror\r\n"); + resultCallBack("dberror\r\n", SEND_FINISH); } + ts_->SetCancel(false); return (ret == 0); } +void RpcServer::CancelSqlQuery() +{ + ts_->SetCancel(true); +} + bool RpcServer::Reset(const uint8_t* data, size_t len, ResultCallBack resultCallBack) { + UNUSED(data); + UNUSED(len); TS_LOGI("RPC reset trace_streamer"); ts_->WaitForParserEnd(); ts_ = std::make_unique(); if (resultCallBack) { - resultCallBack("ok\r\n"); + resultCallBack("ok\r\n", SEND_FINISH); } return true; } int RpcServer::WasmSqlQuery(const uint8_t* data, size_t len, uint8_t* out, int outLen) { + ts_->SetCancel(false); std::string sql(reinterpret_cast(data), len); TS_LOGI("WASM RPC SqlQuery out(%p:%d) sql(%zu:%s)", reinterpret_cast(out), outLen, len, sql.c_str()); @@ -110,5 +177,14 @@ int RpcServer::WasmSqlQuery(const uint8_t* data, size_t len, uint8_t* out, int o int ret = ts_->SearchDatabase(sql, out, outLen); return ret; } +int RpcServer::WasmSqlQueryWithCallback(const uint8_t* data, size_t len, ResultCallBack callback) const +{ + ts_->SetCancel(false); + std::string sql(reinterpret_cast(data), len); + TS_LOGI("WASM RPC SqlQuery sql(%zu:%s)", len, sql.c_str()); + + int ret = ts_->SearchDatabase(sql, callback); + return ret; +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/rpc/rpc_server.h b/host/trace_streamer/src/rpc/rpc_server.h index 0c1137d18ceae59c4d5dad4a3bc0e09b0fb235f5..59e8efa64354dd902a404cd407b262c6379e66d1 100644 --- a/host/trace_streamer/src/rpc/rpc_server.h +++ b/host/trace_streamer/src/rpc/rpc_server.h @@ -23,16 +23,23 @@ namespace SysTuning { namespace TraceStreamer { class RpcServer { public: - using ResultCallBack = std::function; + using ResultCallBack = std::function; + + using SendDataCallBack = std::function; + // In order to bind HTTP, maintain a unified interface, even if some parameters are useless bool ParseData(const uint8_t* data, size_t len, ResultCallBack resultCallBack); bool ParseDataOver(const uint8_t* data, size_t len, ResultCallBack resultCallBack); bool SqlOperate(const uint8_t* data, size_t len, ResultCallBack resultCallBack); bool SqlQuery(const uint8_t* data, size_t len, ResultCallBack resultCallBack); bool Reset(const uint8_t* data, size_t len, ResultCallBack resultCallBack); + void CancelSqlQuery(); // only for wasm, no callback int WasmSqlQuery(const uint8_t* data, size_t len, uint8_t* out, int outLen); - + int WasmSqlQueryWithCallback(const uint8_t* data, size_t len, ResultCallBack callback) const; + int UpdateTraceTime(const uint8_t* data, int len); + int TraceStreamer_Init_ThirdParty_Config(const uint8_t* data, int len); + std::map g_thirdPartyConfig; private: std::unique_ptr ts_ = std::make_unique(); size_t lenParseData_ = 0; diff --git a/host/trace_streamer/src/rpc/wasm_func.cpp b/host/trace_streamer/src/rpc/wasm_func.cpp index 8a0645630a5c33cd205ed9f51a8a26cff1f1db0d..70f87d0568e4539567196281f46542f75ae6df31 100644 --- a/host/trace_streamer/src/rpc/wasm_func.cpp +++ b/host/trace_streamer/src/rpc/wasm_func.cpp @@ -14,13 +14,78 @@ */ #include "wasm_func.h" -#include -#include -#include "rpc_server.h" + namespace SysTuning { namespace TraceStreamer { RpcServer g_wasmTraceStreamer; extern "C" { +using ReplyFunction = void (*)(const char* data, uint32_t len, int finish); +ReplyFunction g_reply; +uint8_t* g_reqBuf; +uint32_t g_reqBufferSize; + +using SendDataCallBack = void (*)(const char* data, int len, int componentId); +SendDataCallBack g_sendData = nullptr; +uint8_t* g_sendDataBuf; +uint32_t g_sendDataBufSize; + +void ResultCallback(const std::string& jsonResult, int finish) +{ + g_reply(jsonResult.data(), jsonResult.size(), finish); +} +EMSCRIPTEN_KEEPALIVE uint8_t* Initialize(ReplyFunction replyFunction, uint32_t reqBufferSize) +{ + g_reply = replyFunction; + g_reqBuf = new uint8_t[reqBufferSize]; + g_reqBufferSize = reqBufferSize; + return g_reqBuf; +} + +EMSCRIPTEN_KEEPALIVE int UpdateTraceTime(int len) +{ + return g_wasmTraceStreamer.UpdateTraceTime(g_reqBuf, len); +} + +void ThirdPary_SendDataCallback(const char* pluginData, int len, int componentId) +{ + if (g_sendData) { + g_sendData(pluginData, len, componentId); + } +} + +EMSCRIPTEN_KEEPALIVE uint8_t* TraceStreamer_Set_ThirdParty_DataDealer(SendDataCallBack sendDataCallBack, uint32_t reqBufferSize) +{ + g_sendData = sendDataCallBack; + g_sendDataBuf = new uint8_t[reqBufferSize]; + g_sendDataBufSize = reqBufferSize; + return g_sendDataBuf; +} + +int TraceStreamer_Plugin_Out_Filter(const char* pluginData, int len, const std::string& componentName) +{ + std::map::iterator itor = g_wasmTraceStreamer.g_thirdPartyConfig.begin(); + int componentId = 0; + for (; itor != g_wasmTraceStreamer.g_thirdPartyConfig.end(); ++itor) { + if (itor->second == componentName) { + componentId = itor->first; + return TraceStreamer_Plugin_Out_SendData(pluginData, len, componentId); + } + } + return -1; +} + +// Tell js to call the corresponding third-party parser interface according to the compositeId +int TraceStreamer_Plugin_Out_SendData(const char* pluginData, int len, int componentId) +{ + ThirdPary_SendDataCallback(pluginData, len, componentId); + return 0; +} + +EMSCRIPTEN_KEEPALIVE int TraceStreamer_Init_ThirdParty_Config(int dataLen) +{ + return g_wasmTraceStreamer.TraceStreamer_Init_ThirdParty_Config(g_reqBuf, dataLen); +} + // return 0 while ok, -1 while failed EMSCRIPTEN_KEEPALIVE int TraceStreamerParseData(const uint8_t* data, int dataLen) { @@ -29,6 +94,14 @@ EMSCRIPTEN_KEEPALIVE int TraceStreamerParseData(const uint8_t* data, int dataLen } return -1; } +// return 0 while ok, -1 while failed +EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataEx(int dataLen) +{ + if (g_wasmTraceStreamer.ParseData(g_reqBuf, dataLen, nullptr)) { + return 0; + } + return -1; +} EMSCRIPTEN_KEEPALIVE int TraceStreamerParseDataOver() { if (g_wasmTraceStreamer.ParseDataOver(nullptr, 0, nullptr)) { @@ -43,6 +116,13 @@ EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen) } return -1; } +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlOperateEx(int sqlLen) +{ + if (g_wasmTraceStreamer.SqlOperate(g_reqBuf, sqlLen, nullptr)) { + return 0; + } + return -1; +} EMSCRIPTEN_KEEPALIVE int TraceStreamerReset() { g_wasmTraceStreamer.Reset(nullptr, 0, nullptr); @@ -53,6 +133,16 @@ EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, u { return g_wasmTraceStreamer.WasmSqlQuery(sql, sqlLen, out, outLen); } +// return the length of result, -1 while failed +EMSCRIPTEN_KEEPALIVE int TraceStreamerSqlQueryEx(int sqlLen) +{ + return g_wasmTraceStreamer.WasmSqlQueryWithCallback(g_reqBuf, sqlLen, &ResultCallback); +} +EMSCRIPTEN_KEEPALIVE int TraceStreamerCancel() +{ + g_wasmTraceStreamer.CancelSqlQuery(); + return 0; +} } // extern "C" } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/rpc/wasm_func.h b/host/trace_streamer/src/rpc/wasm_func.h index 2182d4743c8d755d3014ab89e01a5618de5e329c..2df47f1515ca5c1e18782478f7c1a6256643580b 100644 --- a/host/trace_streamer/src/rpc/wasm_func.h +++ b/host/trace_streamer/src/rpc/wasm_func.h @@ -16,4 +16,39 @@ #ifndef RPC_WASM_FUNC_H #define RPC_WASM_FUNC_H +#include +#ifndef IS_UT +#include +#endif +#ifdef IS_UT +#define EMSCRIPTEN_KEEPALIVE __attribute__((used)) + +#ifdef __wasm__ +#define EM_IMPORT(NAME) __attribute__((import_module("env"), import_name(#NAME))) +#else +#define EM_IMPORT(NAME) +#endif + +#endif +#include "rpc_server.h" + +namespace SysTuning { +namespace TraceStreamer { +extern "C" { +int TraceStreamerParseData(const uint8_t* data, int dataLen); +int TraceStreamerParseDataEx(int dataLen); +int TraceStreamerParseDataOver(); +int TraceStreamerSqlOperate(const uint8_t* sql, int sqlLen); +int TraceStreamerSqlOperateEx(int sqlLen); +int TraceStreamerReset(); +int TraceStreamerSqlQuery(const uint8_t* sql, int sqlLen, uint8_t* out, int outLen); +int TraceStreamer_Plugin_Out_SendData(const char* pluginData, int len, int componentId); +int TraceStreamer_Plugin_Out_Filter(const char* pluginData, int len, const std::string& componentName); + +int TraceStreamerSqlQueryEx(int sqlLen); +int TraceStreamerCancel(); +} // extern "C" +} // namespace TraceStreamer +} // namespace SysTuning + #endif // RPC_WASM_FUNC_H diff --git a/host/trace_streamer/src/table/BUILD.gn b/host/trace_streamer/src/table/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3627e907ecbded487fe640e3fe64df406f40924f --- /dev/null +++ b/host/trace_streamer/src/table/BUILD.gn @@ -0,0 +1,147 @@ +# 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("//build/ohos.gni") + +import("//src/ts.gni") +ohos_source_set("table") { + sources = [ + "appname_table.cpp", + "appname_table.h", + "args_table.cpp", + "args_table.h", + "bio_latency_sample_table.cpp", + "bio_latency_sample_table.h", + "callstack_table.cpp", + "callstack_table.h", + "clk_event_filter_table.cpp", + "clk_event_filter_table.h", + "clock_event_filter_table.cpp", + "clock_event_filter_table.h", + "clock_snapshot_table.cpp", + "cpu_measure_filter_table.cpp", + "cpu_measure_filter_table.h", + "cpu_usage_info_table.cpp", + "cpu_usage_info_table.h", + "data_dict_table.cpp", + "data_dict_table.h", + "data_type_table.cpp", + "data_type_table.h", + "datasource_clockid_table.cpp", + "device_state_table.cpp", + "device_state_table.h", + "disk_io_table.cpp", + "disk_io_table.h", + "ebpf_callstack_table.cpp", + "ebpf_callstack_table.h", + "file_system_sample_table.cpp", + "file_system_sample_table.h", + "filter_constraints.cpp", + "filter_table.cpp", + "filter_table.h", + "hidump_table.cpp", + "hidump_table.h", + "index_map.cpp", + "index_map.h", + "instants_table.cpp", + "instants_table.h", + "irq_table.cpp", + "live_process_table.cpp", + "live_process_table.h", + "log_table.cpp", + "log_table.h", + "measure_filter_table.cpp", + "measure_filter_table.h", + "measure_table.cpp", + "measure_table.h", + "meta_table.cpp", + "meta_table.h", + "native_hook_frame_table.cpp", + "native_hook_frame_table.h", + "native_hook_table.cpp", + "native_hook_table.h", + "network_table.cpp", + "network_table.h", + "paged_memory_sample_table.cpp", + "paged_memory_sample_table.h", + "process_filter_table.cpp", + "process_filter_table.h", + "process_measure_filter_table.cpp", + "process_measure_filter_table.h", + "process_table.cpp", + "process_table.h", + "range_table.cpp", + "raw_table.cpp", + "raw_table.h", + "sched_slice_table.cpp", + "sched_slice_table.h", + "smaps_table.cpp", + "smaps_table.h", + "span_join.cpp", + "span_join.h", + "stat_table.cpp", + "stat_table.h", + "symbols_table.cpp", + "symbols_table.h", + "sysevent_measure_table.cpp", + "sysevent_measure_table.h", + "system_call_table.cpp", + "system_call_table.h", + "system_event_filter_table.cpp", + "table_base.cpp", + "thread_filter_table.cpp", + "thread_state_table.cpp", + "thread_table.cpp", + "trace_config_table.cpp", + "trace_config_table.h", + ] + + include_dirs = [ + "//third_party/sqlite/include", + "//src/base", + "//src/trace_data", + "//src/include", + "//src", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "//third_party/protobuf/src", + ] + + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + if (is_test) { + cflags += [ "-D IS_UT" ] + } + } + if (with_perf) { + sources += [ + "perf_call_chain_table.cpp", + "perf_call_chain_table.h", + "perf_files_table.cpp", + "perf_files_table.h", + "perf_report_table.cpp", + "perf_report_table.h", + "perf_sample_table.cpp", + "perf_sample_table.h", + "perf_thread_table.cpp", + "perf_thread_table.h", + ] + } +} diff --git a/host/trace_streamer/src/table/appname_table.cpp b/host/trace_streamer/src/table/appname_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2655874948a45780c597d1fd50df47b445351465 --- /dev/null +++ b/host/trace_streamer/src/table/appname_table.cpp @@ -0,0 +1,69 @@ +/* + * 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. + */ + +#include "appname_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, FLAG, APP_NAME, APP_KEY }; +} +AppnameTable:: AppnameTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("flag", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("app_name", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("app_key", "INTEGER")); + tablePriKey_.push_back("id"); +} + +AppnameTable::~AppnameTable() {} + +std::unique_ptr AppnameTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +AppnameTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstAppNamesData().Size())), + appName_(dataCache->GetConstAppNamesData()) +{ +} + +AppnameTable::Cursor::~Cursor() {} + +int AppnameTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, dataCache_->GetConstAppNamesData().IdsData()[CurrentRow()]); + break; + case FLAG: + sqlite3_result_int(context_, dataCache_->GetConstAppNamesData().Falgs()[CurrentRow()]); + break; + case APP_NAME: + sqlite3_result_int64(context_, dataCache_->GetConstAppNamesData().EventSourceId()[CurrentRow()]); + break; + case APP_KEY: + sqlite3_result_int64(context_, dataCache_->GetConstAppNamesData().AppName()[CurrentRow()]); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/heap_frame_table.h b/host/trace_streamer/src/table/appname_table.h similarity index 60% rename from host/trace_streamer/src/table/heap_frame_table.h rename to host/trace_streamer/src/table/appname_table.h index 572b66739f1ca91044b49f3dce7f08d76f08bce3..7a9f045176baaf7988b1b1615c39dd75876a1bb1 100644 --- a/host/trace_streamer/src/table/heap_frame_table.h +++ b/host/trace_streamer/src/table/appname_table.h @@ -13,31 +13,39 @@ * limitations under the License. */ -#ifndef HEAP_FRAME_TABLE_H -#define HEAP_FRAME_TABLE_H +#ifndef APPNAME_TABLE_H +#define APPNAME_TABLE_H #include "table_base.h" #include "trace_data_cache.h" namespace SysTuning { namespace TraceStreamer { -class HeapFrameTable : public TableBase { +class AppnameTable : public TableBase { public: - explicit HeapFrameTable(const TraceDataCache* dataCache); - ~HeapFrameTable() override; - void CreateCursor() override; + explicit AppnameTable(const TraceDataCache*); + ~AppnameTable() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; - int Column(int column) const override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; private: - const HeapFrameInfo& heapFrameInfoObj_; + const AppNames& appName_; }; }; } // namespace TraceStreamer } // namespace SysTuning -#endif // HEAP_FRAME_TABLE_H +#endif // APPNAME_TABLE_H diff --git a/host/trace_streamer/src/table/args_table.cpp b/host/trace_streamer/src/table/args_table.cpp index c56414892c5f9fbe923ad7eab72a9aa07080c2f0..a3cf22d91322a6081928c265ae98d9b687a31af0 100644 --- a/host/trace_streamer/src/table/args_table.cpp +++ b/host/trace_streamer/src/table/args_table.cpp @@ -22,34 +22,153 @@ enum Index { ID = 0, KEY, DATATYPE, VALUE, ARGSETID }; } ArgsTable::ArgsTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("key", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("datatype", "UNSIGNED SHORT")); - tableColumn_.push_back(TableBase::ColumnInfo("value", "BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("argset", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("key", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("datatype", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("argset", "INTEGER")); tablePriKey_.push_back("id"); } ArgsTable::~ArgsTable() {} -void ArgsTable::CreateCursor() +void ArgsTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstArgSetData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } } -ArgsTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstArgSetData().Size())), +void ArgsTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool ArgsTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr ArgsTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +ArgsTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstArgSetData().Size())), argSet_(dataCache->GetConstArgSetData()) { } ArgsTable::Cursor::~Cursor() {} -int ArgsTable::Cursor::Column(int column) const +int ArgsTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) { - switch (column) { + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int ArgsTable::Cursor::Column(int col) const +{ + switch (col) { case ID: - sqlite3_result_int64(context_, static_cast(argSet_.IdsData()[CurrentRow()])); + sqlite3_result_int64(context_, CurrentRow()); // IdsData() will be optimized break; case KEY: sqlite3_result_int64(context_, static_cast(argSet_.NamesData()[CurrentRow()])); @@ -64,10 +183,44 @@ int ArgsTable::Cursor::Column(int column) const sqlite3_result_int64(context_, static_cast(argSet_.ArgsData()[CurrentRow()])); break; default: - TS_LOGF("Unregistered column : %d", column); + TS_LOGF("Unregistered column : %d", col); break; } return SQLITE_OK; } + +void ArgsTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL + indexMap_->Intersect(0, 0); + return; + } + + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + indexMap_->Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + indexMap_->Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/table/args_table.h b/host/trace_streamer/src/table/args_table.h index fdcea564db0b2a3c5ce55ef93d5f17eeec90edf9..2c2e298920dd01c6541194487a4233de84f797b6 100644 --- a/host/trace_streamer/src/table/args_table.h +++ b/host/trace_streamer/src/table/args_table.h @@ -24,16 +24,24 @@ namespace TraceStreamer { class ArgsTable : public TableBase { public: enum Column { ID = 0, TYPE = 1, NAME = 2, ARG_ID = 3 }; - explicit ArgsTable(const TraceDataCache* storage); + explicit ArgsTable(const TraceDataCache* dataCache); ~ArgsTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; - int Column(int column) const override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int col) const override; + + void FilterId(unsigned char op, sqlite3_value* argv) override; private: const ArgSet& argSet_; diff --git a/host/trace_streamer/src/table/bio_latency_sample_table.cpp b/host/trace_streamer/src/table/bio_latency_sample_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8db0cceb2a9f8978e688e81d5e24490a30eafec4 --- /dev/null +++ b/host/trace_streamer/src/table/bio_latency_sample_table.cpp @@ -0,0 +1,270 @@ +/* + * 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. + */ + +#include "bio_latency_sample_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + CALLCHAIN_ID, + TYPE, + IPID, + ITID, + START_TS, + END_TS, + LATENCY_DUR, + TIER, + SIZE, + BLOCK_NUMBER, + PATH, + DUR_PER_4K, +}; +} +BioLatencySampleTable::BioLatencySampleTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("latency_dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("tier", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("size", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("block_number", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("path_id", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("dur_per_4k", "INTEGER")); + tablePriKey_.push_back("id"); +} + +BioLatencySampleTable::~BioLatencySampleTable() {} + +void BioLatencySampleTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstHidumpData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void BioLatencySampleTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool BioLatencySampleTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr BioLatencySampleTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +BioLatencySampleTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstBioLatencySampleData().Size())), + bioLatencySampleObj_(dataCache->GetConstBioLatencySampleData()) +{ +} + +BioLatencySampleTable::Cursor::~Cursor() {} + +int BioLatencySampleTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int BioLatencySampleTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.IdsData()[CurrentRow()])); + break; + case CALLCHAIN_ID: + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.CallChainIds()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.Types()[CurrentRow()])); + break; + case IPID: { + if (bioLatencySampleObj_.Ipids()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.Ipids()[CurrentRow()])); + } + break; + } + case ITID: { + if (bioLatencySampleObj_.Itids()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.Itids()[CurrentRow()])); + } + break; + } + case START_TS: { + if (bioLatencySampleObj_.StartTs()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.StartTs()[CurrentRow()])); + } + break; + } + case END_TS: { + if (bioLatencySampleObj_.EndTs()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.EndTs()[CurrentRow()])); + } + break; + } + case LATENCY_DUR: { + if (bioLatencySampleObj_.LatencyDurs()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.LatencyDurs()[CurrentRow()])); + } + break; + } + case TIER: { + if (bioLatencySampleObj_.Tiers()[CurrentRow()] != INVALID_UINT32) { + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.Tiers()[CurrentRow()])); + } + break; + } + case SIZE: { + if (bioLatencySampleObj_.Sizes()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.Sizes()[CurrentRow()])); + } + break; + } + case BLOCK_NUMBER: { + if (bioLatencySampleObj_.BlockNumbers()[CurrentRow()] != INVALID_UINT64) { + auto returnValueIndex0 = bioLatencySampleObj_.BlockNumbers()[CurrentRow()]; + sqlite3_result_text(context_, dataCache_->GetDataFromDict(returnValueIndex0).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case PATH: { + if (bioLatencySampleObj_.FilePathIds()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.FilePathIds()[CurrentRow()])); + } + break; + } + case DUR_PER_4K: { + if (bioLatencySampleObj_.DurPer4k()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(bioLatencySampleObj_.DurPer4k()[CurrentRow()])); + } + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/bio_latency_sample_table.h b/host/trace_streamer/src/table/bio_latency_sample_table.h new file mode 100644 index 0000000000000000000000000000000000000000..16b6ffa4710ef1235a22dbdf6571a6c790a82b88 --- /dev/null +++ b/host/trace_streamer/src/table/bio_latency_sample_table.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef BIO_LATENCY_SAMPLE_TABLE_H +#define BIO_LATENCY_SAMPLE_TABLE_H + +#include "table_base.h" +#include "trace_stdtype.h" + +namespace SysTuning { +namespace TraceStreamer { +class BioLatencySampleTable : public TableBase { +public: + explicit BioLatencySampleTable(const TraceDataCache* dataCache); + ~BioLatencySampleTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + private: + const BioLatencySampleData& bioLatencySampleObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // BIO_LATENCY_SAMPLE_TABLE_H diff --git a/host/trace_streamer/src/table/callstack_table.cpp b/host/trace_streamer/src/table/callstack_table.cpp old mode 100644 new mode 100755 index 0c54940041fb068f871cc362eb8748343b8848b0..c4340c4bb805bc16f39b29a0d84fcc8bc380463b --- a/host/trace_streamer/src/table/callstack_table.cpp +++ b/host/trace_streamer/src/table/callstack_table.cpp @@ -24,6 +24,7 @@ enum Index { DUR, CALL_ID, CAT, + IDENTIFY, NAME, DEPTH, COOKIE_ID, @@ -38,21 +39,22 @@ enum Index { } CallStackTable::CallStackTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("callid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("cat", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("depth", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("cookie", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("parent_id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("argsetid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("chainId", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("spanId", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("parentSpanId", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("flag", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("args", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("cat", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("identify", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("depth", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("cookie", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("parent_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("argsetid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("chainId", "TEXT")); + 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("args", "TEXT")); tablePriKey_.push_back("callid"); tablePriKey_.push_back("ts"); tablePriKey_.push_back("depth"); @@ -60,22 +62,150 @@ CallStackTable::CallStackTable(const TraceDataCache* dataCache) : TableBase(data CallStackTable::~CallStackTable() {} -void CallStackTable::CreateCursor() +void CallStackTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstInternalSlicesData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void CallStackTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } } -CallStackTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstInternalSlicesData().Size())), +bool CallStackTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr CallStackTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +CallStackTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstInternalSlicesData().Size())), slicesObj_(dataCache->GetConstInternalSlicesData()) { } CallStackTable::Cursor::~Cursor() {} -int CallStackTable::Cursor::Column(int column) const +int CallStackTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) { - switch (column) { + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case TS: + FilterTS(c.op, argv[i], slicesObj_.TimeStamData()); + break; + case CALL_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), slicesObj_.CallIds()); + break; + case COOKIE_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), slicesObj_.Cookies()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int CallStackTable::Cursor::Column(int col) const +{ + switch (col) { case ID: sqlite3_result_int64(context_, CurrentRow()); break; @@ -96,6 +226,9 @@ int CallStackTable::Cursor::Column(int column) const } break; } + case IDENTIFY: + sqlite3_result_int(context_, slicesObj_.IdentifysData()[CurrentRow()]); + break; case NAME: { if (slicesObj_.NamesData()[CurrentRow()] != INVALID_UINT64) { auto nameDataIndex = static_cast(slicesObj_.NamesData()[CurrentRow()]); @@ -139,7 +272,7 @@ int CallStackTable::Cursor::Column(int column) const sqlite3_result_text(context_, slicesObj_.ArgsData()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); break; default: - TS_LOGF("Unregistered column : %d", column); + TS_LOGF("Unregistered column : %d", col); break; } return SQLITE_OK; diff --git a/host/trace_streamer/src/table/callstack_table.h b/host/trace_streamer/src/table/callstack_table.h old mode 100644 new mode 100755 index e902e7a730967ef943536b932c8404f04fe57ab2..ba423b91c97afec5d8923fcf53816a0d6e8f9982 --- a/host/trace_streamer/src/table/callstack_table.h +++ b/host/trace_streamer/src/table/callstack_table.h @@ -25,14 +25,20 @@ class CallStackTable : public TableBase { public: explicit CallStackTable(const TraceDataCache* dataCache); ~CallStackTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; - int Column(int column) const override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int col) const override; private: const CallStack& slicesObj_; diff --git a/host/trace_streamer/src/table/clk_event_filter_table.cpp b/host/trace_streamer/src/table/clk_event_filter_table.cpp index 40906948a4da2df4b544b7f3e6094295918f26cb..32e6b78faf6c0ff70d2db3d39e716a9a0c13370e 100644 --- a/host/trace_streamer/src/table/clk_event_filter_table.cpp +++ b/host/trace_streamer/src/table/clk_event_filter_table.cpp @@ -15,6 +15,8 @@ #include "clk_event_filter_table.h" +#include + namespace SysTuning { namespace TraceStreamer { namespace { @@ -22,27 +24,147 @@ enum Index { ID = 0, TYPE, NAME, CPU }; } ClkEventFilterTable::ClkEventFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER")); tablePriKey_.push_back("id"); } ClkEventFilterTable::~ClkEventFilterTable() {} -void ClkEventFilterTable::CreateCursor() + +void ClkEventFilterTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstClkEventFilterData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void ClkEventFilterTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool ClkEventFilterTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr ClkEventFilterTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -ClkEventFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstClkEventFilterData().Size())) +ClkEventFilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstClkEventFilterData().Size())) { } ClkEventFilterTable::Cursor::~Cursor() {} +int ClkEventFilterTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterSorted(c.col, c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int ClkEventFilterTable::Cursor::Column(int col) const { switch (col) { @@ -71,5 +193,49 @@ int ClkEventFilterTable::Cursor::Column(int col) const } return SQLITE_OK; } + +void ClkEventFilterTable::Cursor::FilterSorted(int col, unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL, filter out nothing + indexMap_->Intersect(0, 0); + return; + } + + switch (col) { + case ID: { + auto v = static_cast(sqlite3_value_int64(argv)); + auto getValue = [](const uint32_t& row) { + return row; + }; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->IntersectabcEqual( + dataCache_->GetConstClkEventFilterData().IdsData(), v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + case SQLITE_INDEX_CONSTRAINT_GE: { + indexMap_->IntersectGreaterEqual( + dataCache_->GetConstClkEventFilterData().IdsData(), v, getValue); + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + case SQLITE_INDEX_CONSTRAINT_LT: { + indexMap_->IntersectLessEqual( + dataCache_->GetConstClkEventFilterData().IdsData(), v, getValue); + break; + } + default: + break; + } // end of switch (op) + } // end of case TS + default: + // can't filter, all rows + break; + } +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/table/clk_event_filter_table.h b/host/trace_streamer/src/table/clk_event_filter_table.h index 37a69ff487be275ecb7aee62b04a40a0922c13b2..18970bab0c51e2062b07664b0860814b750955e1 100644 --- a/host/trace_streamer/src/table/clk_event_filter_table.h +++ b/host/trace_streamer/src/table/clk_event_filter_table.h @@ -26,14 +26,22 @@ class ClkEventFilterTable : public TableBase { public: explicit ClkEventFilterTable(const TraceDataCache*); ~ClkEventFilterTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // the column is sorted + bool CanFilterSorted(const char op, size_t& rowCount) const; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int col) const override; + + void FilterSorted(int col, unsigned char op, sqlite3_value* argv); }; }; } // namespace TraceStreamer diff --git a/host/trace_streamer/src/table/clock_event_filter_table.cpp b/host/trace_streamer/src/table/clock_event_filter_table.cpp old mode 100644 new mode 100755 index a123ed86c6e07cd64daf3c415e5b90df2ca3223a..d2b5e4933671da9305ca1a6c8c84875aa09c7f5d --- a/host/trace_streamer/src/table/clock_event_filter_table.cpp +++ b/host/trace_streamer/src/table/clock_event_filter_table.cpp @@ -15,6 +15,8 @@ #include "clock_event_filter_table.h" +#include + namespace SysTuning { namespace TraceStreamer { namespace { @@ -22,27 +24,146 @@ enum Index { ID = 0, TYPE, NAME, CPU }; } ClockEventFilterTable::ClockEventFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER")); tablePriKey_.push_back("id"); } ClockEventFilterTable::~ClockEventFilterTable() {} -void ClockEventFilterTable::CreateCursor() +void ClockEventFilterTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstClockEventFilterData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void ClockEventFilterTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool ClockEventFilterTable::CanFilterSorted(const char op, size_t& rowCount) const { - cursor_ = std::make_unique(dataCache_); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; } -ClockEventFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstClockEventFilterData().Size())) +std::unique_ptr ClockEventFilterTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +ClockEventFilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstClockEventFilterData().Size())) { } ClockEventFilterTable::Cursor::~Cursor() {} +int ClockEventFilterTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterSorted(c.col, c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int ClockEventFilterTable::Cursor::Column(int col) const { switch (col) { @@ -70,5 +191,49 @@ int ClockEventFilterTable::Cursor::Column(int col) const } return SQLITE_OK; } + +void ClockEventFilterTable::Cursor::FilterSorted(int col, unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL, filter out nothing + indexMap_->Intersect(0, 0); + return; + } + + switch (col) { + case ID: { + auto v = static_cast(sqlite3_value_int64(argv)); + auto getValue = [](const uint32_t& row) { + return row; + }; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->IntersectabcEqual( + dataCache_->GetConstClockEventFilterData().IdsData(), v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + case SQLITE_INDEX_CONSTRAINT_GE: { + indexMap_->IntersectGreaterEqual( + dataCache_->GetConstClockEventFilterData().IdsData(), v, getValue); + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + case SQLITE_INDEX_CONSTRAINT_LT: { + indexMap_->IntersectLessEqual( + dataCache_->GetConstClockEventFilterData().IdsData(), v, getValue); + break; + } + default: + break; + } // end of switch (op) + } // end of case TS + default: + // can't filter, all rows + break; + } +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/table/clock_event_filter_table.h b/host/trace_streamer/src/table/clock_event_filter_table.h old mode 100644 new mode 100755 index d7e3cb0e617f514ce14a3765b838520fa2863cf8..0750bc8b7f4734e73f8d13830771d360a2aa3d0c --- a/host/trace_streamer/src/table/clock_event_filter_table.h +++ b/host/trace_streamer/src/table/clock_event_filter_table.h @@ -26,14 +26,22 @@ class ClockEventFilterTable : public TableBase { public: explicit ClockEventFilterTable(const TraceDataCache* dataCache); ~ClockEventFilterTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // the column is sorted + bool CanFilterSorted(const char op, size_t& rowCount) const; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int col) const override; + + void FilterSorted(int col, unsigned char op, sqlite3_value* argv); }; }; } // namespace TraceStreamer diff --git a/host/trace_streamer/src/table/clock_snapshot_table.cpp b/host/trace_streamer/src/table/clock_snapshot_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e28366aab0a13168435e250b653263c1e79f5460 --- /dev/null +++ b/host/trace_streamer/src/table/clock_snapshot_table.cpp @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#include "clock_snapshot_table.h" +#include + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, CLOCK_ID, TS, CLOCK_NAME }; +} +ClockSnapShotTable::ClockSnapShotTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("clock_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("clock_name", "TEXT")); + tablePriKey_.push_back("ts"); + tablePriKey_.push_back("id"); +} + +ClockSnapShotTable::~ClockSnapShotTable() {} + +std::unique_ptr ClockSnapShotTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +ClockSnapShotTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstClockSnapshotData().Size())), + snapShotData_(dataCache->GetConstClockSnapshotData()) +{ +} + +ClockSnapShotTable::Cursor::~Cursor() {} + +int ClockSnapShotTable::Cursor::Column(int column) const +{ + // printf("row:%d\n", CurrentRow()); + switch (column) { + case ID: + sqlite3_result_int64(context_, CurrentRow()); + break; + case CLOCK_ID: + sqlite3_result_int64(context_, static_cast(snapShotData_.ClockIds()[CurrentRow()])); + break; + case TS: + sqlite3_result_int64(context_, static_cast(snapShotData_.Ts()[CurrentRow()])); + break; + case CLOCK_NAME: + sqlite3_result_text(context_, snapShotData_.Names()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/clock_snapshot_table.h b/host/trace_streamer/src/table/clock_snapshot_table.h new file mode 100755 index 0000000000000000000000000000000000000000..7af5411b8636d5c76ed0f6179efb5213d88fb484 --- /dev/null +++ b/host/trace_streamer/src/table/clock_snapshot_table.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef CLOCK_SNAPSHOT_TABLE_H +#define CLOCK_SNAPSHOT_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class ClockSnapShotTable : public TableBase { +public: + explicit ClockSnapShotTable(const TraceDataCache* dataCache); + ~ClockSnapShotTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; + + private: + const ClockSnapshotData& snapShotData_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // CLOCK_SNAPSHOT_TABLE_H diff --git a/host/trace_streamer/src/table/cpu_measure_filter_table.cpp b/host/trace_streamer/src/table/cpu_measure_filter_table.cpp old mode 100644 new mode 100755 index ba89f946a98168b9251e5888917abb68cfb68480..5a644984c3f76ee1e6e52eb048d75b19d5550c77 --- a/host/trace_streamer/src/table/cpu_measure_filter_table.cpp +++ b/host/trace_streamer/src/table/cpu_measure_filter_table.cpp @@ -14,6 +14,9 @@ */ #include "cpu_measure_filter_table.h" + +#include + #include "log.h" namespace SysTuning { @@ -23,28 +26,151 @@ enum Index { ID = 0, TYPE, NAME, CPU }; } CpuMeasureFilterTable::CpuMeasureFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("cpu", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER")); tablePriKey_.push_back("id"); } CpuMeasureFilterTable::~CpuMeasureFilterTable() {} -void CpuMeasureFilterTable::CreateCursor() +void CpuMeasureFilterTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstCpuMeasureData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void CpuMeasureFilterTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) { - cursor_ = std::make_unique(dataCache_); + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool CpuMeasureFilterTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; } -CpuMeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstCpuMeasureData().Size())), +std::unique_ptr CpuMeasureFilterTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +CpuMeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, + static_cast(dataCache->GetConstCpuMeasureData().Size())), cpuMeasureObj_(dataCache->GetConstCpuMeasureData()) { } CpuMeasureFilterTable::Cursor::~Cursor() {} +int CpuMeasureFilterTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterSorted(c.col, c.op, argv[i]); + break; + case CPU: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), cpuMeasureObj_.CpuData()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int CpuMeasureFilterTable::Cursor::Column(int column) const { switch (column) { @@ -69,5 +195,46 @@ int CpuMeasureFilterTable::Cursor::Column(int column) const } return SQLITE_OK; } + +void CpuMeasureFilterTable::Cursor::FilterSorted(int col, unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL, filter out nothing + indexMap_->Intersect(0, 0); + return; + } + + switch (col) { + case ID: { + auto v = static_cast(sqlite3_value_int64(argv)); + auto getValue = [](const uint32_t& row) { + return row; + }; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->IntersectabcEqual(cpuMeasureObj_.IdsData(), v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + case SQLITE_INDEX_CONSTRAINT_GE: { + indexMap_->IntersectGreaterEqual(cpuMeasureObj_.IdsData(), v, getValue); + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + case SQLITE_INDEX_CONSTRAINT_LT: { + indexMap_->IntersectLessEqual(cpuMeasureObj_.IdsData(), v, getValue); + break; + } + default: + break; + } // end of switch (op) + } // end of case TS + default: + // can't filter, all rows + break; + } +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/table/cpu_measure_filter_table.h b/host/trace_streamer/src/table/cpu_measure_filter_table.h old mode 100644 new mode 100755 index 7463d156585d923170bae1dedec205c0f7a95c0a..30c23c1645b7f64741839ac70b8b7dd3a98da9a8 --- a/host/trace_streamer/src/table/cpu_measure_filter_table.h +++ b/host/trace_streamer/src/table/cpu_measure_filter_table.h @@ -25,15 +25,23 @@ class CpuMeasureFilterTable : public TableBase { public: explicit CpuMeasureFilterTable(const TraceDataCache* dataCache); ~CpuMeasureFilterTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // the column is sorted + bool CanFilterSorted(const char op, size_t& rowCount) const; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int column) const override; + void FilterSorted(int col, unsigned char op, sqlite3_value* argv); + private: const CpuMeasureFilter& cpuMeasureObj_; }; diff --git a/host/trace_streamer/src/table/cpu_usage_info_table.cpp b/host/trace_streamer/src/table/cpu_usage_info_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1408fa295c434e839cbedef362a1e4bc8e07c933 --- /dev/null +++ b/host/trace_streamer/src/table/cpu_usage_info_table.cpp @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#include "cpu_usage_info_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { TS = 0, DUR, TOTAL_LOAD, USER_LOAD, SYSTEM_LOAD, THREADS }; +} +CpuUsageInfoTable::CpuUsageInfoTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("total_load", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("user_load", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("system_load", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("process_num", "INTEGER")); + tablePriKey_.push_back("ts"); +} + +CpuUsageInfoTable::~CpuUsageInfoTable() {} + +std::unique_ptr CpuUsageInfoTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +CpuUsageInfoTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstCpuUsageInfoData().Size())), + cpuUsageInfoObj_(dataCache->GetConstCpuUsageInfoData()) +{ +} + +CpuUsageInfoTable::Cursor::~Cursor() {} + +int CpuUsageInfoTable::Cursor::Column(int column) const +{ + switch (column) { + case TS: { + sqlite3_result_int64(context_, static_cast(cpuUsageInfoObj_.TimeStamData()[CurrentRow()])); + break; + } + case DUR: { + sqlite3_result_int64(context_, static_cast(cpuUsageInfoObj_.Durs()[CurrentRow()])); + break; + } + case TOTAL_LOAD: { + sqlite3_result_int64(context_, static_cast(cpuUsageInfoObj_.TotalLoad()[CurrentRow()])); + break; + } + case USER_LOAD: { + sqlite3_result_double(context_, cpuUsageInfoObj_.UserLoad()[CurrentRow()]); + break; + } + case SYSTEM_LOAD: { + sqlite3_result_double(context_, cpuUsageInfoObj_.SystemLoad()[CurrentRow()]); + break; + } + case THREADS: { + sqlite3_result_int(context_, static_cast(cpuUsageInfoObj_.Threads()[CurrentRow()])); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/cpu_usage_info_table.h b/host/trace_streamer/src/table/cpu_usage_info_table.h new file mode 100644 index 0000000000000000000000000000000000000000..7ee6883e500632bb1dd1dd12e36a76ca3e9db420 --- /dev/null +++ b/host/trace_streamer/src/table/cpu_usage_info_table.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef CPU_USAGE_INFO_TABLE_H +#define CPU_USAGE_INFO_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class CpuUsageInfoTable : public TableBase { +public: + explicit CpuUsageInfoTable(const TraceDataCache* dataCache); + ~CpuUsageInfoTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int Column(int column) const override; + + private: + const CpuUsageDetailData& cpuUsageInfoObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // NETWORK_TABLE_H diff --git a/host/trace_streamer/src/table/data_dict_table.cpp b/host/trace_streamer/src/table/data_dict_table.cpp index 9624bf49432198bec13beca64c84a23aeb9ea3fa..b7b8f0b3dc978759e393325b8a353552cdc163a1 100644 --- a/host/trace_streamer/src/table/data_dict_table.cpp +++ b/host/trace_streamer/src/table/data_dict_table.cpp @@ -23,25 +23,144 @@ enum Index { ID = 0, STR }; } DataDictTable::DataDictTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("data", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("data", "TEXT")); tablePriKey_.push_back("id"); } DataDictTable::~DataDictTable() {} -void DataDictTable::CreateCursor() +void DataDictTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->DataDictSize(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void DataDictTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool DataDictTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr DataDictTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); } -DataDictTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->DataDictSize())) +DataDictTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->DataDictSize())) { } DataDictTable::Cursor::~Cursor() {} +int DataDictTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int DataDictTable::Cursor::Column(int col) const { DataIndex index = static_cast(CurrentRow()); diff --git a/host/trace_streamer/src/table/data_dict_table.h b/host/trace_streamer/src/table/data_dict_table.h old mode 100644 new mode 100755 index 9f431e8526e9c2327ebd013718680073326edfeb..b7fd9db06b7235d2efe4b0a87f385cf4d7e49e06 --- a/host/trace_streamer/src/table/data_dict_table.h +++ b/host/trace_streamer/src/table/data_dict_table.h @@ -25,13 +25,19 @@ class DataDictTable : public TableBase { public: explicit DataDictTable(const TraceDataCache* dataCache); ~DataDictTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int col) const override; }; }; diff --git a/host/trace_streamer/src/table/data_type_table.cpp b/host/trace_streamer/src/table/data_type_table.cpp index 479135abe998ffe02671f3cbcc3157fa7276a16d..fe41d1af085598a1c5919541d820379494ffbbdb 100644 --- a/host/trace_streamer/src/table/data_type_table.cpp +++ b/host/trace_streamer/src/table/data_type_table.cpp @@ -23,27 +23,146 @@ enum Index { ID = 0, TYPEID, DESC }; } DataTypeTable::DataTypeTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("typeId", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("desc", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("typeId", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("desc", "TEXT")); tablePriKey_.push_back("id"); } DataTypeTable::~DataTypeTable() {} -void DataTypeTable::CreateCursor() +void DataTypeTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstDataTypeData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void DataTypeTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool DataTypeTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr DataTypeTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); } -DataTypeTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstDataTypeData().Size())), +DataTypeTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstDataTypeData().Size())), dataTypeObj_(dataCache->GetConstDataTypeData()) { } DataTypeTable::Cursor::~Cursor() {} +int DataTypeTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int DataTypeTable::Cursor::Column(int col) const { switch (col) { diff --git a/host/trace_streamer/src/table/data_type_table.h b/host/trace_streamer/src/table/data_type_table.h index af518f538f34159b7abe0f53d5397ae61e1068a7..8f2a3a0adbad3a6996917b26af5326c19e5164f4 100644 --- a/host/trace_streamer/src/table/data_type_table.h +++ b/host/trace_streamer/src/table/data_type_table.h @@ -25,14 +25,21 @@ class DataTypeTable : public TableBase { public: explicit DataTypeTable(const TraceDataCache*); ~DataTypeTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int col) const override; + private: const DataType& dataTypeObj_; }; diff --git a/host/trace_streamer/src/table/datasource_clockid_table.cpp b/host/trace_streamer/src/table/datasource_clockid_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72e6ecb21b0e576cf552d88b2042ba00032ece46 --- /dev/null +++ b/host/trace_streamer/src/table/datasource_clockid_table.cpp @@ -0,0 +1,68 @@ +/* + * 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. + */ + +#include "datasource_clockid_table.h" +#include + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, NAME, CLOCK_ID }; +} +DataSourceClockIdTableTable::DataSourceClockIdTableTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("data_source_name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("clock_id", "INTEGER")); + tablePriKey_.push_back("id"); +} + +DataSourceClockIdTableTable::~DataSourceClockIdTableTable() {} + +std::unique_ptr DataSourceClockIdTableTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +DataSourceClockIdTableTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstDataSourceClockIdData().Size())), + dataSourceClockIdData_(dataCache->GetConstDataSourceClockIdData()) +{ +} + +DataSourceClockIdTableTable::Cursor::~Cursor() {} + +int DataSourceClockIdTableTable::Cursor::Column(int column) const +{ + // printf("row:%d\n", CurrentRow()); + switch (column) { + case ID: + sqlite3_result_int64(context_, CurrentRow()); + break; + case NAME: + sqlite3_result_text(context_, dataSourceClockIdData_.Names()[CurrentRow()].c_str(), STR_DEFAULT_LEN, + nullptr); + break; + case CLOCK_ID: + sqlite3_result_int(context_, static_cast(dataSourceClockIdData_.ClockIds()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/datasource_clockid_table.h b/host/trace_streamer/src/table/datasource_clockid_table.h new file mode 100755 index 0000000000000000000000000000000000000000..25f873758c208721e8fded9371dc8b84f0038176 --- /dev/null +++ b/host/trace_streamer/src/table/datasource_clockid_table.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef DATASOURCE_CLOCKID_TABLE_H +#define DATASOURCE_CLOCKID_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" +namespace SysTuning { +namespace TraceStreamer { +class DataSourceClockIdTableTable : public TableBase { +public: + explicit DataSourceClockIdTableTable(const TraceDataCache* dataCache); + ~DataSourceClockIdTableTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; + + private: + const DataSourceClockIdData& dataSourceClockIdData_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // DATASOURCE_CLOCKID_TABLE_H diff --git a/host/trace_streamer/src/table/device_state_table.cpp b/host/trace_streamer/src/table/device_state_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ee82f2c9c4675a00e9061756ef75de75c8644a7 --- /dev/null +++ b/host/trace_streamer/src/table/device_state_table.cpp @@ -0,0 +1,159 @@ +/* + * 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. + */ + +#include "device_state_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + BRIGHTNESS, + BT_STATE, + LOCATION, + WIFI, + STREAM_DEFAULT, + VOICE_CALL, + MUSIC, + STREAM_RING, + MEDIA, + VOICE_ASSISTANT, + SYSTEM, + ALARM, + NOTIFICATION, + BT_SCO, + ENFORCED_AUDIBLE, + STREAM_DTMF, + STREAM_TTS, + ACCESSIBILITY, + RECORDING, + STREAM_ALL +}; +} +DeviceStateTable::DeviceStateTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("brightness", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("bt_state", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("location", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("wifi", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("stream_default", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("voice_call", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("music", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("stream_ring", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("media", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("voice_assistant", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("system", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("alarm", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("notification", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("bt_sco", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("enforced_audible", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("stream_dtmf", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("stream_tts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("accessibility", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("recording", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("stream_all", "INTEGER")); + tablePriKey_.push_back("id"); +} + +DeviceStateTable::~DeviceStateTable() {} + +std::unique_ptr DeviceStateTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +DeviceStateTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstDeviceStateData().Size())), + deviceStateData_(dataCache->GetConstDeviceStateData()) +{ +} + +DeviceStateTable::Cursor::~Cursor() {} + +int DeviceStateTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, dataCache_->GetConstDeviceStateData().IdsData()[CurrentRow()]); + break; + case BRIGHTNESS: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().Brightness()[CurrentRow()]); + break; + case BT_STATE: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().BtState()[CurrentRow()]); + break; + case LOCATION: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().Location()[CurrentRow()]); + break; + case WIFI: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().Wifi()[CurrentRow()]); + break; + case STREAM_DEFAULT: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().StreamDefault()[CurrentRow()]); + break; + case VOICE_CALL: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().VoiceCall()[CurrentRow()]); + break; + case MUSIC: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().Music()[CurrentRow()]); + break; + case STREAM_RING: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().StreamRing()[CurrentRow()]); + break; + case MEDIA: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().Media()[CurrentRow()]); + break; + case VOICE_ASSISTANT: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().VoiceAssistant()[CurrentRow()]); + break; + case SYSTEM: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().System()[CurrentRow()]); + break; + case ALARM: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().Alarm()[CurrentRow()]); + break; + case NOTIFICATION: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().Notification()[CurrentRow()]); + break; + case BT_SCO: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().BtSco()[CurrentRow()]); + break; + case ENFORCED_AUDIBLE: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().EnforcedAudible()[CurrentRow()]); + break; + case STREAM_DTMF: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().StreamDtmf()[CurrentRow()]); + break; + case STREAM_TTS: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().StreamTts()[CurrentRow()]); + break; + case ACCESSIBILITY: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().Accessibility()[CurrentRow()]); + break; + case RECORDING: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().Recording()[CurrentRow()]); + break; + case STREAM_ALL: + sqlite3_result_int(context_, dataCache_->GetConstDeviceStateData().StreamAll()[CurrentRow()]); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/device_state_table.h b/host/trace_streamer/src/table/device_state_table.h new file mode 100644 index 0000000000000000000000000000000000000000..642ad9b574654b883e5e4918de66d27308f560c3 --- /dev/null +++ b/host/trace_streamer/src/table/device_state_table.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef DEVICE_STATE_TABLE_H +#define DEVICE_STATE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class DeviceStateTable : public TableBase { +public: + explicit DeviceStateTable(const TraceDataCache*); + ~DeviceStateTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int Column(int column) const override; + + private: + const DeviceStateData& deviceStateData_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // DEVICE_STATE__TABLE_H diff --git a/host/trace_streamer/src/table/heap_frame_table.cpp b/host/trace_streamer/src/table/disk_io_table.cpp similarity index 36% rename from host/trace_streamer/src/table/heap_frame_table.cpp rename to host/trace_streamer/src/table/disk_io_table.cpp index 90afefaa54b7b2f0c72e7deeca9d158e1cae0674..272510aacd506c4db3a1e1c951ce89b38616c2f9 100644 --- a/host/trace_streamer/src/table/heap_frame_table.cpp +++ b/host/trace_streamer/src/table/disk_io_table.cpp @@ -13,78 +13,95 @@ * limitations under the License. */ -#include "heap_frame_table.h" +#include "disk_io_table.h" namespace SysTuning { namespace TraceStreamer { namespace { -enum Index { EVENT_ID = 0, DEPTH, IP, SP, SYMBOL_NAME, FILE_PATH, OFFSET, SYMBOL_OFFSET }; +enum Index { + TS = 0, + DUR, + RD, + WR, + RD_SPEED, + WR_SPEED, + RD_COUNT, + WR_COUNT, + RD_COUNT_SPEED, + WR_COUNT_SPEED, +}; } -HeapFrameTable::HeapFrameTable(const TraceDataCache* dataCache) : TableBase(dataCache) +DiskIOTable::DiskIOTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("eventId", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("depth", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("ip", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("sp", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("symbol_name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("file_path", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("offset", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("symbol_offset", "UNSIGNED BIG INT")); - tablePriKey_.push_back("eventId"); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("rd", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("wr", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("rd_speed", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("wr_speed", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("rd_count", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("wr_count", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("rd_count_speed", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("wr_count_speed", "REAL")); + tablePriKey_.push_back("ts"); } -HeapFrameTable::~HeapFrameTable() {} +DiskIOTable::~DiskIOTable() {} -void HeapFrameTable::CreateCursor() +std::unique_ptr DiskIOTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -HeapFrameTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstHeapFrameData().Size())), - heapFrameInfoObj_(dataCache->GetConstHeapFrameData()) +DiskIOTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstDiskIOData().Size())), + diskIODataObj_(dataCache->GetConstDiskIOData()) { } -HeapFrameTable::Cursor::~Cursor() {} +DiskIOTable::Cursor::~Cursor() {} -int HeapFrameTable::Cursor::Column(int column) const +int DiskIOTable::Cursor::Column(int column) const { switch (column) { - case EVENT_ID: - sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.EventIds()[CurrentRow()])); + case TS: { + sqlite3_result_int64(context_, static_cast(diskIODataObj_.TimeStamData()[CurrentRow()])); break; - case DEPTH: - sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.Depths()[CurrentRow()])); + } + case DUR: { + sqlite3_result_int64(context_, static_cast(diskIODataObj_.Durs()[CurrentRow()])); + break; + } + case RD: { + sqlite3_result_int64(context_, static_cast(diskIODataObj_.RdDatas()[CurrentRow()])); + break; + } + case WR: { + sqlite3_result_int64(context_, static_cast(diskIODataObj_.WrDatas()[CurrentRow()])); break; - case IP: - sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.Ips()[CurrentRow()])); + } + case RD_SPEED: { + sqlite3_result_double(context_, static_cast(diskIODataObj_.RdSpeedDatas()[CurrentRow()])); break; - case SP: { - sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.Sps()[CurrentRow()])); + } + case WR_SPEED: { + sqlite3_result_double(context_, static_cast(diskIODataObj_.WrSpeedDatas()[CurrentRow()])); break; } - case SYMBOL_NAME: - if (heapFrameInfoObj_.SymbolNames()[CurrentRow()] != INVALID_UINT64) { - auto symbolNameDataIndex = static_cast(heapFrameInfoObj_.SymbolNames()[CurrentRow()]); - sqlite3_result_text(context_, dataCache_->GetDataFromDict(symbolNameDataIndex).c_str(), STR_DEFAULT_LEN, - nullptr); - } + case RD_COUNT: { + sqlite3_result_int64(context_, static_cast(diskIODataObj_.RdCountDatas()[CurrentRow()])); break; - case FILE_PATH: { - if (heapFrameInfoObj_.FilePaths()[CurrentRow()] != INVALID_UINT64) { - auto filePathDataIndex = static_cast(heapFrameInfoObj_.FilePaths()[CurrentRow()]); - sqlite3_result_text(context_, dataCache_->GetDataFromDict(filePathDataIndex).c_str(), STR_DEFAULT_LEN, - nullptr); - } + } + case WR_COUNT: { + sqlite3_result_int64(context_, static_cast(diskIODataObj_.WrCountDatas()[CurrentRow()])); break; } - case OFFSET: { - sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.Offsets()[CurrentRow()])); + case RD_COUNT_SPEED: { + sqlite3_result_double(context_, static_cast(diskIODataObj_.RdCountPerSecDatas()[CurrentRow()])); break; } - case SYMBOL_OFFSET: { - sqlite3_result_int64(context_, static_cast(heapFrameInfoObj_.SymbolOffsets()[CurrentRow()])); + case WR_COUNT_SPEED: { + sqlite3_result_double(context_, static_cast(diskIODataObj_.WrCountPerSecDatas()[CurrentRow()])); break; } default: diff --git a/host/trace_streamer/src/table/disk_io_table.h b/host/trace_streamer/src/table/disk_io_table.h new file mode 100644 index 0000000000000000000000000000000000000000..eb463c7108d4a4ad52d780d16071ec59fd6aedcf --- /dev/null +++ b/host/trace_streamer/src/table/disk_io_table.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef DISKIO_TABLE_H +#define DISKIO_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class DiskIOTable : public TableBase { +public: + explicit DiskIOTable(const TraceDataCache* dataCache); + ~DiskIOTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int Column(int column) const override; + + private: + const DiskIOData& diskIODataObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // DISKIO_TABLE_H diff --git a/host/trace_streamer/src/table/ebpf_callstack_table.cpp b/host/trace_streamer/src/table/ebpf_callstack_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea487dba3b35c14b4546239628532509156b17f8 --- /dev/null +++ b/host/trace_streamer/src/table/ebpf_callstack_table.cpp @@ -0,0 +1,214 @@ +/* + * 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. + */ + +#include "ebpf_callstack_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + CALLCHAIN_ID, + DEPTH, + IP, + SYMBOLS_ID, + FILE_PATH_ID, +}; +} +EbpfCallStackTable::EbpfCallStackTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("depth", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ip", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("symbols_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("file_path_id", "INTEGER")); + tablePriKey_.push_back("id"); +} + +EbpfCallStackTable::~EbpfCallStackTable() {} + +void EbpfCallStackTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstHidumpData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void EbpfCallStackTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool EbpfCallStackTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr EbpfCallStackTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +EbpfCallStackTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstEbpfCallStackData().Size())), + ebpfCallStackObj_(dataCache->GetConstEbpfCallStackData()) +{ +} + +EbpfCallStackTable::Cursor::~Cursor() {} + +int EbpfCallStackTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int EbpfCallStackTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(ebpfCallStackObj_.IdsData()[CurrentRow()])); + break; + case CALLCHAIN_ID: + sqlite3_result_int64(context_, static_cast(ebpfCallStackObj_.CallChainIds()[CurrentRow()])); + break; + case DEPTH: + sqlite3_result_int64(context_, static_cast(ebpfCallStackObj_.Depths()[CurrentRow()])); + break; + case IP: { + if (ebpfCallStackObj_.Ips()[CurrentRow()] != INVALID_UINT64) { + auto returnValueIndex = ebpfCallStackObj_.Ips()[CurrentRow()]; + sqlite3_result_text(context_, dataCache_->GetDataFromDict(returnValueIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case SYMBOLS_ID: { + if (ebpfCallStackObj_.SymbolIds()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(ebpfCallStackObj_.SymbolIds()[CurrentRow()])); + } + break; + } + case FILE_PATH_ID: { + if (ebpfCallStackObj_.FilePathIds()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(ebpfCallStackObj_.FilePathIds()[CurrentRow()])); + } + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/ebpf_callstack_table.h b/host/trace_streamer/src/table/ebpf_callstack_table.h new file mode 100644 index 0000000000000000000000000000000000000000..894ed5a386934baf86b88c06a7c548b39bbe35f2 --- /dev/null +++ b/host/trace_streamer/src/table/ebpf_callstack_table.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef EBPF_CALLSTACK_TABLE_H +#define EBPF_CALLSTACK_TABLE_H + +#include "table_base.h" +#include "trace_stdtype.h" + +namespace SysTuning { +namespace TraceStreamer { +class EbpfCallStackTable : public TableBase { +public: + explicit EbpfCallStackTable(const TraceDataCache* dataCache); + ~EbpfCallStackTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + private: + const EbpfCallStackData& ebpfCallStackObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // EBPF_CALLSTACK_TABLE_H diff --git a/host/trace_streamer/src/table/ebpf_elf_symbol_table.cpp b/host/trace_streamer/src/table/ebpf_elf_symbol_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6f67d7cdcb9878ca076a23823ec96c82eef1cd91 --- /dev/null +++ b/host/trace_streamer/src/table/ebpf_elf_symbol_table.cpp @@ -0,0 +1,231 @@ +/* + * 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. + */ +#include "ebpf_elf_symbol_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + ELF_ID, + ST_NAME, + ST_VALUE, + ST_SIZE, +}; +} +EbpfElfSymbolTable::EbpfElfSymbolTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("elf_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("st_name", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("st_value", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("st_size", "INTEGER")); + tablePriKey_.push_back("id"); +} + +EbpfElfSymbolTable::~EbpfElfSymbolTable() {} + +void EbpfElfSymbolTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstHidumpData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void EbpfElfSymbolTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool EbpfElfSymbolTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr EbpfElfSymbolTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +EbpfElfSymbolTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstEbpfElfSymbol().Size())), + ebpfElfSymbolObj_(dataCache->GetConstEbpfElfSymbol()) +{ +} + +EbpfElfSymbolTable::Cursor::~Cursor() {} + +int EbpfElfSymbolTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int EbpfElfSymbolTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(ebpfElfSymbolObj_.IdsData()[CurrentRow()])); + break; + case ELF_ID: + sqlite3_result_int64(context_, static_cast(ebpfElfSymbolObj_.ElfIds()[CurrentRow()])); + break; + case ST_NAME: + sqlite3_result_int64(context_, static_cast(ebpfElfSymbolObj_.StNames()[CurrentRow()])); + break; + case ST_VALUE: + sqlite3_result_int64(context_, static_cast(ebpfElfSymbolObj_.StValues()[CurrentRow()])); + break; + case ST_SIZE: + sqlite3_result_int64(context_, static_cast(ebpfElfSymbolObj_.StSizes()[CurrentRow()])); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} + +void EbpfElfSymbolTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL + indexMap_->Intersect(0, 0); + return; + } + + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + indexMap_->Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + indexMap_->Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/ebpf_elf_symbol_table.h b/host/trace_streamer/src/table/ebpf_elf_symbol_table.h new file mode 100644 index 0000000000000000000000000000000000000000..c3af6c0a7d4a88d50fefd3a50c41342f64797b94 --- /dev/null +++ b/host/trace_streamer/src/table/ebpf_elf_symbol_table.h @@ -0,0 +1,50 @@ +/* + * 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. + */ +#ifndef EBPF_ELF_SYMBOL_TABLE_H +#define EBPF_ELF_SYMBOL_TABLE_H + +#include "table_base.h" +#include "trace_stdtype.h" + +namespace SysTuning { +namespace TraceStreamer { +class EbpfElfSymbolTable : public TableBase { +public: + explicit EbpfElfSymbolTable(const TraceDataCache* dataCache); + ~EbpfElfSymbolTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + void FilterId(unsigned char op, sqlite3_value* argv); + + private: + const EbpfElfSymbol& ebpfElfSymbolObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // EBPF_ELF_SYMBOL_TABLE_H diff --git a/host/trace_streamer/src/table/ebpf_elf_table.cpp b/host/trace_streamer/src/table/ebpf_elf_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f25c7bb809e45439a793e68b50437670fbd296e0 --- /dev/null +++ b/host/trace_streamer/src/table/ebpf_elf_table.cpp @@ -0,0 +1,263 @@ +/* + * 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. + */ +#include "ebpf_elf_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + ELF_ID, + TEXT_VADDR, + TEXT_OFFSET, + STR_TAB_LEN, + SYM_TAB_LEN, + FILE_NAME_LEN, + SYM_ENT_LEN, + FILE_PATH_ID, +}; +} +EbpfElfTable::EbpfElfTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("elf_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("text_vaddr", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("text_offset", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("str_tab_len", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("sym_tab_len", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("file_name_len", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("sym_ent_len", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("file_path_id", "INTEGER")); + tablePriKey_.push_back("id"); +} + +EbpfElfTable::~EbpfElfTable() {} + +void EbpfElfTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstHidumpData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void EbpfElfTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool EbpfElfTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr EbpfElfTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +EbpfElfTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstEbpfElf().Size())), + ebpfElfObj_(dataCache->GetConstEbpfElf()) +{ +} + +EbpfElfTable::Cursor::~Cursor() {} + +int EbpfElfTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int EbpfElfTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(ebpfElfObj_.IdsData()[CurrentRow()])); + break; + case ELF_ID: + sqlite3_result_int64(context_, static_cast(ebpfElfObj_.ElfIds()[CurrentRow()])); + break; + case TEXT_VADDR: + sqlite3_result_int64(context_, static_cast(ebpfElfObj_.TextVaddrs()[CurrentRow()])); + break; + case TEXT_OFFSET: + sqlite3_result_int64(context_, static_cast(ebpfElfObj_.TextOffsets()[CurrentRow()])); + break; + case STR_TAB_LEN: + sqlite3_result_int64(context_, static_cast(ebpfElfObj_.StrTabLens()[CurrentRow()])); + break; + case SYM_TAB_LEN: { + if (ebpfElfObj_.SymTabLens()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(ebpfElfObj_.SymTabLens()[CurrentRow()])); + } + break; + } + case FILE_NAME_LEN: { + if (ebpfElfObj_.FileNameLens()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(ebpfElfObj_.FileNameLens()[CurrentRow()])); + } + break; + } + case SYM_ENT_LEN: { + if (ebpfElfObj_.SymEntLens()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(ebpfElfObj_.SymEntLens()[CurrentRow()])); + } + break; + } + case FILE_PATH_ID: { + if (ebpfElfObj_.FileNameIndexs()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(ebpfElfObj_.FileNameIndexs()[CurrentRow()])); + } + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} + +void EbpfElfTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL + indexMap_->Intersect(0, 0); + return; + } + + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + indexMap_->Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + indexMap_->Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/ebpf_elf_table.h b/host/trace_streamer/src/table/ebpf_elf_table.h new file mode 100644 index 0000000000000000000000000000000000000000..b50b52354927e3e8c744cfde6b19d34efdb01073 --- /dev/null +++ b/host/trace_streamer/src/table/ebpf_elf_table.h @@ -0,0 +1,50 @@ +/* + * 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. + */ +#ifndef EBPF_ELF_TABLE_H +#define EBPF_ELF_TABLE_H + +#include "table_base.h" +#include "trace_stdtype.h" + +namespace SysTuning { +namespace TraceStreamer { +class EbpfElfTable : public TableBase { +public: + explicit EbpfElfTable(const TraceDataCache* dataCache); + ~EbpfElfTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + void FilterId(unsigned char op, sqlite3_value* argv); + + private: + const EbpfElf& ebpfElfObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // EBPF_ELF_TABLE_H diff --git a/host/trace_streamer/src/table/ebpf_process_maps_table.cpp b/host/trace_streamer/src/table/ebpf_process_maps_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ecd61209f093e5b2604d59803823a2174e1cc37 --- /dev/null +++ b/host/trace_streamer/src/table/ebpf_process_maps_table.cpp @@ -0,0 +1,250 @@ +/* + * 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. + */ +#include "ebpf_process_maps_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + START_ADDR, + END_ADDR, + OFFSETS, + PID, + FILE_NAME_LEN, + FILE_PATH_ID, +}; +} +EbpfProcessMapsTable::EbpfProcessMapsTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("start_addr", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_addr", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("offset", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("pid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("file_path_len", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("file_path_id", "INTEGER")); + tablePriKey_.push_back("id"); +} + +EbpfProcessMapsTable::~EbpfProcessMapsTable() {} + +void EbpfProcessMapsTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstHidumpData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void EbpfProcessMapsTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool EbpfProcessMapsTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr EbpfProcessMapsTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +EbpfProcessMapsTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstEbpfProcessMaps().Size())), + ebpfProcessMapsObj_(dataCache->GetConstEbpfProcessMaps()) +{ +} + +EbpfProcessMapsTable::Cursor::~Cursor() {} + +int EbpfProcessMapsTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int EbpfProcessMapsTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(ebpfProcessMapsObj_.IdsData()[CurrentRow()])); + break; + case START_ADDR: + sqlite3_result_int64(context_, static_cast(ebpfProcessMapsObj_.Starts()[CurrentRow()])); + break; + case END_ADDR: + sqlite3_result_int64(context_, static_cast(ebpfProcessMapsObj_.Ends()[CurrentRow()])); + break; + case OFFSETS: + sqlite3_result_int64(context_, static_cast(ebpfProcessMapsObj_.Offsets()[CurrentRow()])); + break; + case PID: { + if (ebpfProcessMapsObj_.Pids()[CurrentRow()] != INVALID_UINT32) { + sqlite3_result_int64(context_, static_cast(ebpfProcessMapsObj_.Pids()[CurrentRow()])); + } + break; + } + case FILE_NAME_LEN: { + if (ebpfProcessMapsObj_.FileNameLens()[CurrentRow()] != INVALID_UINT32) { + sqlite3_result_int64(context_, static_cast(ebpfProcessMapsObj_.FileNameLens()[CurrentRow()])); + } + break; + } + case FILE_PATH_ID: { + if (ebpfProcessMapsObj_.FileNameIndexs()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(ebpfProcessMapsObj_.FileNameIndexs()[CurrentRow()])); + } + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} + +void EbpfProcessMapsTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL + indexMap_->Intersect(0, 0); + return; + } + + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + indexMap_->Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + indexMap_->Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/ebpf_process_maps_table.h b/host/trace_streamer/src/table/ebpf_process_maps_table.h new file mode 100644 index 0000000000000000000000000000000000000000..10a7997a23d080c9ab67f430a13b7d7bd158cee5 --- /dev/null +++ b/host/trace_streamer/src/table/ebpf_process_maps_table.h @@ -0,0 +1,50 @@ +/* + * 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. + */ +#ifndef EBPF_PROCESS_MAPS_TABLE_H +#define EBPF_PROCESS_MAPS_TABLE_H + +#include "table_base.h" +#include "trace_stdtype.h" + +namespace SysTuning { +namespace TraceStreamer { +class EbpfProcessMapsTable : public TableBase { +public: + explicit EbpfProcessMapsTable(const TraceDataCache* dataCache); + ~EbpfProcessMapsTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + void FilterId(unsigned char op, sqlite3_value* argv); + + private: + const EbpfProcessMaps& ebpfProcessMapsObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // EBPF_PROCESS_MAPS_TABLE_H diff --git a/host/trace_streamer/src/table/file_system_sample_table.cpp b/host/trace_streamer/src/table/file_system_sample_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6b11ff1d2066862cab956255280fac71d215ed99 --- /dev/null +++ b/host/trace_streamer/src/table/file_system_sample_table.cpp @@ -0,0 +1,300 @@ +/* + * 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. + */ + +#include "file_system_sample_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + CALLCHAIN_ID, + TYPE, + IPID, + ITID, + START_TS, + END_TS, + DUR, + RETURN_VALUE, + ERROR_VALUE, + FD, + FILE_ID, + SIZE, + FIRST_ARGUMENT, + SECOND_ARGUMENT, + THIRD_ARGUMENT, + FOURTH_ARGUMENT, +}; +} +FileSystemSampleTable::FileSystemSampleTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("return_value", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("error_code", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("fd", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("file_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("size", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("first_argument", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("second_argument", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("third_argument", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("fourth_argument", "TEXT")); + tablePriKey_.push_back("id"); +} + +FileSystemSampleTable::~FileSystemSampleTable() {} + +void FileSystemSampleTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstHidumpData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void FileSystemSampleTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool FileSystemSampleTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr FileSystemSampleTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +FileSystemSampleTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstFileSystemSample().Size())), + fileSystemSampleTableObj_(dataCache->GetConstFileSystemSample()) +{ +} + +FileSystemSampleTable::Cursor::~Cursor() {} + +int FileSystemSampleTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case TYPE: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + fileSystemSampleTableObj_.Types()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + return SQLITE_OK; +} + +int FileSystemSampleTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.IdsData()[CurrentRow()])); + break; + case CALLCHAIN_ID: + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.CallChainIds()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.Types()[CurrentRow()])); + break; + case IPID: + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.Ipids()[CurrentRow()])); + break; + case ITID: + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.Itids()[CurrentRow()])); + break; + case START_TS: + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.StartTs()[CurrentRow()])); + break; + case END_TS: + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.EndTs()[CurrentRow()])); + break; + case DUR: + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.Durs()[CurrentRow()])); + break; + case RETURN_VALUE: { + if (fileSystemSampleTableObj_.ReturnValues()[CurrentRow()] != INVALID_UINT64) { + auto returnValueIndex = fileSystemSampleTableObj_.ReturnValues()[CurrentRow()]; + sqlite3_result_text(context_, dataCache_->GetDataFromDict(returnValueIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case ERROR_VALUE: { + if (fileSystemSampleTableObj_.ErrorCodes()[CurrentRow()] != INVALID_UINT64) { + auto errorValueIndex = fileSystemSampleTableObj_.ErrorCodes()[CurrentRow()]; + sqlite3_result_text(context_, dataCache_->GetDataFromDict(errorValueIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case FD: { + if (fileSystemSampleTableObj_.Fds()[CurrentRow()] != INVALID_INT32) { + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.Fds()[CurrentRow()])); + } + break; + } + case FILE_ID: { + if (fileSystemSampleTableObj_.FileIds()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.FileIds()[CurrentRow()])); + } + break; + } + case SIZE: { + if (fileSystemSampleTableObj_.Sizes()[CurrentRow()] != MAX_SIZE_T) { + sqlite3_result_int64(context_, static_cast(fileSystemSampleTableObj_.Sizes()[CurrentRow()])); + } + break; + } + case FIRST_ARGUMENT: { + if (fileSystemSampleTableObj_.FirstArguments()[CurrentRow()] != INVALID_UINT64) { + auto firstArgIndex = fileSystemSampleTableObj_.FirstArguments()[CurrentRow()]; + sqlite3_result_text(context_, dataCache_->GetDataFromDict(firstArgIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case SECOND_ARGUMENT: { + if (fileSystemSampleTableObj_.SecondArguments()[CurrentRow()] != INVALID_UINT64) { + auto secondArgIndex = fileSystemSampleTableObj_.SecondArguments()[CurrentRow()]; + sqlite3_result_text(context_, dataCache_->GetDataFromDict(secondArgIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case THIRD_ARGUMENT: { + if (fileSystemSampleTableObj_.ThirdArguments()[CurrentRow()] != INVALID_UINT64) { + auto thirdArgIndex = fileSystemSampleTableObj_.ThirdArguments()[CurrentRow()]; + sqlite3_result_text(context_, dataCache_->GetDataFromDict(thirdArgIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case FOURTH_ARGUMENT: { + if (fileSystemSampleTableObj_.FourthArguments()[CurrentRow()] != INVALID_UINT64) { + auto fourthArgIndex = fileSystemSampleTableObj_.FourthArguments()[CurrentRow()]; + sqlite3_result_text(context_, dataCache_->GetDataFromDict(fourthArgIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/file_system_sample_table.h b/host/trace_streamer/src/table/file_system_sample_table.h new file mode 100644 index 0000000000000000000000000000000000000000..93d75db068de9d922249ee228ee57ac77ef64ab2 --- /dev/null +++ b/host/trace_streamer/src/table/file_system_sample_table.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef FILE_SYSTEM_SAMPLE_TABLE_H +#define FILE_SYSTEM_SAMPLE_TABLE_H + +#include "table_base.h" +#include "trace_stdtype.h" + +namespace SysTuning { +namespace TraceStreamer { +class FileSystemSampleTable : public TableBase { +public: + explicit FileSystemSampleTable(const TraceDataCache* dataCache); + ~FileSystemSampleTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + private: + const FileSystemSample& fileSystemSampleTableObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // FILE_SYSTEM_SAMPLE_TABLE_H diff --git a/host/trace_streamer/src/table/filter_constraints.cpp b/host/trace_streamer/src/table/filter_constraints.cpp new file mode 100755 index 0000000000000000000000000000000000000000..914d4a81b790299e49abffe1892ae941e30665c2 --- /dev/null +++ b/host/trace_streamer/src/table/filter_constraints.cpp @@ -0,0 +1,132 @@ +/* + * 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. + */ + +#include "filter_constraints.h" + +#include "log.h" + +namespace SysTuning { +namespace TraceStreamer { +void FilterConstraints::AddConstraint(int idx, int col, unsigned char op, bool isSupport) +{ + Constraint& c = constraints_.emplace_back(); + c.idxInaConstraint = idx; + c.col = col; + c.op = op; + c.isSupport = isSupport; +} + +void FilterConstraints::UpdateConstraint(int idx, bool isSupport) +{ + if (idx >= 0 && static_cast(idx) < constraints_.size()) { + constraints_[idx].isSupport = isSupport; + } +} + +void FilterConstraints::AddOrderBy(int col, unsigned char desc) +{ + OrderBy& o = orderBys_.emplace_back(); + o.iColumn = col; + o.desc = desc; +} + +void FilterConstraints::Clear() +{ + constraints_.clear(); + orderBys_.clear(); +} + +void FilterConstraints::ToString(std::string& idxStr) const +{ + idxStr.clear(); + idxStr.reserve(idxStrSize_); + idxStr = "C" + std::to_string(constraints_.size()); + for (size_t i = 0; i < constraints_.size(); i++) { + idxStr += " " + std::to_string(constraints_[i].col); + idxStr += " " + std::to_string(constraints_[i].op); + } + idxStr += " O" + std::to_string(orderBys_.size()); + for (size_t i = 0; i < orderBys_.size(); i++) { + idxStr += " " + std::to_string(orderBys_[i].iColumn); + idxStr += " " + std::to_string(orderBys_[i].desc); + } +} + +void FilterConstraints::FromString(const std::string& idxStr) +{ + const char* p = static_cast(idxStr.c_str()); + char* pNext = nullptr; + TS_ASSERT(*p == 'C'); + errno = 0; + int constraintCount = static_cast(strtol(p + 1, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + for (int i = 0; i < constraintCount; i++) { + p = pNext; + errno = 0; + int col = static_cast(strtol(p, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + p = pNext; + errno = 0; + unsigned char op = static_cast(strtol(p, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + + AddConstraint(i, col, op); + } + + pNext++; // jump the ' ' + p = pNext; + TS_ASSERT(*p == 'O'); + errno = 0; + int orderbyCount = static_cast(strtol(p + 1, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + for (int i = 0; i < orderbyCount; i++) { + p = pNext; + errno = 0; + int col = static_cast(strtol(p, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + p = pNext; + errno = 0; + unsigned char desc = static_cast(strtol(p, &pNext, 10)); + if (errno != 0) { + TS_LOGW("strtol failed!"); + return; + } + TS_ASSERT(p != pNext); + + AddOrderBy(col, desc); + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/filter_constraints.h b/host/trace_streamer/src/table/filter_constraints.h new file mode 100755 index 0000000000000000000000000000000000000000..4170aa661842304dcaf4ceeb851d06983d910aa8 --- /dev/null +++ b/host/trace_streamer/src/table/filter_constraints.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#ifndef TABLE_FILTER_CONSTRAINTS_H +#define TABLE_FILTER_CONSTRAINTS_H + +#include +#include + +#include + +namespace SysTuning { +namespace TraceStreamer { +class FilterConstraints { +public: + struct Constraint { + int idxInaConstraint; // index in sqlite3_index_info.aConstraint[] + int col; // Column this constraint refers to + unsigned char op; // SQLite op for the constraint + bool isSupport = false; + }; + using OrderBy = sqlite3_index_info::sqlite3_index_orderby; + + FilterConstraints() {} + ~FilterConstraints() {} + void AddConstraint(int idx, int col, unsigned char op, bool isSupport = false); + void UpdateConstraint(int idx, bool isSupport); + void AddOrderBy(int col, unsigned char desc); + void Clear(); + + const std::vector& GetOrderBys() const + { + return orderBys_; + } + + const std::vector& GetConstraints() const + { + return constraints_; + } + + // idxStr format: C col1 op1 ... colN opN O col1 desc1 ... colM descM + // like as "C2 0 2 1 4 O1 0 1" + void ToString(std::string& idxStr) const; + void FromString(const std::string& idxStr); + +private: + std::vector constraints_; + std::vector orderBys_; + const std::size_t idxStrSize_ = 512; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TABLE_FILTER_CONSTRAINTS_H diff --git a/host/trace_streamer/src/table/filter_table.cpp b/host/trace_streamer/src/table/filter_table.cpp index 471cca7f75017687b11d728f1ea35ab900e7972f..6c5a406ba029848ab167616e78a893488388adc2 100644 --- a/host/trace_streamer/src/table/filter_table.cpp +++ b/host/trace_streamer/src/table/filter_table.cpp @@ -22,33 +22,152 @@ enum Index { ID = 0, TYPE, NAME, SOURCE_ARG_SET_ID }; } FilterTable::FilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("source_arg_set_id", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("source_arg_set_id", "INTEGER")); tablePriKey_.push_back("id"); } FilterTable::~FilterTable() {} -void FilterTable::CreateCursor() +void FilterTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstFilterData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void FilterTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool FilterTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr FilterTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); } -FilterTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstFilterData().Size())), +FilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstFilterData().Size())), filterObj_(dataCache->GetConstFilterData()) { } FilterTable::Cursor::~Cursor() {} -int FilterTable::Cursor::Column(int column) const +int FilterTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int FilterTable::Cursor::Column(int col) const { - switch (column) { + switch (col) { case ID: - sqlite3_result_int64(context_, static_cast(filterObj_.IdsData()[CurrentRow()])); + sqlite3_result_int64(context_, CurrentRow()); // IdsData() will be optimized break; case TYPE: sqlite3_result_text(context_, filterObj_.TypeData()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); @@ -60,7 +179,7 @@ int FilterTable::Cursor::Column(int column) const sqlite3_result_int64(context_, static_cast(filterObj_.SourceArgSetIdData()[CurrentRow()])); break; default: - TS_LOGF("Unregistered column : %d", column); + TS_LOGF("Unregistered column : %d", col); break; } return SQLITE_OK; diff --git a/host/trace_streamer/src/table/filter_table.h b/host/trace_streamer/src/table/filter_table.h old mode 100644 new mode 100755 index 5b5a359b5d9ebe7950b8af912733a4b8b61af23d..5243cf0d10266931a4b8e41f8769b1c25f3db762 --- a/host/trace_streamer/src/table/filter_table.h +++ b/host/trace_streamer/src/table/filter_table.h @@ -24,19 +24,25 @@ namespace TraceStreamer { class FilterTable : public TableBase { public: enum Column { ID = 0, TYPE = 1, NAME = 2, ARG_ID = 3 }; - explicit FilterTable(const TraceDataCache* storage); + explicit FilterTable(const TraceDataCache* dataCache); ~FilterTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; - int Column(int column) const override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int col) const override; private: - const Filter& filterObj_; + const TraceStreamer::Filter& filterObj_; }; }; } // namespace TraceStreamer diff --git a/host/trace_streamer/src/table/hidump_table.cpp b/host/trace_streamer/src/table/hidump_table.cpp index 0b3cb174bc7b4e7becd51e9d8aa5d95d5020659d..aa605ffc38b221313ef85b455e3ed26d7d0e2586 100644 --- a/host/trace_streamer/src/table/hidump_table.cpp +++ b/host/trace_streamer/src/table/hidump_table.cpp @@ -18,33 +18,163 @@ namespace SysTuning { namespace TraceStreamer { namespace { -enum Index { TS = 0, FPS }; +enum Index { ID = 0, TS, FPS }; } HidumpTable::HidumpTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("fps", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("fps", "INTEGER")); tablePriKey_.push_back("ts"); } HidumpTable::~HidumpTable() {} -void HidumpTable::CreateCursor() +void HidumpTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstHidumpData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void HidumpTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool HidumpTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr HidumpTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); } -HidumpTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstHidumpData().Size())), +HidumpTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstHidumpData().Size())), hidumpObj_(dataCache->GetConstHidumpData()) { } HidumpTable::Cursor::~Cursor() {} +int HidumpTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case TS: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + hidumpObj_.TimeStamData()); + break; + case FPS: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), hidumpObj_.Fpss()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int HidumpTable::Cursor::Column(int column) const { switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; case TS: sqlite3_result_int64(context_, static_cast(hidumpObj_.TimeStamData()[CurrentRow()])); break; diff --git a/host/trace_streamer/src/table/hidump_table.h b/host/trace_streamer/src/table/hidump_table.h index 8c1bb1e8a50624765f43f94980d8c1ade9bfa620..ac923c595b1764b6ae004a40edb94e9bfdff3450 100644 --- a/host/trace_streamer/src/table/hidump_table.h +++ b/host/trace_streamer/src/table/hidump_table.h @@ -25,13 +25,19 @@ class HidumpTable : public TableBase { public: explicit HidumpTable(const TraceDataCache* dataCache); ~HidumpTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int column) const override; private: diff --git a/host/trace_streamer/src/table/index_map.cpp b/host/trace_streamer/src/table/index_map.cpp new file mode 100755 index 0000000000000000000000000000000000000000..8a046db42f243eff0b716cf6353124830bb0849d --- /dev/null +++ b/host/trace_streamer/src/table/index_map.cpp @@ -0,0 +1,273 @@ +/* + * 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. + */ + +#include "index_map.h" + +#include + +#include "log.h" + +namespace SysTuning { +namespace TraceStreamer { +IndexMap::IndexMap(TableRowId start, TableRowId end) + : current_(start), start_(start), end_(end), type_(COMPACT) {} + +void IndexMap::CovertToIndexMap() +{ + if (converted_) { + indexType_ = INDEX_TYPE_OUTER_INDEX; + return; + } + converted_ = true; + if (indexType_ == INDEX_TYPE_ID && HasData()) { + for (auto i = start_; i < end_; i++) { + rowIndex_.push_back(i); + } + current_ = start_ = 0; + end_ = rowIndex_.size(); + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + empty_ = false; +} + +void IndexMap::Print() +{ + for (auto itor = rowIndex_.begin(); itor != rowIndex_.end(); itor++) { + fprintf(stdout, "%d,", *itor); + } + fflush(stdout); +} +void IndexMap::Sort() +{ +} + +void IndexMap::Init() +{ + intersectEable_ = HasData(); +} +bool IndexMap::HasData() { + return !empty_; +} +void IndexMap::Intersect(TableRowId start, TableRowId end) +{ + if (indexType_ == INDEX_TYPE_OUTER_INDEX) { + bool changed = false; + rowIndexBak_.clear(); + for (auto i = rowIndex_.begin(); i != rowIndex_.end(); i++) { + if (*i >= start && *i < end) { + changed = true; + rowIndexBak_.push_back(*i); + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + start_ = current_ = 0; + end_ = rowIndex_.size(); + } else { + start_ = std::max(start_, start); + end_ = std::min(end_, end); + current_ = start_; + } + empty_ = false; +} + +size_t IndexMap::Size() const +{ + return end_ - start_; +} + +void IndexMap::Next() +{ + if (desc_) { + if (current_ > start_ - 1) { + if (current_ == 0) { + current_ = 0; + } + current_--; + } + } else { + if (current_ < end_) { + current_++; + } + } +} +void IndexMap::FilterId(unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL + Intersect(0, 0); + return; + } + if (HasData()) { + CovertToIndexMap(); + } + + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + Intersect(v, end_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + Intersect(v, end_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } +} + +void IndexMap::FilterTS(unsigned char op, sqlite3_value* argv, const std::deque& times) +{ + auto v = static_cast(sqlite3_value_int64(argv)); + auto getValue = [](const uint64_t& row) { return row; }; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + IntersectabcEqual(times, v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + case SQLITE_INDEX_CONSTRAINT_GE: { + IntersectGreaterEqual(times, v, getValue); + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + case SQLITE_INDEX_CONSTRAINT_LT: { + IntersectLessEqual(times, v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: { + RemoveNullElements(times, v); + break; + } + default: + break; + } // end of switch (op) + } +} +void IndexMap::Merge(IndexMap* other) +{ + if (indexType_ == INDEX_TYPE_ID && other->indexType_ == INDEX_TYPE_ID) { + if ((other->start_ >= start_ && other->start_ <= end_) || (start_ >= other->start_ && start_ <= other->end_)) { + start_ = std::min(start_, other->start_); + end_ = std::max(end_, other->end_); + } else if (start_ > other->start_) { + this->CovertToIndexMap(); + other->CovertToIndexMap(); + const std::vector b = other->rowIndex_; + uint32_t bIndex = 0; + uint32_t bSize = b.size(); + while (bIndex != bSize) { + rowIndex_.push_back(b[bIndex]); + } + start_ = current_ = 0; + end_ = rowIndex_.size(); + } else { + this->CovertToIndexMap(); + other->CovertToIndexMap(); + std::vector c = other->rowIndex_; + uint32_t aIndex = 0; + uint32_t aSize = rowIndex_.size(); + while (aIndex != aSize) { + c.push_back(rowIndex_[aIndex]); + } + start_ = current_ = 0; + end_ = rowIndex_.size(); + } + return; + } + this->CovertToIndexMap(); + other->CovertToIndexMap(); + const std::vector b = other->rowIndex_; + const std::vector& a = rowIndex_; + std::vector c; + uint32_t aIndex = 0; + uint32_t aSize = a.size(); + uint32_t bIndex = 0; + uint32_t bSize = b.size(); + while (aIndex != aSize || bIndex != bSize) { + if (aIndex == aSize) { + while (bIndex != bSize) { + c.push_back(b[bIndex]); + bIndex++; + } + break; + } + if (bIndex == bSize) { + while (aIndex != aSize) { + c.push_back(a[aIndex]); + bIndex++; + } + break; + } + if (a[aIndex] < b[bIndex]) { + c.push_back(a[aIndex]); + aIndex++; + } else if (a[aIndex] == b[bIndex]) { + c.push_back(a[aIndex]); + aIndex++; + bIndex++; + } else { + c.push_back(b[bIndex]); + bIndex++; + } + } + rowIndex_ = c; + start_ = current_ = 0; + end_ = rowIndex_.size(); +} + +bool IndexMap::Eof() const +{ + if (desc_) { + return current_ <= start_ - 1; + } else { + return current_ >= end_; + } +} + +TableRowId IndexMap::CurrentRow() const +{ + auto current = current_; + if (indexType_ == INDEX_TYPE_ID) { + return current; + } else { + return rowIndex_[current]; + } +} + +void IndexMap::SortBy(bool desc) +{ + if (desc) { + current_ = end_ - 1; + } else { + current_ = start_; + } + desc_ = desc; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/index_map.h b/host/trace_streamer/src/table/index_map.h new file mode 100755 index 0000000000000000000000000000000000000000..ed441c701572c4753da0ffc2c56e3b174b0559c5 --- /dev/null +++ b/host/trace_streamer/src/table/index_map.h @@ -0,0 +1,375 @@ +/* + * 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. + */ + +#ifndef TABLE_INDEX_MAP_H +#define TABLE_INDEX_MAP_H + +#include +#include +#include +#include +#include +#include "ts_common.h" + +namespace SysTuning { +namespace TraceStreamer { +class IndexMap { +public: + IndexMap() {} + ~IndexMap() {} + + IndexMap(TableRowId start, TableRowId end); + void CovertToIndexMap(); + void Sort(); + void Print(); + void Init(); + void Merge(IndexMap * other); + void FilterId(unsigned char op, sqlite3_value* argv); + void FilterTS(unsigned char op, sqlite3_value* argv, const std::deque& times); + template + void MixRange(unsigned char op, T value, const std::deque& dataQueue) + { + filters_++; + auto invalidValue = std::numeric_limits::max(); + bool remove = false; + if (HasData()) { + CovertToIndexMap(); + remove = true; + } + auto size = dataQueue.size(); + rowIndexBak_.clear(); + bool changed = false; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] != value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] == value) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_NE: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] == value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] != value) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNULL: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] != invalidValue) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] == invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] == invalidValue) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] != invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] <= value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] > value) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] < value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] >= invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] > value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] < invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (dataQueue[*i] >= value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (dataQueue[i] < invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + break; + + + default: + break; + } // end of switch (op) + empty_ = false; + } + void FixSize() + { + if (indexType_ == INDEX_TYPE_OUTER_INDEX) + { + end_ = rowIndex_.size(); + current_ = 0; + } + } + void Remove(TableRowId row) + { + (void)std::remove(rowIndex_.begin(), rowIndex_.end(), row); + } + void Set(TableRowId start, TableRowId end) + { + if (indexType_ == INDEX_TYPE_ID) { + end_ = std::min(end_, end); + current_ = start_ = std::max(start_, start); + } + } + + size_t Size() const; + + void Next(); + + bool Eof() const; + + TableRowId CurrentRow() const; + + void SortBy(bool desc); + void Intersect(TableRowId start, TableRowId end); + + // the follow functions require that thecolData is sotred + template + void IntersectabcEqual(const std::deque& rows, Val v, GetV getValue) + { + auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v); + auto end = std::upper_bound(start, rows.begin() + end_, v); + auto newStart = std::distance(rows.begin(), start); + auto newEnd = std::distance(rows.begin(), end); + Intersect(newStart, newEnd); + return; + } + + template + void IntersectGreaterEqual(const std::deque& rows, Val v, GetV getValue) + { + auto start = std::lower_bound(rows.begin() + start_, rows.begin() + end_, v, + [&](const Row& row, const Val& v) { return v > getValue(row); }); + auto newStart = std::distance(rows.begin(), start); + Intersect(newStart, INVALID_INT32); + return; + } + + template + void IntersectLessEqual(const std::deque& rows, Val v, GetV getValue) + { + auto end = std::upper_bound(rows.begin() + start_, rows.begin() + end_, v, + [&](const Row& row, const Val& v) { return v > getValue(row); }); + auto newEnd = std::distance(rows.begin(), end); + Intersect(0, newEnd); + return; + } + template + void RemoveNullElements(const std::deque& rows, T v) + { + auto invalidValue = std::numeric_limits::max(); + bool remove = false; + if (HasData()) { + CovertToIndexMap(); + remove = true; + } + + if (remove) { + for (auto i = rowIndex_.begin(); i != rowIndex_.end();) { + if (rows[*i] == invalidValue) { + i = rowIndex_.erase(i); + } else { + i++; + } + } + } else { + auto size = rows.size(); + for (auto i = 0; i < size; i++) { + if (rows[i] != invalidValue) { + rowIndex_.push_back(i); + } + } + } + indexType_ = INDEX_TYPE_OUTER_INDEX; + FixSize(); + return; + } + bool HasData(); + std::vector rowIndex_ = {}; + std::vector rowIndexBak_ = {}; +private: + TableRowId end_ = INVALID_INT32; + TableRowId current_ = 0; + TableRowId start_ = 0; + enum FindIndexType { + INDEX_TYPE_ID, + INDEX_TYPE_OUTER_INDEX, + }; + FindIndexType indexType_ = INDEX_TYPE_ID; + uint32_t indexSize_ = 0; + uint32_t index_ = 0; + + enum IndexType { + COMPACT, + SPARSE + }; + uint8_t type_ = COMPACT; + bool empty_ = true; + bool desc_ = false; + bool converted_ = false; + uint8_t filters_ = 0; + bool intersectEable_ = false; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // TABLE_INDEX_MAP_H diff --git a/host/trace_streamer/src/table/instants_table.cpp b/host/trace_streamer/src/table/instants_table.cpp index 9d4ec7099671caf0f906e4c9e512b44500232ef1..72fe1eb1ee9a83f5f542d80b82265b11249df79c 100644 --- a/host/trace_streamer/src/table/instants_table.cpp +++ b/host/trace_streamer/src/table/instants_table.cpp @@ -14,37 +14,186 @@ */ #include "instants_table.h" +#include namespace SysTuning { namespace TraceStreamer { namespace { -enum Index { TS = 0, NAME, REF, REF_TYPE }; +enum Index { TS = 0, NAME, REF, WAKEUP_FROM, REF_TYPE, VALUE }; } InstantsTable::InstantsTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("ref", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("ref_type", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("ref", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("wakeup_from", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ref_type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "REAL")); tablePriKey_.push_back("ts"); tablePriKey_.push_back("ref"); } InstantsTable::~InstantsTable() {} -void InstantsTable::CreateCursor() +std::unique_ptr InstantsTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -InstantsTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstInstantsData().Size())), +InstantsTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstInstantsData().Size())), InstantsObj_(dataCache->GetConstInstantsData()) { } InstantsTable::Cursor::~Cursor() {} +void InstantsTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstMeasureData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case TS: + break; + case NAME: + break; + case REF: + break; + case WAKEUP_FROM: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void InstantsTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case TS: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool InstantsTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +int InstantsTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset + indexMap_ = std::make_unique(0, rowCount_); + if (rowCount_ <= 0) { + return SQLITE_OK; + } + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case TS: + FilterTS(c.op, argv[i], InstantsObj_.TimeStamData()); + break; + case NAME: + indexMap_->MixRange(c.op, + dataCache_->GetConstDataIndex( + std::string(reinterpret_cast(sqlite3_value_text(argv[i])))), + InstantsObj_.NameIndexsData()); + break; + case REF: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + InstantsObj_.InternalTidsData()); + break; + case WAKEUP_FROM: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + InstantsObj_.WakeupFromPidsData()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case TS: + indexMap_->SortBy(orderbys[i].desc); + break; + case NAME: + indexMap_->SortBy(orderbys[i].desc); + break; + case REF: + indexMap_->SortBy(orderbys[i].desc); + break; + case WAKEUP_FROM: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int InstantsTable::Cursor::Column(int column) const { size_t stringIdentity = static_cast(InstantsObj_.NameIndexsData()[CurrentRow()]); @@ -60,10 +209,17 @@ int InstantsTable::Cursor::Column(int column) const case REF: sqlite3_result_int64(context_, static_cast(InstantsObj_.InternalTidsData()[CurrentRow()])); break; + case WAKEUP_FROM: + sqlite3_result_int64(context_, static_cast(InstantsObj_.WakeupFromPidsData()[CurrentRow()])); + break; case REF_TYPE: { sqlite3_result_text(context_, "itid", STR_DEFAULT_LEN, nullptr); break; } + case VALUE: { + sqlite3_result_double(context_, 0.0); + break; + } default: TS_LOGF("Unregistered column : %d", column); break; diff --git a/host/trace_streamer/src/table/instants_table.h b/host/trace_streamer/src/table/instants_table.h old mode 100644 new mode 100755 index 06b7c0aedeb7329600b06e47dc2d5b04a9d19e30..2cf61e9fddf3b1214cbfc11cc91b28613cde9297 --- a/host/trace_streamer/src/table/instants_table.h +++ b/host/trace_streamer/src/table/instants_table.h @@ -25,15 +25,19 @@ class InstantsTable : public TableBase { public: explicit InstantsTable(const TraceDataCache* dataCache); ~InstantsTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + bool CanFilterSorted(const char op, size_t& rowCount) const; + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int column) const override; - private: const Instants& InstantsObj_; }; diff --git a/host/trace_streamer/src/table/irq_table.cpp b/host/trace_streamer/src/table/irq_table.cpp old mode 100644 new mode 100755 index a6e6a76b132b3e917471b9cd7a33641142f20ec0..30886d8f853e2e96cb6a57e59267ee1aaa5574f3 --- a/host/trace_streamer/src/table/irq_table.cpp +++ b/host/trace_streamer/src/table/irq_table.cpp @@ -38,21 +38,21 @@ enum Index { } IrqTable::IrqTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("callid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("cat", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("depth", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("cookie", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("parent_id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("argsetid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("chainId", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("spanId", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("parentSpanId", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("flag", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("args", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("cat", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("depth", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("cookie", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("parent_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("argsetid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("chainId", "TEXT")); + 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("args", "TEXT")); tablePriKey_.push_back("callid"); tablePriKey_.push_back("ts"); tablePriKey_.push_back("depth"); @@ -60,19 +60,138 @@ IrqTable::IrqTable(const TraceDataCache* dataCache) : TableBase(dataCache) IrqTable::~IrqTable() {} -void IrqTable::CreateCursor() +void IrqTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstIrqData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void IrqTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool IrqTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr IrqTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); } -IrqTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstIrqData().Size())), +IrqTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstIrqData().Size())), slicesObj_(dataCache->GetConstIrqData()) { } IrqTable::Cursor::~Cursor() {} +int IrqTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int IrqTable::Cursor::Column(int column) const { switch (column) { diff --git a/host/trace_streamer/src/table/irq_table.h b/host/trace_streamer/src/table/irq_table.h old mode 100644 new mode 100755 index 46b22c7f63c2b6762348830dc53bac25dbdc6525..264da9a79f2e78e7453e384edda116fa15232c4b --- a/host/trace_streamer/src/table/irq_table.h +++ b/host/trace_streamer/src/table/irq_table.h @@ -25,13 +25,19 @@ class IrqTable : public TableBase { public: explicit IrqTable(const TraceDataCache* dataCache); ~IrqTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int column) const override; private: diff --git a/host/trace_streamer/src/table/live_process_table.cpp b/host/trace_streamer/src/table/live_process_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..339f0614d0763170b629bc6743f2907c85904d38 --- /dev/null +++ b/host/trace_streamer/src/table/live_process_table.cpp @@ -0,0 +1,136 @@ +/* + * 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. + */ + +#include "live_process_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + TS = 0, + DUR, + CPU_TIME, + PROCESS_ID, + PROCESS_NAME, + PARENT_PROCESS_ID, + UID, + USER_NAME, + CPU_USAGE, + PSS_INFO, + THREAD_SUM, + DISK_WRITES, + DISK_READS +}; +} +LiveProcessTable::LiveProcessTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu_time", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("process_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("process_name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("parent_process_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("uid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("user_name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu_usage", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("pss_info", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("thread_num", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("disk_writes", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("disk_reads", "INTEGER")); + tablePriKey_.push_back("ts"); +} + +LiveProcessTable::~LiveProcessTable() {} + +std::unique_ptr LiveProcessTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +LiveProcessTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstLiveProcessData().Size())), + liveProcessDetailDataObj_(dataCache->GetConstLiveProcessData()) +{ +} + +LiveProcessTable::Cursor::~Cursor() {} + +int LiveProcessTable::Cursor::Column(int column) const +{ + switch (column) { + case TS: { + sqlite3_result_int64(context_, + static_cast(liveProcessDetailDataObj_.TimeStamData()[CurrentRow()])); + break; + } + case DUR: { + sqlite3_result_int64(context_, static_cast(liveProcessDetailDataObj_.Durs()[CurrentRow()])); + break; + } + case CPU_TIME: { + sqlite3_result_int64(context_, static_cast(liveProcessDetailDataObj_.CpuTimes()[CurrentRow()])); + break; + } + case PROCESS_ID: { + sqlite3_result_int(context_, static_cast(liveProcessDetailDataObj_.ProcessID()[CurrentRow()])); + break; + } + case PROCESS_NAME: { + sqlite3_result_text(context_, liveProcessDetailDataObj_.ProcessName()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); + break; + } + case PARENT_PROCESS_ID: { + sqlite3_result_int(context_, + static_cast(liveProcessDetailDataObj_.ParentProcessID()[CurrentRow()])); + break; + } + case UID: { + sqlite3_result_int(context_, static_cast(liveProcessDetailDataObj_.Uid()[CurrentRow()])); + break; + } + case USER_NAME: { + sqlite3_result_text(context_, liveProcessDetailDataObj_.UserName()[CurrentRow()].c_str(), STR_DEFAULT_LEN, + nullptr); + break; + } + case CPU_USAGE: { + sqlite3_result_double(context_, liveProcessDetailDataObj_.CpuUsage()[CurrentRow()]); + break; + } + case PSS_INFO: { + sqlite3_result_int(context_, static_cast(liveProcessDetailDataObj_.PssInfo()[CurrentRow()])); + break; + } + case THREAD_SUM: { + sqlite3_result_int(context_, static_cast(liveProcessDetailDataObj_.Threads()[CurrentRow()])); + break; + } + case DISK_WRITES: { + sqlite3_result_int(context_, static_cast(liveProcessDetailDataObj_.DiskWrites()[CurrentRow()])); + break; + } + case DISK_READS: { + sqlite3_result_int(context_, static_cast(liveProcessDetailDataObj_.DiskReads()[CurrentRow()])); + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/live_process_table.h b/host/trace_streamer/src/table/live_process_table.h new file mode 100644 index 0000000000000000000000000000000000000000..8c9d50080e1caa5d7a1f16a73f06f915806c0b6b --- /dev/null +++ b/host/trace_streamer/src/table/live_process_table.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef LIVE_PROCESS_TABLE_H +#define LIVE_PROCESS_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class LiveProcessTable : public TableBase { +public: + explicit LiveProcessTable(const TraceDataCache* dataCache); + ~LiveProcessTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int Column(int column) const override; + + private: + const LiveProcessDetailData& liveProcessDetailDataObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // LIVE_PROCESS_TABLE_H diff --git a/host/trace_streamer/src/table/log_table.cpp b/host/trace_streamer/src/table/log_table.cpp index 53b542c49a8fcaf7a41242d198c4783780e78d56..7f01fab48ece0408ad582e5effb90fab326f21c6 100644 --- a/host/trace_streamer/src/table/log_table.cpp +++ b/host/trace_streamer/src/table/log_table.cpp @@ -22,26 +22,26 @@ enum Index { SEQ = 0, TS, PID, TID, LEVEL, TAG, CONTEXT, ORIGINTS }; } LogTable::LogTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("seq", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("pid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("tid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("level", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("tag", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("context", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("origints", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("seq", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("pid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("tid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("level", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("tag", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("context", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("origints", "INTEGER")); tablePriKey_.push_back("ts"); } LogTable::~LogTable() {} -void LogTable::CreateCursor() +std::unique_ptr LogTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -LogTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstHilogData().Size())), +LogTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstHilogData().Size())), logInfoObj_(dataCache->GetConstHilogData()) { } diff --git a/host/trace_streamer/src/table/log_table.h b/host/trace_streamer/src/table/log_table.h index 22c5042b6c35816e8b52265aa8d767427f7d017b..794d02ba946c254a32d62e228f967e3c4185685f 100644 --- a/host/trace_streamer/src/table/log_table.h +++ b/host/trace_streamer/src/table/log_table.h @@ -25,13 +25,22 @@ class LogTable : public TableBase { public: explicit LogTable(const TraceDataCache* dataCache); ~LogTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; private: diff --git a/host/trace_streamer/src/table/measure_filter_table.cpp b/host/trace_streamer/src/table/measure_filter_table.cpp index 18131ee0f9516e26cfcb99f8e5c64daa2daeaf79..1786b63afc11da1c6500edf4e34acfabc7e97010 100644 --- a/host/trace_streamer/src/table/measure_filter_table.cpp +++ b/host/trace_streamer/src/table/measure_filter_table.cpp @@ -22,22 +22,22 @@ enum Index { ID = 0, TYPE, NAME, INTERNAL_TID }; } MeasureFilterTable::MeasureFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); tablePriKey_.push_back("id"); } MeasureFilterTable::~MeasureFilterTable() {} -void MeasureFilterTable::CreateCursor() +std::unique_ptr MeasureFilterTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -MeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstThreadMeasureFilterData().Size())) +MeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstThreadMeasureFilterData().Size())) { } @@ -61,7 +61,8 @@ int MeasureFilterTable::Cursor::Column(int column) const break; } case INTERNAL_TID: - sqlite3_result_int64(context_, + sqlite3_result_int64( + context_, static_cast(dataCache_->GetConstThreadMeasureFilterData().InternalTidData()[CurrentRow()])); break; default: diff --git a/host/trace_streamer/src/table/measure_filter_table.h b/host/trace_streamer/src/table/measure_filter_table.h old mode 100644 new mode 100755 index 54e8ceed1211b0a2701c56b8ed321afcefca8abb..54166e0db8eea1fa8d08718365c7f02c5adcd061 --- a/host/trace_streamer/src/table/measure_filter_table.h +++ b/host/trace_streamer/src/table/measure_filter_table.h @@ -25,13 +25,22 @@ class MeasureFilterTable : public TableBase { public: explicit MeasureFilterTable(const TraceDataCache* dataCache); ~MeasureFilterTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; }; }; diff --git a/host/trace_streamer/src/table/measure_table.cpp b/host/trace_streamer/src/table/measure_table.cpp index 2636dc70b6f2f4902626fbdd2a12574405bf3c0b..08836d2e5f975329251e54e4c10fd8b6a227b7fb 100644 --- a/host/trace_streamer/src/table/measure_table.cpp +++ b/host/trace_streamer/src/table/measure_table.cpp @@ -14,6 +14,7 @@ */ #include "measure_table.h" +#include namespace SysTuning { namespace TraceStreamer { @@ -22,31 +23,168 @@ enum Index { TYPE = 0, TS, VALUE, FILTER_ID }; } MeasureTable::MeasureTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("value", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("filter_id", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("filter_id", "INTEGER")); tablePriKey_.push_back("ts"); tablePriKey_.push_back("filter_id"); } MeasureTable::~MeasureTable() {} -void MeasureTable::CreateCursor() +std::unique_ptr MeasureTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -MeasureTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstMeasureData().Size())), - measureObj(dataCache->GetConstMeasureData()) +MeasureTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor( + dataCache, + table, + static_cast(table->name_ == "measure" || table->name_ == "_measure" + ? dataCache->GetConstMeasureData().Size() + : (table->name_ == "process_measure" || table->name_ == "_process_measure" + ? dataCache->GetConstProcessMeasureData().Size() + : dataCache->GetConstSysMemMeasureData().Size()))), + measureObj(table->name_ == "measure" || table->name_ == "_measure" + ? dataCache->GetConstMeasureData() + : (table->name_ == "process_measure" || table->name_ == "_process_measure" + ? dataCache->GetConstProcessMeasureData() + : dataCache->GetConstSysMemMeasureData())) { } MeasureTable::Cursor::~Cursor() {} +void MeasureTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstMeasureData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case TS: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void MeasureTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case TS: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool MeasureTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +int MeasureTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case TS: + FilterTS(c.op, argv[i], measureObj.TimeStamData()); + break; + case FILTER_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + measureObj.FilterIdData()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case TS: + indexMap_->SortBy(orderbys[i].desc); + break; + case FILTER_ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int MeasureTable::Cursor::Column(int column) const { + // printf("row:%d\n", CurrentRow()); switch (column) { case TYPE: sqlite3_result_text(context_, "measure", STR_DEFAULT_LEN, nullptr); diff --git a/host/trace_streamer/src/table/measure_table.h b/host/trace_streamer/src/table/measure_table.h old mode 100644 new mode 100755 index 418730d13737321e81e5b7e804c101dd26192170..7f220dfc2abd40b3d62935febe0cba73fa1ad776 --- a/host/trace_streamer/src/table/measure_table.h +++ b/host/trace_streamer/src/table/measure_table.h @@ -25,15 +25,19 @@ class MeasureTable : public TableBase { public: explicit MeasureTable(const TraceDataCache* dataCache); ~MeasureTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + bool CanFilterSorted(const char op, size_t& rowCount) const; + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int column) const override; - private: const Measure& measureObj; }; diff --git a/host/trace_streamer/src/table/meta_table.cpp b/host/trace_streamer/src/table/meta_table.cpp old mode 100644 new mode 100755 index 4d9304cfdf802bb03a3897b228f4e69db39686b4..8dcfa65eb2bf6fbfbcc09ec725921a9a0f0b8458 --- a/host/trace_streamer/src/table/meta_table.cpp +++ b/host/trace_streamer/src/table/meta_table.cpp @@ -22,19 +22,22 @@ enum Index { NAMEINDEX = 0, VALUE }; } MetaTable::MetaTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("value", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "TEXT")); tablePriKey_.push_back("name"); } MetaTable::~MetaTable() {} -void MetaTable::CreateCursor() +std::unique_ptr MetaTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -MetaTable::Cursor::Cursor(const TraceDataCache* dataCache) : TableBase::Cursor(dataCache, 0, METADATA_ITEM_MAX) {} +MetaTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, METADATA_ITEM_MAX) +{ +} MetaTable::Cursor::~Cursor() {} diff --git a/host/trace_streamer/src/table/meta_table.h b/host/trace_streamer/src/table/meta_table.h old mode 100644 new mode 100755 index e75e71b7143c8e90aba91c574dea77aff38974e7..44caf03bcd73a817800ac7130178393d2a86d5a9 --- a/host/trace_streamer/src/table/meta_table.h +++ b/host/trace_streamer/src/table/meta_table.h @@ -25,12 +25,22 @@ class MetaTable : public TableBase { public: explicit MetaTable(const TraceDataCache* dataCache); ~MetaTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; + private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; }; }; diff --git a/host/trace_streamer/src/table/native_hook_frame_table.cpp b/host/trace_streamer/src/table/native_hook_frame_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..708a09a6312d1e6e466c41386c8deb8b0c8b3d0a --- /dev/null +++ b/host/trace_streamer/src/table/native_hook_frame_table.cpp @@ -0,0 +1,228 @@ +/* + * 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. + */ + +#include "native_hook_frame_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, CALLCHAIN_ID, DEPTH, SYMBOL_ID, FILE_ID, OFFSET, SYMBOL_OFFSET, VADDR }; +} +NativeHookFrameTable::NativeHookFrameTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("depth", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("symbol_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("file_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("offset", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("symbol_offset", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("vaddr", "TEXT")); + tablePriKey_.push_back("id"); +} + +NativeHookFrameTable::~NativeHookFrameTable() {} + +void NativeHookFrameTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstNativeHookFrameData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void NativeHookFrameTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool NativeHookFrameTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr NativeHookFrameTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +NativeHookFrameTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstNativeHookFrameData().Size())), + nativeHookFrameInfoObj_(dataCache->GetConstNativeHookFrameData()) +{ +} + +NativeHookFrameTable::Cursor::~Cursor() {} + +int NativeHookFrameTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case CALLCHAIN_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + nativeHookFrameInfoObj_.CallChainIds()); + break; + case SYMBOL_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + nativeHookFrameInfoObj_.SymbolNames()); + break; + case FILE_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + nativeHookFrameInfoObj_.FilePaths()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int NativeHookFrameTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case CALLCHAIN_ID: + sqlite3_result_int64(context_, static_cast(nativeHookFrameInfoObj_.CallChainIds()[CurrentRow()])); + break; + case DEPTH: + sqlite3_result_int64(context_, static_cast(nativeHookFrameInfoObj_.Depths()[CurrentRow()])); + break; + case SYMBOL_ID: + if (nativeHookFrameInfoObj_.SymbolNames()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, + static_cast(nativeHookFrameInfoObj_.SymbolNames()[CurrentRow()])); + } + break; + case FILE_ID: { + if (nativeHookFrameInfoObj_.FilePaths()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(nativeHookFrameInfoObj_.FilePaths()[CurrentRow()])); + } + break; + } + case OFFSET: { + sqlite3_result_int64(context_, static_cast(nativeHookFrameInfoObj_.Offsets()[CurrentRow()])); + break; + } + case SYMBOL_OFFSET: { + sqlite3_result_int64(context_, static_cast(nativeHookFrameInfoObj_.SymbolOffsets()[CurrentRow()])); + break; + } + case VADDR: { + if (!nativeHookFrameInfoObj_.Vaddrs()[CurrentRow()].empty()) { + sqlite3_result_text(context_, nativeHookFrameInfoObj_.Vaddrs()[CurrentRow()].c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/native_hook_frame_table.h b/host/trace_streamer/src/table/native_hook_frame_table.h new file mode 100644 index 0000000000000000000000000000000000000000..03b0969deaddbe707a49d7524a19305ebb3ecf21 --- /dev/null +++ b/host/trace_streamer/src/table/native_hook_frame_table.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#ifndef NATIVE_HOOK_FRAME_TABLE_H +#define NATIVE_HOOK_FRAME_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class NativeHookFrameTable : public TableBase { +public: + explicit NativeHookFrameTable(const TraceDataCache* dataCache); + ~NativeHookFrameTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + private: + const NativeHookFrame& nativeHookFrameInfoObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // NATIVE_HOOK_FRAME_TABLE_H diff --git a/host/trace_streamer/src/table/native_hook_table.cpp b/host/trace_streamer/src/table/native_hook_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e9a1022cec42d1d72bb7129ac68beecf208fc32 --- /dev/null +++ b/host/trace_streamer/src/table/native_hook_table.cpp @@ -0,0 +1,272 @@ +/* + * 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. + */ + +#include "native_hook_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + CALLCHAIN_ID, + IPID, + ITID, + EVENT_TYPE, + SUB_TYPE_ID, + START_TS, + END_TS, + DURATION, + ADDR, + MEM_SIZE, + ALL_MEM_SIZE, + CURRENT_SIZE_DUR, + LAST_LIB_ID +}; +} +NativeHookTable::NativeHookTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("event_type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("sub_type_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("addr", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("heap_size", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("all_heap_size", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("current_size_dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("last_lib_id", "INTEGER")); + tablePriKey_.push_back("id"); +} + +NativeHookTable::~NativeHookTable() {} + +void NativeHookTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstNativeHookData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void NativeHookTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool NativeHookTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr NativeHookTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +NativeHookTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstNativeHookData().Size())), + nativeHookObj_(dataCache->GetConstNativeHookData()) +{ +} + +NativeHookTable::Cursor::~Cursor() {} + +int NativeHookTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case IPID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), nativeHookObj_.Ipids()); + break; + case ITID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), nativeHookObj_.Itids()); + break; + case CALLCHAIN_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + nativeHookObj_.CallChainIds()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int NativeHookTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case CALLCHAIN_ID: + sqlite3_result_int64(context_, static_cast(nativeHookObj_.CallChainIds()[CurrentRow()])); + break; + case IPID: + sqlite3_result_int64(context_, static_cast(nativeHookObj_.Ipids()[CurrentRow()])); + break; + case ITID: + sqlite3_result_int64(context_, static_cast(nativeHookObj_.Itids()[CurrentRow()])); + break; + case EVENT_TYPE: { + if (!nativeHookObj_.EventTypes()[CurrentRow()].empty()) { + sqlite3_result_text(context_, nativeHookObj_.EventTypes()[CurrentRow()].c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + case SUB_TYPE_ID: { + if (nativeHookObj_.SubTypes()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, static_cast(nativeHookObj_.SubTypes()[CurrentRow()])); + } + break; + } + case START_TS: + sqlite3_result_int64(context_, static_cast(nativeHookObj_.TimeStamData()[CurrentRow()])); + break; + case END_TS: + if (static_cast(nativeHookObj_.EndTimeStamps()[CurrentRow()]) != 0) { + sqlite3_result_int64(context_, static_cast(nativeHookObj_.EndTimeStamps()[CurrentRow()])); + } + break; + case DURATION: + if (static_cast(nativeHookObj_.Durations()[CurrentRow()]) != 0) { + sqlite3_result_int64(context_, static_cast(nativeHookObj_.Durations()[CurrentRow()])); + } + break; + case ADDR: { + sqlite3_result_int64(context_, static_cast(nativeHookObj_.Addrs()[CurrentRow()])); + break; + } + case MEM_SIZE: { + sqlite3_result_int64(context_, static_cast(nativeHookObj_.MemSizes()[CurrentRow()])); + break; + } + case ALL_MEM_SIZE: { + sqlite3_result_int64(context_, static_cast(nativeHookObj_.AllMemSizes()[CurrentRow()])); + break; + } + case CURRENT_SIZE_DUR: { + sqlite3_result_int64(context_, static_cast(nativeHookObj_.CurrentSizeDurs()[CurrentRow()])); + break; + } + case LAST_LIB_ID: { + if (nativeHookObj_.LastCallerPathIndexs()[CurrentRow()] != INVALID_UINT64) { + sqlite3_result_int64(context_, + static_cast(nativeHookObj_.LastCallerPathIndexs()[CurrentRow()])); + } + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/native_hook_table.h b/host/trace_streamer/src/table/native_hook_table.h new file mode 100644 index 0000000000000000000000000000000000000000..eac4eab6ec8b76d46f8dbc347da8a0fad5d2bf6f --- /dev/null +++ b/host/trace_streamer/src/table/native_hook_table.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef NATIVE_HOOK_TABLE_H +#define NATIVE_HOOK_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class NativeHookTable : public TableBase { +public: + explicit NativeHookTable(const TraceDataCache* dataCache); + ~NativeHookTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + private: + const NativeHook& nativeHookObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // NATIVE_HOOK_TABLE_H diff --git a/host/trace_streamer/src/table/heap_table.cpp b/host/trace_streamer/src/table/network_table.cpp similarity index 30% rename from host/trace_streamer/src/table/heap_table.cpp rename to host/trace_streamer/src/table/network_table.cpp index aee2925fe45440b9dd2e54db9ce7a2da784d34d4..65bdf9c1340e23c328f0b2d9f6b8ff2b3f88bec9 100644 --- a/host/trace_streamer/src/table/heap_table.cpp +++ b/host/trace_streamer/src/table/network_table.cpp @@ -13,103 +13,107 @@ * limitations under the License. */ -#include "heap_table.h" +#include "network_table.h" namespace SysTuning { namespace TraceStreamer { namespace { enum Index { - EVENT_ID = 0, - IPID, - ITID, - EVENT_TYPE, - START_TS, - END_TS, - DURATION, - ADDR, - HEAP_SIZE, - ALL_HEAP_SIZE, - CURRENT_SIZE_DUR + TS = 0, + DUR, + TX, + RX, + TX_SPEED, + RX_SPEED, + PACKET_IN, + PACKET_IN_SEC, + PACKET_OUT, + PACKET_OUT_SEC, + NET_TYPE, }; } -HeapTable::HeapTable(const TraceDataCache* dataCache) : TableBase(dataCache) +NetworkTable::NetworkTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("eventId", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("ipid", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("event_type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("addr", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("heap_size", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("all_heap_size", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("current_size_dur", "UNSIGNED INT")); - tablePriKey_.push_back("eventId"); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("tx", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("rx", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("tx_speed", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("rx_speed", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("packet_in", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("packet_in_sec", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("packet_out", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("packet_out_sec", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("net_type", "TEXT")); + tablePriKey_.push_back("ts"); } -HeapTable::~HeapTable() {} +NetworkTable::~NetworkTable() {} -void HeapTable::CreateCursor() +std::unique_ptr NetworkTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -HeapTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstHeapData().Size())), - heapInfoObj_(dataCache->GetConstHeapData()) +NetworkTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstNetworkData().Size())), + networkDataObj_(dataCache->GetConstNetworkData()) { } -HeapTable::Cursor::~Cursor() {} +NetworkTable::Cursor::~Cursor() {} -int HeapTable::Cursor::Column(int column) const +int NetworkTable::Cursor::Column(int column) const { switch (column) { - case EVENT_ID: - sqlite3_result_int64(context_, static_cast(heapInfoObj_.EventIds()[CurrentRow()])); + case TS: { + sqlite3_result_int64(context_, static_cast(networkDataObj_.TimeStamData()[CurrentRow()])); break; - case IPID: - sqlite3_result_int64(context_, static_cast(heapInfoObj_.Ipids()[CurrentRow()])); + } + case TX: { + sqlite3_result_int64(context_, static_cast(networkDataObj_.TxDatas()[CurrentRow()])); break; - case ITID: - sqlite3_result_int64(context_, static_cast(heapInfoObj_.Itids()[CurrentRow()])); + } + case RX: { + sqlite3_result_int64(context_, static_cast(networkDataObj_.RxDatas()[CurrentRow()])); break; - case EVENT_TYPE: { - if (heapInfoObj_.EventTypes()[CurrentRow()] != INVALID_UINT64) { - auto eventTypeDataIndex = static_cast(heapInfoObj_.EventTypes()[CurrentRow()]); - sqlite3_result_text(context_, dataCache_->GetDataFromDict(eventTypeDataIndex).c_str(), STR_DEFAULT_LEN, - nullptr); - } + } + case DUR: { + sqlite3_result_int64(context_, static_cast(networkDataObj_.Durs()[CurrentRow()])); break; } - case START_TS: - sqlite3_result_int64(context_, static_cast(heapInfoObj_.TimeStamData()[CurrentRow()])); + case TX_SPEED: { + sqlite3_result_double(context_, static_cast(networkDataObj_.TxSpeed()[CurrentRow()])); break; - case END_TS: - if (static_cast(heapInfoObj_.EndTimeStamps()[CurrentRow()]) != 0) { - sqlite3_result_int64(context_, static_cast(heapInfoObj_.EndTimeStamps()[CurrentRow()])); - } + } + case RX_SPEED: { + sqlite3_result_double(context_, + static_cast(dataCache_->GetConstNetworkData().RxSpeed()[CurrentRow()])); break; - case DURATION: - if (static_cast(heapInfoObj_.Durations()[CurrentRow()]) != 0) { - sqlite3_result_int64(context_, static_cast(heapInfoObj_.Durations()[CurrentRow()])); - } + } + case PACKET_IN: { + sqlite3_result_int64(context_, + static_cast(dataCache_->GetConstNetworkData().PacketIn()[CurrentRow()])); break; - case ADDR: { - sqlite3_result_int64(context_, static_cast(heapInfoObj_.Addrs()[CurrentRow()])); + } + case PACKET_IN_SEC: { + sqlite3_result_double(context_, + static_cast(dataCache_->GetConstNetworkData().PacketInSec()[CurrentRow()])); break; } - case HEAP_SIZE: { - sqlite3_result_int64(context_, static_cast(heapInfoObj_.HeapSizes()[CurrentRow()])); + case PACKET_OUT: { + sqlite3_result_int64(context_, + static_cast(dataCache_->GetConstNetworkData().PacketOut()[CurrentRow()])); break; } - case ALL_HEAP_SIZE: { - sqlite3_result_int64(context_, static_cast(heapInfoObj_.AllHeapSizes()[CurrentRow()])); + case PACKET_OUT_SEC: { + sqlite3_result_double(context_, + static_cast(dataCache_->GetConstNetworkData().PacketOutSec()[CurrentRow()])); break; } - case CURRENT_SIZE_DUR: { - sqlite3_result_int64(context_, static_cast(heapInfoObj_.CurrentSizeDurs()[CurrentRow()])); + case NET_TYPE: { + sqlite3_result_text(context_, dataCache_->GetConstNetworkData().NetTypes()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); break; } default: diff --git a/host/trace_streamer/src/table/network_table.h b/host/trace_streamer/src/table/network_table.h new file mode 100644 index 0000000000000000000000000000000000000000..b4e7b1e58923a111cb891bf352255e632198ff99 --- /dev/null +++ b/host/trace_streamer/src/table/network_table.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef NETWORK_TABLE_H +#define NETWORK_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class NetworkTable : public TableBase { +public: + explicit NetworkTable(const TraceDataCache* dataCache); + ~NetworkTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int Column(int column) const override; + + private: + const NetDetailData& networkDataObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // NETWORK_TABLE_H diff --git a/host/trace_streamer/src/table/paged_memory_sample_table.cpp b/host/trace_streamer/src/table/paged_memory_sample_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cbf51349702cb128d51090128297bfde4a1353b --- /dev/null +++ b/host/trace_streamer/src/table/paged_memory_sample_table.cpp @@ -0,0 +1,253 @@ +/* + * 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. + */ + +#include "paged_memory_sample_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, CALLCHAIN_ID, TYPE, IPID, START_TS, END_TS, DUR, SIZE, ADDR, ITID }; +} +PagedMemorySampleTable::PagedMemorySampleTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("size", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("addr", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); + tablePriKey_.push_back("id"); +} + +PagedMemorySampleTable::~PagedMemorySampleTable() {} + +void PagedMemorySampleTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstHidumpData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void PagedMemorySampleTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool PagedMemorySampleTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr PagedMemorySampleTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +PagedMemorySampleTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstPagedMemorySampleData().Size())), + PagedMemorySampleDataObj_(dataCache->GetConstPagedMemorySampleData()) +{ +} + +PagedMemorySampleTable::Cursor::~Cursor() {} + +int PagedMemorySampleTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + return SQLITE_OK; +} + +int PagedMemorySampleTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(PagedMemorySampleDataObj_.IdsData()[CurrentRow()])); + break; + case CALLCHAIN_ID: + sqlite3_result_int64(context_, + static_cast(PagedMemorySampleDataObj_.CallChainIds()[CurrentRow()])); + break; + case TYPE: + sqlite3_result_int64(context_, static_cast(PagedMemorySampleDataObj_.Types()[CurrentRow()])); + break; + case IPID: + sqlite3_result_int64(context_, static_cast(PagedMemorySampleDataObj_.Ipids()[CurrentRow()])); + break; + case ITID: + sqlite3_result_int64(context_, static_cast(PagedMemorySampleDataObj_.Itids()[CurrentRow()])); + break; + case START_TS: + sqlite3_result_int64(context_, static_cast(PagedMemorySampleDataObj_.StartTs()[CurrentRow()])); + break; + case END_TS: + sqlite3_result_int64(context_, static_cast(PagedMemorySampleDataObj_.EndTs()[CurrentRow()])); + break; + case DUR: + sqlite3_result_int64(context_, static_cast(PagedMemorySampleDataObj_.Durs()[CurrentRow()])); + break; + case SIZE: { + if (PagedMemorySampleDataObj_.Sizes()[CurrentRow()] != MAX_SIZE_T) { + sqlite3_result_int64(context_, static_cast(PagedMemorySampleDataObj_.Sizes()[CurrentRow()])); + } + break; + } + case ADDR: { + if (PagedMemorySampleDataObj_.Addr()[CurrentRow()] != INVALID_UINT64) { + auto firstArgIndex = PagedMemorySampleDataObj_.Addr()[CurrentRow()]; + sqlite3_result_text(context_, dataCache_->GetDataFromDict(firstArgIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + } + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} + +void PagedMemorySampleTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL + indexMap_->Intersect(0, 0); + return; + } + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + indexMap_->Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + indexMap_->Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/paged_memory_sample_table.h b/host/trace_streamer/src/table/paged_memory_sample_table.h new file mode 100644 index 0000000000000000000000000000000000000000..6737efa7b43e623d43f0548821d45c4824aa30b6 --- /dev/null +++ b/host/trace_streamer/src/table/paged_memory_sample_table.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef PAGED_MEMORY_SAMPLE_TABLE_H +#define PAGED_MEMORY_SAMPLE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class PagedMemorySampleTable : public TableBase { +public: + explicit PagedMemorySampleTable(const TraceDataCache* dataCache); + ~PagedMemorySampleTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + void FilterId(unsigned char op, sqlite3_value* argv) override; + + private: + const PagedMemorySampleData& PagedMemorySampleDataObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning + +#endif // PAGED_MEMORY_SAMPLE_TABLE_H diff --git a/host/trace_streamer/src/table/perf_call_chain_table.cpp b/host/trace_streamer/src/table/perf_call_chain_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42e8d05ffdbaa7e349845fb93e30baf50ea9c5e1 --- /dev/null +++ b/host/trace_streamer/src/table/perf_call_chain_table.cpp @@ -0,0 +1,212 @@ +/* + * 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. + */ + +#include "perf_call_chain_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, CALLCHAIN_ID, DEPTH, VADDR_IN_FILE, FILE_ID, SYMBOL_ID, NAME }; +} +PerfCallChainTable::PerfCallChainTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("depth", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("vaddr_in_file", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("file_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("symbol_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tablePriKey_.push_back("id"); +} + +PerfCallChainTable::~PerfCallChainTable() {} + +void PerfCallChainTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstPerfCallChainData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void PerfCallChainTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool PerfCallChainTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr PerfCallChainTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +PerfCallChainTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstPerfCallChainData().Size())), + perfCallChainObj_(dataCache->GetConstPerfCallChainData()) +{ +} + +PerfCallChainTable::Cursor::~Cursor() {} + +int PerfCallChainTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case CALLCHAIN_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + perfCallChainObj_.SampleIds()); + break; + case FILE_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + perfCallChainObj_.FileIds()); + break; + case SYMBOL_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + perfCallChainObj_.SymbolIds()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int PerfCallChainTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(perfCallChainObj_.IdsData()[CurrentRow()])); + break; + case CALLCHAIN_ID: + sqlite3_result_int64(context_, static_cast(perfCallChainObj_.SampleIds()[CurrentRow()])); + break; + case DEPTH: + sqlite3_result_int64(context_, static_cast(perfCallChainObj_.CallChainIds()[CurrentRow()])); + break; + case VADDR_IN_FILE: + sqlite3_result_int64(context_, static_cast(perfCallChainObj_.VaddrInFiles()[CurrentRow()])); + break; + case FILE_ID: + sqlite3_result_int64(context_, static_cast(perfCallChainObj_.FileIds()[CurrentRow()])); + break; + case SYMBOL_ID: + sqlite3_result_int64(context_, static_cast(perfCallChainObj_.SymbolIds()[CurrentRow()])); + break; + case NAME: + sqlite3_result_text(context_, perfCallChainObj_.Names()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/perf_call_chain_table.h b/host/trace_streamer/src/table/perf_call_chain_table.h new file mode 100644 index 0000000000000000000000000000000000000000..3b10f0ed8996c6345d54d188e22b343add3c0314 --- /dev/null +++ b/host/trace_streamer/src/table/perf_call_chain_table.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef PERF_CALL_CHAIN_TABLE_H +#define PERF_CALL_CHAIN_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class PerfCallChainTable : public TableBase { +public: + explicit PerfCallChainTable(const TraceDataCache* dataCache); + ~PerfCallChainTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + private: + const PerfCallChain& perfCallChainObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PERF_CALL_CHAIN_TABLE_H diff --git a/host/trace_streamer/src/table/perf_files_table.cpp b/host/trace_streamer/src/table/perf_files_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b69d62523bafb40040045581bd3ffb0ecd0d9e0 --- /dev/null +++ b/host/trace_streamer/src/table/perf_files_table.cpp @@ -0,0 +1,202 @@ +/* + * 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. + */ + +#include "perf_files_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, FILE_ID, SERIAL_ID, SYMBOL, PATH }; +} +PerfFilesTable::PerfFilesTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("file_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("serial_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("symbol", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("path", "TEXT")); + tablePriKey_.push_back("id"); +} + +PerfFilesTable::~PerfFilesTable() {} + +void PerfFilesTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstPerfFilesData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void PerfFilesTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool PerfFilesTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr PerfFilesTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +PerfFilesTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstPerfFilesData().Size())), + perfFilesObj_(dataCache->GetConstPerfFilesData()) +{ +} + +PerfFilesTable::Cursor::~Cursor() {} + +int PerfFilesTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case FILE_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), perfFilesObj_.FileIds()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int PerfFilesTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(perfFilesObj_.IdsData()[CurrentRow()])); + break; + case FILE_ID: + sqlite3_result_int64(context_, static_cast(perfFilesObj_.FileIds()[CurrentRow()])); + break; + case SERIAL_ID: + sqlite3_result_int(context_, static_cast(perfFilesObj_.Serials()[CurrentRow()])); + break; + case SYMBOL: + if (perfFilesObj_.Symbols()[CurrentRow()] != INVALID_UINT64) { + auto symbolIndex = static_cast(perfFilesObj_.Symbols()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(symbolIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + case PATH: + if (perfFilesObj_.FilePaths()[CurrentRow()] != INVALID_UINT64) { + auto pathIndex = static_cast(perfFilesObj_.FilePaths()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(pathIndex).c_str(), STR_DEFAULT_LEN, nullptr); + } + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/perf_files_table.h b/host/trace_streamer/src/table/perf_files_table.h new file mode 100644 index 0000000000000000000000000000000000000000..e30beefa9636e0eacfc3d5aeaa9137fe7bb52cdd --- /dev/null +++ b/host/trace_streamer/src/table/perf_files_table.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef PERF_FILES_TABLE_H +#define PERF_FILES_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class PerfFilesTable : public TableBase { +public: + explicit PerfFilesTable(const TraceDataCache* dataCache); + ~PerfFilesTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + private: + const PerfFiles& perfFilesObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PERF_FILES_TABLE_H diff --git a/host/trace_streamer/src/table/perf_report_table.cpp b/host/trace_streamer/src/table/perf_report_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c0610f1c1491800c8623ca835ca64e660c0c6d8 --- /dev/null +++ b/host/trace_streamer/src/table/perf_report_table.cpp @@ -0,0 +1,72 @@ +/* + * 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. + */ + +#include "perf_report_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, REPORT_TYPE, REPORT_VALUE, }; +} +PerfReportTable::PerfReportTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("report_type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("report_value", "TEXT")); + tablePriKey_.push_back("id"); +} + +PerfReportTable::~PerfReportTable() {} + +std::unique_ptr PerfReportTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +PerfReportTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstPerfReportData().Size())), + perfReportObj_(dataCache->GetConstPerfReportData()) +{ +} + +PerfReportTable::Cursor::~Cursor() {} + +int PerfReportTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(perfReportObj_.IdsData()[CurrentRow()])); + break; + case REPORT_TYPE: + if (perfReportObj_.Types()[CurrentRow()] != INVALID_UINT64) { + auto typeIndex = static_cast(perfReportObj_.Types()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(typeIndex).c_str(), STR_DEFAULT_LEN, nullptr); + } + break; + case REPORT_VALUE: + if (perfReportObj_.Values()[CurrentRow()] != INVALID_UINT64) { + auto typeValueIndex = static_cast(perfReportObj_.Values()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(typeValueIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/perf_report_table.h b/host/trace_streamer/src/table/perf_report_table.h new file mode 100644 index 0000000000000000000000000000000000000000..55eb64126a4108bf8bdfe9982d7fb2767fab66c6 --- /dev/null +++ b/host/trace_streamer/src/table/perf_report_table.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef PERF_REPORT_TABLE_H +#define PERF_REPORT_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class PerfReportTable : public TableBase { +public: + explicit PerfReportTable(const TraceDataCache* dataCache); + ~PerfReportTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {}; + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; + + private: + const PerfReport& perfReportObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PERF_REPORT_TABLE_H diff --git a/host/trace_streamer/src/table/perf_sample_table.cpp b/host/trace_streamer/src/table/perf_sample_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54d23e0efa2ee241bc9ddfb3adedd2ebd8e234df --- /dev/null +++ b/host/trace_streamer/src/table/perf_sample_table.cpp @@ -0,0 +1,235 @@ +/* + * 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. + */ + +#include "perf_sample_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + CALLCHAIN_ID, + TIMESTAMP, + THREAD_ID, + EVENT_COUNT, + EVENT_TYPE_ID, + TIMESTAMP_TRACE, + CPU_ID, + THREAD_STATE +}; +} +PerfSampleTable::PerfSampleTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("timestamp", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("thread_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("event_count", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("event_type_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("timestamp_trace", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("thread_state", "TEXT")); + tablePriKey_.push_back("id"); +} + +PerfSampleTable::~PerfSampleTable() {} + +void PerfSampleTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstPerfSampleData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void PerfSampleTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool PerfSampleTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr PerfSampleTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +PerfSampleTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstPerfSampleData().Size())), + perfSampleObj_(dataCache->GetConstPerfSampleData()) +{ +} + +PerfSampleTable::Cursor::~Cursor() {} + +int PerfSampleTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case CALLCHAIN_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + perfSampleObj_.SampleIds()); + break; + case THREAD_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), perfSampleObj_.Tids()); + break; + case EVENT_TYPE_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + perfSampleObj_.EventTypeIds()); + break; + case CPU_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), perfSampleObj_.CpuIds()); + break; + default: + break; + } + } + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int PerfSampleTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(perfSampleObj_.IdsData()[CurrentRow()])); + break; + case CALLCHAIN_ID: + sqlite3_result_int64(context_, static_cast(perfSampleObj_.SampleIds()[CurrentRow()])); + break; + case TIMESTAMP: + sqlite3_result_int64(context_, static_cast(perfSampleObj_.TimeStamData()[CurrentRow()])); + break; + case THREAD_ID: + sqlite3_result_int64(context_, static_cast(perfSampleObj_.Tids()[CurrentRow()])); + break; + case EVENT_COUNT: + sqlite3_result_int64(context_, static_cast(perfSampleObj_.EventCounts()[CurrentRow()])); + break; + case EVENT_TYPE_ID: + sqlite3_result_int64(context_, static_cast(perfSampleObj_.EventTypeIds()[CurrentRow()])); + break; + case TIMESTAMP_TRACE: + sqlite3_result_int64(context_, static_cast(perfSampleObj_.TimestampTraces()[CurrentRow()])); + break; + case CPU_ID: + sqlite3_result_int64(context_, static_cast(perfSampleObj_.CpuIds()[CurrentRow()])); + break; + case THREAD_STATE: + if (perfSampleObj_.ThreadStates()[CurrentRow()] != INVALID_UINT64) { + auto threadStateIndex = static_cast(perfSampleObj_.ThreadStates()[CurrentRow()]); + sqlite3_result_text(context_, dataCache_->GetDataFromDict(threadStateIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/perf_sample_table.h b/host/trace_streamer/src/table/perf_sample_table.h new file mode 100644 index 0000000000000000000000000000000000000000..bea3e0fdb0d217446d07b62560f975d9967d37f2 --- /dev/null +++ b/host/trace_streamer/src/table/perf_sample_table.h @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#ifndef PERF_SAMPLE_TABLE_H +#define PERF_SAMPLE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class PerfSampleTable : public TableBase { +public: + explicit PerfSampleTable(const TraceDataCache* dataCache); + ~PerfSampleTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + + private: + const PerfSample& perfSampleObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PERF_SAMPLE_TABLE_H diff --git a/host/trace_streamer/src/table/perf_thread_table.cpp b/host/trace_streamer/src/table/perf_thread_table.cpp new file mode 100755 index 0000000000000000000000000000000000000000..c34b0e16ad1a2e2357be590ace0305ed05b91bb8 --- /dev/null +++ b/host/trace_streamer/src/table/perf_thread_table.cpp @@ -0,0 +1,201 @@ +/* + * 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. + */ + +#include "perf_thread_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, THREAD_ID, PROCESS_ID, THREAD_NAME }; +} +PerfThreadTable::PerfThreadTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("thread_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("process_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("thread_name", "TEXT")); + tablePriKey_.push_back("id"); +} + +PerfThreadTable::~PerfThreadTable() {} + +void PerfThreadTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstPerfThreadData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void PerfThreadTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool PerfThreadTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr PerfThreadTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +PerfThreadTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstPerfThreadData().Size())), + perfThreadObj_(dataCache->GetConstPerfThreadData()) +{ +} + +PerfThreadTable::Cursor::~Cursor() {} + +int PerfThreadTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case THREAD_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), perfThreadObj_.Tids()); + break; + case PROCESS_ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), perfThreadObj_.Pids()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int PerfThreadTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(perfThreadObj_.IdsData()[CurrentRow()])); + break; + case THREAD_ID: + sqlite3_result_int64(context_, static_cast(perfThreadObj_.Tids()[CurrentRow()])); + break; + case PROCESS_ID: + sqlite3_result_int64(context_, static_cast(perfThreadObj_.Pids()[CurrentRow()])); + break; + case THREAD_NAME: + if (perfThreadObj_.ThreadNames()[CurrentRow()] != INVALID_UINT64) { + auto threadNameIndex = static_cast(perfThreadObj_.ThreadNames()[CurrentRow()]); + if (dataCache_->GetDataFromDict(threadNameIndex).empty()) { + break; + } + sqlite3_result_text(context_, dataCache_->GetDataFromDict(threadNameIndex).c_str(), STR_DEFAULT_LEN, + nullptr); + } + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/perf_thread_table.h b/host/trace_streamer/src/table/perf_thread_table.h new file mode 100644 index 0000000000000000000000000000000000000000..6b3de3c6203402d2c53ab8a4b366f8dc1b281b03 --- /dev/null +++ b/host/trace_streamer/src/table/perf_thread_table.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#ifndef PERF_THREAD_TABLE_H +#define PERF_THREAD_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class PerfThreadTable : public TableBase { +public: + explicit PerfThreadTable(const TraceDataCache* dataCache); + ~PerfThreadTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + private: + const PerfThread& perfThreadObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // PERF_THREAD_TABLE_H diff --git a/host/trace_streamer/src/table/process_filter_table.cpp b/host/trace_streamer/src/table/process_filter_table.cpp old mode 100644 new mode 100755 index 63bba49acda433425cb067c514fd388aae51577d..95af4c5d0e3567fa4ce8281e235c7530614d854e --- a/host/trace_streamer/src/table/process_filter_table.cpp +++ b/host/trace_streamer/src/table/process_filter_table.cpp @@ -22,22 +22,22 @@ enum Index { ID = 0, TYPE, NAME, INTERNAL_PID }; } ProcessFilterTable::ProcessFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("ipid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); tablePriKey_.push_back("id"); } ProcessFilterTable::~ProcessFilterTable() {} -void ProcessFilterTable::CreateCursor() +std::unique_ptr ProcessFilterTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -ProcessFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstProcessFilterData().Size())), +ProcessFilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstProcessFilterData().Size())), processFilterObj_(dataCache->GetConstProcessFilterData()) { } diff --git a/host/trace_streamer/src/table/process_filter_table.h b/host/trace_streamer/src/table/process_filter_table.h old mode 100644 new mode 100755 index 2e8c2399570e47a770045e6ad9bb928a5be7778d..6fc63a3639dec011faa1c6fbf77ca4359b7297e8 --- a/host/trace_streamer/src/table/process_filter_table.h +++ b/host/trace_streamer/src/table/process_filter_table.h @@ -25,13 +25,22 @@ class ProcessFilterTable : public TableBase { public: explicit ProcessFilterTable(const TraceDataCache* dataCache); ~ProcessFilterTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int col) const override; private: diff --git a/host/trace_streamer/src/table/process_measure_filter_table.cpp b/host/trace_streamer/src/table/process_measure_filter_table.cpp old mode 100644 new mode 100755 index afd6e807355eb491de54db17bd86f3ccb17ae677..3a262e83b4ca5fd59e3f5b732daf1562967f2662 --- a/host/trace_streamer/src/table/process_measure_filter_table.cpp +++ b/host/trace_streamer/src/table/process_measure_filter_table.cpp @@ -15,6 +15,8 @@ #include "process_measure_filter_table.h" +#include + namespace SysTuning { namespace TraceStreamer { namespace { @@ -22,27 +24,157 @@ enum Index { ID = 0, TYPE, NAME, INTERNAL_PID }; } ProcessMeasureFilterTable::ProcessMeasureFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); tablePriKey_.push_back("id"); } ProcessMeasureFilterTable::~ProcessMeasureFilterTable() {} -void ProcessMeasureFilterTable::CreateCursor() +void ProcessMeasureFilterTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstProcessMeasureFilterData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void ProcessMeasureFilterTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool ProcessMeasureFilterTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr ProcessMeasureFilterTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -ProcessMeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstProcessMeasureFilterData().Size())) +ProcessMeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstProcessMeasureFilterData().Size())) { } ProcessMeasureFilterTable::Cursor::~Cursor() {} +int ProcessMeasureFilterTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + dataCache_->GetConstProcessMeasureFilterData().IdsData()); + break; + case INTERNAL_PID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + dataCache_->GetConstProcessMeasureFilterData().UpidsData()); + break; + case NAME: + indexMap_->MixRange(c.op, + dataCache_->GetConstDataIndex( + std::string(reinterpret_cast(sqlite3_value_text(argv[i])))), + dataCache_->GetConstProcessMeasureFilterData().NamesData()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int ProcessMeasureFilterTable::Cursor::Column(int col) const { switch (col) { diff --git a/host/trace_streamer/src/table/process_measure_filter_table.h b/host/trace_streamer/src/table/process_measure_filter_table.h old mode 100644 new mode 100755 index 5b1ff4ae484e801de8e1871a0781166a4129ee02..d45f2b0e02c2287a4f78dde9033a56de4abdcb0f --- a/host/trace_streamer/src/table/process_measure_filter_table.h +++ b/host/trace_streamer/src/table/process_measure_filter_table.h @@ -26,13 +26,19 @@ class ProcessMeasureFilterTable : public TableBase { public: explicit ProcessMeasureFilterTable(const TraceDataCache* dataCache); ~ProcessMeasureFilterTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // the column is sorted + bool CanFilterSorted(const char op, size_t& rowCount) const; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int col) const override; }; }; diff --git a/host/trace_streamer/src/table/process_table.cpp b/host/trace_streamer/src/table/process_table.cpp index 02b05e70fc8c364e00838ec6adced5609bc83dbf..30a87602a238c1e2d0ac8e65431a3cc8d45d5b9b 100644 --- a/host/trace_streamer/src/table/process_table.cpp +++ b/host/trace_streamer/src/table/process_table.cpp @@ -18,37 +18,196 @@ namespace SysTuning { namespace TraceStreamer { namespace { -enum Index { ID = 0, TYPE, PID, NAME, START_TS, END_TS, PARENT_ID, UID, APP_ID }; +enum Index {ID = 0, IPID, TYPE, PID, NAME, START_TS, SWITCH_COUNT, THREAD_COUNT, SLICE_COUNT, MEM_COUNT }; } ProcessTable::ProcessTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("pid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("pid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("swtich_count", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("thread_count", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("slice_count", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("mem_count", "INTEGER")); tablePriKey_.push_back("id"); } ProcessTable::~ProcessTable() {} -void ProcessTable::CreateCursor() +void ProcessTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->ProcessSize(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case IPID: + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } } -ProcessTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->ProcessSize())) +void ProcessTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case IPID: + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool ProcessTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +int ProcessTable::Update(int argc, sqlite3_value** argv, sqlite3_int64* pRowid) +{ + if (argc <= 1) { + return SQLITE_READONLY; + } + if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { + return SQLITE_READONLY; + } + auto id = sqlite3_value_int64(argv[0]); + auto process = wdataCache_->GetProcessData(static_cast(id)); + constexpr int colOffset = 2; + for (auto i = colOffset; i < argc; i++) { + auto col = i - colOffset; + if (col != NAME) { + continue; + } + const char* name = reinterpret_cast(sqlite3_value_text(argv[i])); + if (name == nullptr) { + process->cmdLine_.clear(); + } else { + process->cmdLine_ = name; + } + break; + } + return SQLITE_OK; +} + +std::unique_ptr ProcessTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +ProcessTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, dataCache->ProcessSize()) { } ProcessTable::Cursor::~Cursor() {} -int ProcessTable::Cursor::Column(int column) const +int ProcessTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + case IPID: + FilterId(c.op, argv[i]); + break; + case PID: + FilterIndex(c.col, c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + case IPID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int ProcessTable::Cursor::Column(int col) const { const auto& process = dataCache_->GetConstProcessData(CurrentRow()); - switch (column) { + switch (col) { case ID: + case IPID: sqlite3_result_int64(context_, CurrentRow()); break; case TYPE: @@ -68,11 +227,116 @@ int ProcessTable::Cursor::Column(int column) const sqlite3_result_int64(context_, static_cast(process.startT_)); } break; + case SWITCH_COUNT: + sqlite3_result_int64(context_, process.switchCount_); + break; + case THREAD_COUNT: + sqlite3_result_int64(context_, process.threadCount_); + break; + case SLICE_COUNT: + sqlite3_result_int64(context_, process.sliceSize_); + break; + case MEM_COUNT: + sqlite3_result_int64(context_, process.memSize_); + break; default: - TS_LOGF("Unregistered column : %d", column); + TS_LOGF("Unregistered column : %d", col); break; } return SQLITE_OK; } + +void ProcessTable::Cursor::FilterPid(unsigned char op, uint64_t value) +{ + bool remove = false; + if (indexMap_->HasData()) { + indexMap_->CovertToIndexMap(); + remove = true; + } + const auto& processQueue = dataCache_->GetConstProcessData(); + auto size = processQueue.size(); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + if (remove) { + for (auto i = indexMap_->rowIndex_.begin(); i != indexMap_->rowIndex_.end();) { + if (processQueue[*i].pid_ != value) { + i = indexMap_->rowIndex_.erase(i); + } else { + i++; + } + } + } else { + for (auto i = 0; i < size; i++) { + if (processQueue[i].pid_ == value) { + indexMap_->rowIndex_.push_back(i); + } + } + } + indexMap_->FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_NE: + if (remove) { + for (auto i = indexMap_->rowIndex_.begin(); i != indexMap_->rowIndex_.end();) { + if (processQueue[*i].pid_ == value) { + i = indexMap_->rowIndex_.erase(i); + } else { + i++; + } + } + } else { + for (auto i = 0; i < size; i++) { + if (processQueue[i].pid_ != value) { + indexMap_->rowIndex_.push_back(i); + } + } + } + indexMap_->FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: + break; + default: + break; + } // end of switch (op) +} +void ProcessTable::Cursor::FilterIndex(int col, unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + switch (col) { + case PID: + /* code */ + FilterPid(op, static_cast(sqlite3_value_int64(argv))); + break; + + default: + break; + } +} +void ProcessTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + indexMap_->Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + indexMap_->Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/table/process_table.h b/host/trace_streamer/src/table/process_table.h old mode 100644 new mode 100755 index a614ba8121b5c8c302e0071e44341d9febdeaca4..0aa1a5f8adac7ef1cfcede054d990bd92a5c4613 --- a/host/trace_streamer/src/table/process_table.h +++ b/host/trace_streamer/src/table/process_table.h @@ -25,14 +25,24 @@ class ProcessTable : public TableBase { public: explicit ProcessTable(const TraceDataCache* dataCache); ~ProcessTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + int Update(int argc, sqlite3_value** argv, sqlite3_int64* pRowid) override; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; - int Column(int column) const override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int col) const override; + void FilterPid(unsigned char op, uint64_t value); + void FilterIndex(int col, unsigned char op, sqlite3_value* argv); + void FilterId(unsigned char op, sqlite3_value* argv) override; }; }; } // namespace TraceStreamer diff --git a/host/trace_streamer/src/table/range_table.cpp b/host/trace_streamer/src/table/range_table.cpp index 8ae9f3c287183514927de83bdf773c9e33e94f45..d2a4f018efbee6929ed77027daba0c23ac011007 100644 --- a/host/trace_streamer/src/table/range_table.cpp +++ b/host/trace_streamer/src/table/range_table.cpp @@ -22,19 +22,21 @@ enum Index { START_TS = 0, END_TS }; } RangeTable::RangeTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER")); tablePriKey_.push_back("start_ts"); } RangeTable::~RangeTable() {} -void RangeTable::CreateCursor() +std::unique_ptr RangeTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -RangeTable::Cursor::Cursor(const TraceDataCache* dataCache) : TableBase::Cursor(dataCache, 0, 1) {} +RangeTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) : TableBase::Cursor(dataCache, table, 1) +{ +} RangeTable::Cursor::~Cursor() {} diff --git a/host/trace_streamer/src/table/range_table.h b/host/trace_streamer/src/table/range_table.h old mode 100644 new mode 100755 index ea0d8f6ea67d8e80a17c66b743c45ef1b56a9945..f11581bfc9e9cb44de198d1387724c3052dfec22 --- a/host/trace_streamer/src/table/range_table.h +++ b/host/trace_streamer/src/table/range_table.h @@ -25,12 +25,22 @@ class RangeTable : public TableBase { public: explicit RangeTable(const TraceDataCache* dataCache); ~RangeTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; + private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; }; }; diff --git a/host/trace_streamer/src/table/raw_table.cpp b/host/trace_streamer/src/table/raw_table.cpp index 6a1086c63e1167820f54e8d8d12bd3ea78f84f63..fc2f05c06089a6a93c4a3e72cd34cf6d11a6059d 100644 --- a/host/trace_streamer/src/table/raw_table.cpp +++ b/host/trace_streamer/src/table/raw_table.cpp @@ -14,37 +14,179 @@ */ #include "raw_table.h" - namespace SysTuning { namespace TraceStreamer { namespace { enum Index { ID = 0, TYPE, TS, NAME, CPU, INTERNAL_TID }; } +enum RawType { RAW_CPU_IDLE = 1, RAW_SCHED_WAKEUP = 2, RAW_SCHED_WAKING = 3 }; +uint32_t GetNameIndex(const std::string& name) +{ + if (name == "cpu_idle") { + return RAW_CPU_IDLE; + } else if (name == "sched_wakeup") { + return RAW_SCHED_WAKEUP; + } else if (name == "sched_waking") { + return RAW_SCHED_WAKING; + } else { + return INVALID_UINT32; + } +} RawTable::RawTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("cpu", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); tablePriKey_.push_back("id"); } RawTable::~RawTable() {} -void RawTable::CreateCursor() +void RawTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstRawTableData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } } -RawTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstRawTableData().Size())), +void RawTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool RawTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr RawTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +RawTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstRawTableData().Size())), rawObj_(dataCache->GetConstRawTableData()) { } RawTable::Cursor::~Cursor() {} +int RawTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case NAME: + indexMap_->MixRange( + c.op, GetNameIndex(std::string(reinterpret_cast(sqlite3_value_text(argv[i])))), + rawObj_.NameData()); + break; + case TS: + FilterTS(c.op, argv[i], rawObj_.TimeStamData()); + break; + case INTERNAL_TID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + rawObj_.InternalTidsData()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} int RawTable::Cursor::Column(int column) const { @@ -59,11 +201,11 @@ int RawTable::Cursor::Column(int column) const sqlite3_result_int64(context_, static_cast(rawObj_.TimeStamData()[CurrentRow()])); break; case NAME: { - if (rawObj_.NameData()[CurrentRow()] == CPU_IDLE) { + if (rawObj_.NameData()[CurrentRow()] == RAW_CPU_IDLE) { sqlite3_result_text(context_, "cpu_idle", STR_DEFAULT_LEN, nullptr); - } else if (rawObj_.NameData()[CurrentRow()] == SCHED_WAKEUP) { + } else if (rawObj_.NameData()[CurrentRow()] == RAW_SCHED_WAKEUP) { sqlite3_result_text(context_, "sched_wakeup", STR_DEFAULT_LEN, nullptr); - } else { + } else if (rawObj_.NameData()[CurrentRow()] == RAW_SCHED_WAKING) { sqlite3_result_text(context_, "sched_waking", STR_DEFAULT_LEN, nullptr); } break; diff --git a/host/trace_streamer/src/table/raw_table.h b/host/trace_streamer/src/table/raw_table.h old mode 100644 new mode 100755 index 2cc92b0e28d1d2acf4b62cc23a1cad6996dd75f9..0fe5dc6cafdbfb11646fbb3417053c4d8c1ff39e --- a/host/trace_streamer/src/table/raw_table.h +++ b/host/trace_streamer/src/table/raw_table.h @@ -23,16 +23,21 @@ namespace SysTuning { namespace TraceStreamer { class RawTable : public TableBase { public: - enum EventName : uint32_t { CPU_IDLE = 1, SCHED_WAKEUP = 2, SCHED_WAKING = 3 }; explicit RawTable(const TraceDataCache* dataCache); ~RawTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int column) const override; private: diff --git a/host/trace_streamer/src/table/sched_slice_table.cpp b/host/trace_streamer/src/table/sched_slice_table.cpp index e87e3036d1be77ea10bfd87499fdafcdc6251a8b..6fc4f0e48ab6374d7bf3e0dd97c3e9ba52108f86 100644 --- a/host/trace_streamer/src/table/sched_slice_table.cpp +++ b/host/trace_streamer/src/table/sched_slice_table.cpp @@ -15,39 +15,210 @@ #include "sched_slice_table.h" +#include + namespace SysTuning { namespace TraceStreamer { namespace { -enum Index { ID = 0, TYPE, TS, DUR, CPU, INTERNAL_TID, END_STATE, PRIORITY }; +enum Index { ID = 0, TYPE, TS, DUR, TS_END, CPU, INTERNAL_TID, INTERNAL_PID, END_STATE, PRIORITY }; } SchedSliceTable::SchedSliceTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("ts", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("cpu", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("end_state", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("priority", "INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ts_end", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_state", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("priority", "INTEGER")); tablePriKey_.push_back("id"); } SchedSliceTable::~SchedSliceTable() {} -void SchedSliceTable::CreateCursor() +void SchedSliceTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) +{ + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstSchedSliceData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + case TS: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void SchedSliceTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + case TS: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool SchedSliceTable::CanFilterId(const char op, size_t& rowCount) { - cursor_ = std::make_unique(dataCache_); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; } -SchedSliceTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstSchedSliceData().Size())), +bool SchedSliceTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr SchedSliceTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +SchedSliceTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstSchedSliceData().Size())), schedSliceObj_(dataCache->GetConstSchedSliceData()) { } SchedSliceTable::Cursor::~Cursor() {} +int SchedSliceTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + case TS: + FilterTS(c.op, argv[i], schedSliceObj_.TimeStamData()); + break; + case CPU: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), schedSliceObj_.CpusData()); + break; + case INTERNAL_TID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + schedSliceObj_.InternalTidsData()); + break; + case INTERNAL_PID: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + schedSliceObj_.InternalPidsData()); + break; + case DUR: + indexMap_->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + schedSliceObj_.DursData()); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + case TS: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int SchedSliceTable::Cursor::Column(int col) const { switch (col) { @@ -63,12 +234,18 @@ int SchedSliceTable::Cursor::Column(int col) const case DUR: sqlite3_result_int64(context_, static_cast(schedSliceObj_.DursData()[CurrentRow()])); break; + case TS_END: + sqlite3_result_int64(context_, static_cast(schedSliceObj_.TsEndData()[CurrentRow()])); + break; case CPU: sqlite3_result_int64(context_, static_cast(schedSliceObj_.CpusData()[CurrentRow()])); break; case INTERNAL_TID: sqlite3_result_int64(context_, static_cast(schedSliceObj_.InternalTidsData()[CurrentRow()])); break; + case INTERNAL_PID: + sqlite3_result_int64(context_, static_cast(schedSliceObj_.InternalPidsData()[CurrentRow()])); + break; case END_STATE: { const std::string& str = dataCache_->GetConstSchedStateData(schedSliceObj_.EndStatesData()[CurrentRow()]); sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr); diff --git a/host/trace_streamer/src/table/sched_slice_table.h b/host/trace_streamer/src/table/sched_slice_table.h old mode 100644 new mode 100755 index 2d4fb34093ae7b54a09cc341f4eb0d5f5ec70aeb..73518b39fcba50d49fbcec44861ac8449c9abfdb --- a/host/trace_streamer/src/table/sched_slice_table.h +++ b/host/trace_streamer/src/table/sched_slice_table.h @@ -25,15 +25,22 @@ class SchedSliceTable : public TableBase { public: explicit SchedSliceTable(const TraceDataCache* dataCache); ~SchedSliceTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + // the column is sorted + bool CanFilterSorted(const char op, size_t& rowCount) const; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int col) const override; - private: const SchedSlice& schedSliceObj_; }; diff --git a/host/trace_streamer/src/table/smaps_table.cpp b/host/trace_streamer/src/table/smaps_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e6f19f920eb206dc48da8f8f1fd45d5165434f0 --- /dev/null +++ b/host/trace_streamer/src/table/smaps_table.cpp @@ -0,0 +1,102 @@ +/* + * 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. + */ + +#include "smaps_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, TIME_STAMP, START_ADDRESS, END_ADDRESS, DIRTY, SWAPPER, RSS, PSS, SIZE, RESIDE, PROTECTION, PATH }; +} +SmapsTable::SmapsTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("timestamp", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("start_addr", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("end_addr", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("dirty", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("swapper", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("resident_size", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("pss", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("virtaul_size", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("reside", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("protection_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("path_id", "INTEGER")); + tablePriKey_.push_back("id"); +} + +SmapsTable::~SmapsTable() {} + +std::unique_ptr SmapsTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +SmapsTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstSmapsData().Size())), + smapsObj_(dataCache->GetConstSmapsData()) +{ +} + +SmapsTable::Cursor::~Cursor() {} + +int SmapsTable::Cursor::Column(int col) const +{ + switch (col) { + case ID: + sqlite3_result_int64(context_, smapsObj_.IdsData()[CurrentRow()]); + break; + case TIME_STAMP: + sqlite3_result_int64(context_, smapsObj_.TimeStamps()[CurrentRow()]); + break; + case START_ADDRESS: + sqlite3_result_text(context_, smapsObj_.StartAddrs()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + case END_ADDRESS: + sqlite3_result_text(context_, smapsObj_.EndAddrs()[CurrentRow()].c_str(), STR_DEFAULT_LEN, nullptr); + break; + case DIRTY: + sqlite3_result_int64(context_, smapsObj_.Dirtys()[CurrentRow()]); + break; + case SWAPPER: + sqlite3_result_int64(context_, smapsObj_.Swappers()[CurrentRow()]); + break; + case RSS: + sqlite3_result_int64(context_, smapsObj_.Rss()[CurrentRow()]); + break; + case PSS: + sqlite3_result_int64(context_, smapsObj_.Pss()[CurrentRow()]); + break; + case SIZE: + sqlite3_result_int64(context_, smapsObj_.Sizes()[CurrentRow()]); + break; + case RESIDE: + sqlite3_result_double(context_, smapsObj_.Resides()[CurrentRow()]); + break; + case PROTECTION: + sqlite3_result_int64(context_, smapsObj_.ProtectionIds()[CurrentRow()]); + break; + case PATH: + sqlite3_result_int64(context_, smapsObj_.PathIds()[CurrentRow()]); + break; + default: + TS_LOGF("Unregistered column : %d", col); + break; + } + return SQLITE_OK; +} + +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/smaps_table.h b/host/trace_streamer/src/table/smaps_table.h new file mode 100644 index 0000000000000000000000000000000000000000..513d876710e16e46e4fe3541ceebdfcf3068dc75 --- /dev/null +++ b/host/trace_streamer/src/table/smaps_table.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef SMAPS_TABLE_H +#define SMAPS_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class SmapsTable : public TableBase { +public: + explicit SmapsTable(const TraceDataCache* dataCache); + ~SmapsTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int col) const override; + + private: + const SmapsData& smapsObj_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // SMAPS_TABLE_H diff --git a/host/trace_streamer/src/table/span_join.cpp b/host/trace_streamer/src/table/span_join.cpp new file mode 100644 index 0000000000000000000000000000000000000000..38d7c08dc4e5951543e1a7d891170501b1b5ac11 --- /dev/null +++ b/host/trace_streamer/src/table/span_join.cpp @@ -0,0 +1,451 @@ +/* + * 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. + */ + +#include "span_join.h" +#include + +namespace SysTuning { +namespace TraceStreamer { + +const std::string TS_COLUMN_NAME = "ts"; +const std::string DUR_COLUMN_NAME = "dur"; +constexpr int MINSIZE = 5; +constexpr int MAXSIZE = 1024; +constexpr int NEXT_NUMBER = 1; +constexpr int TSANDDUR_COLUMN = 2; +constexpr int PARTITIONED_COUNT = 3; + +enum Index { TS, DUR, PARTITION }; + +SpanJoin::SpanJoin(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_ = {}; + tablePriKey_ = {}; +} + +void SpanJoin::Init(int argc, const char* const* argv) +{ + if (argc < MINSIZE) { + return; + } + // Parse the fields of the two tables separately + TableParse tableFirstParse; + Parse(std::string(reinterpret_cast(argv[3])), tableFirstParse); + TableParse tableSecondParse; + Parse(std::string(reinterpret_cast(argv[4])), tableSecondParse); + + // you must ensure that the two partitions exist and are the same when using + if (tableFirstDesc_.partition != tableSecondDesc_.partition) { + return; + } + isSamepartitioning_ = true; + GetTableField(tableFirstParse, tableFirstDesc_); + GetTableField(tableSecondParse, tableSecondDesc_); + tableColumn_.emplace_back(TS_COLUMN_NAME, "INTEGER"); + tableColumn_.emplace_back(DUR_COLUMN_NAME, "INTEGER"); + tableColumn_.emplace_back(tableFirstDesc_.partition, "INTEGER"); + CreateCols(tableFirstDesc_, tableColumn_); + CreateCols(tableSecondDesc_, tableColumn_); + std::vector primaryKeys = {"ts"}; + primaryKeys.push_back(tableFirstDesc_.partition); + tablePriKey_ = primaryKeys; + return; +} + +void SpanJoin::CreateCols(TableDesc& tableDesc, std::vector& cols) +{ + for (int i = 0; i < tableDesc.cols.size(); i++) { + auto& n = tableDesc.cols.at(i).name_; + if (IsTsOrDurCol(n)) { + continue; + } + auto columnInfo = &mTableColumnInfo_[cols.size()]; + columnInfo->tableDesc = &tableDesc; + columnInfo->colIdx = i; + if (!DeduplicationForColumn(n, cols)) { + continue; + } + cols.emplace_back(n, tableDesc.cols.at(i).type_); + } +} + +bool SpanJoin::DeduplicationForColumn(const std::string& name, std::vector& cols) +{ + for (size_t i = 0; i < cols.size(); i++) { + if (name == cols.at(i).name_) { + return false; + } + } + return true; +} + +std::vector SpanJoin::TableNameSplitToVec(std::string& str, const std::string& pat) +{ + std::string::size_type pos; + std::vector result; + str += pat; + int size = str.size(); + for (int i = 0; i < size; i++) { + pos = str.find(pat, i); + if (pos == std::string::npos) { + break; + } + if (pos < size) { + std::string s = str.substr(i, pos - i); + result.push_back(s); + i = pos + pat.size() - 1; + } + } + return result; +} + +void SpanJoin::Parse(const std::string& tablePartition, TableParse& tableParse) +{ + std::vector result = TableNameSplitToVec(const_cast(tablePartition), " "); + if (result.size() < PARTITIONED_COUNT) { + TS_LOGW("span_join sql is invalid!"); + } + tableParse.name = result.at(0); + if (0 != strcasecmp(result.at(1).c_str(), "PARTITIONED")) { + TS_LOGW("sql has not PARTITIONED"); + return; + } + tableParse.partitionCol = result.at(2); + return; +} + +bool SpanJoin::IsTsOrDurCol(const std::string& name) +{ + if (name == TS_COLUMN_NAME || name == DUR_COLUMN_NAME) { + return true; + } + return false; +} + +void SpanJoin::GetTableField(TableParse& tableParse, TableDesc& tableDesc) +{ + std::vector cols; + GetColumns(dataCache_, tableParse.name, cols); + int tsDurCount = 0; + for (int i = 0; i < cols.size(); i++) { + auto col = cols.at(i); + if (IsTsOrDurCol(col.name_)) { + tsDurCount++; + } + if (col.name_ == TS_COLUMN_NAME) { + tableDesc.tsIdx = i; + } else if (col.name_ == DUR_COLUMN_NAME) { + tableDesc.durIdx = i; + } else if (col.name_ == tableParse.partitionCol) { + tableDesc.partitionIdx = i; + } + } + if (tsDurCount != TSANDDUR_COLUMN) { + return; + } + tableDesc.name = tableParse.name; + tableDesc.partition = tableParse.partitionCol; + tableDesc.cols = std::move(cols); + return; +} + +void SpanJoin::GetColumns(const TraceDataCache* dataCache, + const std::string& tableName, + std::vector& columns) +{ + char sql[MAXSIZE]; + std::string querySql = "SELECT name, type from PRAGMA_table_info(\"%s\")"; + int n = snprintf(sql, sizeof(sql), querySql.c_str(), tableName.c_str()); + sqlite3_stmt* stmt = nullptr; + int ret = sqlite3_prepare_v2(dataCache->db_, sql, n, &stmt, nullptr); + while (!ret) { + int err = sqlite3_step(stmt); + if (err == SQLITE_ROW) { + columns.emplace_back((reinterpret_cast(sqlite3_column_text(stmt, 0))), + reinterpret_cast(sqlite3_column_text(stmt, 1))); + continue; + } + if (err == SQLITE_DONE) { + break; + } + ret = err; + } + return; +} + +SpanJoin::CaclSpan::CaclSpan(TableBase* tableBase, const TableDesc* tableDesc, sqlite3* db) + : desc_(tableDesc), db_(db), table_(reinterpret_cast(tableBase)) +{ +} + +SpanJoin::CaclSpan::~CaclSpan() = default; + +int SpanJoin::CaclSpan::InitQuerySql(sqlite3_value** argv) +{ + sqlQuery_ = GetSqlQuery(); + bool status = IsQueryNext(); + if (!status) { + return SQLITE_ERROR; + } + return SQLITE_OK; +} + +std::string SpanJoin::CaclSpan::GetSqlQuery() +{ + std::vector columnNames; + for (int i = 0; i < desc_->cols.size(); i++) { + columnNames.push_back(desc_->cols.at(i).name_); + } + std::string str; + str = GetMergeColumns(columnNames); + std::string sql = "SELECT " + str + " FROM " + desc_->name + " ORDER BY " + desc_->partition + ", " + "ts;"; + return sql; +} + +void SpanJoin::CaclSpan::setResult(sqlite3_context* context, size_t index) const +{ + if (partitionState_ != PartitionState::TS_REAL) { + sqlite3_result_null(context); + return; + } + int sqliteType = sqlite3_column_type(stmt_, index); + if (sqliteType == SQLITE_TEXT) { + sqlite3_result_text(context, reinterpret_cast(sqlite3_column_int64(stmt_, index)), -1, + reinterpret_cast(-1)); + } else if (sqliteType == SQLITE_INTEGER) { + sqlite3_result_int64(context, sqlite3_column_int64(stmt_, index)); + } else if (sqliteType == SQLITE_FLOAT) { + sqlite3_result_double(context, sqlite3_column_double(stmt_, index)); + } +} + +bool SpanJoin::CaclSpan::GetCursorNext() +{ + int res; + int rowType; + do { + res = sqlite3_step(stmt_); + rowType = sqlite3_column_type(stmt_, desc_->partitionIdx); + } while (res == SQLITE_ROW && rowType == SQLITE_NULL); + if (res != SQLITE_ROW) { + isEof_ = true; + } else { + isEof_ = false; + } + + return res == SQLITE_ROW || res == SQLITE_DONE; +} + +void SpanJoin::CaclSpan::Next() +{ + GetNextState(); + SearchNextslice(); +} + +bool SpanJoin::CaclSpan::IsQueryNext() +{ + int res = sqlite3_prepare_v2(db_, sqlQuery_.c_str(), static_cast(sqlQuery_.size()), &stmt_, nullptr); + isEof_ = res != SQLITE_OK; + if (res != SQLITE_OK) { + return true; + } + auto status = GetCursorNext(); + if (!status) { + return false; + } + missPartitionEnd_ = sqlite3_column_int64(stmt_, static_cast(desc_->partitionIdx)); + status = SearchNextslice(); + return status; +} + +bool SpanJoin::CaclSpan::SearchNextslice() +{ + while (partitionState_ != TS_REAL) { + bool status = GetNextState(); + if (!status) { + return false; + } + } + return true; +} + +bool SpanJoin::CaclSpan::GetNextState() +{ + switch (partitionState_) { + case PartitionState::TS_REAL: { + GetCursorNext(); + partitionState_ = PartitionState::TS_PARTITION; + ts_ = endTs_; + if (isEof_ || partition_ != sqlite3_column_int64(stmt_, static_cast(desc_->partitionIdx))) { + endTs_ = std::numeric_limits::max(); + } else { + endTs_ = sqlite3_column_int64(stmt_, static_cast(desc_->tsIdx)); + } + return true; + } + case PartitionState::TS_PARTITION: { + if (endTs_ == std::numeric_limits::max()) { + partitionState_ = PartitionState::TS_MISSING; + if (isEof_) { + missPartitionEnd_ = std::numeric_limits::max(); + } else { + missPartitionEnd_ = sqlite3_column_int64(stmt_, static_cast(desc_->partitionIdx)); + } + missPartitionStart_ = partition_ + NEXT_NUMBER; + ts_ = 0; + } else { + partitionState_ = PartitionState::TS_REAL; + ts_ = sqlite3_column_int64(stmt_, static_cast(desc_->tsIdx)); + endTs_ = ts_ + sqlite3_column_int64(stmt_, static_cast(desc_->durIdx)); + } + return true; + } + case PartitionState::TS_MISSING: { + if (missPartitionEnd_ == std::numeric_limits::max()) { + partitionState_ = PartitionState::TS_EOF; + } else { + partitionState_ = PartitionState::TS_PARTITION; + ts_ = 0; + endTs_ = sqlite3_column_int64(stmt_, static_cast(desc_->tsIdx)); + partition_ = missPartitionEnd_; + } + return true; + } + default: + return false; + } +} + +std::string SpanJoin::CaclSpan::GetMergeColumns(std::vector& columns) +{ + std::string str; + int size = columns.size(); + for (int i = 0; i < size; i++) { + if (i == size - 1) { + str += columns.at(i); + } else { + str += columns.at(i) + ", "; + } + } + return str; +} + +int64_t SpanJoin::CaclSpan::GetPatitonForMiss() +{ + return partitionState_ == TS_MISSING ? missPartitionEnd_ - NEXT_NUMBER : partition_; +} + +std::unique_ptr SpanJoin::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +SpanJoin::Cursor::Cursor(const TraceDataCache* dataCache, SpanJoin* table) + : TableBase::Cursor(dataCache, table, 0), + tableFirst_(table, &table->tableFirstDesc_, dataCache_->db_), + tableSecond_(table, &table->tableSecondDesc_, dataCache_->db_), + spanTable_(table) +{ +} + +int SpanJoin::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + tableFirst_.InitQuerySql(argv); + tableSecond_.InitQuerySql(argv); + auto status = IsFindSpan(); + if (!status) { + return SQLITE_ERROR; + } + return SQLITE_OK; +} + +bool SpanJoin::Cursor::CaclOverLap() +{ + if (tableFirst_.ts_ >= tableSecond_.ts_) { + if (tableFirst_.partitionState_ == PartitionState::TS_REAL && + tableSecond_.partitionState_ == PartitionState::TS_REAL || + tableFirst_.ts_ < tableSecond_.endTs_) { + return true; + } + } else if (tableFirst_.ts_ <= tableSecond_.ts_ && tableSecond_.ts_ < tableFirst_.endTs_) { + return true; + } + return false; +} + +bool SpanJoin::Cursor::IsFindSpan() +{ + for (;;) { + if (tableFirst_.isEof_ || tableSecond_.isEof_) { + break; + } + queryNext_ = FindQueryResult(); + if (CaclOverLap()) { + break; + } + queryNext_->Next(); + } + return true; +} + +SpanJoin::CaclSpan* SpanJoin::Cursor::FindQueryResult() +{ + if (!spanTable_->isSamepartitioning_) { + return nullptr; + } + + auto tableFirstResult = std::make_tuple(tableFirst_.GetPatitonForMiss(), tableFirst_.endTs_, + tableFirst_.partitionState_ == PartitionState::TS_REAL ? true : false); + auto tableSecondResult = std::make_tuple(tableSecond_.GetPatitonForMiss(), tableSecond_.endTs_, + tableSecond_.partitionState_ == PartitionState::TS_REAL ? true : false); + if (tableFirstResult < tableSecondResult) { + return &tableFirst_; + } + return &tableSecond_; +} + +int SpanJoin::Cursor::Column(int column) const +{ + switch (column) { + case TS: { + sqlite3_result_int64(context_, static_cast(std::max(tableFirst_.ts_, tableSecond_.ts_))); + break; + } + case DUR: { + sqlite3_result_int64(context_, + static_cast(std::min(tableFirst_.endTs_, tableSecond_.endTs_) - + std::max(tableFirst_.ts_, tableSecond_.ts_))); + break; + } + case PARTITION: { + auto partResult = tableFirst_.partitionState_ == PartitionState::TS_REAL ? tableFirst_.partition_ + : tableSecond_.partition_; + sqlite3_result_int64(context_, static_cast(partResult)); + break; + } + default: { + const auto ColumnInfo = spanTable_->mTableColumnInfo_[column]; + if (ColumnInfo.tableDesc == tableFirst_.desc_) { + tableFirst_.setResult(context_, ColumnInfo.colIdx); + } else { + tableSecond_.setResult(context_, ColumnInfo.colIdx); + } + } + } + return SQLITE_OK; +} + +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/span_join.h b/host/trace_streamer/src/table/span_join.h new file mode 100644 index 0000000000000000000000000000000000000000..7611b72b5612be091df8b1e67bda8fd1c9876295 --- /dev/null +++ b/host/trace_streamer/src/table/span_join.h @@ -0,0 +1,135 @@ + +/* + * 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. + */ +#ifndef SAPN_JOIN_H +#define SAPN_JOIN_H +#include "table_base.h" +#include "trace_data_cache.h" +namespace SysTuning { +namespace TraceStreamer { +struct TableParse { + std::string name; + std::string partitionCol; +}; + +struct TableDesc { + std::string name; + std::string partition; + std::vector cols; + int tsIdx; + int durIdx; + int partitionIdx; +}; + +struct TableColumnInfo { + TableDesc* tableDesc; + int colIdx; +}; + +enum PartitionState { + TS_REAL, + TS_PARTITION, + TS_MISSING, + TS_EOF, +}; + +class SpanJoin : public TableBase { +public: + SpanJoin(const TraceDataCache*); + ~SpanJoin() override{}; + void Parse(const std::string& tablePartition, TableParse& tableParse); + std::vector TableNameSplitToVec(std::string& str, const std::string& pat); + void GetTableField(TableParse& tableParse, TableDesc& tableDesc); + void GetColumns(const TraceDataCache* dataCache, + const std::string& tableName, + std::vector& columns); + void CreateCols(TableDesc& tableDesc, std::vector& cols); + bool IsTsOrDurCol(const std::string& name); + bool DeduplicationForColumn(const std::string& name, std::vector& cols); + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override{}; + void Init(int argc, const char* const* argv) override; + std::unique_ptr CreateCursor() override; + + class CaclSpan { + public: + CaclSpan(TableBase* tableBase, const TableDesc* tableDesc, sqlite3* db); + virtual ~CaclSpan(); + static std::string GetMergeColumns(std::vector& columns); + int InitQuerySql(sqlite3_value** argv); + bool IsQueryNext(); + bool GetCursorNext(); + bool GetNextState(); + bool SearchNextslice(); + void Next(); + std::string GetSqlQuery(); + void setResult(sqlite3_context* context, size_t index) const; + int64_t GetPatitonForMiss(); + + public: + bool isEof_ = false; + int64_t ts_ = 0; + int64_t endTs_ = 0; + PartitionState partitionState_ = PartitionState::TS_MISSING; + int partition_ = 0; + int missPartitionStart_ = 0; + int missPartitionEnd_ = 0; + std::string sqlQuery_; + sqlite3_stmt* stmt_; + const TableDesc* desc_ = nullptr; + sqlite3* db_ = nullptr; + SpanJoin* table_ = nullptr; + }; + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, SpanJoin* table); + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int column) const override; + int Next() override + { + queryNext_->Next(); + auto status = IsFindSpan(); + if (!status) { + return SQLITE_ERROR; + } + return SQLITE_OK; + } + int Eof() override + { + return tableFirst_.isEof_ || tableSecond_.isEof_; + } + + private: + bool IsFindSpan(); + bool CaclOverLap(); + CaclSpan* FindQueryResult(); + CaclSpan tableFirst_; + CaclSpan tableSecond_; + CaclSpan* queryNext_ = nullptr; + SpanJoin* spanTable_; + }; + +public: + bool isSamepartitioning_ = false; + +private: + TableDesc tableFirstDesc_; + TableDesc tableSecondDesc_; + std::unordered_map mTableColumnInfo_; +}; + +} // namespace TraceStreamer +} // namespace SysTuning +#endif // SAPN_JOIN_H diff --git a/host/trace_streamer/src/table/stat_table.cpp b/host/trace_streamer/src/table/stat_table.cpp index 7294826aac2e0b8090f05ac2e6aa143489ac1ce4..396c2b520b66657ff893238b94ce6a5b6efdbdfe 100644 --- a/host/trace_streamer/src/table/stat_table.cpp +++ b/host/trace_streamer/src/table/stat_table.cpp @@ -22,24 +22,24 @@ enum Index { EVENT_NAME = 0, STAT_EVENT_TYPE = 1, COUNT = 2, SEVERITY = 3, SOURC } StatTable::StatTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("event_name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("stat_type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("count", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("serverity", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("source", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("event_name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("stat_type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("count", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("serverity", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("source", "TEXT")); tablePriKey_.push_back("event_name"); tablePriKey_.push_back("stat_type"); } StatTable::~StatTable() {} -void StatTable::CreateCursor() +std::unique_ptr StatTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -StatTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, STAT_EVENT_MAX * TRACE_EVENT_MAX) +StatTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, STAT_EVENT_MAX * TRACE_EVENT_MAX) { } @@ -53,19 +53,20 @@ int StatTable::Cursor::Column(int column) const switch (column) { case EVENT_NAME: sqlite3_result_text(context_, dataCache_->GetConstStatAndInfo().GetEvent(eventType).c_str(), - STR_DEFAULT_LEN, nullptr); + STR_DEFAULT_LEN, nullptr); break; case STAT_EVENT_TYPE: - sqlite3_result_text(context_, dataCache_->GetConstStatAndInfo().GetStat(statType).c_str(), - STR_DEFAULT_LEN, nullptr); + sqlite3_result_text(context_, dataCache_->GetConstStatAndInfo().GetStat(statType).c_str(), STR_DEFAULT_LEN, + nullptr); break; case COUNT: - sqlite3_result_int64(context_, static_cast(dataCache_->GetConstStatAndInfo().GetValue(eventType, - statType))); + sqlite3_result_int64(context_, + static_cast(dataCache_->GetConstStatAndInfo().GetValue(eventType, statType))); break; case SEVERITY: - sqlite3_result_text(context_, dataCache_->GetConstStatAndInfo().GetSeverityDesc(eventType, - statType).c_str(), STR_DEFAULT_LEN, nullptr); + sqlite3_result_text(context_, + dataCache_->GetConstStatAndInfo().GetSeverityDesc(eventType, statType).c_str(), + STR_DEFAULT_LEN, nullptr); break; case SOURCE: sqlite3_result_text(context_, "trace", STR_DEFAULT_LEN, nullptr); diff --git a/host/trace_streamer/src/table/stat_table.h b/host/trace_streamer/src/table/stat_table.h old mode 100644 new mode 100755 index 1e1fd995b8302924d15c9aa682b525882c0ede30..65cc404426c993c1f2667c44ef16cc3eb09b4522 --- a/host/trace_streamer/src/table/stat_table.h +++ b/host/trace_streamer/src/table/stat_table.h @@ -25,12 +25,22 @@ class StatTable : public TableBase { public: explicit StatTable(const TraceDataCache* dataCache); ~StatTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; + private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; }; }; diff --git a/host/trace_streamer/src/table/symbols_table.cpp b/host/trace_streamer/src/table/symbols_table.cpp index 4ec5421d287a6edcb4cabfcc363708eda39c7b94..773164b5e747403e80c5fa9d3cc73810b0a08399 100644 --- a/host/trace_streamer/src/table/symbols_table.cpp +++ b/host/trace_streamer/src/table/symbols_table.cpp @@ -23,26 +23,145 @@ enum Index { ID = 0, STR, ADDR }; } SymbolsTable::SymbolsTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("funcname", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("addr", "UNSIGNED BIG INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("funcname", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("addr", "INTEGER")); tablePriKey_.push_back("id"); } SymbolsTable::~SymbolsTable() {} -void SymbolsTable::CreateCursor() +void SymbolsTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + size_t rowCount = dataCache_->GetConstSymbolsData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void SymbolsTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool SymbolsTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr SymbolsTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); } -SymbolsTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstSymbolsData().Size())) +SymbolsTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstSymbolsData().Size())) { } SymbolsTable::Cursor::~Cursor() {} +int SymbolsTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterId(c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int SymbolsTable::Cursor::Column(int col) const { DataIndex index = static_cast(CurrentRow()); @@ -51,13 +170,14 @@ int SymbolsTable::Cursor::Column(int col) const sqlite3_result_int64(context_, static_cast(CurrentRow())); break; case STR: - sqlite3_result_text(context_, + sqlite3_result_text( + context_, dataCache_->GetDataFromDict(dataCache_->GetConstSymbolsData().GetConstFuncNames()[index]).c_str(), STR_DEFAULT_LEN, nullptr); break; case ADDR: sqlite3_result_int64(context_, - static_cast(dataCache_->GetConstSymbolsData().GetConstAddrs()[index])); + static_cast(dataCache_->GetConstSymbolsData().GetConstAddrs()[index])); break; default: TS_LOGF("Unknown column %d", col); diff --git a/host/trace_streamer/src/table/symbols_table.h b/host/trace_streamer/src/table/symbols_table.h old mode 100644 new mode 100755 index 1f9fdeb6cc23c53a7bde70c32ff6cf0f46a0c9bc..f9ce8527aab348d8bb7278a6e5977cc7dd481620 --- a/host/trace_streamer/src/table/symbols_table.h +++ b/host/trace_streamer/src/table/symbols_table.h @@ -25,13 +25,19 @@ class SymbolsTable : public TableBase { public: explicit SymbolsTable(const TraceDataCache* dataCache); ~SymbolsTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int col) const override; }; }; diff --git a/host/trace_streamer/src/table/sysevent_measure_table.cpp b/host/trace_streamer/src/table/sysevent_measure_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9bbeee4a767382d6c1a0f3443681c742c3e21e72 --- /dev/null +++ b/host/trace_streamer/src/table/sysevent_measure_table.cpp @@ -0,0 +1,86 @@ +/* + * 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. + */ + +#include "sysevent_measure_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { ID = 0, SERIAL, TS, NAME_ID, KEY_ID, TYPE, INT_VALUE, STRING_VALUE }; +} +SysEventMeasureTable::SysEventMeasureTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("serial", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("name_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("key_id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("int_value", "REAL")); + tableColumn_.push_back(TableBase::ColumnInfo("string_value", "TEXT")); + tablePriKey_.push_back("id"); +} + +SysEventMeasureTable::~SysEventMeasureTable() {} + +std::unique_ptr SysEventMeasureTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +SysEventMeasureTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstSyseventMeasureData().Size())), + sysEventMeasure_(dataCache->GetConstSyseventMeasureData()) +{ +} + +SysEventMeasureTable::Cursor::~Cursor() {} + +int SysEventMeasureTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, dataCache_->GetConstSyseventMeasureData().IdsData()[CurrentRow()]); + break; + case SERIAL: + sqlite3_result_int64(context_, dataCache_->GetConstSyseventMeasureData().Serial()[CurrentRow()]); + break; + case TS: + sqlite3_result_int64(context_, dataCache_->GetConstSyseventMeasureData().Ts()[CurrentRow()]); + break; + case NAME_ID: + sqlite3_result_int(context_, dataCache_->GetConstSyseventMeasureData().NameFilterId()[CurrentRow()]); + break; + case KEY_ID: + sqlite3_result_int(context_, dataCache_->GetConstSyseventMeasureData().AppKeyFilterId()[CurrentRow()]); + break; + case TYPE: + sqlite3_result_int(context_, dataCache_->GetConstSyseventMeasureData().Type()[CurrentRow()]); + break; + case INT_VALUE: + sqlite3_result_double(context_, dataCache_->GetConstSyseventMeasureData().NumValue()[CurrentRow()]); + break; + case STRING_VALUE: + sqlite3_result_text(context_, dataCache_->GetDataFromDict(sysEventMeasure_.StringValue()[CurrentRow()]).c_str(), + STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/sysevent_measure_table.h b/host/trace_streamer/src/table/sysevent_measure_table.h new file mode 100644 index 0000000000000000000000000000000000000000..7c2e8cd37736abcc7c6597b4982b75084e11dd27 --- /dev/null +++ b/host/trace_streamer/src/table/sysevent_measure_table.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +#ifndef SYSEVENT_MEASURE_TABLE_H +#define SYSEVENT_MEASURE_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class SysEventMeasureTable : public TableBase { +public: + explicit SysEventMeasureTable(const TraceDataCache*); + ~SysEventMeasureTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int Column(int column) const override; + private: + const SysEventMeasureData& sysEventMeasure_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // SYSEVENT_MEASURE_TABLE_H diff --git a/host/trace_streamer/src/table/system_call_table.cpp b/host/trace_streamer/src/table/system_call_table.cpp index a499eb549c23c923c9e4b9911cced90e7a5c20d5..4b253b6f90dbee3017b0917acb593243eb012607 100644 --- a/host/trace_streamer/src/table/system_call_table.cpp +++ b/host/trace_streamer/src/table/system_call_table.cpp @@ -22,23 +22,23 @@ enum Index { SYSCALL_NUM = 0, TYPE, IPID, TS, RET }; } SystemCallTable::SystemCallTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("syscall_num", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("ipid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("ts", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("ret", "INT")); + 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("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ret", "INTEGER")); tablePriKey_.push_back("syscall_num"); } SystemCallTable::~SystemCallTable() {} -void SystemCallTable::CreateCursor() +std::unique_ptr SystemCallTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -SystemCallTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstSysCallData().Size())), +SystemCallTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstSysCallData().Size())), sysCallObj_(dataCache->GetConstSysCallData()) { } diff --git a/host/trace_streamer/src/table/system_call_table.h b/host/trace_streamer/src/table/system_call_table.h index fab317e1100a62dbe99719d959f6af098c4517fa..4ad1b3db5c17e05475faddd3841b89b66cac5c96 100644 --- a/host/trace_streamer/src/table/system_call_table.h +++ b/host/trace_streamer/src/table/system_call_table.h @@ -25,13 +25,22 @@ class SystemCallTable : public TableBase { public: explicit SystemCallTable(const TraceDataCache*); ~SystemCallTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; private: const SysCall& sysCallObj_; diff --git a/host/trace_streamer/src/table/system_event_filter_table.cpp b/host/trace_streamer/src/table/system_event_filter_table.cpp index 3ce23b8ca90016ea8fb1ebad23ba31242da88e5d..dca6b92e18579637477003a7b9979efd5d041786 100644 --- a/host/trace_streamer/src/table/system_event_filter_table.cpp +++ b/host/trace_streamer/src/table/system_event_filter_table.cpp @@ -15,6 +15,8 @@ #include "system_event_filter_table.h" +#include + namespace SysTuning { namespace TraceStreamer { namespace { @@ -22,30 +24,149 @@ enum Index { ID = 0, TYPE, NAME }; } SystemEventFilterTable::SystemEventFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); tablePriKey_.push_back("id"); } SystemEventFilterTable::~SystemEventFilterTable() {} -void SystemEventFilterTable::CreateCursor() +void SystemEventFilterTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstSysMeasureFilterData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } } -SystemEventFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstSysMeasureFilterData().Size())), +void SystemEventFilterTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool SystemEventFilterTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr SystemEventFilterTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +SystemEventFilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstSysMeasureFilterData().Size())), sysEventObj_(dataCache->GetConstSysMeasureFilterData()) { } SystemEventFilterTable::Cursor::~Cursor() {} -int SystemEventFilterTable::Cursor::Column(int column) const +int SystemEventFilterTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMap_ + indexMap_ = std::make_unique(0, rowCount_); + + if (rowCount_ <= 0) { + return SQLITE_OK; + } + + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + FilterSorted(c.col, c.op, argv[i]); + break; + default: + break; + } + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int SystemEventFilterTable::Cursor::Column(int col) const { - switch (column) { + switch (col) { case ID: sqlite3_result_int64(context_, sysEventObj_.IdsData()[CurrentRow()]); break; @@ -58,10 +179,49 @@ int SystemEventFilterTable::Cursor::Column(int column) const STR_DEFAULT_LEN, nullptr); break; default: - TS_LOGF("Unregistered column : %d", column); + TS_LOGF("Unregistered column : %d", col); break; } return SQLITE_OK; } + +void SystemEventFilterTable::Cursor::FilterSorted(int col, unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL, filter out nothing + indexMap_->Intersect(0, 0); + return; + } + + switch (col) { + case ID: { + auto v = static_cast(sqlite3_value_int64(argv)); + auto getValue = [](const uint32_t& row) { return row; }; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->IntersectabcEqual(sysEventObj_.IdsData(), v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + case SQLITE_INDEX_CONSTRAINT_GE: { + indexMap_->IntersectGreaterEqual(sysEventObj_.IdsData(), v, getValue); + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + case SQLITE_INDEX_CONSTRAINT_LT: { + indexMap_->IntersectLessEqual(sysEventObj_.IdsData(), v, getValue); + break; + } + default: + break; + } // end of switch (op) + } // end of case TS + default: + // can't filter, all rows + break; + } +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/table/system_event_filter_table.h b/host/trace_streamer/src/table/system_event_filter_table.h index 80aeb454612c561c6d3fd973c010d1ee7e1e0d03..2dc5865336c947f9eb5cd2b464fc8a7b99107b70 100644 --- a/host/trace_streamer/src/table/system_event_filter_table.h +++ b/host/trace_streamer/src/table/system_event_filter_table.h @@ -25,14 +25,23 @@ class SystemEventFilterTable : public TableBase { public: explicit SystemEventFilterTable(const TraceDataCache*); ~SystemEventFilterTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // the column is sorted + bool CanFilterSorted(const char op, size_t& rowCount) const; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; - int Column(int column) const override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int col) const override; + + void FilterSorted(int col, unsigned char op, sqlite3_value* argv); + private: const SysMeasureFilter& sysEventObj_; }; diff --git a/host/trace_streamer/src/table/table.pri b/host/trace_streamer/src/table/table.pri deleted file mode 100644 index a5da2ea2038a16001f1d637561d9524c51e3a57f..0000000000000000000000000000000000000000 --- a/host/trace_streamer/src/table/table.pri +++ /dev/null @@ -1,78 +0,0 @@ -# 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. - -INCLUDEPATH += $$PWD -HEADERS += \ - $$PWD/range_table.h \ - $$PWD/cpu_measure_filter_table.h \ - $$PWD/data_dict_table.h \ - $$PWD/filter_table.h \ - $$PWD/instants_table.h \ - $$PWD/callstack_table.h \ - $$PWD/thread_table.h \ - $$PWD/measure_filter_table.h \ - $$PWD/measure_table.h \ - $$PWD/process_filter_table.h \ - $$PWD/process_measure_filter_table.h \ - $$PWD/process_table.h \ - $$PWD/raw_table.h \ - $$PWD/sched_slice_table.h \ - $$PWD/table_base.h \ - $$PWD/thread_filter_table.h \ - $$PWD/thread_state_table.h \ - $$PWD/clock_event_filter_table.h \ - $$PWD/clk_event_filter_table.h \ - $$PWD/stat_table.h \ - $$PWD/meta_table.h \ - $$PWD/symbols_table.h \ - $$PWD/system_call_table.h \ - $$PWD/log_table.h \ - $$PWD/heap_table.h \ - $$PWD/heap_frame_table.h \ - $$PWD/hidump_table.h \ - $$PWD/args_table.h \ - $$PWD/data_type_table.h \ - $$PWD/system_event_filter_table.h - -SOURCES += \ - $$PWD/range_table.cpp \ - $$PWD/cpu_measure_filter_table.cpp \ - $$PWD/data_dict_table.cpp \ - $$PWD/filter_table.cpp \ - $$PWD/instants_table.cpp \ - $$PWD/callstack_table.cpp \ - $$PWD/irq_table.cpp \ - $$PWD/thread_table.cpp \ - $$PWD/measure_filter_table.cpp \ - $$PWD/measure_table.cpp \ - $$PWD/process_filter_table.cpp \ - $$PWD/process_measure_filter_table.cpp \ - $$PWD/process_table.cpp \ - $$PWD/raw_table.cpp \ - $$PWD/sched_slice_table.cpp \ - $$PWD/table_base.cpp \ - $$PWD/thread_filter_table.cpp \ - $$PWD/thread_state_table.cpp \ - $$PWD/clock_event_filter_table.cpp \ - $$PWD/clk_event_filter_table.cpp \ - $$PWD/stat_table.cpp \ - $$PWD/meta_table.cpp \ - $$PWD/symbols_table.cpp \ - $$PWD/system_call_table.cpp \ - $$PWD/log_table.cpp \ - $$PWD/heap_table.cpp \ - $$PWD/heap_frame_table.cpp \ - $$PWD/hidump_table.cpp \ - $$PWD/args_table.cpp \ - $$PWD/data_type_table.cpp \ - $$PWD/system_event_filter_table.cpp diff --git a/host/trace_streamer/src/table/table_base.cpp b/host/trace_streamer/src/table/table_base.cpp old mode 100644 new mode 100755 index fef5f10814c08e6343dbde58718ea78d1bb6eef7..39ea339c651d5321cce855a55059ec1b846a4769 --- a/host/trace_streamer/src/table/table_base.cpp +++ b/host/trace_streamer/src/table/table_base.cpp @@ -14,8 +14,10 @@ */ #include "table_base.h" + #include #include + #include "log.h" #define UNUSED(expr) \ @@ -28,8 +30,9 @@ namespace TraceStreamer { namespace { struct TableContext { TabTemplate tmplate; - const TraceDataCache* dataCache; + TraceDataCache* dataCache; sqlite3_module module; + std::string tableName; }; } // namespace @@ -39,62 +42,93 @@ TableBase::~TableBase() cursor_ = nullptr; } -void TableBase::TableRegister(sqlite3& db, - const TraceDataCache* cache, - const std::string& tableName, - TabTemplate tmplate) +void TableBase::TableRegister(sqlite3& db, TraceDataCache* cache, const std::string& tableName, TabTemplate tmplate) { std::unique_ptr context(std::make_unique()); context->dataCache = cache; context->tmplate = tmplate; + context->tableName = tableName; sqlite3_module& module = context->module; + module = {0}; - auto createFn = [](sqlite3* xdb, void* arg, int argc, const char* const* argv, sqlite3_vtab** tab, char** other) { + auto createFn = [](sqlite3* xdb, void* pAux, int argc, const char* const* argv, sqlite3_vtab** ppVTab, + char** pzErr) { UNUSED(argc); UNUSED(argv); - UNUSED(other); - auto xdesc = static_cast(arg); + UNUSED(pzErr); + auto xdesc = static_cast(pAux); auto table = xdesc->tmplate(xdesc->dataCache); + table->name_ = xdesc->tableName; + if (table->name_ == "process" || table->name_ == "thread") { + table->wdataCache_ = xdesc->dataCache; + } + + table->Init(argc, argv); std::string createStmt = table->CreateTableSql(); - int res = sqlite3_declare_vtab(xdb, createStmt.c_str()); - if (res != SQLITE_OK) { - return res; + TS_LOGD("xCreate table %s, statement: %s", table->name_.c_str(), createStmt.c_str()); + int ret = sqlite3_declare_vtab(xdb, createStmt.c_str()); + if (ret != SQLITE_OK) { + if ((table->name_ == "span_join") || (table->name_ == "_span_join")) { + return ret; + } + TS_LOGE("sqlite3_declare_vtab %s faild: %s", table->name_.c_str(), createStmt.c_str()); + return ret; } - *tab = table.release(); + *ppVTab = table.release(); return SQLITE_OK; }; auto destroyFn = [](sqlite3_vtab* t) { + TS_LOGD("xDestroy table %s", static_cast(t)->name_.c_str()); delete static_cast(t); return SQLITE_OK; }; - module.xCreate = createFn; module.xConnect = createFn; - module.xBestIndex = [](sqlite3_vtab*, sqlite3_index_info*) { return SQLITE_OK; }; module.xDisconnect = destroyFn; module.xDestroy = destroyFn; - module.xOpen = [](sqlite3_vtab* t, sqlite3_vtab_cursor** c) { - return (static_cast(t))->Open(c); + + module.xOpen = [](sqlite3_vtab* pVTab, sqlite3_vtab_cursor** ppCursor) { + TS_LOGD("xOpen: %s", static_cast(pVTab)->name_.c_str()); + return static_cast(pVTab)->Open(ppCursor); }; - module.xClose = [](sqlite3_vtab_cursor* c) { - UNUSED(c); + + module.xClose = [](sqlite3_vtab_cursor* vc) { + TS_LOGD("xClose: %s", static_cast(vc)->table_->name_.c_str()); + delete static_cast(vc); return SQLITE_OK; }; - module.xFilter = [](sqlite3_vtab_cursor* c, int arg1, const char* arg2, int, sqlite3_value** sqlite) { - UNUSED(c); - UNUSED(arg1); - UNUSED(arg2); - UNUSED(sqlite); - return SQLITE_OK; + + module.xBestIndex = [](sqlite3_vtab* pVTab, sqlite3_index_info* idxInfo) { + TS_LOGD("xBestIndex: %s %d", static_cast(pVTab)->name_.c_str(), idxInfo->nConstraint); + return static_cast(pVTab)->BestIndex(idxInfo); }; - module.xNext = [](sqlite3_vtab_cursor* c) { return static_cast(c)->Next(); }; - module.xEof = [](sqlite3_vtab_cursor* c) { return static_cast(c)->Eof(); }; - module.xColumn = [](sqlite3_vtab_cursor* c, sqlite3_context* a, int b) { - static_cast(c)->context_ = a; - return static_cast(c)->Column(b); + + module.xFilter = [](sqlite3_vtab_cursor* vc, int idxNum, const char* idxStr, int argc, sqlite3_value** argv) { + auto* c = static_cast(vc); + c->Reset(); + TS_LOGD("xFilter %s: [%d]%s", static_cast(vc)->table_->name_.c_str(), idxNum, idxStr); + if (c->table_->cacheIdxNum_ != idxNum) { + c->table_->cacheConstraint_.Clear(); + c->table_->cacheConstraint_.FromString(idxStr); + c->table_->cacheIdxNum_ = idxNum; + } + return c->Filter(c->table_->cacheConstraint_, argv); }; + module.xNext = [](sqlite3_vtab_cursor* vc) { return static_cast(vc)->Next(); }; + module.xEof = [](sqlite3_vtab_cursor* vc) { return static_cast(vc)->Eof(); }; + module.xColumn = [](sqlite3_vtab_cursor* vc, sqlite3_context* ctx, int col) { + static_cast(vc)->context_ = ctx; + return static_cast(vc)->Column(col); + }; + if (tableName == "process" || tableName == "thread") { + module.xUpdate = [](sqlite3_vtab* pVTab, int argc, sqlite3_value** argv, sqlite3_int64* pRowid) { + TS_LOGD("xUpdate: %s", static_cast(pVTab)->name_.c_str()); + return static_cast(pVTab)->Update(argc, argv, pRowid); + }; + } + sqlite3_create_module_v2(&db, tableName.c_str(), &module, context.release(), [](void* arg) { delete static_cast(arg); }); } @@ -115,16 +149,82 @@ std::string TableBase::CreateTableSql() const stmt += ")) WITHOUT ROWID;"; return stmt; } +int TableBase::Cursor::Next() +{ + indexMap_->Next(); + return SQLITE_OK; +} + +int TableBase::Cursor::Eof() +{ + return dataCache_->Cancel() || indexMap_->Eof(); +} +uint32_t TableBase::Cursor::CurrentRow() const +{ + return indexMap_->CurrentRow(); +} +void TableBase::Cursor::FilterEnd() +{ + indexMap_->Sort(); +} +int TableBase::BestIndex(sqlite3_index_info* idxInfo) +{ + FilterConstraints filterConstraints; + for (int i = 0; i < idxInfo->nConstraint; i++) { + const auto& constraint = idxInfo->aConstraint[i]; + if (constraint.usable) { + filterConstraints.AddConstraint(i, constraint.iColumn, constraint.op); + } + } + for (int i = 0; i < idxInfo->nOrderBy; i++) { + filterConstraints.AddOrderBy(idxInfo->aOrderBy[i].iColumn, idxInfo->aOrderBy[i].desc); + } + + EstimatedIndexInfo estimate = {idxInfo->estimatedRows, idxInfo->estimatedCost, false}; + EstimateFilterCost(filterConstraints, estimate); + idxInfo->orderByConsumed = estimate.isOrdered; + idxInfo->estimatedCost = estimate.estimatedCost; + idxInfo->estimatedRows = estimate.estimatedRows; + + auto cs = filterConstraints.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + auto& c = cs[i]; + idxInfo->aConstraintUsage[c.idxInaConstraint].argvIndex = static_cast(i + 1); + idxInfo->aConstraintUsage[c.idxInaConstraint].omit = c.isSupport; + } + + std::string str; + filterConstraints.ToString(str); + char* pIdxStr = static_cast(sqlite3_malloc(str.size() + 1)); + std::copy(str.begin(), str.end(), pIdxStr); + pIdxStr[str.size()] = '\0'; + idxInfo->idxStr = pIdxStr; + idxInfo->needToFreeIdxStr = true; + idxInfo->idxNum = ++bestIndexNum_; + + TS_LOGD("%s BestIndex return: %d: %s", name_.c_str(), idxInfo->idxNum, str.c_str()); + TS_LOGD("%s, aConstraintUsage[%d]", idxInfo->idxStr, idxInfo->nConstraint); + for (int i = 0; i < idxInfo->nConstraint; i++) { + TS_LOGD("col: %d op: %d, argvindex: %d omit: %d", idxInfo->aConstraint[i].iColumn, idxInfo->aConstraint[i].op, + idxInfo->aConstraintUsage[i].argvIndex, idxInfo->aConstraintUsage[i].omit); + } + TS_LOGD("estimated: %lld cost:%.3f", idxInfo->estimatedRows, idxInfo->estimatedCost); + + return SQLITE_OK; +} int TableBase::Open(sqlite3_vtab_cursor** ppCursor) { - CreateCursor(); - *ppCursor = static_cast(cursor_.get()); + *ppCursor = static_cast(CreateCursor().release()); return SQLITE_OK; } -TableBase::Cursor::Cursor(const TraceDataCache* dataCache, uint32_t row, uint32_t totalRows) - : context_(nullptr), dataCache_(dataCache), currentRow_(row), rowsTotalNum_(totalRows) +TableBase::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table, uint32_t rowCount) + : context_(nullptr), + table_(table), + dataCache_(dataCache), + rowCount_(rowCount), + indexMap_(std::make_unique(0, rowCount)) { } @@ -133,21 +233,78 @@ TableBase::Cursor::~Cursor() context_ = nullptr; dataCache_ = nullptr; } - -int TableBase::Cursor::Next() +void TableBase::Cursor::FilterTS(unsigned char op, sqlite3_value* argv, const std::deque& times) { - currentRow_++; - return SQLITE_OK; + auto v = static_cast(sqlite3_value_int64(argv)); + auto getValue = [](const uint64_t& row) { return row; }; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->IntersectabcEqual(times, v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + case SQLITE_INDEX_CONSTRAINT_GE: { + indexMap_->IntersectGreaterEqual(times, v, getValue); + break; + } + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + case SQLITE_INDEX_CONSTRAINT_LT: { + indexMap_->IntersectLessEqual(times, v, getValue); + break; + case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: { + indexMap_->RemoveNullElements(times, v); + break; + } + default: + break; + } // end of switch (op) + } } -int TableBase::Cursor::Eof() +int TableBase::Cursor::RowId(sqlite3_int64* id) { - return currentRow_ >= rowsTotalNum_; + if (dataCache_->Cancel() || indexMap_->Eof()) { + return SQLITE_ERROR; + } + *id = static_cast(indexMap_->CurrentRow()); + return SQLITE_OK; } - -uint32_t TableBase::Cursor::CurrentRow() const +void TableBase::Cursor::FilterId(unsigned char op, sqlite3_value* argv) { - return currentRow_; + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL + indexMap_->Intersect(0, 0); + return; + } + if (indexMap_->HasData()) { + indexMap_->CovertToIndexMap(); + } + + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMap_->Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + indexMap_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + indexMap_->Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + indexMap_->Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/table/table_base.h b/host/trace_streamer/src/table/table_base.h old mode 100644 new mode 100755 index 22e51ca24e030e0df3da0c0b8f9679cb158d2a08..c2f7f93e3fbe2333c0bb412987f82a462a9411bf --- a/host/trace_streamer/src/table/table_base.h +++ b/host/trace_streamer/src/table/table_base.h @@ -20,8 +20,15 @@ #include #include #include + +#include "filter_constraints.h" +#include "index_map.h" #include "trace_data_cache.h" +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) namespace SysTuning { namespace TraceStreamer { class TableBase; @@ -33,32 +40,45 @@ public: TableBase& operator=(const TableBase&) = delete; template - static void TableDeclare(sqlite3& db, TraceDataCache* dataCache, const std::string& name) + static void TableDeclare(sqlite3& db, TraceDataCache* dataCache, const std::string& tableName) { - TableRegister(db, dataCache, name, [](const TraceDataCache* cache) { - return std::unique_ptr(std::make_unique(cache)); - }); - dataCache->AppendNewTable(name); + TableRegister(db, dataCache, tableName, + [](const TraceDataCache* cache) { + return std::unique_ptr(std::make_unique(cache)); + }); + dataCache->AppendNewTable(tableName); } - std::string CreateTableSql() const; class Cursor : public sqlite3_vtab_cursor { public: - Cursor(const TraceDataCache*, uint32_t, uint32_t); + Cursor(const TraceDataCache* dataCache, TableBase* table, uint32_t rowCount); virtual ~Cursor(); + virtual void Reset() + { + indexMap_ = std::make_unique(0, rowCount_); + } + virtual int Next(); + virtual int Eof(); - virtual int Column(int) const = 0; + + virtual uint32_t CurrentRow() const; + virtual void FilterTS(unsigned char op, sqlite3_value* argv, const std::deque& times); + + virtual int RowId(sqlite3_int64* id); + virtual int Filter(const FilterConstraints& fc, sqlite3_value** argv) = 0; + virtual int Column(int n) const = 0; + virtual void FilterId(unsigned char op, sqlite3_value* argv); + virtual void FilterEnd(); public: sqlite3_context* context_; - protected: - uint32_t CurrentRow() const; + TableBase* table_ = nullptr; + protected: const TraceDataCache* dataCache_; - private: - uint32_t currentRow_; - uint32_t rowsTotalNum_; + std::unique_ptr indexMap_; + uint32_t rowCount_; }; struct ColumnInfo { @@ -69,15 +89,42 @@ public: protected: explicit TableBase(const TraceDataCache* dataCache) : dataCache_(dataCache), cursor_(nullptr) {} - virtual void CreateCursor() = 0; + + struct EstimatedIndexInfo { + int64_t estimatedRows = 0; + double estimatedCost = 0.0; + bool isOrdered = false; + }; + + static void TableRegister(sqlite3& db, TraceDataCache* cache, const std::string& tableName, TabTemplate tmplate); + virtual int Update(int argc, sqlite3_value** argv, sqlite3_int64* pRowid) + { + return SQLITE_READONLY; + } + int BestIndex(sqlite3_index_info* idxInfo); + // needs to correspond to Cursor::Filter() + virtual void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) = 0; + virtual std::unique_ptr CreateCursor() = 0; + int Open(sqlite3_vtab_cursor** ppCursor); + virtual void Init(int, const char* const*) + { + return; + }; + +public: + std::string name_; + protected: std::vector tableColumn_ = {}; std::vector tablePriKey_ = {}; const TraceDataCache* dataCache_; + TraceDataCache* wdataCache_ = nullptr; std::unique_ptr cursor_; + private: - static void TableRegister(sqlite3& db, const TraceDataCache* cache, const std::string& name, TabTemplate tmplate); - int Open(sqlite3_vtab_cursor** ppCursor); + uint16_t bestIndexNum_ = 0; + int cacheIdxNum_ = 0; + FilterConstraints cacheConstraint_; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/table/thread_filter_table.cpp b/host/trace_streamer/src/table/thread_filter_table.cpp index f26908a74a66e944b1042b65f5270fa3632afb01..a8300485b67564977fce08a865297ef3cbf541ae 100644 --- a/host/trace_streamer/src/table/thread_filter_table.cpp +++ b/host/trace_streamer/src/table/thread_filter_table.cpp @@ -22,22 +22,22 @@ enum Index { ID = 0, TYPE, NAME, INTERNAL_TID }; } ThreadFilterTable::ThreadFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("itid", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); tablePriKey_.push_back("id"); } ThreadFilterTable::~ThreadFilterTable() {} -void ThreadFilterTable::CreateCursor() +std::unique_ptr ThreadFilterTable::CreateCursor() { - cursor_ = std::make_unique(dataCache_); + return std::make_unique(dataCache_, this); } -ThreadFilterTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstThreadFilterData().Size())) +ThreadFilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstThreadFilterData().Size())) { } @@ -47,8 +47,8 @@ int ThreadFilterTable::Cursor::Column(int column) const { switch (column) { case ID: - sqlite3_result_int64(context_, - static_cast(dataCache_->GetConstThreadFilterData().FilterIdData()[CurrentRow()])); + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstThreadFilterData().FilterIdData()[CurrentRow()])); break; case TYPE: sqlite3_result_text(context_, "thread_filter", STR_DEFAULT_LEN, nullptr); @@ -60,8 +60,8 @@ int ThreadFilterTable::Cursor::Column(int column) const break; } case INTERNAL_TID: - sqlite3_result_int64(context_, - static_cast(dataCache_->GetConstThreadFilterData().InternalTidData()[CurrentRow()])); + sqlite3_result_int64(context_, static_cast( + dataCache_->GetConstThreadFilterData().InternalTidData()[CurrentRow()])); break; default: TS_LOGF("Unregistered column : %d", column); diff --git a/host/trace_streamer/src/table/thread_filter_table.h b/host/trace_streamer/src/table/thread_filter_table.h old mode 100644 new mode 100755 index c868dddf45d35a2f16b63e98909f7fd6f64ced8f..c0ddb233d00ad91890db3f359da03d03955955fd --- a/host/trace_streamer/src/table/thread_filter_table.h +++ b/host/trace_streamer/src/table/thread_filter_table.h @@ -25,13 +25,22 @@ class ThreadFilterTable : public TableBase { public: explicit ThreadFilterTable(const TraceDataCache* dataCache); ~ThreadFilterTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + int Column(int column) const override; }; }; diff --git a/host/trace_streamer/src/table/thread_state_table.cpp b/host/trace_streamer/src/table/thread_state_table.cpp index 37dc915651ef98d947ed3f25ab3525e69894df5e..89a259336d74d3c45c709fd1e00d7b268cda5e74 100644 --- a/host/trace_streamer/src/table/thread_state_table.cpp +++ b/host/trace_streamer/src/table/thread_state_table.cpp @@ -15,38 +15,224 @@ #include "thread_state_table.h" +#include + namespace SysTuning { namespace TraceStreamer { namespace { -enum Index { ID = 0, TYPE, TS, DUR, CPU, INTERNAL_TID, STATE }; +enum Index { ID = 0, TYPE, TS, DUR, CPU, INTERNAL_TID, TID, PID, STATE }; } ThreadStateTable::ThreadStateTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("ts", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("dur", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("cpu", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("itid", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("state", "STRING")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("tid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("pid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("state", "TEXT")); tablePriKey_.push_back("id"); } ThreadStateTable::~ThreadStateTable() {} -void ThreadStateTable::CreateCursor() +void ThreadStateTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->GetConstThreadStateData().Size(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ID: + case TS: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } } -ThreadStateTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->GetConstThreadStateData().Size())), +void ThreadStateTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + case TS: { + auto oldRowCount = rowCount; + if (CanFilterSorted(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += log2(oldRowCount); // binary search + } else { + filterCost += oldRowCount; + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool ThreadStateTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +bool ThreadStateTable::CanFilterSorted(const char op, size_t& rowCount) const +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = rowCount / log2(rowCount); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; +} + +std::unique_ptr ThreadStateTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +ThreadStateTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, dataCache->GetConstThreadStateData().Size()), threadStateObj_(dataCache->GetConstThreadStateData()) { } ThreadStateTable::Cursor::~Cursor() {} +int ThreadStateTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset + if (rowCount_ <= 0) { + return SQLITE_OK; + } + IndexMap* indexMapBack = indexMap_.get(); + if (indexMap_->HasData()) { + indexMapBack = std::make_unique(0, rowCount_).get(); + } + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + indexMapBack->FilterId(c.op, argv[i]); + break; + case TS: + indexMapBack->FilterTS(c.op, argv[i], threadStateObj_.TimeStamsData()); + break; + case INTERNAL_TID: + indexMapBack->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + threadStateObj_.ItidsData()); + break; + case TID: + indexMapBack->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + threadStateObj_.TidsData()); + break; + case PID: + indexMapBack->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + threadStateObj_.PidsData()); + break; + case DUR: + indexMapBack->MixRange(c.op, static_cast(sqlite3_value_int64(argv[i])), + threadStateObj_.DursData()); + break; + case CPU: + indexMapBack->MixRange(c.op, static_cast(sqlite3_value_int(argv[i])), + threadStateObj_.CpusData()); + break; + case STATE: + indexMapBack->MixRange(c.op, + dataCache_->GetConstDataIndex( + std::string(reinterpret_cast(sqlite3_value_text(argv[i])))), + threadStateObj_.StatesData()); + break; + default: + break; + } + } + if (indexMap_->HasData()) { + indexMap_->Merge(indexMapBack); + } + + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + case TS: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + int ThreadStateTable::Cursor::Column(int col) const { switch (col) { @@ -57,21 +243,26 @@ int ThreadStateTable::Cursor::Column(int col) const sqlite3_result_text(context_, "thread_state", STR_DEFAULT_LEN, nullptr); break; case TS: - sqlite3_result_int64(context_, static_cast(threadStateObj_.TimeStamData()[CurrentRow()])); + sqlite3_result_int64(context_, static_cast(threadStateObj_.TimeStamsData()[CurrentRow()])); break; case DUR: - if (static_cast(threadStateObj_.DursData()[CurrentRow()]) >= 0) { + if (static_cast(threadStateObj_.DursData()[CurrentRow()]) != INVALID_TIME) { sqlite3_result_int64(context_, static_cast(threadStateObj_.DursData()[CurrentRow()])); } break; case CPU: - if (static_cast(threadStateObj_.CpusData()[CurrentRow()]) >= 0) { + if (threadStateObj_.CpusData()[CurrentRow()] != INVALID_CPU) { sqlite3_result_int64(context_, static_cast(threadStateObj_.CpusData()[CurrentRow()])); } break; case INTERNAL_TID: - sqlite3_result_int64(context_, - static_cast(threadStateObj_.InternalTidsData()[CurrentRow()])); + sqlite3_result_int64(context_, static_cast(threadStateObj_.ItidsData()[CurrentRow()])); + break; + case TID: + sqlite3_result_int64(context_, static_cast(threadStateObj_.TidsData()[CurrentRow()])); + break; + case PID: + sqlite3_result_int64(context_, static_cast(threadStateObj_.PidsData()[CurrentRow()])); break; case STATE: { const std::string& str = dataCache_->GetConstSchedStateData(threadStateObj_.StatesData()[CurrentRow()]); diff --git a/host/trace_streamer/src/table/thread_state_table.h b/host/trace_streamer/src/table/thread_state_table.h old mode 100644 new mode 100755 index 374a4a8ddf8228c927e4e88d55d081da94b701da..d8ad7c45e795277ee7fb1b9f7d92aaf2e5c4049a --- a/host/trace_streamer/src/table/thread_state_table.h +++ b/host/trace_streamer/src/table/thread_state_table.h @@ -25,15 +25,22 @@ class ThreadStateTable : public TableBase { public: explicit ThreadStateTable(const TraceDataCache* dataCache); ~ThreadStateTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + // the column is sorted + bool CanFilterSorted(const char op, size_t& rowCount) const; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; int Column(int col) const override; - private: const ThreadState& threadStateObj_; }; diff --git a/host/trace_streamer/src/table/thread_table.cpp b/host/trace_streamer/src/table/thread_table.cpp index af67cb7cedccbda6e7f3f67101a300e9eda0ea47..4c5e370188f098bac40faffaacedbcaea0e657d6 100644 --- a/host/trace_streamer/src/table/thread_table.cpp +++ b/host/trace_streamer/src/table/thread_table.cpp @@ -18,39 +18,412 @@ namespace SysTuning { namespace TraceStreamer { namespace { -enum Index { ID = 0, TYPE, TID, NAME, START_TS, END_TS, INTERNAL_PID, IS_MAIN_THREAD }; +enum Index { ID = 0, ITID, TYPE, TID, NAME, START_TS, END_TS, INTERNAL_PID, IS_MAIN_THREAD, SWITCH_COUNT }; } ThreadTable::ThreadTable(const TraceDataCache* dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("id", "INT")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("tid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("name", "STRING")); - tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "UNSIGNED BIG INT")); - tableColumn_.push_back(TableBase::ColumnInfo("ipid", "UNSIGNED INT")); - tableColumn_.push_back(TableBase::ColumnInfo("is_main_thread", "UNSIGNED INT")); + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("tid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("start_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("end_ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("is_main_thread", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("switch_count", "INTEGER")); tablePriKey_.push_back("id"); } ThreadTable::~ThreadTable() {} -void ThreadTable::CreateCursor() +void ThreadTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) { - cursor_ = std::make_unique(dataCache_); + constexpr double filterBaseCost = 1000.0; // set-up and tear-down + constexpr double indexCost = 2.0; + ei.estimatedCost = filterBaseCost; + + auto rowCount = dataCache_->ThreadSize(); + if (rowCount == 0 || rowCount == 1) { + ei.estimatedRows = rowCount; + ei.estimatedCost += indexCost * rowCount; + return; + } + + double filterCost = 0.0; + auto constraints = fc.GetConstraints(); + if (constraints.empty()) { // scan all rows + filterCost = rowCount; + } else { + FilterByConstraint(fc, filterCost, rowCount); + } + ei.estimatedCost += filterCost; + ei.estimatedRows = rowCount; + ei.estimatedCost += rowCount * indexCost; + + ei.isOrdered = true; + auto orderbys = fc.GetOrderBys(); + for (auto i = 0; i < orderbys.size(); i++) { + switch (orderbys[i].iColumn) { + case ITID: + case ID: + break; + default: // other columns can be sorted by SQLite + ei.isOrdered = false; + break; + } + } +} + +void ThreadTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount) +{ + auto fcConstraints = fc.GetConstraints(); + for (int i = 0; i < static_cast(fcConstraints.size()); i++) { + if (rowCount <= 1) { + // only one row or nothing, needn't filter by constraint + filterCost += rowCount; + break; + } + const auto& c = fcConstraints[i]; + switch (c.col) { + case ITID: + case ID: { + if (CanFilterId(c.op, rowCount)) { + fc.UpdateConstraint(i, true); + filterCost += 1; // id can position by 1 step + } else { + filterCost += rowCount; // scan all rows + } + break; + } + default: // other column + filterCost += rowCount; // scan all rows + break; + } + } +} + +bool ThreadTable::CanFilterId(const char op, size_t& rowCount) +{ + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + rowCount = 1; + break; + case SQLITE_INDEX_CONSTRAINT_GT: + case SQLITE_INDEX_CONSTRAINT_GE: + case SQLITE_INDEX_CONSTRAINT_LE: + case SQLITE_INDEX_CONSTRAINT_LT: + // assume filter out a half of rows + rowCount = (rowCount >> 1); + break; + default: + return false; + } + return true; } -ThreadTable::Cursor::Cursor(const TraceDataCache* dataCache) - : TableBase::Cursor(dataCache, 0, static_cast(dataCache->ThreadSize())) +std::unique_ptr ThreadTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +ThreadTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, dataCache->ThreadSize()) { } ThreadTable::Cursor::~Cursor() {} +void ThreadTable::Cursor::FilterTid(unsigned char op, uint64_t value) +{ + bool remove = false; + if (indexMapBack_->HasData()) { + indexMapBack_->CovertToIndexMap(); + remove = true; + } + const auto& threadQueue = dataCache_->GetConstThreadData(); + auto size = threadQueue.size(); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + if (remove) { + for (auto i = indexMapBack_->rowIndex_.begin(); i != indexMapBack_->rowIndex_.end();) { + if (threadQueue[*i].tid_ != value) { + i = indexMapBack_->rowIndex_.erase(i); + } else { + i++; + } + } + } else { + for (auto i = 0; i < size; i++) { + if (threadQueue[i].tid_ == value) { + indexMapBack_->rowIndex_.push_back(i); + } + } + } + indexMapBack_->FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNOT: + case SQLITE_INDEX_CONSTRAINT_NE: + if (remove) { + for (auto i = indexMapBack_->rowIndex_.begin(); i != indexMapBack_->rowIndex_.end();) { + if (threadQueue[*i].tid_ == value) { + i = indexMapBack_->rowIndex_.erase(i); + } else { + i++; + } + } + } else { + for (auto i = 0; i < size; i++) { + if (threadQueue[i].tid_ != value) { + indexMapBack_->rowIndex_.push_back(i); + } + } + } + indexMapBack_->FixSize(); + break; + default: + break; + } // end of switch (op) +} +void ThreadTable::Cursor::FilterIpid(unsigned char op, uint64_t value) +{ + bool remove = false; + if (indexMapBack_->HasData()) { + indexMapBack_->CovertToIndexMap(); + remove = true; + } + const auto& threadQueue = dataCache_->GetConstThreadData(); + auto size = threadQueue.size(); + rowIndexBak_.clear(); + bool changed = false; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + if (remove) { + for (auto i = indexMapBack_->rowIndex_.begin(); i != indexMapBack_->rowIndex_.end();) { + if (threadQueue[*i].internalPid_ != value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + indexMapBack_->rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (threadQueue[i].internalPid_ == value) { + indexMapBack_->rowIndex_.push_back(i); + } + } + } + indexMapBack_->FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNULL: + if (remove) { + for (auto i = indexMapBack_->rowIndex_.begin(); i != indexMapBack_->rowIndex_.end();) { + if (threadQueue[*i].internalPid_ != INVALID_UINT32) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + indexMapBack_->rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (threadQueue[i].internalPid_ == INVALID_UINT32) { + indexMapBack_->rowIndex_.push_back(i); + } + } + } + indexMapBack_->FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: + if (remove) { + for (auto i = indexMapBack_->rowIndex_.begin(); i != indexMapBack_->rowIndex_.end();) { + if (threadQueue[*i].internalPid_ == INVALID_UINT32) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + indexMapBack_->rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (threadQueue[i].internalPid_ != INVALID_UINT32) { + indexMapBack_->rowIndex_.push_back(i); + } + } + } + indexMapBack_->FixSize(); + break; + default: + break; + } // end of switch (op) +} +void ThreadTable::Cursor::FilterSwitchCount(unsigned char op, uint64_t value) +{ + bool remove = false; + if (indexMapBack_->HasData()) { + indexMapBack_->CovertToIndexMap(); + remove = true; + } + const auto& threadQueue = dataCache_->GetConstThreadData(); + auto size = threadQueue.size(); + rowIndexBak_.clear(); + bool changed = false; + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + if (remove) { + for (auto i = indexMapBack_->rowIndex_.begin(); i != indexMapBack_->rowIndex_.end();) { + if (threadQueue[*i].switchCount_ != value) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + indexMapBack_->rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (threadQueue[i].switchCount_ == value) { + indexMapBack_->rowIndex_.push_back(i); + } + } + } + indexMapBack_->FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNULL: + if (remove) { + for (auto i = indexMapBack_->rowIndex_.begin(); i != indexMapBack_->rowIndex_.end();) { + if (threadQueue[*i].switchCount_ != INVALID_UINT32) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + indexMapBack_->rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (threadQueue[i].switchCount_ == INVALID_UINT32) { + indexMapBack_->rowIndex_.push_back(i); + } + } + } + indexMapBack_->FixSize(); + break; + case SQLITE_INDEX_CONSTRAINT_ISNOTNULL: + if (remove) { + for (auto i = indexMapBack_->rowIndex_.begin(); i != indexMapBack_->rowIndex_.end();) { + if (threadQueue[*i].switchCount_ == INVALID_UINT32) { + i++; + } else { + changed = true; + rowIndexBak_.push_back(*i); + i++; + } + } + if (changed) { + indexMapBack_->rowIndex_ = rowIndexBak_; + } + } else { + for (auto i = 0; i < size; i++) { + if (threadQueue[i].switchCount_ != INVALID_UINT32) { + indexMapBack_->rowIndex_.push_back(i); + } + } + } + indexMapBack_->FixSize(); + break; + default: + break; + } // end of switch (op) +} +void ThreadTable::Cursor::FilterIndex(int col, unsigned char op, sqlite3_value* argv) +{ + switch (col) { + case INTERNAL_PID: + FilterIpid(op, static_cast(sqlite3_value_int64(argv))); + break; + case TID: + FilterTid(op, static_cast(sqlite3_value_int64(argv))); + break; + case SWITCH_COUNT: + FilterSwitchCount(op, static_cast(sqlite3_value_int64(argv))); + break; + default: + // we can't filter all rows + break; + } +} +int ThreadTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv) +{ + // reset indexMapBack_ + if (rowCount_ <= 0) { + return SQLITE_OK; + } + indexMapBack_ = indexMap_.get(); + if (indexMap_->HasData()) { + indexMapBack_ = std::make_unique(0, rowCount_).get(); + } + auto& cs = fc.GetConstraints(); + for (size_t i = 0; i < cs.size(); i++) { + const auto& c = cs[i]; + switch (c.col) { + case ID: + case ITID: + FilterId(c.op, argv[i]); + break; + case TID: + case INTERNAL_PID: + case SWITCH_COUNT: + FilterIndex(c.col, c.op, argv[i]); + break; + default: + break; + } + } + if (indexMap_->HasData()) { + indexMap_->Merge(indexMapBack_); + } -int ThreadTable::Cursor::Column(int column) const + auto orderbys = fc.GetOrderBys(); + for (auto i = orderbys.size(); i > 0;) { + i--; + switch (orderbys[i].iColumn) { + case ID: + case ITID: + indexMap_->SortBy(orderbys[i].desc); + break; + default: + break; + } + } + + return SQLITE_OK; +} + +int ThreadTable::Cursor::Column(int col) const { - switch (column) { - case ID: { + const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); + switch (col) { + case ID: + case ITID: { sqlite3_result_int64(context_, CurrentRow()); break; } @@ -59,52 +432,112 @@ int ThreadTable::Cursor::Column(int column) const break; } case TID: { - const auto& process = dataCache_->GetConstThreadData(CurrentRow()); - sqlite3_result_int64(context_, static_cast(process.tid_)); + sqlite3_result_int64(context_, static_cast(thread.tid_)); break; } case NAME: { - const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); const auto& name = dataCache_->GetDataFromDict(thread.nameIndex_); - sqlite3_result_text(context_, name.c_str(), static_cast(name.length()), nullptr); + if (name.size()) { + sqlite3_result_text(context_, name.c_str(), static_cast(name.length()), nullptr); + } break; } case START_TS: { - const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); if (thread.startT_) { sqlite3_result_int64(context_, static_cast(thread.startT_)); } break; } case END_TS: { - const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); if (thread.endT_) { sqlite3_result_int64(context_, static_cast(thread.endT_)); } break; } case INTERNAL_PID: { - const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); - if (thread.internalPid_) { + if (thread.internalPid_ != INVALID_UINT32) { sqlite3_result_int(context_, static_cast(thread.internalPid_)); } break; } case IS_MAIN_THREAD: { - const auto& thread = dataCache_->GetConstThreadData(CurrentRow()); // When it is not clear which process the thread belongs to, is_main_thread should be set to null - if (!thread.internalPid_) { + if (thread.internalPid_ == INVALID_UINT32) { break; } const auto& process = dataCache_->GetConstProcessData(thread.internalPid_); sqlite3_result_int(context_, thread.tid_ == process.pid_); break; } + case SWITCH_COUNT: { + // When it is not clear which process the thread belongs to, is_main_thread should be set to null + sqlite3_result_int(context_, thread.switchCount_); + break; + } + default: - TS_LOGF("Unregistered column : %d", column); + TS_LOGF("Unregistered column : %d", col); break; } return SQLITE_OK; } + +int ThreadTable::Update(int argc, sqlite3_value** argv, sqlite3_int64* pRowid) +{ + if (argc <= 1) { + return SQLITE_READONLY; + } + if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { + return SQLITE_READONLY; + } + auto id = sqlite3_value_int64(argv[0]); + auto thread = wdataCache_->GetThreadData(static_cast(id)); + constexpr int colOffset = 2; + for (auto i = colOffset; i < argc; i++) { + auto col = i - colOffset; + if (col != INTERNAL_PID) { + continue; + } + auto ipid = static_cast(sqlite3_value_int(argv[i])); + if (ipid) { + thread->internalPid_ = ipid; + } + break; + } + return SQLITE_OK; +} +void ThreadTable::Cursor::FilterId(unsigned char op, sqlite3_value* argv) +{ + auto type = sqlite3_value_type(argv); + if (type != SQLITE_INTEGER) { + // other type consider it NULL + indexMapBack_->Intersect(0, 0); + return; + } + + auto v = static_cast(sqlite3_value_int64(argv)); + switch (op) { + case SQLITE_INDEX_CONSTRAINT_EQ: + indexMapBack_->Intersect(v, v + 1); + break; + case SQLITE_INDEX_CONSTRAINT_GE: + indexMapBack_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_GT: + v++; + indexMapBack_->Intersect(v, rowCount_); + break; + case SQLITE_INDEX_CONSTRAINT_LE: + v++; + indexMapBack_->Intersect(0, v); + break; + case SQLITE_INDEX_CONSTRAINT_LT: + indexMapBack_->Intersect(0, v); + break; + default: + // can't filter, all rows + break; + } +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/table/thread_table.h b/host/trace_streamer/src/table/thread_table.h old mode 100644 new mode 100755 index 960f90812b67e2eef63f73f39021c6cdde590557..8f54612eae7533eac0440728b2a3352b764bbf41 --- a/host/trace_streamer/src/table/thread_table.h +++ b/host/trace_streamer/src/table/thread_table.h @@ -25,14 +25,30 @@ class ThreadTable : public TableBase { public: explicit ThreadTable(const TraceDataCache* dataCache); ~ThreadTable() override; - void CreateCursor() override; + std::unique_ptr CreateCursor() override; private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override; + // filter out by operator[=, >, <...] from column(ID) + bool CanFilterId(const char op, size_t& rowCount); + int Update(int argc, sqlite3_value** argv, sqlite3_int64* pRowid) override; + void FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount); + class Cursor : public TableBase::Cursor { public: - explicit Cursor(const TraceDataCache* dataCache); + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); ~Cursor() override; - int Column(int column) const override; + void FilterIpid(unsigned char op, uint64_t value); + void FilterTid(unsigned char op, uint64_t value); + void FilterSwitchCount(unsigned char op, uint64_t value); + void FilterIndex(int col, unsigned char op, sqlite3_value* argv); + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override; + int Column(int col) const override; + + void FilterId(unsigned char op, sqlite3_value* argv) override; + private: + std::vector rowIndexBak_; + IndexMap* indexMapBack_ = nullptr; }; }; } // namespace TraceStreamer diff --git a/host/trace_streamer/src/table/trace_config_table.cpp b/host/trace_streamer/src/table/trace_config_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..701c1cbc30d93153c7b0fefb0ef86c2a06a59911 --- /dev/null +++ b/host/trace_streamer/src/table/trace_config_table.cpp @@ -0,0 +1,78 @@ +/* + * 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. + */ + +#include "trace_config_table.h" + +namespace SysTuning { +namespace TraceStreamer { +namespace { +enum Index { + ID = 0, + TRACE_SOURCE, + KEY, + VALUE +}; +} +TraceConfigTable::TraceConfigTable(const TraceDataCache* dataCache) : TableBase(dataCache) +{ + tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("trace_source", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("key", "TEXT")); + tableColumn_.push_back(TableBase::ColumnInfo("value", "TEXT")); + tablePriKey_.push_back("id"); +} + +TraceConfigTable::~TraceConfigTable() {} + +std::unique_ptr TraceConfigTable::CreateCursor() +{ + return std::make_unique(dataCache_, this); +} + +TraceConfigTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table) + : TableBase::Cursor(dataCache, table, static_cast(dataCache->GetConstTraceConfigData().Size())), + TraceConfigData_(dataCache->GetConstTraceConfigData()) +{ +} + +TraceConfigTable::Cursor::~Cursor() {} + +int TraceConfigTable::Cursor::Column(int column) const +{ + switch (column) { + case ID: + sqlite3_result_int64(context_, static_cast(CurrentRow())); + break; + case TRACE_SOURCE: + sqlite3_result_text(context_, dataCache_->GetConstTraceConfigData().TraceSource()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case KEY: + sqlite3_result_text(context_, dataCache_->GetConstTraceConfigData().Key()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); + break; + case VALUE: + sqlite3_result_text(context_, + dataCache_->GetConstTraceConfigData().Value()[CurrentRow()].c_str(), + STR_DEFAULT_LEN, nullptr); + break; + default: + TS_LOGF("Unregistered column : %d", column); + break; + } + return SQLITE_OK; +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/src/table/trace_config_table.h b/host/trace_streamer/src/table/trace_config_table.h new file mode 100644 index 0000000000000000000000000000000000000000..eb8a070b090e13bb4e6c204590166de8c6bc08e4 --- /dev/null +++ b/host/trace_streamer/src/table/trace_config_table.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef TEACE_CONFIG_TABLE_H +#define TEACE_CONFIG_TABLE_H + +#include "table_base.h" +#include "trace_data_cache.h" + +namespace SysTuning { +namespace TraceStreamer { +class TraceConfigTable : public TableBase { +public: + explicit TraceConfigTable(const TraceDataCache*); + ~TraceConfigTable() override; + std::unique_ptr CreateCursor() override; + +private: + void EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei) override {} + + class Cursor : public TableBase::Cursor { + public: + explicit Cursor(const TraceDataCache* dataCache, TableBase* table); + ~Cursor() override; + int Filter(const FilterConstraints& fc, sqlite3_value** argv) override + { + UNUSED(fc); + UNUSED(argv); + return 0; + } + + int Column(int column) const override; + + private: + const TraceConfigData& TraceConfigData_; + }; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // TRACE_CONFIG_TABLE_H diff --git a/host/trace_streamer/src/trace_data/BUILD.gn b/host/trace_streamer/src/trace_data/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0cc7d0db619f12ecf18158eec4f21159c2044764 --- /dev/null +++ b/host/trace_streamer/src/trace_data/BUILD.gn @@ -0,0 +1,57 @@ +# 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("//build/ohos.gni") +import("//src/ts.gni") + +ohos_source_set("trace_data") { + sources = [ + "trace_data_cache.cpp", + "trace_data_cache.h", + "trace_data_cache_base.cpp", + "trace_data_cache_base.h", + "trace_data_cache_reader.cpp", + "trace_data_cache_reader.h", + "trace_data_cache_writer.cpp", + "trace_data_cache_writer.h", + "trace_data_db.cpp", + "trace_data_db.h", + "trace_stdtype.cpp", + "trace_stdtype.h", + ] + + if (enable_ts_utest && !use_wasm) { + cflags = [ + "-fprofile-arcs", + "-ftest-coverage", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + if (is_test) { + cflags += [ "-D IS_UT" ] + } + } + include_dirs = [ + "//third_party/sqlite/include", + "//src", + "//src/base", + "//src/include", + "//src/table", + ".", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "//third_party/protobuf/src", + ] +} diff --git a/host/trace_streamer/src/trace_data/trace_data.pri b/host/trace_streamer/src/trace_data/trace_data.pri deleted file mode 100644 index ec15f896fd4d6ec5b34313c593bdb30842f1aa3f..0000000000000000000000000000000000000000 --- a/host/trace_streamer/src/trace_data/trace_data.pri +++ /dev/null @@ -1,28 +0,0 @@ -# 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. -INCLUDEPATH +=$$PWD -HEADERS += \ - $$PWD/trace_data_cache.h \ - $$PWD/trace_data_cache_base.h \ - $$PWD/trace_data_cache_reader.h \ - $$PWD/trace_data_cache_writer.h \ - $$PWD/trace_data_db.h \ - $$PWD/trace_stdtype.h - -SOURCES += \ - $$PWD/trace_data_cache.cpp \ - $$PWD/trace_data_cache_base.cpp \ - $$PWD/trace_data_cache_reader.cpp \ - $$PWD/trace_data_cache_writer.cpp \ - $$PWD/trace_data_db.cpp \ - $$PWD/trace_stdtype.cpp diff --git a/host/trace_streamer/src/trace_data/trace_data_cache.cpp b/host/trace_streamer/src/trace_data/trace_data_cache.cpp old mode 100644 new mode 100755 index 900d411edb5bbaaa6670fb231c1cf62ea2190655..43b5e0dbeb169b581057fb1444799c05974c7c44 --- a/host/trace_streamer/src/trace_data/trace_data_cache.cpp +++ b/host/trace_streamer/src/trace_data/trace_data_cache.cpp @@ -15,31 +15,60 @@ #include "trace_data_cache.h" #include + +#include "appname_table.h" #include "args_table.h" +#include "bio_latency_sample_table.h" #include "callstack_table.h" #include "clk_event_filter_table.h" #include "clock_event_filter_table.h" +#include "clock_snapshot_table.h" #include "cpu_measure_filter_table.h" +#include "cpu_usage_info_table.h" +#include "datasource_clockid_table.h" #include "data_dict_table.h" #include "data_type_table.h" +#include "device_state_table.h" +#include "disk_io_table.h" +#include "ebpf_callstack_table.h" +#if WITH_EBPF_HELP +#include "ebpf_elf_symbol_table.h" +#include "ebpf_elf_table.h" +#include "ebpf_process_maps_table.h" +#endif +#include "file_system_sample_table.h" #include "filter_table.h" -#include "heap_frame_table.h" -#include "heap_table.h" #include "hidump_table.h" +#include "trace_config_table.h" #include "instants_table.h" #include "irq_table.h" +#include "live_process_table.h" #include "log_table.h" #include "measure_filter_table.h" #include "measure_table.h" #include "meta_table.h" +#include "native_hook_frame_table.h" +#include "native_hook_table.h" +#include "network_table.h" +#include "paged_memory_sample_table.h" +#if WITH_PERF +#include "perf_call_chain_table.h" +#include "perf_files_table.h" +#include "perf_sample_table.h" +#include "perf_thread_table.h" +#include "perf_report_table.h" +#endif #include "process_filter_table.h" #include "process_measure_filter_table.h" #include "process_table.h" #include "range_table.h" #include "raw_table.h" #include "sched_slice_table.h" +#include "smaps_table.h" +#include "span_join.h" #include "stat_table.h" #include "symbols_table.h" +#include "sysevent_measure_table.h" #include "system_call_table.h" #include "system_event_filter_table.h" #include "table_base.h" @@ -47,7 +76,6 @@ #include "thread_state_table.h" #include "thread_table.h" - namespace SysTuning { namespace TraceStreamer { TraceDataCache::TraceDataCache() @@ -62,33 +90,139 @@ void TraceDataCache::InitDB() if (dbInited) { return; } +#ifdef USE_VTABLE + TableBase::TableDeclare(*db_, this, "process"); + TableBase::TableDeclare(*db_, this, "sched_slice"); + TableBase::TableDeclare(*db_, this, "callstack"); + TableBase::TableDeclare(*db_, this, "thread"); + TableBase::TableDeclare(*db_, this, "thread_state"); + TableBase::TableDeclare(*db_, this, "thread_filter"); + TableBase::TableDeclare(*db_, this, "process_filter"); + TableBase::TableDeclare(*db_, this, "measure_filter"); + TableBase::TableDeclare(*db_, this, "irq"); + TableBase::TableDeclare(*db_, this, "data_dict"); + TableBase::TableDeclare(*db_, this, "raw"); + TableBase::TableDeclare(*db_, this, "symbols"); + TableBase::TableDeclare(*db_, this, "data_type"); + TableBase::TableDeclare(*db_, this, "hidump"); + TableBase::TableDeclare(*db_, this, "native_hook"); + TableBase::TableDeclare(*db_, this, "native_hook_frame"); + TableBase::TableDeclare(*db_, this, "span_join"); + + // no id + TableBase::TableDeclare(*db_, this, "instant"); + TableBase::TableDeclare(*db_, this, "measure"); + TableBase::TableDeclare(*db_, this, "sys_mem_measure"); + TableBase::TableDeclare(*db_, this, "process_measure"); + TableBase::TableDeclare(*db_, this, "trace_range"); + TableBase::TableDeclare(*db_, this, "stat"); + TableBase::TableDeclare(*db_, this, "syscall"); + TableBase::TableDeclare(*db_, this, "meta"); + TableBase::TableDeclare(*db_, this, "log"); + TableBase::TableDeclare(*db_, this, "network"); + + // id is not real id + TableBase::TableDeclare(*db_, this, "cpu_measure_filter"); + TableBase::TableDeclare(*db_, this, "measure_filter"); + TableBase::TableDeclare(*db_, this, "process_measure_filter"); + TableBase::TableDeclare(*db_, this, "clock_event_filter"); + TableBase::TableDeclare(*db_, this, "clk_event_filter"); + TableBase::TableDeclare(*db_, this, "args"); + + TableBase::TableDeclare(*db_, this, "sys_event_filter"); + TableBase::TableDeclare(*db_, this, "diskio"); + TableBase::TableDeclare(*db_, this, "cpu_usage"); + TableBase::TableDeclare(*db_, this, "live_process"); + TableBase::TableDeclare(*db_, this, "file_system_sample"); + TableBase::TableDeclare(*db_, this, "ebpf_callstack"); + TableBase::TableDeclare(*db_, this, "paged_memory_sample"); +#if WITH_EBPF_HELP + TableBase::TableDeclare(*db_, this, "ebpf_process_maps"); + TableBase::TableDeclare(*db_, this, "ebpf_elf"); + TableBase::TableDeclare(*db_, this, "ebpf_elf_symbol"); +#endif + TableBase::TableDeclare(*db_, this, "app_name"); + TableBase::TableDeclare(*db_, this, "hisys_event_measure"); + TableBase::TableDeclare(*db_, this, "trace_config"); + TableBase::TableDeclare(*db_, this, "device_state"); + TableBase::TableDeclare(*db_, this, "smaps"); + TableBase::TableDeclare(*db_, this, "bio_latency_sample"); + TableBase::TableDeclare(*db_, this, "datasource_clockid"); + TableBase::TableDeclare(*db_, this, "clock_snapshot"); + +#if WITH_PERF + TableBase::TableDeclare(*db_, this, "perf_report"); + TableBase::TableDeclare(*db_, this, "perf_sample"); + TableBase::TableDeclare(*db_, this, "perf_callchain"); + TableBase::TableDeclare(*db_, this, "perf_thread"); + TableBase::TableDeclare(*db_, this, "perf_files"); +#endif +#else TableBase::TableDeclare(*db_, this, "_process"); TableBase::TableDeclare(*db_, this, "_sched_slice"); TableBase::TableDeclare(*db_, this, "_callstack"); + TableBase::TableDeclare(*db_, this, "_thread"); + TableBase::TableDeclare(*db_, this, "_thread_state"); + TableBase::TableDeclare(*db_, this, "_thread_filter"); + TableBase::TableDeclare(*db_, this, "_process_filter"); + TableBase::TableDeclare(*db_, this, "_measure_filter"); TableBase::TableDeclare(*db_, this, "_irq"); TableBase::TableDeclare(*db_, this, "_data_dict"); - TableBase::TableDeclare(*db_, this, "_thread_state"); + TableBase::TableDeclare(*db_, this, "_raw"); + TableBase::TableDeclare(*db_, this, "_symbols"); + TableBase::TableDeclare(*db_, this, "_data_type"); + TableBase::TableDeclare(*db_, this, "_hidump"); + TableBase::TableDeclare(*db_, this, "_native_hook"); + TableBase::TableDeclare(*db_, this, "_native_hook_frame"); + TableBase::TableDeclare(*db_, this, "_span_join"); + + // no id TableBase::TableDeclare(*db_, this, "_instant"); TableBase::TableDeclare(*db_, this, "_measure"); + TableBase::TableDeclare(*db_, this, "_sys_mem_measure"); + TableBase::TableDeclare(*db_, this, "_process_measure"); TableBase::TableDeclare(*db_, this, "_trace_range"); - TableBase::TableDeclare(*db_, this, "_thread"); - TableBase::TableDeclare(*db_, this, "_raw"); + TableBase::TableDeclare(*db_, this, "_stat"); + TableBase::TableDeclare(*db_, this, "_syscall"); + TableBase::TableDeclare(*db_, this, "_meta"); + TableBase::TableDeclare(*db_, this, "_log"); + TableBase::TableDeclare(*db_, this, "_network"); + + // id is not real id TableBase::TableDeclare(*db_, this, "_cpu_measure_filter"); TableBase::TableDeclare(*db_, this, "_measure_filter"); TableBase::TableDeclare(*db_, this, "_process_measure_filter"); - TableBase::TableDeclare(*db_, this, "_stat"); TableBase::TableDeclare(*db_, this, "_clock_event_filter"); TableBase::TableDeclare(*db_, this, "_clk_event_filter"); - TableBase::TableDeclare(*db_, this, "_symbols"); - TableBase::TableDeclare(*db_, this, "_syscall"); TableBase::TableDeclare(*db_, this, "_args"); - TableBase::TableDeclare(*db_, this, "_data_type"); - TableBase::TableDeclare(*db_, this, "_meta"); - TableBase::TableDeclare(*db_, this, "_log"); - TableBase::TableDeclare(*db_, this, "_heap"); - TableBase::TableDeclare(*db_, this, "_heap_frame"); - TableBase::TableDeclare(*db_, this, "_hidump"); TableBase::TableDeclare(*db_, this, "_sys_event_filter"); + TableBase::TableDeclare(*db_, this, "_diskio"); + TableBase::TableDeclare(*db_, this, "_cpu_usage"); + TableBase::TableDeclare(*db_, this, "_live_process"); + TableBase::TableDeclare(*db_, this, "_file_system_sample"); + TableBase::TableDeclare(*db_, this, "_ebpf_callstack"); + TableBase::TableDeclare(*db_, this, "_paged_memory_sample"); + TableBase::TableDeclare(*db_, this, "_smaps"); + TableBase::TableDeclare(*db_, this, "_bio_latency_sample"); + TableBase::TableDeclare(*db_, this, "_datasource_clockid"); + TableBase::TableDeclare(*db_, this, "_clock_snapshot"); +#if WITH_EBPF_HELP + TableBase::TableDeclare(*db_, this, "_ebpf_process_maps"); + TableBase::TableDeclare(*db_, this, "_ebpf_elf"); + TableBase::TableDeclare(*db_, this, "_ebpf_elf_symbol"); +#endif + TableBase::TableDeclare(*db_, this, "_app_name"); + TableBase::TableDeclare(*db_, this, "_hisys_event_measure"); + TableBase::TableDeclare(*db_, this, "_device_state"); + TableBase::TableDeclare(*db_, this, "_trace_config"); +#if WITH_PERF + TableBase::TableDeclare(*db_, this, "_perf_report"); + TableBase::TableDeclare(*db_, this, "_perf_sample"); + TableBase::TableDeclare(*db_, this, "_perf_callchain"); + TableBase::TableDeclare(*db_, this, "_perf_thread"); + TableBase::TableDeclare(*db_, this, "_perf_files"); +#endif +#endif dbInited = true; } } // namespace TraceStreamer diff --git a/host/trace_streamer/src/trace_data/trace_data_cache.h b/host/trace_streamer/src/trace_data/trace_data_cache.h old mode 100644 new mode 100755 index e1f995d67dabbae517d85f10e57d3d7108c8b0a0..a53e2ae0a635e252cdaa42f87cc6b9edd41fc864 --- a/host/trace_streamer/src/trace_data/trace_data_cache.h +++ b/host/trace_streamer/src/trace_data/trace_data_cache.h @@ -16,6 +16,7 @@ #ifndef TRACE_DATA_CACHE_H #define TRACE_DATA_CACHE_H +#include #include "trace_data_cache_reader.h" #include "trace_data_cache_writer.h" #include "trace_data_db.h" diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_base.cpp b/host/trace_streamer/src/trace_data/trace_data_cache_base.cpp index 62314ea418beccfff9b9ae5ea7e1a50698ddcf47..606ad5e3341904a3169c8f1a2895480d1e68d77e 100644 --- a/host/trace_streamer/src/trace_data/trace_data_cache_base.cpp +++ b/host/trace_streamer/src/trace_data/trace_data_cache_base.cpp @@ -22,12 +22,25 @@ TraceDataCacheBase::TraceDataCacheBase() { internalProcessesData_.emplace_back(0); internalThreadsData_.emplace_back(0); - + internalThreadsData_.front().internalPid_ = 0; GetDataIndex(""); } DataIndex TraceDataCacheBase::GetDataIndex(std::string_view str) { return dataDict_.GetStringIndex(str); } + +DataIndex TraceDataCacheBase::GetConstDataIndex(std::string_view str) const +{ + return dataDict_.GetStringIndexNoWrite(str); +} +void TraceDataCacheBase::UpdataZeroThreadInfo() +{ + const std::string ZERO_THREAD_NAME = "swapper"; + internalProcessesData_.front().cmdLine_ = ZERO_THREAD_NAME; + auto& thread = internalThreadsData_.front(); + thread.internalPid_ = 0; + thread.nameIndex_ = dataDict_.GetStringIndex(ZERO_THREAD_NAME); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_base.h b/host/trace_streamer/src/trace_data/trace_data_cache_base.h index cc1181ab5c67edefad6946fcbbd4bc837ade9dde..b085dba640213434ed0ca81976c093fb20a39179 100644 --- a/host/trace_streamer/src/trace_data/trace_data_cache_base.h +++ b/host/trace_streamer/src/trace_data/trace_data_cache_base.h @@ -44,6 +44,7 @@ public: return internalProcessesData_.size(); } + void UpdataZeroThreadInfo(); size_t DataDictSize() const { return dataDict_.Size(); @@ -53,22 +54,12 @@ public: metaData_.SetTraceDuration((traceEndTime_ - traceStartTime_) / SEC_TO_NS); } DataIndex GetDataIndex(std::string_view str); - std::map statusString_ = {{TASK_RUNNABLE, "R"}, - {TASK_INTERRUPTIBLE, "S"}, - {TASK_UNINTERRUPTIBLE, "D"}, - {TASK_RUNNING, "Running"}, - {TASK_INTERRUPTED, "I"}, - {TASK_TRACED, "T"}, - {TASK_EXIT_DEAD, "X"}, - {TASK_ZOMBIE, "Z"}, - {TASK_KILLED, "I"}, - {TASK_WAKEKILL, "R"}, - {TASK_INVALID, "U"}, - {TASK_CLONE, "I"}, - {TASK_DK, "DK"}, - {TASK_TRACED_KILL, "TK"}, - {TASK_FOREGROUND, "R+"}, - {TASK_MAX, "S"}}; + DataIndex GetConstDataIndex(std::string_view str) const; + std::map statusString_ = { + {TASK_RUNNABLE, "R"}, {TASK_INTERRUPTIBLE, "S"}, {TASK_UNINTERRUPTIBLE, "D"}, {TASK_RUNNING, "Running"}, + {TASK_INTERRUPTED, "I"}, {TASK_TRACED, "T"}, {TASK_EXIT_DEAD, "X"}, {TASK_ZOMBIE, "Z"}, + {TASK_KILLED, "I"}, {TASK_WAKEKILL, "R"}, {TASK_INVALID, "U"}, {TASK_CLONE, "I"}, + {TASK_DK, "DK"}, {TASK_TRACED_KILL, "TK"}, {TASK_FOREGROUND, "R+"}, {TASK_MAX, "S"}}; uint64_t traceStartTime_ = std::numeric_limits::max(); uint64_t traceEndTime_ = 0; @@ -89,14 +80,21 @@ public: CallStack callstackData_; CallStack irqData_; LogInfo hilogData_; - HeapInfo heapData_; - HeapFrameInfo heapFrameData_; + NativeHook nativeHookData_; + NativeHookFrame nativeHookFrameData_; Hidump hidumpData_; + PerfSample perfSample_; + PerfCallChain perfCallChain_; + PerfThread perfThread_; + PerfFiles perfFiles_; + PerfReport perfReport_; std::deque internalProcessesData_ = {}; std::deque internalThreadsData_ = {}; Measure measureData_; + Measure sysMemMeasureData_; + Measure processMeasureData_; CpuMeasureFilter cpuMeasureData_; StatAndInfo stat_; @@ -106,6 +104,27 @@ public: ArgSet argSet_; DataType dataType_; SysMeasureFilter sysEvent_; + NetDetailData networkData_; + NetDetailData networkDetailData_; + CpuUsageDetailData cpuUsageData_; + DiskIOData diskIOData_; + LiveProcessDetailData liveProcessDetailData_; + FileSystemSample fileSamplingTableData_; + EbpfCallStackData ebpfCallStackData_; + PagedMemorySampleData PagedMemorySampleData_; +#if WITH_EBPF_HELP + EbpfProcessMaps ebpfProcessMaps_; + EbpfElf ebpfElf_; + EbpfElfSymbol ebpfElfSymbol_; +#endif + AppNames appNames_; + SysEventMeasureData sysEventMeasureData_; + DeviceStateData deviceStateData_; + TraceConfigData traceConfigData_; + SmapsData smapsData_; + BioLatencySampleData bioLatencySampleData_; + ClockSnapshotData clockSnapshotData_; + DataSourceClockIdData dataSourceClockIdData_; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_reader.cpp b/host/trace_streamer/src/trace_data/trace_data_cache_reader.cpp index 095e64804cc52fdb7dd3b55c4da7a5209b47cdbb..e7ac9b6262c873aebc4e84cb4f2ebd8b13c513a4 100644 --- a/host/trace_streamer/src/trace_data/trace_data_cache_reader.cpp +++ b/host/trace_streamer/src/trace_data/trace_data_cache_reader.cpp @@ -23,6 +23,11 @@ const std::string& TraceDataCacheReader::GetDataFromDict(DataIndex id) const { return dataDict_.GetDataFromDict(id); } + +const std::deque& TraceDataCacheReader::GetConstProcessData() const +{ + return internalProcessesData_; +} const Process& TraceDataCacheReader::GetConstProcessData(InternalPid internalPid) const { TS_ASSERT(internalPid < internalProcessesData_.size()); @@ -33,6 +38,11 @@ const Thread& TraceDataCacheReader::GetConstThreadData(InternalTid internalTid) TS_ASSERT(internalTid < internalThreadsData_.size()); return internalThreadsData_[internalTid]; } + +const std::deque& TraceDataCacheReader::GetConstThreadData() const +{ + return internalThreadsData_; +} const CallStack& TraceDataCacheReader::GetConstInternalSlicesData() const { return callstackData_; @@ -53,6 +63,15 @@ const Measure& TraceDataCacheReader::GetConstMeasureData() const { return measureData_; } +const Measure& TraceDataCacheReader::GetConstSysMemMeasureData() const +{ + return sysMemMeasureData_; +} +const Measure& TraceDataCacheReader::GetConstProcessMeasureData() const +{ + return processMeasureData_; +} + const ThreadMeasureFilter& TraceDataCacheReader::GetConstThreadMeasureFilterData() const { @@ -128,14 +147,14 @@ const LogInfo& TraceDataCacheReader::GetConstHilogData() const return hilogData_; } -const HeapInfo& TraceDataCacheReader::GetConstHeapData() const +const NativeHook& TraceDataCacheReader::GetConstNativeHookData() const { - return heapData_; + return nativeHookData_; } -const HeapFrameInfo& TraceDataCacheReader::GetConstHeapFrameData() const +const NativeHookFrame& TraceDataCacheReader::GetConstNativeHookFrameData() const { - return heapFrameData_; + return nativeHookFrameData_; } const Hidump& TraceDataCacheReader::GetConstHidumpData() const @@ -143,6 +162,26 @@ const Hidump& TraceDataCacheReader::GetConstHidumpData() const return hidumpData_; } +const PerfCallChain& TraceDataCacheReader::GetConstPerfCallChainData() const +{ + return perfCallChain_; +} +const PerfFiles& TraceDataCacheReader::GetConstPerfFilesData() const +{ + return perfFiles_; +} +const PerfSample& TraceDataCacheReader::GetConstPerfSampleData() const +{ + return perfSample_; +} +const PerfThread& TraceDataCacheReader::GetConstPerfThreadData() const +{ + return perfThread_; +} +const PerfReport& TraceDataCacheReader::GetConstPerfReportData() const +{ + return perfReport_; +} const SysCall& TraceDataCacheReader::GetConstSysCallData() const { return sysCallData_; @@ -161,5 +200,81 @@ const SysMeasureFilter& TraceDataCacheReader::GetConstSysMeasureFilterData() con { return sysEvent_; } +const NetDetailData& TraceDataCacheReader::GetConstNetworkData() const +{ + return networkData_; +} +const CpuUsageDetailData& TraceDataCacheReader::GetConstCpuUsageInfoData() const +{ + return cpuUsageData_; +} +const DiskIOData& TraceDataCacheReader::GetConstDiskIOData() const +{ + return diskIOData_; +} +const LiveProcessDetailData& TraceDataCacheReader::GetConstLiveProcessData() const +{ + return liveProcessDetailData_; +} +const FileSystemSample& TraceDataCacheReader::GetConstFileSystemSample() const +{ + return fileSamplingTableData_; +} +const EbpfCallStackData& TraceDataCacheReader::GetConstEbpfCallStackData() const +{ + return ebpfCallStackData_; +} +const PagedMemorySampleData& TraceDataCacheReader::GetConstPagedMemorySampleData() const +{ + return PagedMemorySampleData_; +} +#if WITH_EBPF_HELP +const EbpfProcessMaps& TraceDataCacheReader::GetConstEbpfProcessMaps() const +{ + return ebpfProcessMaps_; +} +const EbpfElf& TraceDataCacheReader::GetConstEbpfElf() const +{ + return ebpfElf_; +} +const EbpfElfSymbol& TraceDataCacheReader::GetConstEbpfElfSymbol() const +{ + return ebpfElfSymbol_; +} +#endif +const AppNames& TraceDataCacheReader::GetConstAppNamesData() const +{ + return appNames_; +} +const SysEventMeasureData& TraceDataCacheReader::GetConstSyseventMeasureData() const +{ + return sysEventMeasureData_; +} +const TraceConfigData& TraceDataCacheReader::GetConstTraceConfigData() const +{ + return traceConfigData_; +} +const DeviceStateData& TraceDataCacheReader::GetConstDeviceStateData() const +{ + return deviceStateData_; +} +const SmapsData& TraceDataCacheReader::GetConstSmapsData() const +{ + return smapsData_; +} +const BioLatencySampleData& TraceDataCacheReader::GetConstBioLatencySampleData() const +{ + return bioLatencySampleData_; +} + +const ClockSnapshotData& TraceDataCacheReader::GetConstClockSnapshotData() const +{ + return clockSnapshotData_; +} + +const DataSourceClockIdData& TraceDataCacheReader::GetConstDataSourceClockIdData() const +{ + return dataSourceClockIdData_; +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_reader.h b/host/trace_streamer/src/trace_data/trace_data_cache_reader.h index ffe1f81c3db9966eb006280593da5e7441653d1a..c0b70afd9e2ae025eb9417c31660e3cb08d0d907 100644 --- a/host/trace_streamer/src/trace_data/trace_data_cache_reader.h +++ b/host/trace_streamer/src/trace_data/trace_data_cache_reader.h @@ -33,12 +33,16 @@ public: public: const std::string& GetDataFromDict(DataIndex id) const; const Process& GetConstProcessData(InternalPid internalPid) const; + const std::deque& GetConstProcessData() const; const Thread& GetConstThreadData(InternalTid internalTid) const; + const std::deque& GetConstThreadData() const; const CallStack& GetConstInternalSlicesData() const; const CallStack& GetConstIrqData() const; const Filter& GetConstFilterData() const; const Raw& GetConstRawTableData() const; const Measure& GetConstMeasureData() const; + const Measure& GetConstSysMemMeasureData() const; + const Measure& GetConstProcessMeasureData() const; const ThreadMeasureFilter& GetConstThreadMeasureFilterData() const; const ThreadState& GetConstThreadStateData() const; const SchedSlice& GetConstSchedSliceData() const; @@ -57,12 +61,37 @@ public: const SymbolsData& GetConstSymbolsData() const; const SysCall& GetConstSysCallData() const; const LogInfo& GetConstHilogData() const; - const HeapInfo& GetConstHeapData() const; - const HeapFrameInfo& GetConstHeapFrameData() const; + const NativeHook& GetConstNativeHookData() const; + const NativeHookFrame& GetConstNativeHookFrameData() const; const Hidump& GetConstHidumpData() const; + const PerfCallChain& GetConstPerfCallChainData() const; + const PerfFiles& GetConstPerfFilesData() const; + const PerfSample& GetConstPerfSampleData() const; + const PerfThread& GetConstPerfThreadData() const; + const PerfReport& GetConstPerfReportData() const; const ArgSet& GetConstArgSetData() const; const DataType& GetConstDataTypeData() const; const SysMeasureFilter& GetConstSysMeasureFilterData() const; + const NetDetailData& GetConstNetworkData() const; + const CpuUsageDetailData& GetConstCpuUsageInfoData() const; + const DiskIOData& GetConstDiskIOData() const; + const LiveProcessDetailData& GetConstLiveProcessData() const; + const FileSystemSample& GetConstFileSystemSample() const; + const DeviceStateData& GetConstDeviceStateData() const; + const EbpfCallStackData& GetConstEbpfCallStackData() const; + const PagedMemorySampleData& GetConstPagedMemorySampleData() const; +#if WITH_EBPF_HELP + const EbpfProcessMaps& GetConstEbpfProcessMaps() const; + const EbpfElf& GetConstEbpfElf() const; + const EbpfElfSymbol& GetConstEbpfElfSymbol() const; +#endif + const AppNames& GetConstAppNamesData() const; + const SysEventMeasureData& GetConstSyseventMeasureData() const; + const TraceConfigData& GetConstTraceConfigData() const; + const SmapsData& GetConstSmapsData() const; + const BioLatencySampleData& GetConstBioLatencySampleData() const; + const ClockSnapshotData& GetConstClockSnapshotData() const; + const DataSourceClockIdData& GetConstDataSourceClockIdData() const; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_writer.cpp b/host/trace_streamer/src/trace_data/trace_data_cache_writer.cpp old mode 100644 new mode 100755 index 4fc2925a0a9547988f23ebdad82d862dafb7f64e..9757feb404b0cd936f4bffe7aabac7eb8326f587 --- a/host/trace_streamer/src/trace_data/trace_data_cache_writer.cpp +++ b/host/trace_streamer/src/trace_data/trace_data_cache_writer.cpp @@ -30,6 +30,15 @@ Process* TraceDataCacheWriter::GetProcessData(InternalPid internalPid) return &internalProcessesData_[internalPid]; } +uint32_t TraceDataCacheWriter::AppendNewProcessData(uint32_t pid, const std::string& name, uint64_t startTs) +{ + internalProcessesData_.emplace_back(pid); + auto& process = internalProcessesData_.back(); + process.cmdLine_ = name; + process.startT_ = startTs; + return internalProcessesData_.size() - 1; +} + InternalTid TraceDataCacheWriter::NewInternalThread(uint32_t tid) { internalThreadsData_.emplace_back(tid); @@ -45,8 +54,10 @@ Thread* TraceDataCacheWriter::GetThreadData(InternalTid internalTid) void TraceDataCacheWriter::UpdateTraceTime(uint64_t timestamp) { - traceStartTime_ = std::min(traceStartTime_, timestamp); - traceEndTime_ = std::max(traceEndTime_, timestamp); + if (timestamp) { + traceStartTime_ = std::min(traceStartTime_, timestamp); + traceEndTime_ = std::max(traceEndTime_, timestamp); + } } void TraceDataCacheWriter::MixTraceTime(uint64_t timestampMin, uint64_t timestampMax) @@ -89,6 +100,15 @@ Measure* TraceDataCacheWriter::GetMeasureData() return &measureData_; } +Measure* TraceDataCacheWriter::GetSysMemMeasureData() +{ + return &sysMemMeasureData_; +} +Measure* TraceDataCacheWriter::GetProcessMeasureData() +{ + return &processMeasureData_; +} + ThreadState* TraceDataCacheWriter::GetThreadStateData() { return &threadStateData_; @@ -161,21 +181,40 @@ LogInfo* TraceDataCacheWriter::GetHilogData() return &hilogData_; } -HeapInfo* TraceDataCacheWriter::GetHeapData() +NativeHook* TraceDataCacheWriter::GetNativeHookData() { - return &heapData_; + return &nativeHookData_; } -HeapFrameInfo* TraceDataCacheWriter::GetHeapFrameData() +NativeHookFrame* TraceDataCacheWriter::GetNativeHookFrameData() { - return &heapFrameData_; + return &nativeHookFrameData_; } Hidump* TraceDataCacheWriter::GetHidumpData() { return &hidumpData_; } - +PerfCallChain* TraceDataCacheWriter::GetPerfCallChainData() +{ + return &perfCallChain_; +} +PerfFiles* TraceDataCacheWriter::GetPerfFilesData() +{ + return &perfFiles_; +} +PerfSample* TraceDataCacheWriter::GetPerfSampleData() +{ + return &perfSample_; +} +PerfThread* TraceDataCacheWriter::GetPerfThreadData() +{ + return &perfThread_; +} +PerfReport* TraceDataCacheWriter::GetPerfReportData() +{ + return &perfReport_; +} ArgSet* TraceDataCacheWriter::GetArgSetData() { return &argSet_; @@ -190,6 +229,86 @@ SysMeasureFilter* TraceDataCacheWriter::GetSysMeasureFilterData() { return &sysEvent_; } +NetDetailData* TraceDataCacheWriter::GetNetworkData() +{ + return &networkData_; +} +NetDetailData* TraceDataCacheWriter::GetNetworkDetailData() +{ + return &networkDetailData_; +} +DiskIOData* TraceDataCacheWriter::GetDiskIOData() +{ + return &diskIOData_; +} + +CpuUsageDetailData* TraceDataCacheWriter::GetCpuUsageInfoData() +{ + return &cpuUsageData_; +} +LiveProcessDetailData* TraceDataCacheWriter::GetLiveProcessData() +{ + return &liveProcessDetailData_; +} +FileSystemSample* TraceDataCacheWriter::GetFileSystemSample() +{ + return &fileSamplingTableData_; +} +EbpfCallStackData* TraceDataCacheWriter::GetEbpfCallStack() +{ + return &ebpfCallStackData_; +} +PagedMemorySampleData* TraceDataCacheWriter::GetPagedMemorySampleData() +{ + return &PagedMemorySampleData_; +} +#if WITH_EBPF_HELP +EbpfProcessMaps* TraceDataCacheWriter::GetEbpfProcessMaps() +{ + return &ebpfProcessMaps_; +} +EbpfElf* TraceDataCacheWriter::GetEbpfElf() +{ + return &ebpfElf_; +} +EbpfElfSymbol* TraceDataCacheWriter::GetEbpfElfSymbol() +{ + return &ebpfElfSymbol_; +} +#endif +AppNames* TraceDataCacheWriter::GetAppNamesData() +{ + return &appNames_; +} +SysEventMeasureData* TraceDataCacheWriter::GetSyseventMeasureData() +{ + return &sysEventMeasureData_; +} +DeviceStateData* TraceDataCacheWriter::GetDeviceStateData() +{ + return &deviceStateData_; +} +TraceConfigData* TraceDataCacheWriter::GetTraceConfigData() +{ + return &traceConfigData_; +} +SmapsData* TraceDataCacheWriter::GetSmapsData() +{ + return &smapsData_; +} +BioLatencySampleData* TraceDataCacheWriter::GetBioLatencySampleData() +{ + return &bioLatencySampleData_; +} + +ClockSnapshotData* TraceDataCacheWriter::GetClockSnapshotData() +{ + return &clockSnapshotData_; +} +DataSourceClockIdData* TraceDataCacheWriter::GetDataSourceClockIdData() +{ + return &dataSourceClockIdData_; +} void TraceDataCacheWriter::Clear() { rawData_.Clear(); @@ -209,8 +328,8 @@ void TraceDataCacheWriter::Clear() callstackData_.Clear(); irqData_.Clear(); hilogData_.Clear(); - heapData_.Clear(); - heapFrameData_.Clear(); + nativeHookData_.Clear(); + nativeHookFrameData_.Clear(); hidumpData_.Clear(); internalProcessesData_.clear(); @@ -225,6 +344,29 @@ void TraceDataCacheWriter::Clear() argSet_.Clear(); dataType_.Clear(); sysEvent_.Clear(); + networkData_.Clear(); + networkDetailData_.Clear(); + perfSample_.Clear(); + perfCallChain_.Clear(); + perfThread_.Clear(); + perfFiles_.Clear(); + perfReport_.Clear(); + cpuUsageData_.Clear(); + diskIOData_.Clear(); + liveProcessDetailData_.Clear(); + fileSamplingTableData_.Clear(); + ebpfCallStackData_.Clear(); + PagedMemorySampleData_.Clear(); +#if WITH_EBPF_HELP + ebpfProcessMaps_.Clear(); + ebpfElf_.Clear(); + ebpfElfSymbol_.Clear(); +#endif + appNames_.Clear(); + sysEventMeasureData_.Clear(); + deviceStateData_.Clear(); + smapsData_.Clear(); + bioLatencySampleData_.Clear(); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_cache_writer.h b/host/trace_streamer/src/trace_data/trace_data_cache_writer.h index 5d421046a5d64750b113961bde3f4ce325b78618..0123bee3a2e2859613b80d5fb1cb81fea1e93156 100644 --- a/host/trace_streamer/src/trace_data/trace_data_cache_writer.h +++ b/host/trace_streamer/src/trace_data/trace_data_cache_writer.h @@ -32,6 +32,7 @@ public: public: InternalPid GetProcessInternalPid(uint32_t pid); Process* GetProcessData(InternalPid internalPid); + uint32_t AppendNewProcessData(uint32_t pid, const std::string& name, uint64_t startTs); InternalTid NewInternalThread(uint32_t tid); Thread* GetThreadData(InternalTid internalTid); void UpdateTraceTime(uint64_t timestamp); @@ -41,6 +42,8 @@ public: Filter* GetFilterData(); Raw* GetRawData(); Measure* GetMeasureData(); + Measure* GetSysMemMeasureData(); + Measure* GetProcessMeasureData(); ThreadState* GetThreadStateData(); SchedSlice* GetSchedSliceData(); CpuMeasureFilter* GetCpuMeasuresData(); @@ -56,12 +59,38 @@ public: SymbolsData* GetSymbolsData(); SysCall* GetSysCallData(); LogInfo* GetHilogData(); - HeapInfo* GetHeapData(); - HeapFrameInfo* GetHeapFrameData(); + NativeHook* GetNativeHookData(); + NativeHookFrame* GetNativeHookFrameData(); Hidump* GetHidumpData(); + PerfCallChain* GetPerfCallChainData(); + PerfFiles* GetPerfFilesData(); + PerfSample* GetPerfSampleData(); + PerfThread* GetPerfThreadData(); + PerfReport* GetPerfReportData(); ArgSet* GetArgSetData(); DataType* GetDataTypeData(); SysMeasureFilter* GetSysMeasureFilterData(); + NetDetailData* GetNetworkData(); + NetDetailData* GetNetworkDetailData(); + DiskIOData* GetDiskIOData(); + CpuUsageDetailData* GetCpuUsageInfoData(); + LiveProcessDetailData* GetLiveProcessData(); + FileSystemSample* GetFileSystemSample(); + EbpfCallStackData* GetEbpfCallStack(); + PagedMemorySampleData* GetPagedMemorySampleData(); +#if WITH_EBPF_HELP + EbpfProcessMaps* GetEbpfProcessMaps(); + EbpfElf* GetEbpfElf(); + EbpfElfSymbol* GetEbpfElfSymbol(); +#endif + AppNames* GetAppNamesData(); + SysEventMeasureData* GetSyseventMeasureData(); + DeviceStateData* GetDeviceStateData(); + TraceConfigData* GetTraceConfigData(); + SmapsData* GetSmapsData(); + BioLatencySampleData* GetBioLatencySampleData(); + ClockSnapshotData* GetClockSnapshotData(); + DataSourceClockIdData* GetDataSourceClockIdData(); }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_data_db.cpp b/host/trace_streamer/src/trace_data/trace_data_db.cpp old mode 100644 new mode 100755 index 07fd63aeb0b7551859560b6af1e0d70292681060..481acaac9f98868330756f60e1308772c011c214 --- a/host/trace_streamer/src/trace_data/trace_data_db.cpp +++ b/host/trace_streamer/src/trace_data/trace_data_db.cpp @@ -14,6 +14,7 @@ */ #include "trace_data_db.h" +#include #include #include #include @@ -27,19 +28,16 @@ #include "ext/sqlite_ext_funcs.h" #include "file.h" #include "log.h" +#include "string_help.h" +const int ONCE_MAX_MB = 1024 * 1024 * 4; namespace SysTuning { namespace TraceStreamer { -int PrintQueryResult(void* para, int column, char** columnValue, char** columnName) -{ - int i; - printf("Query results include %d column\n", column); - for (i = 0; i < column; i++) { - printf("name : %s \t value : %s\n", columnName[i], columnValue[i]); - } - printf("------------------\n"); - return 0; -} +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) +using namespace SysTuning::base; TraceDataDB::TraceDataDB() : db_(nullptr) { if (sqlite3_threadsafe() > 0) { @@ -55,7 +53,7 @@ TraceDataDB::TraceDataDB() : db_(nullptr) if (sqlite3_open(":memory:", &db_)) { TS_LOGF("open :memory db failed"); } - CreateExtendFunction(db_); + ts_create_extend_function(db_); } TraceDataDB::~TraceDataDB() @@ -79,7 +77,8 @@ int TraceDataDB::ExportDatabase(const std::string& outputName) fprintf(stdout, "Failed to create file: %s", outputName.c_str()); return 1; } - ftruncate(fd, 0); + auto ret = ftruncate(fd, 0); + UNUSED(ret); close(fd); } @@ -92,20 +91,22 @@ int TraceDataDB::ExportDatabase(const std::string& outputName) ExecuteSql(attachSql); for (auto itor = internalTables_.begin(); itor != internalTables_.end(); itor++) { - if (*itor == "meta") { - if (!exportMetaTable_) { - continue; - } - if ((*itor) != "_data_dict") { - std::string exportSql("CREATE TABLE systuning_export." + (*itor).substr(1, -1) + - " AS SELECT * FROM " + *itor); - ExecuteSql(exportSql); - } +#ifndef USE_VTABLE + if (*itor == "_meta" && !exportMetaTable_) { + continue; + } else { + std::string exportSql("CREATE TABLE systuning_export." + (*itor).substr(1, -1) + " AS SELECT * FROM " + + *itor); + ExecuteSql(exportSql); + } +#else + if (*itor == "meta" && !exportMetaTable_) { + continue; } else { - std::string exportSql("CREATE TABLE systuning_export." + (*itor).substr(1, -1) + - " AS SELECT * FROM " + *itor); + std::string exportSql("CREATE TABLE systuning_export." + (*itor) + " AS SELECT * FROM " + *itor); ExecuteSql(exportSql); } +#endif } std::string createArgsView = "create view systuning_export.args_view AS select A.argset, V2.data as keyName, A.id, D.desc, (case when " @@ -126,16 +127,23 @@ void TraceDataDB::Prepare() return; } pared_ = true; +#ifndef USE_VTABLE for (auto itor = internalTables_.begin(); itor != internalTables_.end(); itor++) { std::string exportSql("CREATE TABLE " + (*itor).substr(1, -1) + " AS SELECT * FROM " + *itor); ExecuteSql(exportSql); } +#endif + ExecuteSql( + "update thread set ipid = \ + (select id from process where \ + thread.tid = process.pid) where thread.ipid is null;"); std::string createArgsView = "create view args_view AS select A.argset, V2.data as keyName, A.id, D.desc, (case when " "A.datatype==1 then V.data else A.value end) as strValue from args as A left join data_type as D on " "(D.typeId " "= A.datatype) left join data_dict as V on V.id = A.value left join data_dict as V2 on V2.id = A.key"; ExecuteSql(createArgsView); + std::string updateProcessNewName = "update process set name = (select name from thread t where t.ipid = process.id and t.name is not " "null and " @@ -163,9 +171,8 @@ void TraceDataDB::ExecuteSql(const std::string_view& sql) int TraceDataDB::SearchData() { Prepare(); - int result; - char* errmsg = nullptr; std::string line; + bool printResult = false; for (;;) { std::cout << "> "; getline(std::cin, line); @@ -181,11 +188,79 @@ int TraceDataDB::SearchData() } else if (!line.compare("-help") || !line.compare("-h")) { std::cout << "use info" << std::endl; continue; + } else if (!line.compare("-p")) { + std::cout << "will print result of query" << std::endl; + printResult = true; + continue; + } else if (!line.compare("-up")) { + std::cout << "will not print result of query" << std::endl; + printResult = false; + continue; + } else if (line.find("-c:") == 0) { + line = line.substr(strlen("-c:")); + if (OperateDatabase(line) == SQLITE_OK) { + printf("operate SQL success\n"); + } + continue; } - result = sqlite3_exec(db_, line.c_str(), PrintQueryResult, NULL, &errmsg); + + using namespace std::chrono; + const auto start = steady_clock::now(); + int rowCount = SearchDatabase(line, printResult); + std::chrono::nanoseconds searchDur = duration_cast(steady_clock::now() - start); + printf("\"%s\"\n\tused %.3fms row: %d\n", line.c_str(), searchDur.count() / 1E6, rowCount); } return 0; } +int TraceDataDB::SearchDatabase(const std::string& sql, bool print) +{ + Prepare(); + int rowCount = 0; + sqlite3_stmt* stmt = nullptr; + int ret = sqlite3_prepare_v2(db_, sql.c_str(), static_cast(sql.size()), &stmt, nullptr); + if (ret != SQLITE_OK) { + TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:%s", sql.c_str(), ret, sqlite3_errmsg(db_)); + return 0; + } + + int colCount = sqlite3_column_count(stmt); + if (colCount == 0) { + TS_LOGI("sqlite3_column_count(%s) no column", sql.c_str()); + sqlite3_finalize(stmt); + return 0; + } + if (print) { + for (int i = 0; i < colCount; i++) { + printf("%s\t", sqlite3_column_name(stmt, i)); + } + printf("\n"); + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + rowCount++; + for (int i = 0; i < colCount; i++) { + const char* p = reinterpret_cast(sqlite3_column_text(stmt, i)); + int type = sqlite3_column_type(stmt, i); + if (!print) { + continue; + } + if (p == nullptr) { + printf("null\t"); + continue; + } + if (type == SQLITE_TEXT) { + printf("\"%s\"\t", p); + } else { + printf("%s\t", p); + } + } + if (print) { + printf("\n"); + } + } + sqlite3_finalize(stmt); + return rowCount; +} int TraceDataDB::OperateDatabase(const std::string& sql) { Prepare(); @@ -203,20 +278,18 @@ int TraceDataDB::SearchDatabase(const std::string& sql, ResultCallBack resultCal sqlite3_stmt* stmt = nullptr; int ret = sqlite3_prepare_v2(db_, sql.c_str(), static_cast(sql.size()), &stmt, nullptr); if (ret != SQLITE_OK) { - TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:", sql.c_str(), ret); + resultCallBack("false\r\n", SEND_FINISH); + TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:%s", sql.c_str(), ret, sqlite3_errmsg(db_)); return ret; } if (!resultCallBack) { return ret; } - const size_t maxLenResponse = 4 * 1024; - std::string res; - res.reserve(maxLenResponse); - res = "ok\r\n"; + std::string res = "ok\r\n"; int colCount = sqlite3_column_count(stmt); if (colCount == 0) { - resultCallBack(res); + resultCallBack(res, SEND_FINISH); return ret; } res += "{\"columns\":["; @@ -234,17 +307,17 @@ int TraceDataDB::SearchDatabase(const std::string& sql, ResultCallBack resultCal while (sqlite3_step(stmt) == SQLITE_ROW) { hasRow = true; GetRowString(stmt, colCount, row); - if (res.size() + row.size() + strlen(",]}\r\n") >= maxLenResponse) { - resultCallBack(res); - res.clear(); - } res += row + ","; + if (res.size() >= ONCE_MAX_MB) { + resultCallBack(res, SEND_CONTINUE); + res = ""; + } } if (hasRow) { res.pop_back(); // remove the last ',' } res += "]}\r\n"; - resultCallBack(res); + resultCallBack(res, SEND_FINISH); sqlite3_finalize(stmt); return ret; @@ -255,11 +328,11 @@ int TraceDataDB::SearchDatabase(const std::string& sql, uint8_t* out, int outLen sqlite3_stmt* stmt = nullptr; int ret = sqlite3_prepare_v2(db_, sql.c_str(), static_cast(sql.size()), &stmt, nullptr); if (ret != SQLITE_OK) { - TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:", sql.c_str(), ret); + TS_LOGE("sqlite3_prepare_v2(%s) failed: %d:%s", sql.c_str(), ret, sqlite3_errmsg(db_)); return -1; } char* res = reinterpret_cast(out); - int retSnprintf = std::snprintf(res, outLen, "%s", "ok\r\n"); + int retSnprintf = snprintf_s(res, outLen, 1, "ok\r\n"); if (retSnprintf < 0) { return -1; } @@ -268,20 +341,20 @@ int TraceDataDB::SearchDatabase(const std::string& sql, uint8_t* out, int outLen if (colCount == 0) { return pos; } - retSnprintf = std::snprintf(res + pos, outLen - pos, "%s", "{\"columns\":["); + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "%s", "{\"columns\":["); if (retSnprintf < 0) { return -1; } pos += retSnprintf; for (int i = 0; i < colCount; i++) { - retSnprintf = std::snprintf(res + pos, outLen - pos, "%s%s%s", "\"", sqlite3_column_name(stmt, i), "\","); + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "%s%s%s", "\"", sqlite3_column_name(stmt, i), "\","); if (retSnprintf < 0) { return -1; } pos += retSnprintf; } pos--; // rmove the last ',' - retSnprintf = std::snprintf(res + pos, outLen - pos, "%s", "],\"values\":["); + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "],\"values\":["); if (retSnprintf < 0) { return -1; } @@ -294,7 +367,7 @@ int TraceDataDB::SearchDatabase(const std::string& sql, uint8_t* out, int outLen hasRow = true; GetRowString(stmt, colCount, row); if (pos + row.size() + strlen(",]}\r\n") >= size_t(outLen)) { - retSnprintf = std::snprintf(res + pos, outLen - pos, "%s", "]}\r\n"); + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "]}\r\n"); if (retSnprintf < 0) { return -1; } @@ -302,7 +375,7 @@ int TraceDataDB::SearchDatabase(const std::string& sql, uint8_t* out, int outLen sqlite3_finalize(stmt); return pos; } - retSnprintf = std::snprintf(res + pos, outLen - pos, "%s%s", row.c_str(), ","); + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "%s%s", row.c_str(), ","); if (retSnprintf < 0) { return -1; } @@ -311,7 +384,7 @@ int TraceDataDB::SearchDatabase(const std::string& sql, uint8_t* out, int outLen if (hasRow) { pos--; // remove the last ',' } - retSnprintf = std::snprintf(res + pos, outLen - pos, "%s", "]}\r\n"); + retSnprintf = snprintf_s(res + pos, outLen - pos, 1, "]}\r\n"); if (retSnprintf < 0) { return -1; } @@ -319,6 +392,10 @@ int TraceDataDB::SearchDatabase(const std::string& sql, uint8_t* out, int outLen sqlite3_finalize(stmt); return pos; } +void TraceDataDB::SetCancel(bool cancel) +{ + cancelQuery_ = cancel; +} void TraceDataDB::GetRowString(sqlite3_stmt* stmt, int colCount, std::string& rowStr) { rowStr.clear(); diff --git a/host/trace_streamer/src/trace_data/trace_data_db.h b/host/trace_streamer/src/trace_data/trace_data_db.h index d9ff9b68cb2827bd2ea8a04c3aaea4e787169a5c..0a2f37feb134e8bdd3d77068fb78889b5cc028d9 100644 --- a/host/trace_streamer/src/trace_data/trace_data_db.h +++ b/host/trace_streamer/src/trace_data/trace_data_db.h @@ -26,6 +26,8 @@ extern "C" { namespace SysTuning { namespace TraceStreamer { +const int SEND_CONTINUE = 0; +const int SEND_FINISH = 1; class TraceDataDB { public: TraceDataDB(); @@ -34,25 +36,33 @@ public: virtual ~TraceDataDB(); virtual void InitDB() = 0; void Prepare(); + public: int ExportDatabase(const std::string& outputName); int SearchData(); int OperateDatabase(const std::string& sql); - using ResultCallBack = std::function; + using ResultCallBack = std::function; int SearchDatabase(const std::string& sql, ResultCallBack resultCallBack); int SearchDatabase(const std::string& sql, uint8_t* out, int outLen); + void SetCancel(bool cancel); void AppendNewTable(std::string tableName); void EnableMetaTable(bool enabled); + bool Cancel() const + { + return cancelQuery_; + } public: sqlite3* db_; private: void ExecuteSql(const std::string_view& sql); - void GetRowString(sqlite3_stmt* stmt, int colCount, std::string& rowStr); + static void GetRowString(sqlite3_stmt* stmt, int colCount, std::string& rowStr); + int SearchDatabase(const std::string& sql, bool print); std::list internalTables_ = {}; - bool exportMetaTable_ = false; + bool exportMetaTable_ = true; bool pared_ = false; + bool cancelQuery_ = false; }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_stdtype.cpp b/host/trace_streamer/src/trace_data/trace_stdtype.cpp old mode 100644 new mode 100755 index c791a84d9b452a28c1f3970003e02484e79d9bb9..81115a4156159b52fd5732c0970fcd6011c9bf2c --- a/host/trace_streamer/src/trace_data/trace_stdtype.cpp +++ b/host/trace_streamer/src/trace_data/trace_stdtype.cpp @@ -14,48 +14,79 @@ */ #include "trace_stdtype.h" +#include #include namespace SysTuning { namespace TraceStdtype { -size_t ThreadState::AppendThreadState(uint64_t ts, uint64_t dur, uint64_t cpu, uint64_t internalTid, uint64_t state) +void CpuCacheBase::SetDur(uint64_t index, uint64_t dur) +{ + durs_[index] = dur; +} +TableRowId ThreadState::AppendThreadState(InternalTime ts, + InternalTime dur, + InternalCpu cpu, + InternalTid itid, + TableRowId idState) { - internalTids_.emplace_back(internalTid); - states_.emplace_back(state); timeStamps_.emplace_back(ts); - durs_.emplace_back(dur); + durations_.emplace_back(dur); + itids_.emplace_back(itid); + tids_.emplace_back(INVALID_UINT32); + pids_.emplace_back(INVALID_UINT32); + states_.emplace_back(idState); cpus_.emplace_back(cpu); - return Size() - 1; + return itids_.size() - 1; } -void ThreadState::SetDuration(size_t index, uint64_t duration) +void ThreadState::SetDuration(TableRowId index, InternalTime dur) { - durs_[index] = duration; + durations_[index] = dur; } -uint64_t ThreadState::UpdateDuration(size_t index, uint64_t timestamp) +void DataDict::Finish() +{ + std::string::size_type pos(0); + for (auto i = 0; i < dataDict_.size(); i++) { + while ((pos = dataDict_[i].find("\"")) != std::string::npos) { + dataDict_[i].replace(pos, 1, "\'"); + } + while ((dataDict_[i].back() >= '\001' && dataDict_[i].back() <= '\007') || dataDict_[i].back() == '\n' || + dataDict_[i].back() == '\r') { + dataDict_[i].pop_back(); + } + } +} +TableRowId ThreadState::UpdateDuration(TableRowId index, InternalTime ts) { - if (durs_[index] == INVALID_UINT64) { - durs_[index] = timestamp - timeStamps_[index]; + if (durations_[index] == INVALID_TIME) { + durations_[index] = ts - timeStamps_[index]; } - return internalTids_[index]; + return itids_[index]; } -void ThreadState::UpdateState(size_t index, uint64_t state) +void ThreadState::UpdateState(TableRowId index, TableRowId idState) { - states_[index] = state; + states_[index] = idState; } -void ThreadState::UpdateDuration(size_t index, uint64_t timestamp, uint64_t state) + +void ThreadState::UpdateDuration(TableRowId index, InternalTime ts, TableRowId idState) { - durs_[index] = timestamp - timeStamps_[index]; - states_[index] = state; + durations_[index] = ts - timeStamps_[index]; + states_[index] = idState; +} + +void ThreadState::UpdateTidAndPid(TableRowId index, InternalTid tid, InternalTid pid) +{ + tids_[index] = tid; + pids_[index] = pid; } -uint64_t ThreadState::UpdateDuration(size_t index, uint64_t timestamp, uint64_t cpu, uint64_t state) +TableRowId ThreadState::UpdateDuration(TableRowId index, InternalTime ts, InternalCpu cpu, TableRowId idState) { cpus_[index] = cpu; - durs_[index] = timestamp - timeStamps_[index]; - states_[index] = state; - return internalTids_[index]; + durations_[index] = ts - timeStamps_[index]; + states_[index] = idState; + return itids_[index]; } size_t SchedSlice::AppendSchedSlice(uint64_t ts, @@ -68,6 +99,7 @@ size_t SchedSlice::AppendSchedSlice(uint64_t ts, timeStamps_.emplace_back(ts); durs_.emplace_back(dur); cpus_.emplace_back(cpu); + tsEnds_.emplace_back(0); internalTids_.emplace_back(internalTid); endStates_.emplace_back(endState); priority_.emplace_back(priority); @@ -77,6 +109,7 @@ size_t SchedSlice::AppendSchedSlice(uint64_t ts, void SchedSlice::SetDuration(size_t index, uint64_t duration) { durs_[index] = duration; + tsEnds_[index] = timeStamps_[index] + duration; } void SchedSlice::Update(uint64_t index, uint64_t ts, uint64_t state, uint64_t pior) @@ -90,6 +123,7 @@ size_t CallStack::AppendInternalAsyncSlice(uint64_t startT, uint64_t durationNs, InternalTid internalTid, DataIndex cat, + uint16_t nameIdentify, DataIndex name, uint8_t depth, uint64_t cookid, @@ -100,20 +134,24 @@ size_t CallStack::AppendInternalAsyncSlice(uint64_t startT, AppendDistributeInfo(); cookies_.emplace_back(cookid); ids_.emplace_back(ids_.size()); + identifys_.emplace_back(nameIdentify + depth); return Size() - 1; } size_t CallStack::AppendInternalSlice(uint64_t startT, uint64_t durationNs, InternalTid internalTid, DataIndex cat, + uint16_t nameIdentify, DataIndex name, uint8_t depth, const std::optional& parentId) { AppendCommonInfo(startT, durationNs, internalTid); AppendCallStack(cat, name, depth, parentId); + identifys_.emplace_back(nameIdentify + depth); ids_.emplace_back(ids_.size()); cookies_.emplace_back(INVALID_UINT64); + AppendDistributeInfo(); return Size() - 1; } @@ -130,6 +168,20 @@ void CallStack::AppendCallStack(DataIndex cat, DataIndex name, uint8_t depth, st names_.emplace_back(name); depths_.emplace_back(depth); } +void CallStack::SetDistributeInfo(size_t index, + const std::string& chainId, + const std::string& spanId, + const std::string& parentSpanId, + const std::string& flag, + const std::string& args) +{ + chainIds_[index] = chainId; + spanIds_[index] = spanId; + parentSpanIds_[index] = parentSpanId; + flags_[index] = flag; + args_[index] = args; + argSet_[index] = INVALID_UINT32; +} void CallStack::AppendDistributeInfo(const std::string& chainId, const std::string& spanId, const std::string& parentSpanId, @@ -152,21 +204,12 @@ void CallStack::AppendDistributeInfo() args_.emplace_back(""); argSet_.emplace_back(INVALID_UINT32); } -void CallStack::AppendArgSet(uint32_t argSetId) -{ - chainIds_.emplace_back(""); - spanIds_.emplace_back(""); - parentSpanIds_.emplace_back(""); - flags_.emplace_back(""); - args_.emplace_back(""); - argSet_.emplace_back(argSetId); -} void CallStack::SetDuration(size_t index, uint64_t timestamp) { durs_[index] = timestamp - timeStamps_[index]; } -void CallStack::SetDurationAndArg(size_t index, uint64_t timestamp, uint32_t argSetId) +void CallStack::SetIrqDurAndArg(size_t index, uint64_t timestamp, uint32_t argSetId) { SetTimeStamp(index, timestamp); argSet_[index] = argSetId; @@ -176,6 +219,14 @@ void CallStack::SetTimeStamp(size_t index, uint64_t timestamp) timeStamps_[index] = timestamp; } +void CallStack::SetDepth(size_t index, uint8_t depth) +{ + depths_[index] = depth; +} +void CallStack::SetArgSetId(size_t index, uint32_t argSetId) +{ + argSet_[index] = argSetId; +} const std::deque>& CallStack::ParentIdData() const { return parentIds_; @@ -184,6 +235,10 @@ const std::deque& CallStack::CatsData() const { return cats_; } +const std::deque& CallStack::IdentifysData() const +{ + return identifys_; +} const std::deque& CallStack::NamesData() const { return names_; @@ -196,7 +251,7 @@ const std::deque& CallStack::Cookies() const { return cookies_; } -const std::deque& CallStack::CallIds() const +const std::deque& CallStack::CallIds() const { return callIds_; } @@ -319,11 +374,15 @@ size_t ThreadMeasureFilter::AppendNewFilter(uint64_t filterId, uint32_t nameInde return Size() - 1; } -size_t Instants::AppendInstantEventData(uint64_t timestamp, DataIndex nameIndex, int64_t internalTid) +size_t Instants::AppendInstantEventData(uint64_t timestamp, + DataIndex nameIndex, + int64_t internalTid, + int64_t wakeupFromInternalPid) { internalTids_.emplace_back(internalTid); timeStamps_.emplace_back(timestamp); NameIndexs_.emplace_back(nameIndex); + wakeupFromInternalPids_.emplace_back(wakeupFromInternalPid); return Size() - 1; } size_t LogInfo::AppendNewLogInfo(uint64_t seq, @@ -374,138 +433,216 @@ const std::deque& LogInfo::OriginTimeStamData() const return originTs_; } -size_t HeapInfo::AppendNewHeapInfo(uint64_t eventId, - uint32_t ipid, - uint32_t itid, - DataIndex eventType, - uint64_t timestamp, - uint64_t endTimestamp, - uint64_t duration, - uint64_t addr, - int64_t heapSize, - int64_t allHeapSize, - uint64_t currentSizeDur) -{ - eventIds_.emplace_back(eventId); +size_t NativeHook::AppendNewNativeHookData(uint64_t callChainId, + uint32_t ipid, + uint32_t itid, + std::string eventType, + DataIndex subType, + uint64_t timestamp, + uint64_t endTimestamp, + uint64_t duration, + uint64_t addr, + int64_t memSize, + int64_t allMemSize) +{ + callChainIds_.emplace_back(callChainId); ipids_.emplace_back(ipid); itids_.emplace_back(itid); eventTypes_.emplace_back(eventType); + subTypes_.emplace_back(subType); timeStamps_.emplace_back(timestamp); endTimestamps_.emplace_back(endTimestamp); durations_.emplace_back(duration); addrs_.emplace_back(addr); - heapSizes_.emplace_back(heapSize); - countHeapSizes_ += allHeapSize; - allHeapSizes_.emplace_back(countHeapSizes_); - currentSizeDurs_.emplace_back(currentSizeDur); + memSizes_.emplace_back(memSize); + if (eventType == ALLOC_EVET || eventType == FREE_EVENT) { + countHeapSizes_ += allMemSize; + allMemSizes_.emplace_back(countHeapSizes_); + } else if (eventType == MMAP_EVENT || eventType == MUNMAP_EVENT) { + countMmapSizes_ += allMemSize; + allMemSizes_.emplace_back(countMmapSizes_); + } + currentSizeDurs_.emplace_back(0); + lastCallerPathIndexs_.emplace_back(INVALID_UINT64); return Size() - 1; } -void HeapInfo::UpdateHeapDuration(size_t row, uint64_t endTimestamp) +void NativeHook::UpdateHeapDuration(size_t row, uint64_t endTimestamp) { endTimestamps_[row] = endTimestamp; durations_[row] = endTimestamp - timeStamps_[row]; } -void HeapInfo::UpdateCurrentSizeDur(size_t row, uint64_t nextStartTime) +void NativeHook::UpdateCurrentSizeDur(size_t row, uint64_t timeStamp) +{ + currentSizeDurs_[row] = timeStamp - timeStamps_[row]; +} +void NativeHook::UpdateMemMapSubType() +{ + if (addrToMmapTag_.Empty()) { + return; + } + for (auto i = 0; i < Size(); ++i) { + if (eventTypes_[i].compare(MMAP_EVENT) == 0) { + auto tagId = addrToMmapTag_.Find(addrs_[i], memSizes_[i]); + if (tagId != INVALID_UINT64) { + subTypes_[i] = tagId; + } + } + } +} +void NativeHook::UpdateAddrToMemMapSubType(uint64_t addr, int64_t size, uint64_t tagId) +{ + addrToMmapTag_.Insert(addr, size, tagId); +} +void NativeHook::UpdateLastCallerPathIndexs(std::map& callIdToLasLibId) { - if (row == 0) { + if (callIdToLasLibId.empty()) { return; } - if (nextStartTime > timeStamps_[--row]) { - currentSizeDurs_[row] = nextStartTime - timeStamps_[row]; + for (auto i = 0; i < Size(); ++i) { + auto symbolIt = callIdToLasLibId.find(callChainIds_[i]); + if (symbolIt != callIdToLasLibId.end()) { + lastCallerPathIndexs_[i] = symbolIt->second; + } else { + lastCallerPathIndexs_[i] = INVALID_UINT64; + } } } -const std::deque& HeapInfo::EventIds() const +const std::deque& NativeHook::CallChainIds() const { - return eventIds_; + return callChainIds_; } -const std::deque& HeapInfo::Ipids() const +const std::deque& NativeHook::Ipids() const { return ipids_; } -const std::deque& HeapInfo::Itids() const +const std::deque& NativeHook::Itids() const { return itids_; } -const std::deque& HeapInfo::EventTypes() const +const std::deque& NativeHook::EventTypes() const { return eventTypes_; } -const std::deque& HeapInfo::EndTimeStamps() const +const std::deque& NativeHook::SubTypes() const +{ + return subTypes_; +} +const std::deque& NativeHook::EndTimeStamps() const { return endTimestamps_; } -const std::deque& HeapInfo::Durations() const +const std::deque& NativeHook::Durations() const { return durations_; } -const std::deque& HeapInfo::Addrs() const +const std::deque& NativeHook::Addrs() const { return addrs_; } -const std::deque& HeapInfo::HeapSizes() const +const std::deque& NativeHook::MemSizes() const { - return heapSizes_; + return memSizes_; } -const std::deque& HeapInfo::AllHeapSizes() const +const std::deque& NativeHook::AllMemSizes() const { - return allHeapSizes_; + return allMemSizes_; } -const std::deque& HeapInfo::CurrentSizeDurs() const +const std::deque& NativeHook::CurrentSizeDurs() const { return currentSizeDurs_; } - -size_t HeapFrameInfo::AppendNewHeapFrameInfo(uint64_t eventId, - uint64_t depth, - DataIndex ip, - DataIndex sp, - DataIndex symbolName, - DataIndex filePath, - DataIndex offset, - uint64_t symbolOffset) +const std::deque& NativeHook::LastCallerPathIndexs() const { - eventIds_.emplace_back(eventId); - depths_.emplace_back(depth); + return lastCallerPathIndexs_; +} +size_t NativeHookFrame::AppendNewNativeHookFrame(uint64_t callChainId, + uint64_t depth, + uint64_t ip, + uint64_t sp, + DataIndex symbolName, + DataIndex filePath, + uint64_t offset, + uint64_t symbolOffset) +{ + callChainIds_.emplace_back(callChainId); ips_.emplace_back(ip); sps_.emplace_back(sp); + depths_.emplace_back(depth); symbolNames_.emplace_back(symbolName); filePaths_.emplace_back(filePath); offsets_.emplace_back(offset); symbolOffsets_.emplace_back(symbolOffset); return Size() - 1; } -const std::deque& HeapFrameInfo::EventIds() const +void NativeHookFrame::UpdateSymbolIdToNameMap(uint64_t originSymbolId, uint64_t symbolId) +{ + symbolIdToSymbolName_.insert(std::make_pair(originSymbolId, symbolId)); +} + +void NativeHookFrame::UpdateSymbolId() +{ + if (symbolIdToSymbolName_.empty()) { + return; + } + for (auto i = 0; i < Size(); ++i) { + auto symbolIt = symbolIdToSymbolName_.find(symbolNames_[i]); + if (symbolIt != symbolIdToSymbolName_.end()) { + symbolNames_[i] = symbolIt->second; + } + } +} +void NativeHookFrame::UpdateFileId(std::map& filePathIdToFilePathName) { - return eventIds_; + if (filePathIdToFilePathName.empty()) { + return; + } + for (auto i = 0; i < Size(); ++i) { + auto symbolIt = filePathIdToFilePathName.find(filePaths_[i]); + if (symbolIt != filePathIdToFilePathName.end()) { + filePaths_[i] = symbolIt->second; + } + } +} +void NativeHookFrame::UpdateVaddrs(std::deque& vaddrs) +{ + vaddrs_.assign(vaddrs.begin(), vaddrs.end()); +} +const std::deque& NativeHookFrame::CallChainIds() const +{ + return callChainIds_; } -const std::deque& HeapFrameInfo::Depths() const +const std::deque& NativeHookFrame::Depths() const { return depths_; } -const std::deque& HeapFrameInfo::Ips() const +const std::deque& NativeHookFrame::Ips() const { return ips_; } -const std::deque& HeapFrameInfo::Sps() const +const std::deque& NativeHookFrame::Sps() const { return sps_; } -const std::deque& HeapFrameInfo::SymbolNames() const +const std::deque& NativeHookFrame::SymbolNames() const { return symbolNames_; } -const std::deque& HeapFrameInfo::FilePaths() const +const std::deque& NativeHookFrame::FilePaths() const { return filePaths_; } -const std::deque& HeapFrameInfo::Offsets() const +const std::deque& NativeHookFrame::Offsets() const { return offsets_; } -const std::deque& HeapFrameInfo::SymbolOffsets() const +const std::deque& NativeHookFrame::SymbolOffsets() const { return symbolOffsets_; } +const std::deque& NativeHookFrame::Vaddrs() const +{ + return vaddrs_; +} size_t Hidump::AppendNewHidumpInfo(uint64_t timestamp, uint32_t fps) { @@ -517,6 +654,162 @@ const std::deque& Hidump::Fpss() const { return fpss_; } + +size_t PerfCallChain::AppendNewPerfCallChain(uint64_t sampleId, + uint64_t callChainId, + uint64_t vaddrInFile, + uint64_t fileId, + uint64_t symbolId) +{ + ids_.emplace_back(Size()); + sampleIds_.emplace_back(sampleId); + callChainIds_.emplace_back(callChainId); + vaddrInFiles_.emplace_back(vaddrInFile); + fileIds_.emplace_back(fileId); + symbolIds_.emplace_back(symbolId); + names_.emplace_back(""); + return Size() - 1; +} +const std::deque& PerfCallChain::SampleIds() const +{ + return sampleIds_; +} +const std::deque& PerfCallChain::CallChainIds() const +{ + return callChainIds_; +} +const std::deque& PerfCallChain::VaddrInFiles() const +{ + return vaddrInFiles_; +} +const std::deque& PerfCallChain::FileIds() const +{ + return fileIds_; +} +const std::deque& PerfCallChain::SymbolIds() const +{ + return symbolIds_; +} + +const std::deque& PerfCallChain::Names() const +{ + return names_; +} +void PerfCallChain::SetName(uint64_t index, const std::string& name) +{ + names_[index] = name; +} +size_t PerfFiles::AppendNewPerfFiles(uint64_t fileIds, uint32_t serial, DataIndex symbols, DataIndex filePath) +{ + ids_.emplace_back(Size()); + fileIds_.emplace_back(fileIds); + serials_.emplace_back(serial); + symbols_.emplace_back(symbols); + filePaths_.emplace_back(filePath); + return Size() - 1; +} +const std::deque& PerfFiles::FileIds() const +{ + return fileIds_; +} + +const std::deque& PerfFiles::Serials() const +{ + return serials_; +} +const std::deque& PerfFiles::Symbols() const +{ + return symbols_; +} +const std::deque& PerfFiles::FilePaths() const +{ + return filePaths_; +} + +size_t PerfSample::AppendNewPerfSample(uint64_t sampleId, + uint64_t timestamp, + uint64_t tid, + uint64_t eventCount, + uint64_t eventTypeId, + uint64_t timestampTrace, + uint64_t cpuId, + uint64_t threadState) +{ + ids_.emplace_back(Size()); + sampleIds_.emplace_back(sampleId); + timeStamps_.emplace_back(timestamp); + tids_.emplace_back(tid); + eventCounts_.emplace_back(eventCount); + eventTypeIds_.emplace_back(eventTypeId); + timestampTraces_.emplace_back(timestampTrace); + cpuIds_.emplace_back(cpuId); + threadStates_.emplace_back(threadState); + return Size() - 1; +} +const std::deque& PerfSample::SampleIds() const +{ + return sampleIds_; +} +const std::deque& PerfSample::Tids() const +{ + return tids_; +} +const std::deque& PerfSample::EventCounts() const +{ + return eventCounts_; +} +const std::deque& PerfSample::EventTypeIds() const +{ + return eventTypeIds_; +} +const std::deque& PerfSample::TimestampTraces() const +{ + return timestampTraces_; +} +const std::deque& PerfSample::CpuIds() const +{ + return cpuIds_; +} +const std::deque& PerfSample::ThreadStates() const +{ + return threadStates_; +} + +size_t PerfThread::AppendNewPerfThread(uint64_t pid, uint64_t tid, DataIndex threadName) +{ + ids_.emplace_back(Size()); + pids_.emplace_back(pid); + tids_.emplace_back(tid); + threadNames_.emplace_back(threadName); + return Size() - 1; +} +const std::deque& PerfThread::Pids() const +{ + return pids_; +} +const std::deque& PerfThread::Tids() const +{ + return tids_; +} +const std::deque& PerfThread::ThreadNames() const +{ + return threadNames_; +} +size_t PerfReport::AppendNewPerfReport(DataIndex type, DataIndex value) +{ + ids_.emplace_back(Size()); + types_.emplace_back(type); + values_.emplace_back(value); + return Size() - 1; +} +const std::deque& PerfReport::Types() const +{ + return types_; +} +const std::deque& PerfReport::Values() const +{ + return values_; +} size_t ProcessMeasureFilter::AppendNewFilter(uint64_t id, DataIndex name, uint32_t internalPid) { internalPids_.emplace_back(internalPid); @@ -577,6 +870,12 @@ StatAndInfo::StatAndInfo() statCount_[i][j] = 0; } } + clockid2ClockNameMap_ = { + {TS_CLOCK_UNKNOW, "unknown"}, {TS_CLOCK_BOOTTIME, "boottime"}, + {TS_CLOCK_REALTIME, "realtime"}, {TS_CLOCK_REALTIME_COARSE, "realtime_corse"}, + {TS_MONOTONIC, "monotonic"}, {TS_MONOTONIC_COARSE, "monotonic-coarse"}, + {TS_MONOTONIC_RAW, "monotonic-raw"}, + }; } void StatAndInfo::IncreaseStat(SupportedTraceEventType eventType, StatType type) { @@ -602,6 +901,7 @@ const StatSeverityLevel& StatAndInfo::GetSeverity(SupportedTraceEventType eventT { return statSeverity_[eventType][type]; } + uint64_t SymbolsData::Size() const { return addrs_.size(); @@ -665,6 +965,8 @@ void MetaData::SetTraceDataSize(uint64_t dataSize) void(time(&rawtime)); timeinfo = localtime(&rawtime); values_[METADATA_ITEM_PARSERTIME] = asctime(timeinfo); + // sometimes there will be a extra \n at last + values_[METADATA_ITEM_PARSERTIME].pop_back(); } void MetaData::SetTraceDuration(uint64_t dur) { @@ -683,13 +985,974 @@ DataIndex DataDict::GetStringIndex(std::string_view str) auto hashValue = hashFun(str); auto itor = dataDictInnerMap_.find(hashValue); if (itor != dataDictInnerMap_.end()) { - TS_ASSERT(std::string_view(dataDict_[itor->second]) == str); return itor->second; } + mutex_.lock(); dataDict_.emplace_back(std::string(str)); DataIndex stringIdentity = dataDict_.size() - 1; dataDictInnerMap_.emplace(hashValue, stringIdentity); + mutex_.unlock(); return stringIdentity; } +DataIndex DataDict::GetStringIndexNoWrite(std::string_view str) const +{ + auto hashValue = hashFun(str); + auto itor = dataDictInnerMap_.find(hashValue); + if (itor != dataDictInnerMap_.end()) { + return itor->second; + } + return INVALID_UINT64; +} +size_t CpuUsageDetailData::AppendNewData(uint64_t newTimeStamp, + uint64_t dur, + double totalLoad, + double userLoad, + double systemLoad, + int64_t threads) +{ + timeStamps_.emplace_back(newTimeStamp); + durs_.emplace_back(dur); + totalLoad_.emplace_back(totalLoad); + userLoad_.emplace_back(userLoad); + systemLoad_.emplace_back(systemLoad); + threads_.emplace_back(threads); + return Size() - 1; +} +const std::deque& CpuUsageDetailData::Durs() const +{ + return durs_; +} +const std::deque& CpuUsageDetailData::TotalLoad() const +{ + return totalLoad_; +} +const std::deque& CpuUsageDetailData::UserLoad() const +{ + return userLoad_; +} +const std::deque& CpuUsageDetailData::SystemLoad() const +{ + return systemLoad_; +} +const std::deque& CpuUsageDetailData::Threads() const +{ + return threads_; +} +size_t LiveProcessDetailData::AppendNewData(uint64_t newTimeStamp, + uint64_t dur, + int32_t processID, + std::string processName, + int32_t parentProcessID, + int32_t uid, + std::string userName, + double cpuUsage, + int32_t pssInfo, + uint64_t cpuTime, + int32_t threads, + int64_t diskWrites, + int64_t diskReads) +{ + timeStamps_.emplace_back(newTimeStamp); + durs_.emplace_back(dur); + processID_.emplace_back(processID); + processName_.emplace_back(processName); + parentProcessID_.emplace_back(parentProcessID); + uid_.emplace_back(uid); + userName_.emplace_back(userName); + cpuUsage_.emplace_back(cpuUsage); + pssInfo_.emplace_back(pssInfo); + threads_.emplace_back(threads); + diskWrites_.emplace_back(diskWrites); + diskReads_.emplace_back(diskReads); + cpuTimes_.emplace_back(cpuTime); + return Size() - 1; +} +const std::deque& LiveProcessDetailData::Durs() const +{ + return durs_; +} +const std::deque& LiveProcessDetailData::ProcessID() const +{ + return processID_; +} +const std::deque& LiveProcessDetailData::ProcessName() const +{ + return processName_; +} +const std::deque& LiveProcessDetailData::ParentProcessID() const +{ + return parentProcessID_; +} +const std::deque& LiveProcessDetailData::Uid() const +{ + return uid_; +} +const std::deque& LiveProcessDetailData::UserName() const +{ + return userName_; +} +const std::deque& LiveProcessDetailData::CpuUsage() const +{ + return cpuUsage_; +} +const std::deque& LiveProcessDetailData::PssInfo() const +{ + return pssInfo_; +} +const std::deque& LiveProcessDetailData::Threads() const +{ + return threads_; +} +const std::deque& LiveProcessDetailData::DiskWrites() const +{ + return diskWrites_; +} +const std::deque& LiveProcessDetailData::DiskReads() const +{ + return diskReads_; +} + +const std::deque& LiveProcessDetailData::CpuTimes() const +{ + return cpuTimes_; +} + +size_t NetDetailData::AppendNewNetData(uint64_t newTimeStamp, + uint64_t tx, + uint64_t rx, + uint64_t dur, + double rxSpeed, + double txSpeed, + uint64_t packetIn, + double packetInSec, + uint64_t packetOut, + double packetOutSec, + const std::string& netType) +{ + timeStamps_.emplace_back(newTimeStamp); + txs_.emplace_back(tx); + rxs_.emplace_back(rx); + durs_.emplace_back(dur); + txSpeeds_.emplace_back(txSpeed); + rxSpeeds_.emplace_back(rxSpeed); + netTypes_.emplace_back(netType); + packetIn_.emplace_back(packetIn); + packetInSec_.emplace_back(packetInSec); + packetOut_.emplace_back(packetOut); + packetOutSec_.emplace_back(packetOutSec); + + return Size() - 1; +} +const std::deque& NetDetailData::Durs() const +{ + return durs_; +} +const std::deque& NetDetailData::RxSpeed() const +{ + return rxSpeeds_; +} +const std::deque& NetDetailData::TxSpeed() const +{ + return txSpeeds_; +} +const std::deque& NetDetailData::NetTypes() const +{ + return netTypes_; +} +const std::deque& NetDetailData::RxDatas() const +{ + return rxs_; +} +const std::deque& NetDetailData::TxDatas() const +{ + return txs_; +} +const std::deque& NetDetailData::PacketIn() const +{ + return packetIn_; +} +const std::deque& NetDetailData::PacketInSec() const +{ + return packetInSec_; +} +const std::deque& NetDetailData::PacketOut() const +{ + return packetOut_; +} +const std::deque& NetDetailData::PacketOutSec() const +{ + return packetOutSec_; +} + +void DiskIOData::AppendNewData(uint64_t ts, + uint64_t dur, + uint64_t rd, + uint64_t wr, + uint64_t rdPerSec, + uint64_t wrPerSec, + double rdCountPerSec, + double wrCountPerSec, + uint64_t rdCount, + uint64_t wrCount) +{ + timeStamps_.emplace_back(ts); + durs_.emplace_back(dur); + rdDatas_.emplace_back(rd); + wrDatas_.emplace_back(wr); + rdPerSec_.emplace_back(rdPerSec); + wrPerSec_.emplace_back(wrPerSec); + rdCountPerSec_.emplace_back(rdCountPerSec); + wrCountPerSec_.emplace_back(wrCountPerSec); + rdCountDatas_.emplace_back(rdCount); + wrCountDatas_.emplace_back(wrCount); +} +const std::deque& DiskIOData::Durs() const +{ + return durs_; +} +const std::deque& DiskIOData::RdDatas() const +{ + return rdDatas_; +} +const std::deque& DiskIOData::WrDatas() const +{ + return wrDatas_; +} +const std::deque& DiskIOData::RdSpeedDatas() const +{ + return rdPerSec_; +} +const std::deque& DiskIOData::WrSpeedDatas() const +{ + return wrPerSec_; +} + +const std::deque& DiskIOData::RdCountPerSecDatas() const +{ + return rdCountPerSec_; +} +const std::deque& DiskIOData::WrCountPerSecDatas() const +{ + return wrCountPerSec_; +} +const std::deque& DiskIOData::RdCountDatas() const +{ + return rdCountDatas_; +} +const std::deque& DiskIOData::WrCountDatas() const +{ + return wrCountDatas_; +} + +size_t FileSystemSample::AppendNewData(uint64_t callChainId, + uint16_t type, + uint32_t ipid, + uint32_t itid, + uint64_t startTs, + uint64_t endTs, + uint64_t dur, + DataIndex returnValue, + DataIndex errorCode, + size_t size, + int32_t fd, + DataIndex fileId, + DataIndex firstArgument, + DataIndex secondArgument, + DataIndex thirdArgument, + DataIndex fourthArgument) +{ + callChainIds_.emplace_back(callChainId); + types_.emplace_back(type); + ipids_.emplace_back(ipid); + itids_.emplace_back(itid); + startTs_.emplace_back(startTs); + endTs_.emplace_back(endTs); + durs_.emplace_back(dur); + returnValues_.emplace_back(returnValue); + errorCodes_.emplace_back(errorCode); + fds_.emplace_back(fd); + fileIds_.emplace_back(fileId); + Sizes_.emplace_back(size); + firstArguments_.emplace_back(firstArgument); + secondArguments_.emplace_back(secondArgument); + thirdArguments_.emplace_back(thirdArgument); + fourthArguments_.emplace_back(fourthArgument); + ids_.emplace_back(Size()); + return Size() - 1; +} +const std::deque& FileSystemSample::CallChainIds() const +{ + return callChainIds_; +} +const std::deque& FileSystemSample::Types() const +{ + return types_; +} +const std::deque& FileSystemSample::Ipids() const +{ + return ipids_; +} +const std::deque& FileSystemSample::Itids() const +{ + return itids_; +} +const std::deque& FileSystemSample::StartTs() const +{ + return startTs_; +} +const std::deque& FileSystemSample::EndTs() const +{ + return endTs_; +} +const std::deque& FileSystemSample::Durs() const +{ + return durs_; +} +const std::deque& FileSystemSample::ReturnValues() const +{ + return returnValues_; +} +const std::deque& FileSystemSample::ErrorCodes() const +{ + return errorCodes_; +} +const std::deque& FileSystemSample::Fds() const +{ + return fds_; +} +const std::deque& FileSystemSample::FileIds() const +{ + return fileIds_; +} +const std::deque& FileSystemSample::Sizes() const +{ + return Sizes_; +} +const std::deque& FileSystemSample::FirstArguments() const +{ + return firstArguments_; +} +const std::deque& FileSystemSample::SecondArguments() const +{ + return secondArguments_; +} +const std::deque& FileSystemSample::ThirdArguments() const +{ + return thirdArguments_; +} +const std::deque& FileSystemSample::FourthArguments() const +{ + return fourthArguments_; +} + +size_t PagedMemorySampleData::AppendNewData(uint64_t callChainId, + uint16_t type, + uint32_t ipid, + uint64_t startTs, + uint64_t endTs, + uint64_t dur, + size_t size, + DataIndex addr, + uint32_t itid) +{ + callChainIds_.emplace_back(callChainId); + types_.emplace_back(type); + ipids_.emplace_back(ipid); + startTs_.emplace_back(startTs); + endTs_.emplace_back(endTs); + durs_.emplace_back(dur); + Sizes_.emplace_back(size); + addrs_.emplace_back(addr); + itids_.emplace_back(itid); + ids_.emplace_back(Size()); + return Size() - 1; +} +const std::deque& PagedMemorySampleData::CallChainIds() const +{ + return callChainIds_; +} +const std::deque& PagedMemorySampleData::Types() const +{ + return types_; +} +const std::deque& PagedMemorySampleData::Ipids() const +{ + return ipids_; +} +const std::deque& PagedMemorySampleData::Itids() const +{ + return itids_; +} +const std::deque& PagedMemorySampleData::StartTs() const +{ + return startTs_; +} +const std::deque& PagedMemorySampleData::EndTs() const +{ + return endTs_; +} +const std::deque& PagedMemorySampleData::Durs() const +{ + return durs_; +} +const std::deque& PagedMemorySampleData::Sizes() const +{ + return Sizes_; +} +const std::deque& PagedMemorySampleData::Addr() const +{ + return addrs_; +} + +size_t EbpfCallStackData::AppendNewData(uint64_t callChainId, + uint32_t depth, + uint64_t ip, + uint64_t symbolId, + uint64_t filePathId) +{ + callChainIds_.emplace_back(callChainId); + depths_.emplace_back(depth); + ips_.emplace_back(ip); + symbolIds_.emplace_back(symbolId); + filePathIds_.emplace_back(filePathId); + ids_.emplace_back(Size()); + return Size() - 1; +} +const std::deque& EbpfCallStackData::CallChainIds() const +{ + return callChainIds_; +} +const std::deque& EbpfCallStackData::Depths() const +{ + return depths_; +} +const std::deque& EbpfCallStackData::Ips() const +{ + return ips_; +} +const std::deque& EbpfCallStackData::SymbolIds() const +{ + return symbolIds_; +} +const std::deque& EbpfCallStackData::FilePathIds() const +{ + return filePathIds_; +} +#if WITH_EBPF_HELP +size_t EbpfProcessMaps::AppendNewData(uint64_t start, + uint64_t end, + uint32_t offset, + uint32_t pid, + uint32_t fileNameLen, + uint64_t fileNameIndex) +{ + starts_.emplace_back(start); + ends_.emplace_back(end); + offsets_.emplace_back(offset); + pids_.emplace_back(pid); + fileNameLens_.emplace_back(fileNameLen); + fileNameIndexs_.emplace_back(fileNameIndex); + ids_.emplace_back(Size()); + return Size() - 1; +} + +const std::deque& EbpfProcessMaps::Starts() const +{ + return starts_; +} +const std::deque& EbpfProcessMaps::Ends() const +{ + return ends_; +} +const std::deque& EbpfProcessMaps::Offsets() const +{ + return offsets_; +} +const std::deque& EbpfProcessMaps::Pids() const +{ + return pids_; +} +const std::deque& EbpfProcessMaps::FileNameLens() const +{ + return fileNameLens_; +} +const std::deque& EbpfProcessMaps::FileNameIndexs() const +{ + return fileNameIndexs_; +} + +size_t EbpfElf::AppendNewData(uint64_t elfId, + uint64_t textVaddr, + uint32_t textOffset, + uint32_t strTabLen, + uint32_t symTabLen, + uint32_t fileNameLen, + uint32_t symEntLen, + uint64_t fileNameIndex) +{ + elfIds_.emplace_back(elfId); + textVaddrs_.emplace_back(textVaddr); + textOffsets_.emplace_back(textOffset); + strTabLens_.emplace_back(strTabLen); + symTabLens_.emplace_back(symTabLen); + fileNameLens_.emplace_back(fileNameLen); + symEntLens_.emplace_back(symEntLen); + fileNameIndexs_.emplace_back(fileNameIndex); + ids_.emplace_back(Size()); + return Size() - 1; +} +const std::deque& EbpfElf::ElfIds() const +{ + return elfIds_; +} +const std::deque& EbpfElf::TextVaddrs() const +{ + return textVaddrs_; +} +const std::deque& EbpfElf::TextOffsets() const +{ + return textOffsets_; +} +const std::deque& EbpfElf::StrTabLens() const +{ + return strTabLens_; +} +const std::deque& EbpfElf::SymTabLens() const +{ + return symTabLens_; +} +const std::deque& EbpfElf::FileNameLens() const +{ + return fileNameLens_; +} +const std::deque& EbpfElf::SymEntLens() const +{ + return symEntLens_; +} +const std::deque& EbpfElf::FileNameIndexs() const +{ + return fileNameIndexs_; +} + +size_t EbpfElfSymbol::AppendNewData(uint64_t elfId, uint32_t stName, uint64_t stValue, uint64_t stSize) +{ + elfIds_.emplace_back(elfId); + stNames_.emplace_back(stName); + stValues_.emplace_back(stValue); + stSizes_.emplace_back(stSize); + ids_.emplace_back(Size()); + return Size() - 1; +} +const std::deque& EbpfElfSymbol::ElfIds() const +{ + return elfIds_; +} +const std::deque& EbpfElfSymbol::StNames() const +{ + return stNames_; +} +const std::deque& EbpfElfSymbol::StValues() const +{ + return stValues_; +} +const std::deque& EbpfElfSymbol::StSizes() const +{ + return stSizes_; +} +#endif +uint32_t AppNames::AppendAppName(uint8_t flags, DataIndex eventSource, DataIndex appName) +{ + flags_.push_back(flags); + appNames_.push_back(eventSource); + keyNames_.push_back(appName); + ids_.push_back(keyNames_.size() - 1); + return Size() - 1; +} +const std::deque& AppNames::Falgs() const +{ + return flags_; +} +const std::deque& AppNames::EventSourceId() const +{ + return appNames_; +} +const std::deque& AppNames::AppName() const +{ + return keyNames_; +} + +void SysEventMeasureData::AppendData(uint64_t serial, + uint64_t ts, + uint32_t nameId, + uint32_t keyId, + int32_t type, + double numericValue, + DataIndex stringValue) +{ + serial_.emplace_back(serial); + ts_.emplace_back(ts); + nameFilterIds_.emplace_back(nameId); + appKeyFilterIds_.emplace_back(keyId); + types_.emplace_back(type); + numValues_.emplace_back(numericValue); + stringValues_.emplace_back(stringValue); + ids_.push_back(rowCount_); + rowCount_++; +} +const std::deque& SysEventMeasureData::Serial() const +{ + return serial_; +} +const std::deque& SysEventMeasureData::Ts() const +{ + return ts_; +} +const std::deque& SysEventMeasureData::NameFilterId() const +{ + return nameFilterIds_; +} +const std::deque& SysEventMeasureData::AppKeyFilterId() const +{ + return appKeyFilterIds_; +} +const std::deque& SysEventMeasureData::Type() const +{ + return types_; +} +const std::deque& SysEventMeasureData::NumValue() const +{ + return numValues_; +} +const std::deque& SysEventMeasureData::StringValue() const +{ + return stringValues_; +} +void DeviceStateData::AppendNewData(int32_t brightness, + int32_t btState, + int32_t location, + int32_t wifi, + int32_t streamDefault, + int32_t voiceCall, + int32_t music, + int32_t streamRing, + int32_t media, + int32_t voiceAssistant, + int32_t system, + int32_t alarm, + int32_t notification, + int32_t btSco, + int32_t enforcedAudible, + int32_t streamDtmf, + int32_t streamTts, + int32_t accessibility, + int32_t recording, + int32_t streamAll) +{ + brightness_.emplace_back(brightness); + btStates_.emplace_back(btState); + locations_.emplace_back(location); + wifis_.emplace_back(wifi); + streamDefaults_.emplace_back(streamDefault); + voiceCalls_.emplace_back(voiceCall); + musics_.emplace_back(music); + streamRings_.emplace_back(streamRing); + medias_.emplace_back(media); + voiceAssistants_.emplace_back(voiceAssistant); + systems_.emplace_back(system); + alarms_.emplace_back(alarm); + notifications_.emplace_back(notification); + btScos_.emplace_back(btSco); + enforcedAudibles_.emplace_back(enforcedAudible); + streamDtmfs_.emplace_back(streamDtmf); + streamTts_.emplace_back(streamTts); + accessibilitys_.emplace_back(accessibility); + recordings_.emplace_back(recording); + streamAlls_.emplace_back(streamAll); + ids_.push_back(rowCounts_); + rowCounts_++; +} +const std::deque& DeviceStateData::Brightness() const +{ + return brightness_; +} +const std::deque& DeviceStateData::BtState() const +{ + return btStates_; +} +const std::deque& DeviceStateData::Location() const +{ + return locations_; +} +const std::deque& DeviceStateData::Wifi() const +{ + return wifis_; +} +const std::deque& DeviceStateData::StreamDefault() const +{ + return streamDefaults_; +} +const std::deque& DeviceStateData::VoiceCall() const +{ + return voiceCalls_; +} +const std::deque& DeviceStateData::Music() const +{ + return musics_; +} +const std::deque& DeviceStateData::StreamRing() const +{ + return streamRings_; +} +const std::deque& DeviceStateData::Media() const +{ + return medias_; +} +const std::deque& DeviceStateData::VoiceAssistant() const +{ + return voiceAssistants_; +} +const std::deque& DeviceStateData::System() const +{ + return systems_; +} +const std::deque& DeviceStateData::Alarm() const +{ + return alarms_; +} +const std::deque& DeviceStateData::Notification() const +{ + return notifications_; +} +const std::deque& DeviceStateData::BtSco() const +{ + return btScos_; +} +const std::deque& DeviceStateData::EnforcedAudible() const +{ + return enforcedAudibles_; +} +const std::deque& DeviceStateData::StreamDtmf() const +{ + return streamDtmfs_; +} +const std::deque& DeviceStateData::StreamTts() const +{ + return streamTts_; +} +const std::deque& DeviceStateData::Accessibility() const +{ + return accessibilitys_; +} +const std::deque& DeviceStateData::Recording() const +{ + return recordings_; +} +const std::deque& DeviceStateData::StreamAll() const +{ + return streamAlls_; +} +void TraceConfigData::AppendNewData(std::string traceSource, std::string key, std::string value) +{ + traceSource_.emplace_back(traceSource); + key_.emplace_back(key); + value_.emplace_back(value); + ids_.push_back(rowCounts_); + rowCounts_++; +} +const std::deque& TraceConfigData::TraceSource() const +{ + return traceSource_; +} +const std::deque& TraceConfigData::Key() const +{ + return key_; +} +const std::deque& TraceConfigData::Value() const +{ + return value_; +} +void SmapsData::AppendNewData(uint64_t timeStamp, + std::string startAddr, + std::string endAddr, + uint64_t dirty, + uint64_t swapper, + uint64_t rss, + uint64_t pss, + uint64_t size, + double reside, + DataIndex protectionId, + DataIndex pathId) +{ + smapTimeStamps_.emplace_back(timeStamp); + startAddrs_.emplace_back(startAddr); + endAddrs_.emplace_back(endAddr); + dirtys_.emplace_back(dirty); + swappers_.emplace_back(swapper); + rss_.emplace_back(rss); + pss_.emplace_back(pss); + sizes_.emplace_back(size); + resides_.emplace_back(reside); + protectionIds_.emplace_back(protectionId); + pathIds_.emplace_back(pathId); + ids_.push_back(rowCount_); + rowCount_++; +} +const std::deque& SmapsData::TimeStamps() const +{ + return timeStamps_; +} +const std::deque& SmapsData::StartAddrs() const +{ + return startAddrs_; +} +const std::deque& SmapsData::EndAddrs() const +{ + return endAddrs_; +} +const std::deque& SmapsData::Dirtys() const +{ + return dirtys_; +} +const std::deque& SmapsData::Swappers() const +{ + return swappers_; +} +const std::deque& SmapsData::Rss() const +{ + return rss_; +} +const std::deque& SmapsData::Pss() const +{ + return pss_; +} +const std::deque& SmapsData::Sizes() const +{ + return sizes_; +} +const std::deque& SmapsData::Resides() const +{ + return resides_; +} +const std::deque& SmapsData::ProtectionIds() const +{ + return protectionIds_; +} +const std::deque& SmapsData::PathIds() const +{ + return pathIds_; +} +void BioLatencySampleData::AppendNewData(uint64_t callChainId, + uint64_t type, + uint64_t ipid, + uint64_t itid, + uint64_t startTs, + uint64_t endTs, + uint64_t latencyDur, + uint32_t tier, + uint64_t size, + uint64_t blockNumber, + uint64_t filePathId, + uint64_t durPer4k) +{ + callChainIds_.emplace_back(callChainId); + types_.emplace_back(type); + ipids_.emplace_back(ipid); + itids_.emplace_back(itid); + startTs_.emplace_back(startTs); + endTs_.emplace_back(endTs); + latencyDurs_.emplace_back(latencyDur); + tiers_.emplace_back(tier); + sizes_.emplace_back(size); + blockNumbers_.emplace_back(blockNumber); + filePathIds_.emplace_back(filePathId); + durPer4ks_.emplace_back(durPer4k); + ids_.emplace_back(rowCount_); + rowCount_++; +} +const std::deque& BioLatencySampleData::CallChainIds() const +{ + return callChainIds_; +} +const std::deque& BioLatencySampleData::Types() const +{ + return types_; +} +const std::deque& BioLatencySampleData::Ipids() const +{ + return ipids_; +} +const std::deque& BioLatencySampleData::Itids() const +{ + return itids_; +} +const std::deque& BioLatencySampleData::StartTs() const +{ + return startTs_; +} +const std::deque& BioLatencySampleData::EndTs() const +{ + return endTs_; +} +const std::deque& BioLatencySampleData::LatencyDurs() const +{ + return latencyDurs_; +} +const std::deque& BioLatencySampleData::Tiers() const +{ + return tiers_; +} +const std::deque& BioLatencySampleData::Sizes() const +{ + return sizes_; +} +const std::deque& BioLatencySampleData::BlockNumbers() const +{ + return blockNumbers_; +} +const std::deque& BioLatencySampleData::FilePathIds() const +{ + return filePathIds_; +} +const std::deque& BioLatencySampleData::DurPer4k() const +{ + return durPer4ks_; +} +DataSourceClockIdData::DataSourceClockIdData() + : dataSource2PluginNameMap_({{DATA_SOURCE_TYPE_TRACE, "ftrace-plugin"}, + {DATA_SOURCE_TYPE_MEM, "memory-plugin"}, + {DATA_SOURCE_TYPE_HILOG, "hilog-plugin"}, + {DATA_SOURCE_TYPE_ALLOCATION, "nativehook"}, + {DATA_SOURCE_TYPE_FPS, "hidump-plugin"}, + {DATA_SOURCE_TYPE_NETWORK, "network-plugin"}, + {DATA_SOURCE_TYPE_DISKIO, "diskio-plugin"}, + {DATA_SOURCE_TYPE_CPU, "cpu-plugin"}, + {DATA_SOURCE_TYPE_PROCESS, "process-plugin"}, + {DATA_SOURCE_TYPE_HISYSEVENT, "hisysevent-plugin"}}), + dataSource2ClockIdMap_({{DATA_SOURCE_TYPE_TRACE, TS_CLOCK_UNKNOW}, + {DATA_SOURCE_TYPE_MEM, TS_CLOCK_UNKNOW}, + {DATA_SOURCE_TYPE_HILOG, TS_CLOCK_UNKNOW}, + {DATA_SOURCE_TYPE_ALLOCATION, TS_CLOCK_UNKNOW}, + {DATA_SOURCE_TYPE_FPS, TS_CLOCK_UNKNOW}, + {DATA_SOURCE_TYPE_NETWORK, TS_CLOCK_UNKNOW}, + {DATA_SOURCE_TYPE_DISKIO, TS_CLOCK_UNKNOW}, + {DATA_SOURCE_TYPE_CPU, TS_CLOCK_UNKNOW}, + {DATA_SOURCE_TYPE_PROCESS, TS_CLOCK_UNKNOW}, + {DATA_SOURCE_TYPE_HISYSEVENT, TS_CLOCK_UNKNOW}}) +{ +} + +void DataSourceClockIdData::Finish() +{ + for (auto i = dataSource2ClockIdMap_.begin(); i != dataSource2ClockIdMap_.end(); i++) { + if (i->second) { // ignore the empty datasource, for which the clockid is default TS_CLOCK_UNKNOW 0 + dataSourceNames_.emplace_back(dataSource2PluginNameMap_.at(i->first)); + clockIds_.emplace_back(i->second); + } + } +} +void DataSourceClockIdData::SetDataSourceClockId(DataSourceType source, uint32_t id) +{ + dataSource2ClockIdMap_.at(source) = id; +} } // namespace TraceStdtype } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_data/trace_stdtype.h b/host/trace_streamer/src/trace_data/trace_stdtype.h old mode 100644 new mode 100755 index 2ecd2360d011d16ffef948924ae66467304942d2..64985f74dd9f82b16f59dae446610e987154b74e --- a/host/trace_streamer/src/trace_data/trace_stdtype.h +++ b/host/trace_streamer/src/trace_data/trace_stdtype.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include "cfg/trace_streamer_config.h" +#include "double_map.h" #include "log.h" #include "ts_common.h" @@ -41,7 +43,7 @@ public: { return std::max(timeStamps_.size(), ids_.size()); } - const std::deque& IdsData() const + const std::deque& IdsData() const { return ids_; } @@ -53,16 +55,17 @@ public: { return internalTids_; } - void Clear() + virtual void Clear() { internalTids_.clear(); timeStamps_.clear(); ids_.clear(); } + public: std::deque internalTids_ = {}; std::deque timeStamps_ = {}; - std::deque ids_ = {}; + std::deque ids_ = {}; }; class CpuCacheBase { @@ -72,27 +75,31 @@ public: return durs_; } - const std::deque& CpusData() const + const std::deque& CpusData() const { return cpus_; } - void Clear() + virtual void Clear() { durs_.clear(); cpus_.clear(); } + void SetDur(uint64_t index, uint64_t dur); public: std::deque durs_; - std::deque cpus_; + std::deque cpus_; }; class Thread { public: explicit Thread(uint32_t t) : tid_(t) {} - InternalPid internalPid_ = 0; + InternalPid internalPid_ = INVALID_UINT32; uint32_t tid_ = 0; DataIndex nameIndex_ = 0; InternalTime startT_ = 0; InternalTime endT_ = 0; + uint32_t switchCount_ = 0; + uint32_t sliceSize_ = 0; + uint32_t cpuStatesCount_ = 0; }; class Process { @@ -101,29 +108,75 @@ public: std::string cmdLine_ = ""; InternalTime startT_ = 0; uint32_t pid_ = 0; + uint32_t memSize_ = 0; + uint32_t threadSize_ = 0; + uint32_t sliceSize_ = 0; + uint32_t switchCount_ = 0; + int32_t threadCount_ = -1; + uint32_t cpuStatesCount_ = 0; }; -class ThreadState : public CacheBase, public CpuCacheBase { +class ThreadState { public: - size_t AppendThreadState(uint64_t ts, uint64_t dur, uint64_t cpu, uint64_t internalTid, uint64_t state); - void SetDuration(size_t index, uint64_t duration); - uint64_t UpdateDuration(size_t index, uint64_t timestamp); - void UpdateState(size_t index, uint64_t state); - void UpdateDuration(size_t index, uint64_t timestamp, uint64_t state); - uint64_t UpdateDuration(size_t index, uint64_t timestamp, uint64_t cpu, uint64_t state); + TableRowId + AppendThreadState(InternalTime ts, InternalTime dur, InternalCpu cpu, InternalTid itid, TableRowId idState); + void SetDuration(TableRowId index, InternalTime dur); + TableRowId UpdateDuration(TableRowId index, InternalTime ts); + void UpdateState(TableRowId index, TableRowId idState); + void UpdateDuration(TableRowId index, InternalTime ts, TableRowId idState); + void UpdateTidAndPid(TableRowId index, InternalTid tid, InternalTid pid); + TableRowId UpdateDuration(TableRowId index, InternalTime ts, InternalCpu cpu, TableRowId idState); + void Clear() + { + timeStamps_.clear(); + durations_.clear(); + itids_.clear(); + tids_.clear(); + pids_.clear(); + states_.clear(); + cpus_.clear(); + } + const uint32_t Size() const + { + return itids_.size(); + } + + const std::deque& TimeStamsData() const + { + return timeStamps_; + } + const std::deque& DursData() const + { + return durations_; + } + const std::deque& ItidsData() const + { + return itids_; + } + const std::deque& TidsData() const + { + return tids_; + } + const std::deque& PidsData() const + { + return pids_; + } const std::deque& StatesData() const { return states_; } - void Clear() + const std::deque& CpusData() const { - CacheBase::Clear(); - CpuCacheBase::Clear(); - states_.clear(); + return cpus_; } - private: - std::deque states_ = {}; + std::deque timeStamps_; + std::deque durations_; + std::deque itids_; + std::deque tids_; + std::deque pids_; + std::deque states_; + std::deque cpus_; }; class SchedSlice : public CacheBase, public CpuCacheBase { @@ -146,15 +199,31 @@ public: { return priority_; } - void Clear() + const std::deque& TsEndData() const + { + return tsEnds_; + } + const std::deque& InternalPidsData() const + { + return internalPids_; + } + void AppendInternalPid(InternalPid ipid) + { + internalPids_.emplace_back(ipid); + } + void Clear() override { CacheBase::Clear(); CpuCacheBase::Clear(); endStates_.clear(); priority_.clear(); + internalPids_.clear(); + tsEnds_.clear(); } private: + std::deque internalPids_ = {}; + std::deque tsEnds_ = {}; std::deque endStates_ = {}; std::deque priority_ = {}; }; @@ -165,6 +234,7 @@ public: uint64_t durationNs, InternalTid internalTid, DataIndex cat, + uint16_t nameIdentify, DataIndex name, uint8_t depth, uint64_t cookid, @@ -173,20 +243,28 @@ public: uint64_t durationNs, InternalTid internalTid, DataIndex cat, + uint16_t nameIdentify, DataIndex name, uint8_t depth, const std::optional& parentId); + void SetDistributeInfo(size_t index, + const std::string& chainId, + const std::string& spanId, + const std::string& parentSpanId, + const std::string& flag, + const std::string& args); void AppendDistributeInfo(const std::string& chainId, const std::string& spanId, const std::string& parentSpanId, const std::string& flag, const std::string& args); - void AppendArgSet(uint32_t argSetId); void AppendDistributeInfo(); void SetDuration(size_t index, uint64_t timestamp); - void SetDurationAndArg(size_t index, uint64_t timestamp, uint32_t argSetId); + void SetIrqDurAndArg(size_t index, uint64_t timestamp, uint32_t argSetId); void SetTimeStamp(size_t index, uint64_t timestamp); - void Clear() + void SetDepth(size_t index, uint8_t depth); + void SetArgSetId(size_t index, uint32_t argSetId); + void Clear() override { CacheBase::Clear(); CpuCacheBase::Clear(); @@ -208,7 +286,8 @@ public: const std::deque& NamesData() const; const std::deque& Depths() const; const std::deque& Cookies() const; - const std::deque& CallIds() const; + const std::deque& CallIds() const; + const std::deque& IdentifysData() const; const std::deque& ChainIds() const; const std::deque& SpanIds() const; const std::deque& ParentSpanIds() const; @@ -224,7 +303,8 @@ private: std::deque> parentIds_; std::deque cats_ = {}; std::deque cookies_ = {}; - std::deque callIds_ = {}; + std::deque callIds_ = {}; + std::deque identifys_ = {}; std::deque names_ = {}; std::deque depths_ = {}; @@ -251,7 +331,7 @@ public: { return sourceArgSetId_; } - void Clear() + void Clear() override { CacheBase::Clear(); nameDeque_.clear(); @@ -280,7 +360,7 @@ public: { return filterIdDeque_; } - void Clear() + void Clear() override { CacheBase::Clear(); typeDeque_.clear(); @@ -309,7 +389,7 @@ public: { return itidDeque_; } - void Clear() + void Clear() override { CacheBase::Clear(); nameDeque_.clear(); @@ -357,7 +437,7 @@ private: class CpuMeasureFilter : public CacheBase { public: - inline size_t AppendNewFilter(uint64_t filterId, DataIndex name, uint64_t cpu) + inline size_t AppendNewFilter(uint64_t filterId, DataIndex name, uint32_t cpu) { ids_.emplace_back(filterId); cpu_.emplace_back(cpu); @@ -365,7 +445,7 @@ public: return Size() - 1; } - const std::deque& CpuData() const + const std::deque& CpuData() const { return cpu_; } @@ -379,7 +459,7 @@ public: { return name_; } - void Clear() + void Clear() override { CacheBase::Clear(); cpu_.clear(); @@ -388,27 +468,36 @@ public: } private: - std::deque cpu_ = {}; + std::deque cpu_ = {}; std::deque type_ = {}; std::deque name_ = {}; }; class Instants : public CacheBase { public: - size_t AppendInstantEventData(uint64_t timestamp, DataIndex nameIndex, int64_t internalTid); + size_t AppendInstantEventData(uint64_t timestamp, + DataIndex nameIndex, + int64_t internalTid, + int64_t wakeupFromInternalPid); const std::deque& NameIndexsData() const { return NameIndexs_; } - void Clear() + const std::deque& WakeupFromPidsData() const + { + return wakeupFromInternalPids_; + } + void Clear() override { CacheBase::Clear(); NameIndexs_.clear(); + wakeupFromInternalPids_.clear(); } private: std::deque NameIndexs_; + std::deque wakeupFromInternalPids_; }; class ProcessMeasureFilter : public CacheBase { @@ -424,7 +513,7 @@ public: { return names_; } - void Clear() + void Clear() override { CacheBase::Clear(); internalPids_.clear(); @@ -452,7 +541,7 @@ public: { return types_; } - void Clear() + void Clear() override { CacheBase::Clear(); cpus_.clear(); @@ -481,7 +570,7 @@ public: { return cpus_; } - void Clear() + void Clear() override { CacheBase::Clear(); names_.clear(); @@ -513,7 +602,7 @@ public: { return rets_; } - void Clear() + void Clear() override { CacheBase::Clear(); sysCallNums_.clear(); @@ -536,7 +625,7 @@ public: const std::deque& ArgsData() const; const std::deque& NamesData() const; - void Clear() + void Clear() override { CacheBase::Clear(); names_.clear(); @@ -544,6 +633,7 @@ public: values_.clear(); argset_.clear(); } + private: std::deque names_ = {}; std::deque dataTypes_ = {}; @@ -555,7 +645,7 @@ public: size_t AppendNewFilter(uint64_t filterId, DataIndex type, DataIndex nameId); const std::deque& NamesData() const; const std::deque& TypesData() const; - void Clear() + void Clear() override { CacheBase::Clear(); types_.clear(); @@ -571,7 +661,7 @@ public: size_t AppendNewDataType(BaseDataType dataType, DataIndex dataDescIndex); const std::deque& DataTypes() const; const std::deque& DataDesc() const; - void Clear() + void Clear() override { CacheBase::Clear(); dataTypes_.clear(); @@ -599,7 +689,7 @@ public: const std::deque& Tags() const; const std::deque& Contexts() const; const std::deque& OriginTimeStamData() const; - void Clear() + void Clear() override { CacheBase::Clear(); hilogLineSeqs_.clear(); @@ -620,71 +710,90 @@ private: std::deque originTs_ = {}; }; -class HeapInfo : public CacheBase { +class NativeHook : public CacheBase { public: - size_t AppendNewHeapInfo(uint64_t eventId, - uint32_t ipid, - uint32_t itid, - DataIndex eventType, - uint64_t timestamp, - uint64_t endTimestamp, - uint64_t duration, - uint64_t addr, - int64_t heapSize, - int64_t allHeapSize, - uint64_t currentSizeDur); + size_t AppendNewNativeHookData(uint64_t callChainId, + uint32_t ipid, + uint32_t itid, + std::string eventType, + DataIndex subType, + uint64_t timestamp, + uint64_t endTimestamp, + uint64_t duration, + uint64_t addr, + int64_t memSize, + int64_t allMemSize); void UpdateHeapDuration(size_t row, uint64_t endTimestamp); - void UpdateCurrentSizeDur(size_t row, uint64_t nextStartTime); - const std::deque& EventIds() const; + void UpdateCurrentSizeDur(size_t row, uint64_t timeStamp); + void UpdateMemMapSubType(); + void UpdateAddrToMemMapSubType(uint64_t addr, int64_t size, uint64_t tagId); + void UpdateLastCallerPathIndexs(std::map& callIdToLasLibId); + const std::deque& CallChainIds() const; const std::deque& Ipids() const; const std::deque& Itids() const; - const std::deque& EventTypes() const; + const std::deque& EventTypes() const; + const std::deque& SubTypes() const; const std::deque& EndTimeStamps() const; const std::deque& Durations() const; const std::deque& Addrs() const; - const std::deque& HeapSizes() const; - const std::deque& AllHeapSizes() const; + const std::deque& MemSizes() const; + const std::deque& AllMemSizes() const; const std::deque& CurrentSizeDurs() const; - void Clear() + const std::deque& LastCallerPathIndexs() const; + void Clear() override { CacheBase::Clear(); - eventIds_.clear(); + callChainIds_.clear(); ipids_.clear(); itids_.clear(); eventTypes_.clear(); + subTypes_.clear(); endTimestamps_.clear(); durations_.clear(); addrs_.clear(); - heapSizes_.clear(); - allHeapSizes_.clear(); + memSizes_.clear(); + allMemSizes_.clear(); currentSizeDurs_.clear(); + lastCallerPathIndexs_.clear(); } private: - std::deque eventIds_ = {}; + std::deque callChainIds_ = {}; std::deque ipids_ = {}; std::deque itids_ = {}; - std::deque eventTypes_ = {}; + std::deque eventTypes_ = {}; + std::deque subTypes_ = {}; std::deque endTimestamps_ = {}; std::deque durations_ = {}; std::deque addrs_ = {}; - std::deque heapSizes_ = {}; - std::deque allHeapSizes_ = {}; + std::deque memSizes_ = {}; + std::deque allMemSizes_ = {}; std::deque currentSizeDurs_ = {}; + std::deque lastCallerPathIndexs_ = {}; + DoubleMap addrToMmapTag_ = INVALID_UINT64; int64_t countHeapSizes_ = 0; + int64_t countMmapSizes_ = 0; + const std::string ALLOC_EVET = "AllocEvent"; + const std::string FREE_EVENT = "FreeEvent"; + const std::string MMAP_EVENT = "MmapEvent"; + const std::string MUNMAP_EVENT = "MunmapEvent"; }; -class HeapFrameInfo { +class NativeHookFrame { public: - size_t AppendNewHeapFrameInfo(uint64_t eventId, - uint64_t depth, - DataIndex ip, - DataIndex sp, - DataIndex symbolName, - DataIndex filePath, - DataIndex offset, - uint64_t symbolOffset); - const std::deque& EventIds() const; + size_t AppendNewNativeHookFrame(uint64_t callChainId, + uint64_t depth, + uint64_t ip, + uint64_t sp, + DataIndex symbolName, + DataIndex filePath, + uint64_t offset, + uint64_t symbolOffset); + void UpdateSymbolIdToNameMap(uint64_t originSymbolId, uint64_t symbolId); + void UpdateSymbolId(); + void UpdateFileId(std::map& filePathIdToFilePathName); + void UpdateVaddrs(std::deque& vaddrs); + const std::deque& CallChainIds() const; const std::deque& Depths() const; const std::deque& Ips() const; const std::deque& Sps() const; @@ -692,13 +801,14 @@ public: const std::deque& FilePaths() const; const std::deque& Offsets() const; const std::deque& SymbolOffsets() const; + const std::deque& Vaddrs() const; size_t Size() const { - return eventIds_.size(); + return callChainIds_.size(); } void Clear() { - eventIds_.clear(); + callChainIds_.clear(); depths_.clear(); ips_.clear(); sps_.clear(); @@ -706,10 +816,11 @@ public: filePaths_.clear(); offsets_.clear(); symbolOffsets_.clear(); + vaddrs_.clear(); } private: - std::deque eventIds_ = {}; + std::deque callChainIds_ = {}; std::deque depths_ = {}; std::deque ips_ = {}; std::deque sps_ = {}; @@ -717,16 +828,108 @@ private: std::deque filePaths_ = {}; std::deque offsets_ = {}; std::deque symbolOffsets_ = {}; + std::deque vaddrs_ = {}; + std::map symbolIdToSymbolName_ = {}; + DataIndex libcFilePathIndex_ = INVALID_UINT64; + DataIndex muslFilePathIndex_ = INVALID_UINT64; }; class Hidump : public CacheBase { public: size_t AppendNewHidumpInfo(uint64_t timestamp, uint32_t fps); const std::deque& Fpss() const; + private: std::deque fpss_ = {}; }; +class PerfCallChain : public CacheBase { +public: + size_t AppendNewPerfCallChain(uint64_t sampleId, + uint64_t callChainId, + uint64_t vaddrInFile, + uint64_t fileId, + uint64_t symbolId); + const std::deque& SampleIds() const; + const std::deque& CallChainIds() const; + const std::deque& VaddrInFiles() const; + const std::deque& FileIds() const; + const std::deque& SymbolIds() const; + const std::deque& Names() const; + void SetName(uint64_t index, const std::string& name); + +private: + std::deque sampleIds_ = {}; + std::deque callChainIds_ = {}; + std::deque vaddrInFiles_ = {}; + std::deque fileIds_ = {}; + std::deque symbolIds_ = {}; + std::deque names_ = {}; +}; + +class PerfFiles : public CacheBase { +public: + size_t AppendNewPerfFiles(uint64_t fileIds, uint32_t serial, DataIndex symbols, DataIndex filePath); + const std::deque& FileIds() const; + const std::deque& Symbols() const; + const std::deque& FilePaths() const; + const std::deque& Serials() const; + +private: + std::deque fileIds_ = {}; + std::deque serials_ = {}; + std::deque symbols_ = {}; + std::deque filePaths_ = {}; +}; + +class PerfSample : public CacheBase { +public: + size_t AppendNewPerfSample(uint64_t sampleId, + uint64_t timestamp, + uint64_t tid, + uint64_t eventCount, + uint64_t eventTypeId, + uint64_t timestampTrace, + uint64_t cpuId, + uint64_t threadState); + const std::deque& SampleIds() const; + const std::deque& Tids() const; + const std::deque& EventCounts() const; + const std::deque& EventTypeIds() const; + const std::deque& TimestampTraces() const; + const std::deque& CpuIds() const; + const std::deque& ThreadStates() const; +private: + std::deque sampleIds_ = {}; + std::deque tids_ = {}; + std::deque eventCounts_ = {}; + std::deque eventTypeIds_ = {}; + std::deque timestampTraces_ = {}; + std::deque cpuIds_ = {}; + std::deque threadStates_ = {}; +}; + +class PerfThread : public CacheBase { +public: + size_t AppendNewPerfThread(uint64_t pid, uint64_t tid, DataIndex threadName); + const std::deque& Pids() const; + const std::deque& Tids() const; + const std::deque& ThreadNames() const; +private: + std::deque tids_ = {}; + std::deque pids_ = {}; + std::deque threadNames_ = {}; +}; + +class PerfReport : public CacheBase { +public: + size_t AppendNewPerfReport(DataIndex type, DataIndex value); + const std::deque& Types() const; + const std::deque& Values() const; +private: + std::deque types_ = {}; + std::deque values_ = {}; +}; class StatAndInfo { public: StatAndInfo(); @@ -737,14 +940,14 @@ public: const std::string& GetStat(StatType type) const; const std::string& GetSeverityDesc(SupportedTraceEventType eventType, StatType type) const; const StatSeverityLevel& GetSeverity(SupportedTraceEventType eventType, StatType type) const; - + std::map clockid2ClockNameMap_ = {}; private: uint32_t statCount_[TRACE_EVENT_MAX][STAT_EVENT_MAX]; std::string event_[TRACE_EVENT_MAX]; std::string stat_[STAT_EVENT_MAX]; std::string statSeverityDesc_[TRACE_EVENT_MAX][STAT_EVENT_MAX]; StatSeverityLevel statSeverity_[TRACE_EVENT_MAX][STAT_EVENT_MAX]; - TraceStreamerConfig config_; + TraceStreamerConfig config_{}; }; class SymbolsData { public: @@ -759,10 +962,46 @@ public: addrs_.clear(); funcName_.clear(); } + private: std::deque addrs_ = {}; std::deque funcName_ = {}; }; +class DiskIOData : public CacheBase { +public: + DiskIOData() = default; + ~DiskIOData() = default; + void AppendNewData(uint64_t ts, + uint64_t dur, + uint64_t rd, + uint64_t wr, + uint64_t rdPerSec, + uint64_t wrPerSec, + double rdCountPerSec, + double wrCountPerSec, + uint64_t rdCount, + uint64_t wrCount); + const std::deque& Durs() const; + const std::deque& RdDatas() const; + const std::deque& WrDatas() const; + const std::deque& RdSpeedDatas() const; + const std::deque& WrSpeedDatas() const; + const std::deque& RdCountPerSecDatas() const; + const std::deque& WrCountPerSecDatas() const; + const std::deque& RdCountDatas() const; + const std::deque& WrCountDatas() const; + +private: + std::deque durs_ = {}; + std::deque rdDatas_ = {}; + std::deque wrDatas_ = {}; + std::deque wrPerSec_ = {}; + std::deque rdPerSec_ = {}; + std::deque wrCountPerSec_ = {}; + std::deque rdCountPerSec_ = {}; + std::deque rdCountDatas_ = {}; + std::deque wrCountDatas_ = {}; +}; class MetaData { public: MetaData(); @@ -781,6 +1020,7 @@ public: columnNames_.clear(); values_.clear(); } + private: const std::string METADATA_ITEM_DATASIZE_COLNAME = "datasize"; const std::string METADATA_ITEM_PARSETOOL_NAME_COLNAME = "parse_tool"; @@ -802,21 +1042,748 @@ public: return dataDict_.size(); } DataIndex GetStringIndex(std::string_view str); + DataIndex GetStringIndexNoWrite(std::string_view str) const; const std::string& GetDataFromDict(DataIndex id) const { TS_ASSERT(id < dataDict_.size()); return dataDict_[id]; } + void Finish(); void Clear() { dataDict_.clear(); } + public: std::deque dataDict_; std::unordered_map dataDictInnerMap_; private: std::hash hashFun; + std::mutex mutex_; +}; +class NetDetailData : public CacheBase { +public: + size_t AppendNewNetData(uint64_t newTimeStamp, + uint64_t tx, + uint64_t rx, + uint64_t dur, + double rxSpeed, + double txSpeed, + uint64_t packetIn, + double packetInSec, + uint64_t packetOut, + double packetOutSec, + const std::string& netType); + const std::deque& Durs() const; + const std::deque& RxSpeed() const; + const std::deque& TxSpeed() const; + const std::deque& NetTypes() const; + const std::deque& RxDatas() const; + const std::deque& TxDatas() const; + const std::deque& PacketIn() const; + const std::deque& PacketInSec() const; + const std::deque& PacketOut() const; + const std::deque& PacketOutSec() const; + void Clear() override + { + CacheBase::Clear(); + durs_.clear(); + rxSpeeds_.clear(); + txSpeeds_.clear(); + netTypes_.clear(); + packetIn_.clear(); + packetInSec_.clear(); + packetOut_.clear(); + packetOutSec_.clear(); + } + +private: + std::deque rxs_ = {}; + std::deque txs_ = {}; + std::deque durs_ = {}; + std::deque rxSpeeds_ = {}; + std::deque txSpeeds_ = {}; + std::deque packetIn_ = {}; + std::deque packetInSec_ = {}; + std::deque packetOut_ = {}; + std::deque packetOutSec_ = {}; + std::deque netTypes_ = {}; +}; +class LiveProcessDetailData : public CacheBase { +public: + size_t AppendNewData(uint64_t newTimeStamp, + uint64_t dur, + int32_t processID, + std::string processName, + int32_t parentProcessID, + int32_t uid, + std::string userName, + double cpuUsage, + int32_t pssInfo, + uint64_t cpuTime, + int32_t threads, + int64_t diskWrites, + int64_t diskReads); + const std::deque& Durs() const; + const std::deque& ProcessID() const; + const std::deque& ProcessName() const; + const std::deque& ParentProcessID() const; + const std::deque& Uid() const; + const std::deque& UserName() const; + const std::deque& CpuUsage() const; + const std::deque& PssInfo() const; + const std::deque& Threads() const; + const std::deque& DiskWrites() const; + const std::deque& DiskReads() const; + const std::deque& CpuTimes() const; + void Clear() override + { + CacheBase::Clear(); + durs_.clear(); + processID_.clear(); + processName_.clear(); + parentProcessID_.clear(); + uid_.clear(); + userName_.clear(); + cpuUsage_.clear(); + pssInfo_.clear(); + threads_.clear(); + diskWrites_.clear(); + diskReads_.clear(); + } + +private: + std::deque durs_ = {}; + std::deque processID_ = {}; + std::deque processName_ = {}; + std::deque parentProcessID_ = {}; + std::deque uid_ = {}; + std::deque userName_ = {}; + std::deque cpuUsage_ = {}; + std::deque pssInfo_ = {}; + std::deque threads_ = {}; + std::deque diskWrites_ = {}; + std::deque diskReads_ = {}; + std::deque cpuTimes_ = {}; +}; +class CpuUsageDetailData : public CacheBase { +public: + size_t AppendNewData(uint64_t newTimeStamp, + uint64_t dur, + double totalLoad, + double userLoad, + double systemLoad, + int64_t threads); + const std::deque& Durs() const; + const std::deque& TotalLoad() const; + const std::deque& UserLoad() const; + const std::deque& SystemLoad() const; + const std::deque& Threads() const; + void Clear() override + { + CacheBase::Clear(); + durs_.clear(); + totalLoad_.clear(); + userLoad_.clear(); + systemLoad_.clear(); + threads_.clear(); + } + +private: + std::deque durs_ = {}; + std::deque totalLoad_ = {}; + std::deque userLoad_ = {}; + std::deque systemLoad_ = {}; + std::deque threads_ = {}; +}; +class FileSystemSample : public CacheBase { +public: + size_t AppendNewData(uint64_t callChainId, + uint16_t type, + uint32_t ipid, + uint32_t itid, + uint64_t startTs, + uint64_t endTs, + uint64_t dur, + DataIndex returnValue, + DataIndex errorCode, + size_t size, + int32_t fd, + DataIndex fileId, + DataIndex firstArgument, + DataIndex secondArgument, + DataIndex thirdArgument, + DataIndex fourthArgument); + const std::deque& CallChainIds() const; + const std::deque& Types() const; + const std::deque& Ipids() const; + const std::deque& Itids() const; + const std::deque& StartTs() const; + const std::deque& EndTs() const; + const std::deque& Durs() const; + const std::deque& ReturnValues() const; + const std::deque& ErrorCodes() const; + const std::deque& Fds() const; + const std::deque& FileIds() const; + const std::deque& Sizes() const; + const std::deque& FirstArguments() const; + const std::deque& SecondArguments() const; + const std::deque& ThirdArguments() const; + const std::deque& FourthArguments() const; + void Clear() override + { + CacheBase::Clear(); + callChainIds_.clear(); + types_.clear(); + ipids_.clear(); + itids_.clear(); + startTs_.clear(); + endTs_.clear(); + durs_.clear(); + returnValues_.clear(); + errorCodes_.clear(); + fds_.clear(); + Sizes_.clear(); + firstArguments_.clear(); + secondArguments_.clear(); + thirdArguments_.clear(); + fourthArguments_.clear(); + } + +private: + std::deque callChainIds_ = {}; + std::deque types_ = {}; + std::deque ipids_ = {}; + std::deque itids_ = {}; + std::deque startTs_ = {}; + std::deque endTs_ = {}; + std::deque durs_ = {}; + std::deque returnValues_ = {}; + std::deque errorCodes_ = {}; + std::deque fds_ = {}; + std::deque fileIds_ = {}; + std::deque Sizes_ = {}; + std::deque firstArguments_ = {}; + std::deque secondArguments_ = {}; + std::deque thirdArguments_ = {}; + std::deque fourthArguments_ = {}; +}; +class EbpfCallStackData : public CacheBase { +public: + size_t AppendNewData(uint64_t callChainId, + uint32_t depth, + uint64_t ip, + uint64_t symbolId, + uint64_t filePathId); + const std::deque& CallChainIds() const; + const std::deque& Depths() const; + const std::deque& Ips() const; + const std::deque& SymbolIds() const; + const std::deque& FilePathIds() const; + void Clear() override + { + CacheBase::Clear(); + callChainIds_.clear(); + depths_.clear(); + symbolIds_.clear(); + filePathIds_.clear(); + } + +private: + std::deque callChainIds_ = {}; + std::deque depths_ = {}; + std::deque ips_ = {}; + std::deque symbolIds_ = {}; + std::deque filePathIds_ = {}; +}; +class PagedMemorySampleData : public CacheBase { +public: + size_t AppendNewData(uint64_t callChainId, + uint16_t type, + uint32_t ipid, + uint64_t startTs, + uint64_t endTs, + uint64_t dur, + size_t size, + DataIndex addr, + uint32_t itid); + const std::deque& CallChainIds() const; + const std::deque& Types() const; + const std::deque& Ipids() const; + const std::deque& StartTs() const; + const std::deque& EndTs() const; + const std::deque& Durs() const; + const std::deque& Sizes() const; + const std::deque& Addr() const; + const std::deque& Itids() const; + void Clear() override + { + CacheBase::Clear(); + callChainIds_.clear(); + types_.clear(); + ipids_.clear(); + startTs_.clear(); + endTs_.clear(); + durs_.clear(); + Sizes_.clear(); + addrs_.clear(); + itids_.clear(); + } + +private: + std::deque callChainIds_ = {}; + std::deque types_ = {}; + std::deque ipids_ = {}; + std::deque startTs_ = {}; + std::deque endTs_ = {}; + std::deque durs_ = {}; + std::deque Sizes_ = {}; + std::deque addrs_ = {}; + std::deque itids_ = {}; +}; +#if WITH_EBPF_HELP +class EbpfProcessMaps : public CacheBase { +public: + size_t AppendNewData(uint64_t start, + uint64_t end, + uint32_t offset, + uint32_t pid, + uint32_t fileNameLen, + uint64_t fileNameIndex); + const std::deque& Starts() const; + const std::deque& Ends() const; + const std::deque& Offsets() const; + const std::deque& Pids() const; + const std::deque& FileNameLens() const; + const std::deque& FileNameIndexs() const; + void Clear() override + { + CacheBase::Clear(); + starts_.clear(); + ends_.clear(); + offsets_.clear(); + pids_.clear(); + fileNameLens_.clear(); + fileNameIndexs_.clear(); + } +private: + std::deque starts_ = {}; + std::deque ends_ = {}; + std::deque offsets_ = {}; + std::deque pids_ = {}; + std::deque fileNameLens_ = {}; + std::deque fileNameIndexs_ = {}; +}; + +class EbpfElf : public CacheBase { +public: + size_t AppendNewData(uint64_t elfId, + uint64_t textVaddr, + uint32_t textOffset, + uint32_t strTabLen, + uint32_t symTabLen, + uint32_t fileNameLen, + uint32_t symEntLen, + uint64_t fileNameIndex); + const std::deque& ElfIds() const; + const std::deque& TextVaddrs() const; + const std::deque& TextOffsets() const; + const std::deque& StrTabLens() const; + const std::deque& SymTabLens() const; + const std::deque& FileNameLens() const; + const std::deque& SymEntLens() const; + const std::deque& FileNameIndexs() const; + + void Clear() override + { + CacheBase::Clear(); + elfIds_.clear(); + textVaddrs_.clear(); + textOffsets_.clear(); + strTabLens_.clear(); + symTabLens_.clear(); + fileNameLens_.clear(); + symEntLens_.clear(); + fileNameIndexs_.clear(); + } + +private: + std::deque elfIds_ = {}; + std::deque textVaddrs_ = {}; + std::deque textOffsets_ = {}; + std::deque strTabLens_ = {}; + std::deque symTabLens_ = {}; + std::deque fileNameLens_ = {}; + std::deque symEntLens_ = {}; + std::deque fileNameIndexs_ = {}; +}; + +class EbpfElfSymbol : public CacheBase { +public: + size_t AppendNewData(uint64_t elfId, + uint32_t stName, + uint64_t stValue, + uint64_t stSize); + const std::deque& ElfIds() const; + const std::deque& StNames() const; + const std::deque& StValues() const; + const std::deque& StSizes() const; + + void Clear() override + { + CacheBase::Clear(); + elfIds_.clear(); + stNames_.clear(); + stValues_.clear(); + stSizes_.clear(); + } + +private: + std::deque elfIds_ = {}; + std::deque stNames_ = {}; + std::deque stValues_ = {}; + std::deque stSizes_ = {}; +}; +#endif +class AppNames : public CacheBase { +public: + uint32_t AppendAppName(uint8_t flags, DataIndex eventSource, DataIndex appName); + const std::deque& Falgs() const; + const std::deque& EventSourceId() const; + const std::deque& AppName() const; + void Clear() override + { + CacheBase::Clear(); + flags_.clear(); + appNames_.clear(); + keyNames_.clear(); + } +private: + std::deque flags_ = {}; + std::deque appNames_ = {}; + std::deque keyNames_ = {}; + uint32_t rowCount_ = 0; +}; +class SysEventMeasureData : public CacheBase { +public: + void AppendData(uint64_t serial, + uint64_t ts, + uint32_t nameId, + uint32_t keyId, + int32_t type, + double numericValue, + DataIndex stringValue); + const std::deque& Serial() const; + const std::deque& Ts() const; + const std::deque& NameFilterId() const; + const std::deque& AppKeyFilterId() const; + const std::deque& Type() const; + const std::deque& NumValue() const; + const std::deque& StringValue() const; + void Clear() override + { + CacheBase::Clear(); + serial_.clear(); + ts_.clear(); + nameFilterIds_.clear(); + appKeyFilterIds_.clear(); + types_.clear(); + numValues_.clear(); + stringValues_.clear(); + } +private: + std::deque serial_ = {}; + std::deque ts_ = {}; + std::deque nameFilterIds_ = {}; + std::deque appKeyFilterIds_ = {}; + std::deque types_ = {}; + std::deque numValues_ = {}; + std::deque stringValues_ = {}; + uint32_t rowCount_ = 0; +}; +class DeviceStateData : public CacheBase { +public: + void AppendNewData(int32_t brightness, + int32_t btState, + int32_t location, + int32_t wifi, + int32_t streamDefault, + int32_t voiceCall, + int32_t music, + int32_t streamRing, + int32_t media, + int32_t voiceAssistant, + int32_t system, + int32_t alarm, + int32_t notification, + int32_t btSco, + int32_t enforcedAudible, + int32_t streamDtmf, + int32_t streamTts, + int32_t accessibility, + int32_t recording, + int32_t streamAll); + const std::deque& Brightness() const; + const std::deque& BtState() const; + const std::deque& Location() const; + const std::deque& Wifi() const; + const std::deque& StreamDefault() const; + const std::deque& VoiceCall() const; + const std::deque& Music() const; + const std::deque& StreamRing() const; + const std::deque& Media() const; + const std::deque& VoiceAssistant() const; + const std::deque& System() const; + const std::deque& Alarm() const; + const std::deque& Notification() const; + const std::deque& BtSco() const; + const std::deque& EnforcedAudible() const; + const std::deque& StreamDtmf() const; + const std::deque& StreamTts() const; + const std::deque& Accessibility() const; + const std::deque& Recording() const; + const std::deque& StreamAll() const; + void Clear() override + { + CacheBase::Clear(); + brightness_.clear(); + btStates_.clear(); + locations_.clear(); + wifis_.clear(); + streamDefaults_.clear(); + voiceCalls_.clear(); + musics_.clear(); + streamRings_.clear(); + medias_.clear(); + voiceAssistants_.clear(); + systems_.clear(); + alarms_.clear(); + notifications_.clear(); + btScos_.clear(); + enforcedAudibles_.clear(); + streamDtmfs_.clear(); + streamTts_.clear(); + accessibilitys_.clear(); + recordings_.clear(); + streamAlls_.clear(); + } +private: + std::deque stringValues_ = {}; + std::deque brightness_ = {}; + std::deque btStates_ = {}; + std::deque locations_ = {}; + std::deque wifis_ = {}; + std::deque streamDefaults_ = {}; + std::deque voiceCalls_ = {}; + std::deque musics_ = {}; + std::deque streamRings_ = {}; + std::deque medias_ = {}; + std::deque voiceAssistants_ = {}; + std::deque systems_ = {}; + std::deque alarms_ = {}; + std::deque notifications_ = {}; + std::deque btScos_ = {}; + std::deque enforcedAudibles_ = {}; + std::deque streamDtmfs_ = {}; + std::deque streamTts_ = {}; + std::deque accessibilitys_ = {}; + std::deque recordings_ = {}; + std::deque streamAlls_ = {}; + uint32_t rowCounts_ = 0; +}; +class TraceConfigData : public CacheBase { +public: + void AppendNewData(std::string traceSource, std::string key, std::string value); + const std::deque& TraceSource() const; + const std::deque& Key() const; + const std::deque& Value() const; + void Clear() override + { + CacheBase::Clear(); + traceSource_.clear(); + key_.clear(); + value_.clear(); + } +private: + std::deque traceSource_ = {}; + std::deque key_ = {}; + std::deque value_ = {}; + uint32_t rowCounts_ = 0; +}; +class SmapsData : public CacheBase { +public: + void AppendNewData(uint64_t timeStamp, + std::string startAddr, + std::string endAddr, + uint64_t dirty, + uint64_t swapper, + uint64_t rss, + uint64_t pss, + uint64_t size, + double reside, + DataIndex protectionId, + DataIndex pathId); + const std::deque& Id() const; + const std::deque& TimeStamps() const; + const std::deque& StartAddrs() const; + const std::deque& EndAddrs() const; + const std::deque& Dirtys() const; + const std::deque& Swappers() const; + const std::deque& Rss() const; + const std::deque& Pss() const; + const std::deque& Sizes() const; + const std::deque& Resides() const; + const std::deque& ProtectionIds() const; + const std::deque& PathIds() const; + void Clear() override + { + CacheBase::Clear(); + smapTimeStamps_.clear(); + startAddrs_.clear(); + endAddrs_.clear(); + dirtys_.clear(); + swappers_.clear(); + rss_.clear(); + pss_.clear(); + sizes_.clear(); + resides_.clear(); + protectionIds_.clear(); + pathIds_.clear(); + } +private: + std::deque smapTimeStamps_ = {}; + std::deque startAddrs_ = {}; + std::deque endAddrs_ = {}; + std::deque dirtys_ = {}; + std::deque swappers_ = {}; + std::deque rss_ = {}; + std::deque pss_ = {}; + std::deque sizes_ = {}; + std::deque resides_ = {}; + std::deque protectionIds_ = {}; + std::deque pathIds_ = {}; + uint32_t rowCount_ = 0; +}; +class BioLatencySampleData : public CacheBase { +public: + void AppendNewData(uint64_t callChainId, + uint64_t type, + uint64_t ipid, + uint64_t itid, + uint64_t startTs, + uint64_t endTs, + uint64_t latencyDur, + uint32_t tier, + uint64_t size, + uint64_t blockNumber, + uint64_t filePathId, + uint64_t durPer4k); + const std::deque& Id() const; + const std::deque& CallChainIds() const; + const std::deque& Types() const; + const std::deque& Ipids() const; + const std::deque& Itids() const; + const std::deque& StartTs() const; + const std::deque& EndTs() const; + const std::deque& LatencyDurs() const; + const std::deque& Tiers() const; + const std::deque& Sizes() const; + const std::deque& BlockNumbers() const; + const std::deque& FilePathIds() const; + const std::deque& DurPer4k() const; + void Clear() override + { + CacheBase::Clear(); + callChainIds_.clear(); + types_.clear(); + ipids_.clear(); + itids_.clear(); + startTs_.clear(); + endTs_.clear(); + latencyDurs_.clear(); + tiers_.clear(); + sizes_.clear(); + blockNumbers_.clear(); + filePathIds_.clear(); + durPer4ks_.clear(); + } + +private: + std::deque callChainIds_ = {}; + std::deque types_ = {}; + std::deque ipids_ = {}; + std::deque itids_ = {}; + std::deque startTs_ = {}; + std::deque endTs_ = {}; + std::deque latencyDurs_ = {}; + std::deque tiers_ = {}; + std::deque sizes_ = {}; + std::deque blockNumbers_ = {}; + std::deque filePathIds_ = {}; + std::deque durPer4ks_ = {}; + uint32_t rowCount_ = 0; +}; +class ClockSnapshotData { +public: + size_t AppendNewSnapshot(uint8_t clockId, uint64_t ts, const std::string& name) + { + clockIds_.emplace_back(clockId); + ts_.emplace_back(ts); + names_.emplace_back(name); + return ts_.size(); + } + const size_t Size() const + { + return ts_.size(); + } + const std::deque& ClockIds() const + { + return clockIds_; + } + const std::deque& Ts() const + { + return ts_; + } + const std::deque& Names() const + { + return names_; + } + +private: + std::deque clockIds_ = {}; + std::deque ts_ = {}; + std::deque names_ = {}; +}; +class DataSourceClockIdData { +public: + DataSourceClockIdData(); + size_t AppendNewDataSourceClockId(const std::string& dataSoruceName, uint8_t clockId) + { + dataSourceNames_.emplace_back(dataSoruceName); + clockIds_.emplace_back(clockId); + return dataSourceNames_.size(); + } + const size_t Size() const + { + return dataSourceNames_.size(); + } + const std::deque& ClockIds() const + { + return clockIds_; + } + const std::deque& Names() const + { + return dataSourceNames_; + } + void SetDataSourceClockId(DataSourceType source, uint32_t id); + void Finish(); + +private: + std::deque dataSourceNames_ = {}; + std::deque clockIds_ = {}; + std::map dataSource2ClockIdMap_ = {}; + std::map dataSource2PluginNameMap_ = {}; }; } // namespace TraceStdtype } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_streamer.pro b/host/trace_streamer/src/trace_streamer.pro deleted file mode 100644 index 45afeed64405658f50f15f42f494329b9811994a..0000000000000000000000000000000000000000 --- a/host/trace_streamer/src/trace_streamer.pro +++ /dev/null @@ -1,79 +0,0 @@ -# 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. -QT -= gui core -TEMPLATE = app -#TEMPLATE = lib -CONFIG += c++17 console -#CONFIG += c++17 lib -#CONFIG += c++17 -CONFIG += WITHRPC -TARGET = trace_streamer -DEFINES += SUPPORTTHREAD - -#CONFIG += release - -DEFINES += HAVE_PTHREAD -DEFINES += _LIBCPP_DISABLE_AVAILABILITY - -DEFINES += HAVE_PTHREAD -ROOTSRCDIR = $$PWD/../ - -#QMAKE_CXXFLAGS =-ftrapv -fPIE -fstack-protector-strong -fstack-protector-all -D_FORTIFY_SOURCE=2 -O2 -#QMAKE_CFLAGS=-ftrapv -fPIE -fstack-protector-strong -fstack-protector-all -D_FORTIFY_SOURCE=2 -O2 -!unix{ -#QMAKE_LFLAGS=-fpie -Wl,-rpath=\$ORIGIN/. -} else { -#QMAKE_LFLAGS=-fpie -#QMAKE_LFLAGS=-fpie -Wl,-z,noexecstack -Wl,-z,now -Wl,-rpath=\$ORIGIN/. -Wl,-z,relro -} -include($$PWD/multi_platform/global.pri) -INCLUDEPATH += $$PWD/include \ - $$PWD/../third_party/protobuf/src \ - $$PWD/../third_party/sqlite/include \ - $$PWD/../third_party/protogen/gen \ - $$PWD/../third_party/protogen/gen/types/plugins/memory_data \ - $$PWD/../third_party/protogen/gen/types/plugins/ftrace_data \ - $$PWD/../third_party/protogen/gen/types/plugins/hilog_data \ - $$PWD/../third_party/protogen/gen/types/plugins/native_hook \ - $$PWD/../third_party/protogen/gen/types/plugins/hidump_data - - -include($$PWD/trace_streamer/trace_streamer.pri) -include($$PWD/base/base.pri) -WITHRPC{ -DEFINES += WIN32_LEAN_AND_MEAN -include($$PWD/rpc/rpc.pri) -INCLUDEPATH += $$PWD/rpc -!unix{ -LIBS += -lws2_32 -} -} -include($$PWD/filter/filter.pri) -include($$PWD/parser/parser.pri) -include($$PWD/multi_platform/protogen.pri) -include($$PWD/table/table.pri) -include($$PWD/trace_data/trace_data.pri) -include($$PWD/cfg/cfg.pri) -include($$PWD/ext/sqlite_ext.pri) - -unix{ -LIBS += -L$$DESTDIR/ -lstdc++ \ - -L$${ROOTSRCDIR}/lib/$${DESTFOLDER} -lprotobuf -lsqlite -ldl -} else { -LIBS += -L$$DESTDIR/ -lstdc++ \ - -L$${ROOTSRCDIR}/lib/$${DESTFOLDER} -lprotobuf -lsqlite -} -INCLUDEPATH +=$$PWD/include - -SOURCES += \ - main.cpp diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp b/host/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp old mode 100644 new mode 100755 index a39ee3fee1557fd0e16e77a2a2d4c842a8691a6f..d2362c2adf7004418d8f291bc710050dcdb3808d --- a/host/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp +++ b/host/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp @@ -19,8 +19,10 @@ #include "clock_filter.h" #include "cpu_filter.h" #include "filter_filter.h" +#include "hi_sysevent_measure_filter.h" #include "irq_filter.h" #include "measure_filter.h" +#include "perf_data_filter.h" #include "process_filter.h" #include "slice_filter.h" #include "stat_filter.h" diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer_filters.h b/host/trace_streamer/src/trace_streamer/trace_streamer_filters.h old mode 100644 new mode 100755 index 22e405a22a51878e0c04380e5970470087e932d7..3dccbf083e21e525d6f085f12277df2d5300ae63 --- a/host/trace_streamer/src/trace_streamer/trace_streamer_filters.h +++ b/host/trace_streamer/src/trace_streamer/trace_streamer_filters.h @@ -31,11 +31,14 @@ class BinderFilter; class ArgsFilter; class IrqFilter; class SystemEventMeasureFilter; +class HiSysEventMeasureFilter; +#if WITH_PERF +class PerfDataFilter; +#endif class TraceStreamerFilters { public: TraceStreamerFilters(); ~TraceStreamerFilters(); - std::unique_ptr clockFilter_; std::unique_ptr filterFilter_; std::unique_ptr sliceFilter_; @@ -59,6 +62,11 @@ public: std::unique_ptr irqFilter_; std::unique_ptr sysEventMemMeasureFilter_; std::unique_ptr sysEventVMemMeasureFilter_; + std::unique_ptr sysEventSourceFilter_; + std::unique_ptr hiSysEventMeasureFilter_; +#if WITH_PERF + std::unique_ptr perfDataFilter_; +#endif }; } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/host/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp old mode 100644 new mode 100755 index c3978598609b8678ff4ec764db07ef6e4eff9612..bf1e586b9fde560381305f51450fb5faaf852e5a --- a/host/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp +++ b/host/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -24,13 +24,18 @@ #include "cpu_filter.h" #include "file.h" #include "filter_filter.h" +#include "hi_sysevent_measure_filter.h" #include "irq_filter.h" #include "measure_filter.h" #include "parser/bytrace_parser/bytrace_parser.h" #include "parser/htrace_parser/htrace_parser.h" +#if WITH_PERF +#include "perf_data_filter.h" +#endif #include "process_filter.h" #include "slice_filter.h" #include "stat_filter.h" +#include "string_help.h" #include "symbols_filter.h" #include "system_event_measure_filter.h" @@ -50,6 +55,12 @@ TraceFileType GuessFileType(const uint8_t* data, size_t size) if (start.find("# TRACE") != std::string::npos) { return TRACE_FILETYPE_BY_TRACE; } + if (start.find("# SYSEVENT") != std::string::npos) { + return TRACE_FILETYPE_SYSEVENT; + } + if (start.find("# sysevent") != std::string::npos) { + return TRACE_FILETYPE_SYSEVENT; + } if ((start.compare(0, std::string("").length(), "") == 0) || (start.compare(0, std::string("").length(), "") == 0)) { return TRACE_FILETYPE_BY_TRACE; @@ -120,6 +131,13 @@ void TraceStreamerSelector::InitFilter() std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_SYS_MEMORY_FILTER); streamFilters_->sysEventVMemMeasureFilter_ = std::make_unique( traceDataCache_.get(), streamFilters_.get(), E_SYS_VIRTUAL_MEMORY_FILTER); +#if WITH_PERF + streamFilters_->perfDataFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); +#endif + streamFilters_->sysEventSourceFilter_ = std::make_unique( + traceDataCache_.get(), streamFilters_.get(), E_SYS_EVENT_SOURCE_FILTER); + streamFilters_->hiSysEventMeasureFilter_ = + std::make_unique(traceDataCache_.get(), streamFilters_.get()); } void TraceStreamerSelector::WaitForParserEnd() @@ -130,12 +148,23 @@ void TraceStreamerSelector::WaitForParserEnd() if (fileType_ == TRACE_FILETYPE_BY_TRACE) { bytraceParser_->WaitForParserEnd(); } + traceDataCache_->UpdateTraceRange(); } MetaData* TraceStreamerSelector::GetMetaData() { return traceDataCache_->GetMetaData(); } + +void TraceStreamerSelector::SetDataType(TraceFileType type) +{ + fileType_ = type; + if (fileType_ == TRACE_FILETYPE_H_TRACE) { + htraceParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + } else if (fileType_ == TRACE_FILETYPE_BY_TRACE) { + bytraceParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + } +} bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr data, size_t size) { if (size == 0) { @@ -145,8 +174,9 @@ bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr dat fileType_ = GuessFileType(data.get(), size); if (fileType_ == TRACE_FILETYPE_H_TRACE) { htraceParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); - } else if (fileType_ == TRACE_FILETYPE_BY_TRACE) { + } else if (fileType_ == TRACE_FILETYPE_BY_TRACE || fileType_ == TRACE_FILETYPE_SYSEVENT) { bytraceParser_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + bytraceParser_->EnableBytrace(fileType_ == TRACE_FILETYPE_BY_TRACE); } if (fileType_ == TRACE_FILETYPE_UN_KNOW) { SetAnalysisResult(TRACE_PARSER_FILE_TYPE_ERROR); @@ -159,8 +189,7 @@ bool TraceStreamerSelector::ParseTraceDataSegment(std::unique_ptr dat } if (fileType_ == TRACE_FILETYPE_H_TRACE) { htraceParser_->ParseTraceDataSegment(std::move(data), size); - } - if (fileType_ == TRACE_FILETYPE_BY_TRACE) { + } else if (fileType_ == TRACE_FILETYPE_BY_TRACE || fileType_ == TRACE_FILETYPE_SYSEVENT) { bytraceParser_->ParseTraceDataSegment(std::move(data), size); } SetAnalysisResult(TRACE_PARSER_NORMAL); @@ -202,5 +231,32 @@ int TraceStreamerSelector::SearchDatabase(const std::string& sql, uint8_t* out, { return traceDataCache_->SearchDatabase(sql, out, outLen); } +int TraceStreamerSelector::UpdateTraceRangeTime(uint8_t* data, int len) +{ + std::string traceRangeStr; + memcpy(&traceRangeStr, data, len); + int size = traceRangeStr.size(); + std::vector vTraceRangeStr; + for (int i = 0, pos = 0; i < size; i++) { + pos = traceRangeStr.find(";", i); + if (pos == std::string::npos) { + break; + } + if (pos < size) { + std::string s = traceRangeStr.substr(i, pos - i); + vTraceRangeStr.push_back(s); + i = pos; + } + } + uint64_t minTs = std::stoull(vTraceRangeStr.at(0)); + uint64_t maxTs = std::stoull(vTraceRangeStr.at(1)); + traceDataCache_->UpdateTraceTime(minTs); + traceDataCache_->UpdateTraceTime(maxTs); + return 0; +} +void TraceStreamerSelector::SetCancel(bool cancel) +{ + traceDataCache_->SetCancel(cancel); +} } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/src/trace_streamer/trace_streamer_selector.h b/host/trace_streamer/src/trace_streamer/trace_streamer_selector.h old mode 100644 new mode 100755 index 69eb9732bff175030ede70a1c7f9054c32adb2cd..b7d824ceb73904d1225087afa42ba5b05b5b34a7 --- a/host/trace_streamer/src/trace_streamer/trace_streamer_selector.h +++ b/host/trace_streamer/src/trace_streamer/trace_streamer_selector.h @@ -24,27 +24,26 @@ namespace SysTuning { namespace TraceStreamer { class BytraceParser; class HtraceParser; -enum TraceFileType { TRACE_FILETYPE_BY_TRACE, TRACE_FILETYPE_H_TRACE, TRACE_FILETYPE_UN_KNOW }; +enum TraceFileType { TRACE_FILETYPE_BY_TRACE, TRACE_FILETYPE_H_TRACE, TRACE_FILETYPE_SYSEVENT, TRACE_FILETYPE_UN_KNOW }; class TraceStreamerSelector { public: TraceStreamerSelector(); ~TraceStreamerSelector(); bool ParseTraceDataSegment(std::unique_ptr data, size_t size); void EnableMetaTable(bool enabled); - void SetCleanMode(bool cleanMode); + static void SetCleanMode(bool cleanMode); int ExportDatabase(const std::string& outputName) const; int SearchData(); int OperateDatabase(const std::string& sql); int SearchDatabase(const std::string& sql, TraceDataDB::ResultCallBack resultCallBack); int SearchDatabase(const std::string& sql, uint8_t* out, int outLen); + int UpdateTraceRangeTime(uint8_t* data, int len); void WaitForParserEnd(); void Clear(); MetaData* GetMetaData(); - void SetDataType(TraceFileType type) - { - fileType_ = type; - } - TraceFileType DataType() + void SetDataType(TraceFileType type); + void SetCancel(bool cancel); + TraceFileType DataType() const { return fileType_; } diff --git a/host/trace_streamer/src/ts.gni b/host/trace_streamer/src/ts.gni old mode 100644 new mode 100755 index 3dd4e2a5a520f3bd4b19ede491b673e48dc1a660..16279772850e6b180cc5c0b02a8945bfef54999b --- a/host/trace_streamer/src/ts.gni +++ b/host/trace_streamer/src/ts.gni @@ -12,8 +12,7 @@ # limitations under the License. OHOS_PROTO_DIR = "" -if (target_os == "linux" || target_os == "windows" || target_os == "wasm" || - target_os == "test") { +if (target_os == "linux" || target_os == "macx" || target_os == "windows") { # OHOS_FTRACE_PROTO_DIR="//third_party/protogen" OHOS_FTRACE_PROTO_DIR = "//src/multi_platform" @@ -32,16 +31,23 @@ if (target_os == "linux" || target_os == "windows" || target_os == "wasm" || # OHOS_SERVICE_PROTO_DIR = "//third_party/protogen" OHOS_SERVICE_PROTO_DIR = "//src/multi_platform" OHOS_PROTO_GEN = "//third_party/protogen" - if (target_os == "test") { + + # kernel_version = "5.10.79_aarch64" + kernel_version = "." + if (target == "test") { enable_ts_utest = true } else { enable_ts_utest = false } + is_openharmony = false } else { enable_ts_utest = true use_wasm = false - OHOS_FTRACE_PROTO_DIR = - "//developtools/profiler/protos/types/plugins/ftrace_data" + kernel_version = "." + is_fuzz = false + target = "trace_streamer" + is_openharmony = true + OHOS_FTRACE_PROTO_DIR = "//developtools/profiler/protos/types/plugins/ftrace_data/${kernel_version}" OHOS_MEMORY_PROTO_DIR = "//developtools/profiler/protos/types/plugins/memory_data" OHOS_HILOG_PROTO_DIR = @@ -51,6 +57,5 @@ if (target_os == "linux" || target_os == "windows" || target_os == "wasm" || OHOS_HIDUMP_PROTO_DIR = "//developtools/profiler/protos/types/plugins/hidump_data" OHOS_SERVICE_PROTO_DIR = "//developtools/profiler/protos/services" - OHOS_PROTO_GEN = - "//developtools/profiler/trace_analyzer/third_party/protogen/" + OHOS_PROTO_GEN = "//out/ohos-arm-release/gen/cpp/developtools/profiler/protos" } diff --git a/host/trace_streamer/test/BUILD.gn b/host/trace_streamer/test/BUILD.gn old mode 100644 new mode 100755 index 1d20471e7ef42f9630aabc2fd2f23bd5b4b9214b..b8912c96356296f82f4f5cf9c70f78b3336c0238 --- a/host/trace_streamer/test/BUILD.gn +++ b/host/trace_streamer/test/BUILD.gn @@ -13,118 +13,137 @@ import("//build/ohos.gni") import("//build/test.gni") - -#import("../../device/base/config.gni") import("test_ts.gni") -#module_output_path = "${OHOS_PROFILER_TEST_MODULE_OUTPUT_PATH}/trace_analyzer" -config("module_private_config") { - visibility = [ ":*" ] - cflags_cc = [ "-std=c++17" ] - - # if (current_toolchain != host_toolchain) { - # defines = [ "HAVE_HILOG" ] - # } -} - -ohos_unittest("hiprofiler_ts_ut") { - # module_out_path = module_output_path - sources = [ - "unittest/binder_filter_test.cpp", - "unittest/bytrace_parser_test.cpp", - "unittest/clock_filter_test.cpp", - "unittest/cpu_filter_test.cpp", - "unittest/event_parser_test.cpp", - "unittest/filter_filter_test.cpp", - "unittest/hilog_parser_test.cpp", - "unittest/htrace_binder_event_test.cpp", - "unittest/htrace_event_parser_test.cpp", - "unittest/htrace_irq_event_test.cpp", - "unittest/htrace_mem_parser_test.cpp", - "unittest/htrace_sys_mem_parser_test.cpp", - "unittest/htrace_sys_vmem_parser_test.cpp", - "unittest/irq_filter_test.cpp", - "unittest/measure_filter_test.cpp", - "unittest/parser_test.cpp", - "unittest/process_filter_test.cpp", - "unittest/slice_filter_test.cpp", - ] - deps = [ - # "${OHOS_FTRACE_PROTO_DIR}:ftrace_data_cpp", - # "${OHOS_MEMORY_PROTO_DIR}:memory_data_cpp", - # "${OHOS_HILOG_PROTO_DIR}:hilog_data_cpp", - # "${OHOS_NATIVE_HOOK_PROTO_DIR}:native_hook_cpp", - # "${OHOS_HIDUMP_PROTO_DIR}:hidump_data_cpp", - # "${OHOS_SERVICE_PROTO_DIR}:proto_services_cpp", - "../src:trace_streamer_source", - "//prebuilts/protos:ts_proto_data_cpp", - "//third_party/googletest:gtest_main", - "//third_party/protobuf:protobuf", - "//third_party/protobuf:protobuf_lite", - "//third_party/sqlite:sqlite", - - # "//utils/native/base:utilsecurec", - ] - include_dirs = [ - "../src", - "../src/trace_data", - "../src/table", - "../src/filter", - "../src/base", - "../src/include", - "../src/trace_streamer", - "../src/parser/bytrace_parser", - "../src/parser", - "../src/cfg", - "../src/parser/htrace_parser", - "../src/parser/htrace_parser/htrace_event_parser", - "../src/parser/htrace_parser/htrace_cpu_parser", - "..", - "//third_party/googletest/googletest/include/gtest", - "//utils/native/base/include", - "//third_party/protobuf/src", - "${OHOS_PROTO_GEN}", - "${OHOS_FTRACE_PROTO_DIR}", - "${OHOS_MEMORY_PROTO_DIR}", - "${OHOS_HILOG_PROTO_DIR}", - "${OHOS_NATIVE_HOOK_PROTO_DIR}", - "${OHOS_HIDUMP_PROTO_DIR}", - "${OHOS_SERVICE_PROTO_DIR}", - ] - cflags = [ - "-Wno-inconsistent-missing-override", - "-Dprivate=public", #allow test code access private members - "-fprofile-arcs", - "-ftest-coverage", - "-Wno-unused-command-line-argument", - "-Wno-format", - "-Wno-unused-const-variable", - "-Wno-unused-variable", - "-Wno-used-but-marked-unused", - ] - ldflags = [ - "-fprofile-arcs", - "-ftest-coverage", - "--coverage", - ] - - # external_deps = [ "hiviewdfx_hilog_native:libhilog" ] - # public_configs = [ "${OHOS_PROFILER_DIR}/device/base:hiprofiler_test_config" ] - configs = [ ":module_private_config" ] - - # subsystem_name = "${OHOS_PROFILER_SUBSYS_NAME}" +if (target == "test") { + ohos_unittest("trace_streamer_ut") { + sources = [ + "unittest/binder_filter_test.cpp", + "unittest/bio_parser_test.cpp", + "unittest/bytrace_parser_test.cpp", + "unittest/clock_filter_test.cpp", + "unittest/cpu_filter_test.cpp", + "unittest/ebpf_file_system_test.cpp", + "unittest/ebpf_parser_test.cpp", + "unittest/event_parser_test.cpp", + "unittest/filter_filter_test.cpp", + "unittest/hidump_parser_test.cpp", + "unittest/hilog_parser_test.cpp", + "unittest/hisys_event_parser_test.cpp", + "unittest/htrace_binder_event_test.cpp", + "unittest/htrace_cpu_data_parser_test.cpp", + "unittest/htrace_cpu_detail_parser_test.cpp", + "unittest/htrace_diskio_parser_test.cpp", + "unittest/htrace_event_parser_test.cpp", + "unittest/htrace_irq_event_test.cpp", + "unittest/htrace_mem_parser_test.cpp", + "unittest/htrace_network_parser_test.cpp", + "unittest/htrace_process_parser_test.cpp", + "unittest/htrace_sys_mem_parser_test.cpp", + "unittest/htrace_sys_vmem_parser_test.cpp", + "unittest/http_server_test.cpp", + "unittest/irq_filter_test.cpp", + "unittest/measure_filter_test.cpp", + "unittest/native_hook_parser_test.cpp", + "unittest/paged_memory_parser_test.cpp", + "unittest/parser_test.cpp", + "unittest/process_filter_test.cpp", + "unittest/rpc_server_test.cpp", + "unittest/slice_filter_test.cpp", + "unittest/smaps_parser_test.cpp", + "unittest/span_join_test.cpp", + "unittest/table_test.cpp", + "unittest/wasm_func_test.cpp", + ] + deps = [ + "../src:trace_streamer_source", + "//prebuilts/protos:ts_proto_data_cpp", + "//third_party/googletest:gtest", + "//third_party/googletest:gtest_main", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + "//third_party/sqlite:sqlite", + ] + include_dirs = [ + "../src", + "../src/trace_data", + "../src/table", + "../src/filter", + "../src/base", + "../src/rpc", + "../src/include", + "../src/trace_streamer", + "../src/parser/bytrace_parser", + "../src/parser", + "../src/cfg", + "../src/parser/htrace_parser", + "../src/parser/htrace_parser/htrace_event_parser", + "../src/parser/htrace_parser/htrace_cpu_parser", + "../src/parser/ebpf_parser", + "../prebuilts/emsdk/emsdk/emscripten/system/include", + "..", + "//third_party/googletest/googletest/include/gtest", + "//third_party/protobuf/src", + "//third_party/json-master/include", + "//third_party/json-master/include/nlohmann", + "//third_party/perf_include/musl", + "${OHOS_PROTO_GEN}", + "${OHOS_FTRACE_PROTO_DIR}", + "${OHOS_MEMORY_PROTO_DIR}", + "${OHOS_HILOG_PROTO_DIR}", + "${OHOS_NATIVE_HOOK_PROTO_DIR}", + "${OHOS_HIDUMP_PROTO_DIR}", + "${OHOS_NETWORK_PROTO_DIR}", + "${OHOS_DISKIO_PROTO_DIR}", + "${OHOS_CPUDATA_PROTO_DIR}", + "${OHOS_PROCESS_PROTO_DIR}", + "${OHOS_SERVICE_PROTO_DIR}", + ] + cflags = [ + "-Wno-inconsistent-missing-override", + "-Dprivate=public", #allow test code access private members + "-Dprotected=public", #allow test code access protect members + "-fprofile-arcs", + "-ftest-coverage", + "-Wno-unused-command-line-argument", + "-Wno-format", + "-Wno-unused-const-variable", + "-Wno-unused-variable", + "-Wno-used-but-marked-unused", + ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + cflags += [ + # clang coverage options: + "--coverage", + "-mllvm", + "-limited-coverage-experimental=true", + "-fno-use-cxa-atexit", + "-DIS_UT", + ] + if (is_macx) { + lib_dirs = [ "/usr/local/opt/llvm/lib" ] + } + libs = [ "LLVMCore" ] + } } # this is the dest for ohos.build -group("unittest") { - testonly = true - deps = [ ":hiprofiler_ts_ut" ] +if (target == "test") { + group("unittest") { + testonly = true + deps = [ ":trace_streamer_ut" ] + } +} else if (target == "fuzz") { + group("fuzztest") { + testonly = true + deps = [ + "test_fuzzer/bytrace_fuzzer:fuzztest", + "test_fuzzer/htrace_fuzzer:fuzztest", + "test_fuzzer/selector_fuzzer:fuzztest", + ] + } } -#group("fuzztest") { -# testonly = true -# deps = [ -# "test_fuzzer/bytrace_fuzzer:fuzztest", -# "test_fuzzer/htrace_fuzzer:fuzztest", -# "test_fuzzer/selector_fuzzer:fuzztest", -# ] -#} diff --git a/host/trace_streamer/test/resource/htrace.bin b/host/trace_streamer/test/resource/htrace.bin new file mode 100755 index 0000000000000000000000000000000000000000..c6fa0f8d8b9d057840ae1c033aed86f649be1b29 Binary files /dev/null and b/host/trace_streamer/test/resource/htrace.bin differ diff --git a/host/trace_streamer/test/resource/htrace_ebpf.bin b/host/trace_streamer/test/resource/htrace_ebpf.bin new file mode 100755 index 0000000000000000000000000000000000000000..6af3c0bc0cd489a73081ce8f46cecf5bbe81ae73 Binary files /dev/null and b/host/trace_streamer/test/resource/htrace_ebpf.bin differ diff --git a/host/trace_streamer/test/resource/htrace_ebpf_gold.db b/host/trace_streamer/test/resource/htrace_ebpf_gold.db new file mode 100755 index 0000000000000000000000000000000000000000..4e9ee8918a1167227677352b9b25f860097a60bd Binary files /dev/null and b/host/trace_streamer/test/resource/htrace_ebpf_gold.db differ diff --git a/host/trace_streamer/test/resource/htrace_gold.db b/host/trace_streamer/test/resource/htrace_gold.db new file mode 100755 index 0000000000000000000000000000000000000000..381f69302a03bad08189968db1eb2015d34ab550 Binary files /dev/null and b/host/trace_streamer/test/resource/htrace_gold.db differ diff --git a/host/trace_streamer/test/resource/htrace_perf.bin b/host/trace_streamer/test/resource/htrace_perf.bin new file mode 100755 index 0000000000000000000000000000000000000000..7e07460ebc739e896cd2f501ca97c25c78b0eb23 Binary files /dev/null and b/host/trace_streamer/test/resource/htrace_perf.bin differ diff --git a/host/trace_streamer/test/resource/htrace_perf_gold.db b/host/trace_streamer/test/resource/htrace_perf_gold.db new file mode 100755 index 0000000000000000000000000000000000000000..25ecb9e7c3bd0c055c28b85f84df1a024088a5eb Binary files /dev/null and b/host/trace_streamer/test/resource/htrace_perf_gold.db differ diff --git a/host/trace_streamer/test/resource/ut_bytrace_input_full.txt b/host/trace_streamer/test/resource/ut_bytrace_input_full.txt new file mode 100755 index 0000000000000000000000000000000000000000..0a0588c4628428677936486271326d3e5f10de47 --- /dev/null +++ b/host/trace_streamer/test/resource/ut_bytrace_input_full.txt @@ -0,0 +1,75 @@ +# TRACE: +# tracer: nop +# +# entries-in-buffer/entries-written: 1373949/1373949 #P:4 +# +# _-----=> irqs-off +# / _----=> need-resched +# | / _---=> hardirq/softirq +# || / _--=> preempt-depth +# ||| / delay +# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION +# | | | | |||| | | + ACCS0-2716 ( 2519) [000] ...1 168758.662861: binder_transaction: transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3 + ACCS0-2716 ( 2519) [000] ...1 168758.662869: binder_transaction_alloc_buf: transaction=25137708 data_size=80 offsets_size=0 + ACCS0-2716 ( 2519) [000] d..5 168758.662877: sched_waking: comm=Binder:924_3 pid=1200 prio=120 target_cpu=001 + ACCS0-2716 ( 2519) [000] d..6 168758.662898: sched_wakeup: comm=Binder:924_3 pid=1200 prio=120 target_cpu=001 + ACCS0-2716 ( 2519) [000] d..3 168758.662919: sched_switch: prev_comm=ACCS0 prev_pid=2716 prev_prio=120 prev_state=S ==> next_comm=HeapTaskDaemon next_pid=2532 next_prio=124 + HeapTaskDaemon-2532 ( 2519) [000] ...1 168758.662947: tracing_mark_write: E|2519 + HeapTaskDaemon-2532 ( 2519) [000] ...1 168758.662957: tracing_mark_write: B|2519|VisitNonThreadRoots + atrace-8528 ( 8528) [003] ...1 168758.662972: tracing_mark_write: trace_event_clock_sync: parent_ts=20445.875000 + atrace-8528 ( 8528) [003] ...1 168758.662986: tracing_mark_write: trace_event_clock_sync: realtime_ts=1616434280685 + -0 (-----) [001] dn.2 168758.662989: ipi_entry: (Rescheduling interrupts) + -0 (-----) [001] dn.2 168758.662992: ipi_exit: (Rescheduling interrupts) + -0 (-----) [001] .n.2 168758.662996: cpu_idle: state=4294967295 cpu_id=1 + HeapTaskDaemon-2532 ( 2519) [000] ...1 168758.663011: tracing_mark_write: E|2519 + -0 (-----) [001] d..3 168758.663017: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=Binder:924_3 next_pid=1200 next_prio=120 + HeapTaskDaemon-2532 ( 2519) [000] ...1 168758.663018: tracing_mark_write: B|2519|ProcessMarkStack + <...>-1200 (-----) [001] ...1 168758.663028: binder_transaction_received: transaction=25137708 + atrace-8528 ( 8528) [003] d..3 168758.663039: sched_switch: prev_comm=atrace prev_pid=8528 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120 + -0 (-----) [003] d..4 168758.663078: sched_waking: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + HeapTaskDaemon-2532 ( 2519) [000] d..1 168758.663089: ipi_entry: (Rescheduling interrupts) + -0 (-----) [003] d..2 168758.663089: softirq_raise: vec=9 [action=RCU] + -0 (-----) [003] d..3 168758.663092: sched_waking: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] dnh2 168758.663097: sched_wakeup: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + HeapTaskDaemon-2532 ( 2519) [000] dn.1 168758.663100: ipi_exit: (Rescheduling interrupts) + -0 (-----) [003] dn.4 168758.663104: sched_wakeup: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] d..3 168758.663107: sched_switch: prev_comm=HeapTaskDaemon prev_pid=2532 prev_prio=124 prev_state=R ==> next_comm=rcu_preempt next_pid=7 next_prio=98 + rcu_preempt-7 ( 7) [000] d..3 168758.663126: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=98 prev_state=S ==> next_comm=HeapTaskDaemon next_pid=2532 next_prio=124 + -0 (-----) [003] d..3 168758.663126: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/3 next_pid=29 next_prio=120 + ksoftirqd/3-29 ( 29) [003] ..s1 168758.663134: softirq_entry: vec=9 [action=RCU] + ksoftirqd/3-29 ( 29) [003] ..s1 168758.663141: softirq_exit: vec=9 [action=RCU] + ksoftirqd/3-29 ( 29) [003] d..3 168758.663159: sched_switch: prev_comm=ksoftirqd/3 prev_pid=29 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120 + -0 (-----) [003] d..4 168758.663181: sched_waking: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + -0 (-----) [003] d..2 168758.663188: softirq_raise: vec=9 [action=RCU] + HeapTaskDaemon-2532 ( 2519) [000] d..1 168758.663190: ipi_entry: (Rescheduling interrupts) + -0 (-----) [003] d..3 168758.663190: sched_waking: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] dnh2 168758.663194: sched_wakeup: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + HeapTaskDaemon-2532 ( 2519) [000] dn.1 168758.663195: ipi_exit: (Rescheduling interrupts) + -0 (-----) [003] dn.4 168758.663198: sched_wakeup: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] d..3 168758.663199: sched_switch: prev_comm=HeapTaskDaemon prev_pid=2532 prev_prio=124 prev_state=R+ ==> next_comm=rcu_preempt next_pid=7 next_prio=98 + rcu_preempt-7 ( 7) [000] d..3 168758.663209: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=98 prev_state=S ==> next_comm=HeapTaskDaemon next_pid=2532 next_prio=124 + -0 (-----) [003] d..3 168758.663212: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/3 next_pid=29 next_prio=120 + ksoftirqd/3-29 ( 29) [003] ..s1 168758.663218: softirq_entry: vec=9 [action=RCU] + ksoftirqd/3-29 ( 29) [003] ..s1 168758.663222: softirq_exit: vec=9 [action=RCU] + ksoftirqd/3-29 ( 29) [003] d..3 168758.663239: sched_switch: prev_comm=ksoftirqd/3 prev_pid=29 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120 + -0 (-----) [003] d..4 168758.663261: sched_waking: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + HeapTaskDaemon-2532 ( 2519) [000] d..1 168758.663270: ipi_entry: (Rescheduling interrupts) + -0 (-----) [003] d..2 168758.663270: softirq_raise: vec=9 [action=RCU] + -0 (-----) [003] d..3 168758.663272: sched_waking: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] dnh2 168758.663274: sched_wakeup: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + HeapTaskDaemon-2532 ( 2519) [000] dn.1 168758.663276: ipi_exit: (Rescheduling interrupts) + -0 (-----) [003] dn.4 168758.663279: sched_wakeup: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] d..3 168758.663280: sched_switch: prev_comm=HeapTaskDaemon prev_pid=2532 prev_prio=124 prev_state=R ==> next_comm=rcu_preempt next_pid=7 next_prio=98 + rcu_preempt-7 ( 7) [000] d..3 168758.663290: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=98 prev_state=S ==> next_comm=HeapTaskDaemon next_pid=2532 next_prio=124 + -0 (-----) [003] d..3 168758.663294: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/3 next_pid=29 next_prio=120 + ksoftirqd/3-29 ( 29) [003] ..s1 168758.663298: softirq_entry: vec=9 [action=RCU] + ksoftirqd/3-29 ( 29) [003] ..s1 168758.663301: softirq_exit: vec=9 [action=RCU] + <...>-1200 (-----) [001] ...1 168758.663302: binder_transaction: transaction=25137709 dest_node=0 dest_proc=2519 dest_thread=2716 reply=1 flags=0x0 code=0x0 + <...>-1200 (-----) [001] ...1 168758.663307: binder_transaction_alloc_buf: transaction=25137709 data_size=8 offsets_size=0 + <...>-1200 (-----) [001] d..3 168758.663312: sched_waking: comm=ACCS0 pid=2716 prio=120 target_cpu=000 + ksoftirqd/3-29 ( 29) [003] d..3 168758.663316: sched_switch: prev_comm=ksoftirqd/3 prev_pid=29 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120 + HeapTaskDaemon-2532 ( 2519) [000] dn.1 168758.663324: ipi_entry: (Rescheduling interrupts) + <...>-1200 (-----) [001] d..4 168758.663324: sched_wakeup: comm=ACCS0 pid=2716 prio=120 target_cpu=000 + HeapTaskDaemon-2532 ( 2519) [000] dn.1 168758.663325: ipi_exit: (Rescheduling interrupts) + HeapTaskDaemon-2532 ( 2519) [000] d..3 168758.663329: sched_switch: prev_comm=HeapTaskDaemon prev_pid=2532 prev_prio=124 prev_state=R ==> next_comm=ACCS0 next_pid=2716 next_prio=120 \ No newline at end of file diff --git a/host/trace_streamer/test/resource/ut_bytrace_input_full_gold.db b/host/trace_streamer/test/resource/ut_bytrace_input_full_gold.db new file mode 100755 index 0000000000000000000000000000000000000000..3fcc3e6696a9917fb635fb67b925d24f03fc18ec Binary files /dev/null and b/host/trace_streamer/test/resource/ut_bytrace_input_full_gold.db differ diff --git a/host/trace_streamer/test/resource/ut_bytrace_input_thread.txt b/host/trace_streamer/test/resource/ut_bytrace_input_thread.txt new file mode 100755 index 0000000000000000000000000000000000000000..1e6486754a3c12a68f1ad5e2f35641a47cf69ba7 --- /dev/null +++ b/host/trace_streamer/test/resource/ut_bytrace_input_thread.txt @@ -0,0 +1,43 @@ +# TRACE: +# tracer: nop +# +# entries-in-buffer/entries-written: 1373949/1373949 #P:4 +# +# _-----=> irqs-off +# / _----=> need-resched +# | / _---=> hardirq/softirq +# || / _--=> preempt-depth +# ||| / delay +# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION +# | | | | |||| | | + ACCS0-2716 ( 2519) [000] d..5 168758.662877: sched_waking: comm=Binder:924_3 pid=1200 prio=120 target_cpu=001 + ACCS0-2716 ( 2519) [000] d..6 168758.662898: sched_wakeup: comm=Binder:924_3 pid=1200 prio=120 target_cpu=001 + -0 (-----) [001] d..3 168758.663017: sched_switch: prev_comm=swapper/1 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=Binder:924_3 next_pid=1200 next_prio=120 + atrace-8528 ( 8528) [003] d..3 168758.663039: sched_switch: prev_comm=atrace prev_pid=8528 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120 + -0 (-----) [003] d..3 168758.663092: sched_waking: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] dnh2 168758.663097: sched_wakeup: comm=rcu_preempt pid=7 prio=98 target_cpu=000) + -0 (-----) [003] dn.4 168758.663104: sched_wakeup: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] d..3 168758.663107: sched_switch: prev_comm=HeapTaskDaemon prev_pid=2532 prev_prio=124 prev_state=R ==> next_comm=rcu_preempt next_pid=7 next_prio=98 + rcu_preempt-7 ( 7) [000] d..3 168758.663126: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=98 prev_state=S ==> next_comm=HeapTaskDaemon next_pid=2532 next_prio=124 + -0 (-----) [003] d..3 168758.663126: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/3 next_pid=29 next_prio=120 + ksoftirqd/3-29 ( 29) [003] d..3 168758.663159: sched_switch: prev_comm=ksoftirqd/3 prev_pid=29 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120 + -0 (-----) [003] d..4 168758.663181: sched_waking: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + -0 (-----) [003] d..3 168758.663190: sched_waking: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] dnh2 168758.663194: sched_wakeup: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + -0 (-----) [003] dn.4 168758.663198: sched_wakeup: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] d..3 168758.663199: sched_switch: prev_comm=HeapTaskDaemon prev_pid=2532 prev_prio=124 prev_state=R+ ==> next_comm=rcu_preempt next_pid=7 next_prio=98 + rcu_preempt-7 ( 7) [000] d..3 168758.663209: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=98 prev_state=S ==> next_comm=HeapTaskDaemon next_pid=2532 next_prio=124 + -0 (-----) [003] d..3 168758.663212: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/3 next_pid=29 next_prio=120 + ksoftirqd/3-29 ( 29) [003] d..3 168758.663239: sched_switch: prev_comm=ksoftirqd/3 prev_pid=29 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120 + -0 (-----) [003] d..4 168758.663261: sched_waking: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + -0 (-----) [003] d..3 168758.663272: sched_waking: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] dnh2 168758.663274: sched_wakeup: comm=rcu_preempt pid=7 prio=98 target_cpu=000 + -0 (-----) [003] dn.4 168758.663279: sched_wakeup: comm=ksoftirqd/3 pid=29 prio=120 target_cpu=003 + HeapTaskDaemon-2532 ( 2519) [000] d..3 168758.663280: sched_switch: prev_comm=HeapTaskDaemon prev_pid=2532 prev_prio=124 prev_state=R ==> next_comm=rcu_preempt next_pid=7 next_prio=98 + rcu_preempt-7 ( 7) [000] d..3 168758.663290: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=98 prev_state=S ==> next_comm=HeapTaskDaemon next_pid=2532 next_prio=124 + -0 (-----) [003] d..3 168758.663294: sched_switch: prev_comm=swapper/3 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=ksoftirqd/3 next_pid=29 next_prio=120 + <...>-1200 (-----) [001] d..3 168758.663312: sched_waking: comm=ACCS0 pid=2716 prio=120 target_cpu=000 + ksoftirqd/3-29 ( 29) [003] d..3 168758.663316: sched_switch: prev_comm=ksoftirqd/3 prev_pid=29 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120 + <...>-1200 (-----) [001] d..4 168758.663324: sched_wakeup: comm=ACCS0 pid=2716 prio=120 target_cpu=000 + HeapTaskDaemon-2532 ( 2519) [000] d..3 168758.663329: sched_switch: prev_comm=HeapTaskDaemon prev_pid=2532 prev_prio=124 prev_state=R ==> next_comm=ACCS0 next_pid=2716 next_prio=120 + \ No newline at end of file diff --git a/host/trace_streamer/test/resource/ut_bytrace_input_thread_gold.db b/host/trace_streamer/test/resource/ut_bytrace_input_thread_gold.db new file mode 100755 index 0000000000000000000000000000000000000000..8e429972480b4b1b1c5574afe868ef32f30ff9f6 Binary files /dev/null and b/host/trace_streamer/test/resource/ut_bytrace_input_thread_gold.db differ diff --git a/host/trace_streamer/test/test_fuzzer/README.md b/host/trace_streamer/test/test_fuzzer/README.md new file mode 100644 index 0000000000000000000000000000000000000000..bbb57beec4db2bdf6f6b52c9271cd32f5f9d381e --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/README.md @@ -0,0 +1,49 @@ +# Hi3516烧录OH2代码 + 1. 连接串口线, USB和网线。 + 2. 使用HiTool工具加载并烧写OH2代码编译镜像。 + 镜像路径: OH2_TOOL\out\ohos-arm-release\packages\phone\images\Hi3516DV300-emmc.xml + 3. 在新烧录好的开发板配置网络信息。 + 配置IP: ifconfig eth0 xxx.xxx.xxx.xxx + 配置子网掩码: ifconfig eth0 xxx.xxx.xxx.xxx netmask 255.255.255.0 + 分配hdcd端口: hdcd -t & + 查看端口: netstat -nat + +# 编译FUZZ测试二进制文件 + 1. 修改OH2_TOOL/developtools/profiler/ohos.build + 在testlist中添加:"//developtools/profiler/trace_analyzer/test:fuzztest" + 2. 启动测试shell。 + cd OH2_TOOL + ./test/developertest/start.sh 根据输出提示选择 hi3516DV300对应的数字。 + 3. 编译可执行程序。 + run -t FUZZ -ss developtools -ts hiprofiler_ts_bytrace_fuzz_test + run -t FUZZ -ss developtools -ts hiprofiler_ts_htrace_fuzz_test + run -t FUZZ -ss developtools -ts hiprofiler_ts_selector_fuzz_test + 生成可执行文件路径: OH2_TOOL/out/ohos-arm-release/packages/phone/tests/fuzztest/hiprofiler/ts_fuzz/ + +# 准备FUZZ测试环境 + 1. 使用hdc工具将上一步生成的可执行程序上传到开发板指定目录。 + 例如: hdc_std file send hiprofiler_ts_htrace_fuzz_test /data/local/tmp/FuzzTest + 添加执行权限 chmod +x hiprofiler_ts_htrace_fuzz_test + 2. 上传动态库。 + 代码目录下查询以下动态库, 并上传到开发板/system/lib目录。 + libsqlite.z.so + libcrypto.so + libssl.z.so + libcrypto.z.so + libgrpc.z.so + +# 执行FUZZ测试用例 + cd /data/local/tmp/FuzzTest + ./hiprofiler_ts_bytrace_fuzz_test -max_total_time=20 + ./hiprofiler_ts_htrace_fuzz_test -max_total_time=20 + ./hiprofiler_ts_selector_fuzz_test -max_total_time=20 + +# 可能遇到的问题 + 1. 开发板启动失败,重启开发板,进入uboot中配置启动参数。 + setenv bootargs 'mem=640M console=ttyAMA0,115200 mmz=anonymous,0,0xA8000000,384M clk_ignore_unused androidboot.selinux=permissive skip_initramfs rootdelay=10 init=/init root=/dev/mmcblk0p5 rootfstype=ext4 rw blkdevparts=mmcblk0:1M(boot),15M(kernel),20M(updater),1M(misc),3307M(system),256M(vendor),-(userdata)' + setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; bootm 0x80000000"; + save + reset + 2. 执行测试用例过程中报“cannot merge previous GCDA ”。 + 在开发板上进入OH2_TOOL目录,执行以下命令: + find . -name "*.gcda" -print0 | xargs -0 rm diff --git a/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn b/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0f47af2ad0af507a64e9089722284311207980db --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/BUILD.gn @@ -0,0 +1,79 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/ohos.gni") +import("//build/test.gni") +import("../../test_ts.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ts_bytrace_fuzz_test") { + include_dirs = [ + "../../../src", + "../../../src/base", + "../../../src/table", + "../../../src/filter", + "../../../src/trace_data", + "../../../src/parser", + "../../../src/trace_streamer", + "../../../src/include", + "../../../src/parser/bytrace_parser", + "../../../src/cfg", + "../../../src/parser/htrace_parser", + "../../../src/parser/htrace_parser/htrace_event_parser", + "../../../src/parser/htrace_parser/htrace_cpu_parser", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/${kernel_version}", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data", + "${OHOS_PROTO_GEN}/types/plugins/native_hook", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}/types/plugins/network_data", + "${OHOS_PROTO_GEN}/types/plugins/cpu_data", + "${OHOS_PROTO_GEN}/types/plugins/diskio_data", + "${OHOS_PROTO_GEN}/types/plugins/process_data", + "${OHOS_PROTO_GEN}/types/plugins/hisysevent_data", + "${OHOS_PROTO_GEN}", + "//third_party/protobuf/src", + ] + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "bytrace_fuzzer.cpp" ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + deps = [ + "../../../src:trace_streamer_source", + "//prebuilts/protos:ts_proto_data_cpp", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + "//third_party/sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":ts_bytrace_fuzz_test", + ] +} +############################################################################### diff --git a/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/bytrace_fuzzer.cpp b/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/bytrace_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac631addf854da2756605f7c5a1633d77bca4c28 --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/bytrace_fuzzer.cpp @@ -0,0 +1,53 @@ +/* + * 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. + */ + +#include "bytrace_fuzzer.h" +#include +#include +#include +#include "common_types.h" +#include "string_help.h" +#include "trace_streamer_selector.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::base; +bool BytraceParserFuzzTest(const uint8_t* data, size_t size) +{ + if (!size) { + return true; + } + TS_LOGI("size:%u", size); + TraceStreamerSelector stream_ = {}; + stream_.SetDataType(TRACE_FILETYPE_BY_TRACE); + std::unique_ptr buf = std::make_unique(size); + if (memcpy_s(buf.get(), size, data, size)) { + return false; + } + stream_.SetCleanMode(true); + stream_.ParseTraceDataSegment(std::move(buf), size); + stream_.WaitForParserEnd(); + return true; +} +} // namespace TraceStreamer +} // namespace SysTuning + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + SysTuning::TraceStreamer::BytraceParserFuzzTest(data, size); + return 0; +} diff --git a/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/bytrace_fuzzer.h b/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/bytrace_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..39b435f1c56eaf1de1c0c58c3b3cd866876eecee --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/bytrace_fuzzer.h @@ -0,0 +1,19 @@ +/* + * 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. + */ + +#ifndef BYTRACE_FUZZER_H +#define BYTRACE_FUZZER_H +#define FUZZ_PROJECT_NAME "bytrace_fuzzer" +#endif diff --git a/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/project.xml b/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..85e7ef2c1cc6471e288306f6e3dcea5287a78b0e --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/bytrace_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn b/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..09a13fbb96a13079fcb9a4016f897a7e5899e21d --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/BUILD.gn @@ -0,0 +1,79 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/ohos.gni") +import("//build/test.gni") +import("../../test_ts.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ts_htrace_fuzz_test") { + include_dirs = [ + "../../../src", + "../../../src/base", + "../../../src/table", + "../../../src/filter", + "../../../src/trace_data", + "../../../src/parser", + "../../../src/trace_streamer", + "../../../src/include", + "../../../src/parser/bytrace_parser", + "../../../src/cfg", + "../../../src/parser/htrace_parser", + "../../../src/parser/htrace_parser/htrace_event_parser", + "../../../src/parser/htrace_parser/htrace_cpu_parser", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/${kernel_version}", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data", + "${OHOS_PROTO_GEN}/types/plugins/native_hook", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}/types/plugins/network_data", + "${OHOS_PROTO_GEN}/types/plugins/cpu_data", + "${OHOS_PROTO_GEN}/types/plugins/diskio_data", + "${OHOS_PROTO_GEN}/types/plugins/process_data", + "${OHOS_PROTO_GEN}/types/plugins/hisysevent_data", + "${OHOS_PROTO_GEN}", + "//third_party/protobuf/src", + ] + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "htrace_fuzzer.cpp" ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + deps = [ + "../../../src:trace_streamer_source", + "//prebuilts/protos:ts_proto_data_cpp", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + "//third_party/sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":ts_htrace_fuzz_test", + ] +} +############################################################################### diff --git a/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/htrace_fuzzer.cpp b/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/htrace_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f294751a7dd5f52b166840c3657a0d1860d2c5f --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/htrace_fuzzer.cpp @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#include "htrace_fuzzer.h" +#include +#include +#include +#include "common_types.h" +#include "string_help.h" +#include "trace_streamer_selector.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::base; +bool HtraceParserFuzzTest(const uint8_t* data, size_t size) +{ + TraceStreamerSelector stream_ = {}; + stream_.SetDataType(TRACE_FILETYPE_H_TRACE); + std::unique_ptr buf = std::make_unique(size); + if (memcpy_s(buf.get(), size, data, size)) { + return false; + } + stream_.SetCleanMode(true); + stream_.ParseTraceDataSegment(std::move(buf), size); + stream_.WaitForParserEnd(); + return true; +} +} // namespace TraceStreamer +} // namespace SysTuning + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + SysTuning::TraceStreamer::HtraceParserFuzzTest(data, size); + return 0; +} diff --git a/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/htrace_fuzzer.h b/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/htrace_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..534420bf9655aab17c1799b3610489cfd6bee577 --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/htrace_fuzzer.h @@ -0,0 +1,18 @@ +/* + * 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. + */ +#ifndef HTRACE_FUZZER_H +#define HTRACE_FUZZER_H +#define FUZZ_PROJECT_NAME "htrace_fuzzer" +#endif diff --git a/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/project.xml b/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..85e7ef2c1cc6471e288306f6e3dcea5287a78b0e --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/htrace_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/host/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn b/host/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..bb8d8c7558e2e8d5c436c7ce38d1cb69d376075c --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/selector_fuzzer/BUILD.gn @@ -0,0 +1,79 @@ +# 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. + +#####################hydra-fuzz################### +import("//build/ohos.gni") +import("//build/test.gni") +import("../../test_ts.gni") + +##############################fuzztest########################################## +ohos_fuzztest("ts_selector_fuzz_test") { + include_dirs = [ + "../../../src", + "../../../src/base", + "../../../src/table", + "../../../src/filter", + "../../../src/trace_data", + "../../../src/parser", + "../../../src/trace_streamer", + "../../../src/include", + "../../../src/parser/bytrace_parser", + "../../../src/cfg", + "../../../src/parser/htrace_parser", + "../../../src/parser/htrace_parser/htrace_event_parser", + "../../../src/parser/htrace_parser/htrace_cpu_parser", + "//third_party/sqlite/include", + "${OHOS_PROTO_GEN}/types/plugins/memory_data", + "${OHOS_PROTO_GEN}/types/plugins/ftrace_data/${kernel_version}", + "${OHOS_PROTO_GEN}/types/plugins/hilog_data", + "${OHOS_PROTO_GEN}/types/plugins/native_hook", + "${OHOS_PROTO_GEN}/types/plugins/hidump_data", + "${OHOS_PROTO_GEN}/types/plugins/network_data", + "${OHOS_PROTO_GEN}/types/plugins/cpu_data", + "${OHOS_PROTO_GEN}/types/plugins/diskio_data", + "${OHOS_PROTO_GEN}/types/plugins/process_data", + "${OHOS_PROTO_GEN}/types/plugins/hisysevent_data", + "${OHOS_PROTO_GEN}", + "//third_party/protobuf/src", + ] + cflags = [ + "-g", + "-O0", + "-Wno-unused-variable", + "-fno-omit-frame-pointer", + ] + sources = [ "selector_fuzzer.cpp" ] + ldflags = [ + "-fprofile-arcs", + "-ftest-coverage", + "--coverage", + ] + deps = [ + "../../../src:trace_streamer_source", + "//prebuilts/protos:ts_proto_data_cpp", + "//third_party/protobuf:protobuf", + "//third_party/protobuf:protobuf_lite", + "//third_party/sqlite:sqlite", + ] +} + +############################################################################### +group("fuzztest") { + testonly = true + deps = [] + deps += [ + # deps file + ":ts_selector_fuzz_test", + ] +} +############################################################################### diff --git a/host/trace_streamer/test/test_fuzzer/selector_fuzzer/project.xml b/host/trace_streamer/test/test_fuzzer/selector_fuzzer/project.xml new file mode 100644 index 0000000000000000000000000000000000000000..85e7ef2c1cc6471e288306f6e3dcea5287a78b0e --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/selector_fuzzer/project.xml @@ -0,0 +1,25 @@ + + + + + + 1000 + + 300 + + 4096 + + diff --git a/host/trace_streamer/test/test_fuzzer/selector_fuzzer/selector_fuzzer.cpp b/host/trace_streamer/test/test_fuzzer/selector_fuzzer/selector_fuzzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0847c1583f7a4786f909c59ce97b018faa38b56f --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/selector_fuzzer/selector_fuzzer.cpp @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#include "selector_fuzzer.h" +#include +#include +#include +#include "common_types.h" +#include "string_help.h" +#include "trace_streamer_selector.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::base; +bool TraceStreamerSelectorFuzzTest(const uint8_t* data, size_t size) +{ + TraceStreamerSelector stream_ = {}; + std::unique_ptr buf = std::make_unique(size); + if (memcpy_s(buf.get(), size, data, size)) { + return false; + } + stream_.SetCleanMode(true); + stream_.ParseTraceDataSegment(std::move(buf), size); + stream_.WaitForParserEnd(); + return true; +} +} // namespace TraceStreamer +} // namespace SysTuning + +/* Fuzzer entry point */ +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + /* Run your code on data */ + SysTuning::TraceStreamer::TraceStreamerSelectorFuzzTest(data, size); + return 0; +} diff --git a/host/trace_streamer/test/test_fuzzer/selector_fuzzer/selector_fuzzer.h b/host/trace_streamer/test/test_fuzzer/selector_fuzzer/selector_fuzzer.h new file mode 100644 index 0000000000000000000000000000000000000000..cf572ff388f80b369cabf76845ae6ee535b7cd98 --- /dev/null +++ b/host/trace_streamer/test/test_fuzzer/selector_fuzzer/selector_fuzzer.h @@ -0,0 +1,19 @@ +/* + * 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. + */ + +#ifndef SELECTOR_FUZZER_H +#define SELECTOR_FUZZER_H +#define FUZZ_PROJECT_NAME "selector_fuzzer" +#endif diff --git a/host/trace_streamer/test/test_ts.gni b/host/trace_streamer/test/test_ts.gni old mode 100644 new mode 100755 index 6b7c44b89c21b411b5fa6b6d166006766bafc5c4..0a5bdaa1cb57e83000e31308943367d57edac6ca --- a/host/trace_streamer/test/test_ts.gni +++ b/host/trace_streamer/test/test_ts.gni @@ -10,23 +10,23 @@ # 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. - OHOS_PROTO_DIR = "" - -if (target_os == "linux" || target_os == "windows" || target_os == "test") { +kernel_version = "." +if (target_os == "linux" || target_os == "windows" || target_os == "macx") { OHOS_FTRACE_PROTO_DIR = "//src/multi_platform" OHOS_MEMORY_PROTO_DIR = "//src/multi_platform" OHOS_SERVICE_PROTO_DIR = "//src/multi_platform" OHOS_PROTO_GEN = "//third_party/protogen" - if (target_os == "test") { - OHOS_MEMORY_PROTO_DIR = "//third_party/protogen/types/plugins/memory_data" + if (target == "test") { + OHOS_MEMORY_PROTO_DIR = "$OHOS_PROTO_GEN/types/plugins/memory_data" + OHOS_NETWORK_PROTO_DIR = "$OHOS_PROTO_GEN/types/plugins/network_data" + OHOS_DISKIO_PROTO_DIR = "$OHOS_PROTO_GEN/types/plugins/diskio_data" + OHOS_CPUDATA_PROTO_DIR = "$OHOS_PROTO_GEN/types/plugins/cpu_data" + OHOS_PROCESS_PROTO_DIR = "$OHOS_PROTO_GEN/types/plugins/process_data" + OHOS_HISYSEVENT_PROTO_DIR = "$OHOS_PROTO_GEN/types/plugins/hisysevent_data" enable_ts_utest = true OHOS_HILOG_PROTO_DIR = "//src/multi_platform" - - # OHOS_NATIVE_HOOK_PROTO_DIR="//third_party/protogen" OHOS_NATIVE_HOOK_PROTO_DIR = "//src/multi_platform" - - # OHOS_HIDUMP_PROTO_DIR="//third_party/protogen" OHOS_HIDUMP_PROTO_DIR = "//src/multi_platform" } } else { diff --git a/host/trace_streamer/test/unittest/binder_filter_test.cpp b/host/trace_streamer/test/unittest/binder_filter_test.cpp index 4e028b407e5dd1e275c9439a1b0da0a7a908eabc..a1d4ce26fc6ed8d2ac08ad1597978fd98f82182f 100644 --- a/host/trace_streamer/test/unittest/binder_filter_test.cpp +++ b/host/trace_streamer/test/unittest/binder_filter_test.cpp @@ -53,7 +53,7 @@ public: */ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReply, TestSize.Level1) { - TS_LOGI("test9-1"); + TS_LOGI("test1-1"); uint64_t ts1 = 100; uint32_t tid1 = 1; uint64_t transactionId1 = 1; @@ -65,7 +65,6 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReply, TestSize.Level1) int32_t code = 0; // not important streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, destTid1, isReply, flags, code); // start binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 7); @@ -79,7 +78,7 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReply, TestSize.Level1) */ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceive, TestSize.Level1) { - TS_LOGI("test9-2"); + TS_LOGI("test1-2"); int64_t ts1 = 100; uint32_t tid1 = 1; uint64_t transactionId1 = 1; @@ -91,13 +90,11 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceive, TestSize.Level int32_t code = 0; // not importent streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, destTid1, isReply, flags, code); // start binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 7); ts1 = 200; uint32_t pid1 = 1; streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId1); // receive binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); @@ -125,7 +122,7 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceive, TestSize.Level */ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, TestSize.Level1) { - TS_LOGI("test9-3"); + TS_LOGI("test1-3"); int64_t ts1 = 100; uint32_t tid1 = 1; uint64_t transactionId1 = 1; @@ -138,7 +135,6 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, TestS streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, destTid1, isReply, flags, code); // start binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 7); @@ -146,13 +142,11 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, TestS uint64_t dataSize = 100; uint64_t offsetSize = 200; streamFilters_.binderFilter_->TransactionAllocBuf(ts1, tid1, dataSize, offsetSize); - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 9); ts1 = 200; uint32_t pid1 = 1; streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId1); // receive binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); @@ -166,7 +160,7 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, TestS */ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceiveNotmatch, TestSize.Level1) { - TS_LOGI("test9-4"); + TS_LOGI("test1-4"); int64_t ts1 = 100; uint32_t tid1 = 1; uint64_t transactionId1 = 1; @@ -179,13 +173,11 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceiveNotmatch, TestSi streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, destTid1, isReply, flags, code); // start binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); ts1 = 200; uint32_t pid1 = 1; uint64_t transactionId2 = 2; streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId2); // receive binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); } @@ -197,7 +189,7 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNeedReplyAndReceiveNotmatch, TestSi */ HWTEST_F(BinderFilterTest, BinderSenderfilterNoNeedReply, TestSize.Level1) { - TS_LOGI("test9-5"); + TS_LOGI("test1-5"); int64_t ts1 = 100; uint32_t tid1 = 1; uint64_t transactionId1 = 1; @@ -209,7 +201,6 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNoNeedReply, TestSize.Level1) int32_t code = 0; // not importent streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, destTid1, isReply, flags, code); // start binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); } @@ -220,7 +211,7 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterNoNeedReply, TestSize.Level1) */ HWTEST_F(BinderFilterTest, BinderSenderNoneedReplyAndReceivefilter, TestSize.Level1) { - TS_LOGI("test9-6"); + TS_LOGI("test1-6"); int64_t ts1 = 100; uint32_t tid1 = 1; uint64_t transactionId1 = 1; @@ -233,16 +224,14 @@ HWTEST_F(BinderFilterTest, BinderSenderNoneedReplyAndReceivefilter, TestSize.Lev streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, destTid1, isReply, flags, code); // start binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); ts1 = 200; uint32_t pid1 = 1; streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId1); // receive binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); + EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[1] == 0); } /** @@ -252,7 +241,7 @@ HWTEST_F(BinderFilterTest, BinderSenderNoneedReplyAndReceivefilter, TestSize.Lev */ HWTEST_F(BinderFilterTest, BinderSenderNoneedReplyAndReceivefilterNotmatch, TestSize.Level1) { - TS_LOGI("test9-7"); + TS_LOGI("test1-7"); int64_t ts1 = 100; uint32_t tid1 = 1; uint64_t transactionId1 = 1; @@ -265,14 +254,12 @@ HWTEST_F(BinderFilterTest, BinderSenderNoneedReplyAndReceivefilterNotmatch, Test streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, destTid1, isReply, flags, code); // start binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); ts1 = 200; uint32_t pid1 = 1; uint64_t transactionId2 = 2; streamFilters_.binderFilter_->ReceiveTraction(ts1, pid1, transactionId2); // receive binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); } @@ -284,7 +271,7 @@ HWTEST_F(BinderFilterTest, BinderSenderNoneedReplyAndReceivefilterNotmatch, Test */ HWTEST_F(BinderFilterTest, BinderSenderfilterWrongReply, TestSize.Level1) { - TS_LOGI("test9-8"); + TS_LOGI("test1-8"); int64_t ts1 = 100; uint32_t tid1 = 1; uint64_t transactionId1 = 1; @@ -297,7 +284,6 @@ HWTEST_F(BinderFilterTest, BinderSenderfilterWrongReply, TestSize.Level1) streamFilters_.binderFilter_->SendTraction(ts1, tid1, transactionId1, destNode1, destTgid1, destTid1, isReply, flags, code); // start binder - streamFilters_.binderFilter_->FinishBinderEvent(); EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 0); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 0); } diff --git a/host/trace_streamer/test/unittest/bio_parser_test.cpp b/host/trace_streamer/test/unittest/bio_parser_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..a055e4dc9a463a0ce964b1c46cc72565aae902dd --- /dev/null +++ b/host/trace_streamer/test/unittest/bio_parser_test.cpp @@ -0,0 +1,317 @@ + +/* + * 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. + */ +#include +#include +#include "bio_latency_data_parser.h" +#include "cpu_filter.h" +#include "ebpf_data_parser.h" +#include "ebpf_stdtype.h" +#include "process_filter.h" +#include "trace_streamer_selector.h" +#include "ts_common.h" +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +using namespace SysTuning::EbpfStdtype; +namespace SysTuning ::TraceStreamer { +const std::string COMMAND_LINE = "hiebpf --events ptrace --duration 50"; +const uint64_t EPBF_ERROR_MAGIC = 0x12345678; +const uint32_t EPBF_ERROR_HEAD_SIZE = 0; +class EbpfBioParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} + +public: + TraceStreamerSelector stream_ = {}; +}; +const char PROCESS_NAME_01[MAX_PROCESS_NAME_SZIE] = "process01"; +const uint64_t START_TIME = 1725645867369; +const uint64_t END_TIME = 1725645967369; +const uint64_t BLKCNT = 7829248; +const uint64_t IPS_01 = 548606407208; +const uint64_t IPS_02 = 548607407208; +const uint64_t EBPF_COMMAND_MAX_SIZE = 1000; +const uint32_t DURPER4K = 4096; +/** + * @tc.name: EbpfBioParserCorrectWithoutCallback + * @tc.desc: Test parse BIO data without callback + * @tc.type: FUNC + */ +HWTEST_F(EbpfBioParserTest, EbpfBioParserCorrectWithoutCallback, TestSize.Level1) +{ + TS_LOGI("test32-1"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = COMMAND_LINE.length(); + strcpy(ebpfHeader.cmdline, COMMAND_LINE.c_str()); + std::deque dequeBuffer; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(BIOFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_BIO; + BIOFixedHeader bioFixedHeader; + bioFixedHeader.pid = 32; + bioFixedHeader.tid = 32; + memcpy_s(bioFixedHeader.processName, MAX_PROCESS_NAME_SZIE, "process", MAX_PROCESS_NAME_SZIE); + bioFixedHeader.startTime = START_TIME; + bioFixedHeader.endTime = END_TIME; + bioFixedHeader.prio = 0; + bioFixedHeader.size = DURPER4K; + bioFixedHeader.blkcnt = BLKCNT; + bioFixedHeader.nips = 0; + bioFixedHeader.type = 2; + dequeBuffer.insert(dequeBuffer.end(), &(reinterpret_cast(&ebpfTypeAndLength))[0], + &(reinterpret_cast(&ebpfTypeAndLength))[sizeof(EbpfTypeAndLength)]); + dequeBuffer.insert(dequeBuffer.end(), &(reinterpret_cast(&bioFixedHeader))[0], + &(reinterpret_cast(&bioFixedHeader))[sizeof(BIOFixedHeader)]); + std::unique_ptr ebpfDataParser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(ebpfDataParser->reader_->GetBIOSampleMap().size()); + ebpfDataParser->ParseBioLatencyEvent(); + ebpfDataParser->Finish(); + EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstBioLatencySampleData().CallChainIds()[0]; + EXPECT_EQ(callChainId, INVALID_UINT64); + auto type = stream_.traceDataCache_->GetConstBioLatencySampleData().Types()[0]; + EXPECT_EQ(type, 2); + auto startTs = stream_.traceDataCache_->GetConstBioLatencySampleData().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME); + auto endTs = stream_.traceDataCache_->GetConstBioLatencySampleData().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME); + auto dur = stream_.traceDataCache_->GetConstBioLatencySampleData().LatencyDurs()[0]; + EXPECT_EQ(dur, END_TIME - START_TIME); + auto tier = stream_.traceDataCache_->GetConstBioLatencySampleData().Tiers()[0]; + EXPECT_EQ(tier, 0); + auto size = stream_.traceDataCache_->GetConstBioLatencySampleData().Sizes()[0]; + EXPECT_EQ(size, DURPER4K); + auto Expectblk = ebpfDataParser->ConvertToHexTextIndex(BLKCNT); + auto blk = stream_.traceDataCache_->GetConstBioLatencySampleData().BlockNumbers()[0]; + EXPECT_EQ(blk, Expectblk); + auto durPer4K = stream_.traceDataCache_->GetConstBioLatencySampleData().DurPer4k()[0]; + EXPECT_EQ(durPer4K, dur / (size / DURPER4K)); +} + +/** + * @tc.name: EbpfBioParserwrongWithoutCallback + * @tc.desc: Test parse BIO data without callback and startTs > endTs + * @tc.type: FUNC + */ +HWTEST_F(EbpfBioParserTest, EbpfBioParserwrongWithoutCallback, TestSize.Level1) +{ + TS_LOGI("test32-2"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = COMMAND_LINE.length(); + strcpy(ebpfHeader.cmdline, COMMAND_LINE.c_str()); + std::deque dequeBuffer; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(BIOFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_BIO; + BIOFixedHeader bioFixedHeader; + bioFixedHeader.pid = 32; + bioFixedHeader.tid = 32; + memcpy_s(bioFixedHeader.processName, MAX_PROCESS_NAME_SZIE, "process", MAX_PROCESS_NAME_SZIE); + bioFixedHeader.startTime = END_TIME; + bioFixedHeader.endTime = START_TIME; + bioFixedHeader.prio = 0; + bioFixedHeader.size = DURPER4K; + bioFixedHeader.blkcnt = BLKCNT; + bioFixedHeader.nips = 0; + bioFixedHeader.type = 2; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&bioFixedHeader), + reinterpret_cast(&bioFixedHeader + 1)); + std::unique_ptr ebpfDataParser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(ebpfDataParser->reader_->GetBIOSampleMap().size()); + ebpfDataParser->ParseBioLatencyEvent(); + ebpfDataParser->Finish(); + EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstBioLatencySampleData().CallChainIds()[0]; + EXPECT_FALSE(callChainId == INVALID_UINT64); + auto type = stream_.traceDataCache_->GetConstBioLatencySampleData().Types()[0]; + EXPECT_FALSE(type == 2); + auto startTs = stream_.traceDataCache_->GetConstBioLatencySampleData().StartTs()[0]; + EXPECT_FALSE(startTs == END_TIME); + auto endTs = stream_.traceDataCache_->GetConstBioLatencySampleData().EndTs()[0]; + EXPECT_FALSE(endTs == START_TIME); + auto dur = stream_.traceDataCache_->GetConstBioLatencySampleData().LatencyDurs()[0]; + EXPECT_FALSE(dur == endTs - startTs); + auto tier = stream_.traceDataCache_->GetConstBioLatencySampleData().Tiers()[0]; + EXPECT_FALSE(tier == 0); + auto size = stream_.traceDataCache_->GetConstBioLatencySampleData().Sizes()[0]; + EXPECT_FALSE(size == DURPER4K); + auto Expectblk = ebpfDataParser->ConvertToHexTextIndex(BLKCNT); + auto blk = stream_.traceDataCache_->GetConstBioLatencySampleData().BlockNumbers()[0]; + EXPECT_FALSE(blk == Expectblk); + auto durPer4K = stream_.traceDataCache_->GetConstBioLatencySampleData().DurPer4k()[0]; + EXPECT_FALSE(durPer4K == dur / (size / DURPER4K)); +} + +/** + * @tc.name: EbpfBioParserCorrectWithOneCallback + * @tc.desc: Test parse BIO data with one callback + * @tc.type: FUNC + */ +HWTEST_F(EbpfBioParserTest, EbpfBioParserCorrectWithOneCallback, TestSize.Level1) +{ + TS_LOGI("test32-3"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = COMMAND_LINE.length(); + memcpy_s(ebpfHeader.cmdline, EBPF_COMMAND_MAX_SIZE, COMMAND_LINE.c_str(), COMMAND_LINE.length()); + std::deque dequeBuffer; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(BIOFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_BIO; + BIOFixedHeader bioFixedHeader; + bioFixedHeader.pid = 32; + bioFixedHeader.tid = 32; + memcpy_s(bioFixedHeader.processName, MAX_PROCESS_NAME_SZIE, "process", MAX_PROCESS_NAME_SZIE); + bioFixedHeader.startTime = START_TIME; + bioFixedHeader.endTime = END_TIME; + bioFixedHeader.prio = 0; + bioFixedHeader.size = DURPER4K; + bioFixedHeader.blkcnt = BLKCNT; + bioFixedHeader.nips = 1; + bioFixedHeader.type = 2; + const uint64_t ips[1] = {IPS_01}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&bioFixedHeader), + reinterpret_cast(&bioFixedHeader + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(ips), + reinterpret_cast(&ips + 1)); + std::unique_ptr ebpfDataParser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(ebpfDataParser->reader_->GetBIOSampleMap().size()); + ebpfDataParser->ParseBioLatencyEvent(); + ebpfDataParser->Finish(); + EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstBioLatencySampleData().CallChainIds()[0]; + EXPECT_EQ(callChainId, 0); + auto type = stream_.traceDataCache_->GetConstBioLatencySampleData().Types()[0]; + EXPECT_EQ(type, 2); + auto ipid = stream_.traceDataCache_->GetConstBioLatencySampleData().Ipids()[0]; + EXPECT_EQ(ipid, 1); + auto itid = stream_.traceDataCache_->GetConstBioLatencySampleData().Itids()[0]; + EXPECT_EQ(itid, 1); + auto startTs = stream_.traceDataCache_->GetConstBioLatencySampleData().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME); + auto endTs = stream_.traceDataCache_->GetConstBioLatencySampleData().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME); + auto dur = stream_.traceDataCache_->GetConstBioLatencySampleData().LatencyDurs()[0]; + EXPECT_EQ(dur, END_TIME - START_TIME); + auto tier = stream_.traceDataCache_->GetConstBioLatencySampleData().Tiers()[0]; + EXPECT_EQ(tier, 0); + auto size = stream_.traceDataCache_->GetConstBioLatencySampleData().Sizes()[0]; + EXPECT_EQ(size, DURPER4K); + auto Expectblk = ebpfDataParser->ConvertToHexTextIndex(BLKCNT); + auto blk = stream_.traceDataCache_->GetConstBioLatencySampleData().BlockNumbers()[0]; + EXPECT_EQ(blk, Expectblk); + auto durPer4K = stream_.traceDataCache_->GetConstBioLatencySampleData().DurPer4k()[0]; + EXPECT_EQ(durPer4K, dur / (size / DURPER4K)); + auto ExpectIps0 = ebpfDataParser->ConvertToHexTextIndex(ips[0]); + auto ips0 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[0]; + EXPECT_EQ(ips0, ExpectIps0); +} + +/** + * @tc.name: EbpfBioParserCorrectWithMultipleCallback + * @tc.desc: Test parse BIO data with multiple callback + * @tc.type: FUNC + */ +HWTEST_F(EbpfBioParserTest, EbpfBioParserCorrectWithMultipleCallback, TestSize.Level1) +{ + TS_LOGI("test32-4"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = COMMAND_LINE.length(); + memcpy_s(ebpfHeader.cmdline, EBPF_COMMAND_MAX_SIZE, COMMAND_LINE.c_str(), COMMAND_LINE.length()); + std::deque dequeBuffer; + dequeBuffer.insert(dequeBuffer.end(), &(reinterpret_cast(&ebpfHeader))[0], + &(reinterpret_cast(&ebpfHeader))[EbpfDataHeader::EBPF_DATA_HEADER_SIZE]); + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(BIOFixedHeader) + 2 * sizeof(uint64_t); + ebpfTypeAndLength.type = ITEM_EVENT_BIO; + BIOFixedHeader bioFixedHeader; + bioFixedHeader.pid = 32; + bioFixedHeader.tid = 32; + memcpy_s(bioFixedHeader.processName, MAX_PROCESS_NAME_SZIE, "process", MAX_PROCESS_NAME_SZIE); + bioFixedHeader.startTime = START_TIME; + bioFixedHeader.endTime = END_TIME; + bioFixedHeader.prio = 0; + bioFixedHeader.size = DURPER4K; + bioFixedHeader.blkcnt = BLKCNT; + bioFixedHeader.nips = 2; + bioFixedHeader.type = 2; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&bioFixedHeader), + reinterpret_cast(&bioFixedHeader + 1)); + const uint64_t ips[2] = {IPS_01, IPS_02}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(ips), + reinterpret_cast(&ips + 1)); + std::unique_ptr ebpfDataParser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(ebpfDataParser->reader_->GetBIOSampleMap().size()); + ebpfDataParser->ParseBioLatencyEvent(); + ebpfDataParser->Finish(); + EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstBioLatencySampleData().CallChainIds()[0]; + EXPECT_EQ(callChainId, 0); + auto type = stream_.traceDataCache_->GetConstBioLatencySampleData().Types()[0]; + EXPECT_EQ(type, 2); + auto ipid = stream_.traceDataCache_->GetConstBioLatencySampleData().Ipids()[0]; + EXPECT_EQ(ipid, 1); + auto itid = stream_.traceDataCache_->GetConstBioLatencySampleData().Itids()[0]; + EXPECT_EQ(itid, 1); + auto startTs = stream_.traceDataCache_->GetConstBioLatencySampleData().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME); + auto endTs = stream_.traceDataCache_->GetConstBioLatencySampleData().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME); + auto dur = stream_.traceDataCache_->GetConstBioLatencySampleData().LatencyDurs()[0]; + EXPECT_EQ(dur, END_TIME - START_TIME); + auto tier = stream_.traceDataCache_->GetConstBioLatencySampleData().Tiers()[0]; + EXPECT_EQ(tier, 0); + auto size = stream_.traceDataCache_->GetConstBioLatencySampleData().Sizes()[0]; + EXPECT_EQ(size, DURPER4K); + auto Expectblk = ebpfDataParser->ConvertToHexTextIndex(BLKCNT); + auto blk = stream_.traceDataCache_->GetConstBioLatencySampleData().BlockNumbers()[0]; + EXPECT_EQ(blk, Expectblk); + auto durPer4K = stream_.traceDataCache_->GetConstBioLatencySampleData().DurPer4k()[0]; + EXPECT_EQ(durPer4K, dur / (size / DURPER4K)); + auto ExpectIps0 = ebpfDataParser->ConvertToHexTextIndex(ips[0]); + auto ips0 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[1]; + EXPECT_EQ(ips0, ExpectIps0); + auto ExpectIps1 = ebpfDataParser->ConvertToHexTextIndex(ips[1]); + auto ips1 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[0]; + EXPECT_EQ(ips1, ExpectIps1); +} +} // namespace SysTuning::TraceStreamer diff --git a/host/trace_streamer/test/unittest/bytrace_parser_test.cpp b/host/trace_streamer/test/unittest/bytrace_parser_test.cpp old mode 100644 new mode 100755 index b613d1819b72fac5574d83d647d5e8a772f0601a..70bcfa68e325f6d695c4ad762df9e41f943b001a --- a/host/trace_streamer/test/unittest/bytrace_parser_test.cpp +++ b/host/trace_streamer/test/unittest/bytrace_parser_test.cpp @@ -21,11 +21,12 @@ #include "parser/bytrace_parser/bytrace_parser.h" #include "parser/common_types.h" -#include "securec.h" +#include "string_help.h" #include "trace_streamer_selector.h" using namespace testing::ext; using namespace SysTuning::TraceStreamer; +using namespace SysTuning::base; namespace SysTuning { namespace TraceStreamer { @@ -40,7 +41,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "/data/resource/out.db"; + const std::string dbPath_ = "data/resource/out.db"; }; /** @@ -50,14 +51,11 @@ public: */ HWTEST_F(BytraceParserTest, ParseNoData, TestSize.Level1) { - TS_LOGI("test1-1"); + TS_LOGI("test2-1"); auto buf = std::make_unique(1); BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - printf("xxx\n"); bytraceParser.ParseTraceDataSegment(std::move(buf), 1); - printf("xxx2\n"); bytraceParser.WaitForParserEnd(); - printf("xxx3\n"); EXPECT_TRUE(bytraceParser.TraceCommentLines() == 0); EXPECT_TRUE(bytraceParser.ParsedTraceValidLines() == 0); EXPECT_TRUE(bytraceParser.ParsedTraceInvalidLines() == 0); @@ -70,15 +68,16 @@ HWTEST_F(BytraceParserTest, ParseNoData, TestSize.Level1) */ HWTEST_F(BytraceParserTest, ParseNoDataWhithLineFlag, TestSize.Level1) { - TS_LOGI("test1-2"); + TS_LOGI("test2-2"); constexpr uint32_t bufSize = 1024; auto buf = std::make_unique(bufSize); - if (memcpy_s(buf.get(), bufSize, " \n", strlen(" \n"))) { + auto realBufSize = strlen(" \n"); + if (memcpy_s(buf.get(), bufSize, " \n", realBufSize)) { EXPECT_TRUE(false); return; } BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - bytraceParser.ParseTraceDataSegment(std::move(buf), bufSize); + bytraceParser.ParseTraceDataSegment(std::move(buf), realBufSize); bytraceParser.WaitForParserEnd(); stream_.traceDataCache_->ExportDatabase(dbPath_); EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); @@ -94,15 +93,16 @@ HWTEST_F(BytraceParserTest, ParseNoDataWhithLineFlag, TestSize.Level1) */ HWTEST_F(BytraceParserTest, ParseInvalidData, TestSize.Level1) { - TS_LOGI("test1-3"); + TS_LOGI("test2-3"); constexpr uint32_t bufSize = 1024; auto buf = std::make_unique(bufSize); - if (memcpy_s(buf.get(), bufSize, "0123456789\n", strlen("0123456789\n"))) { + auto realBufSize = strlen("0123456789\n"); + if (memcpy_s(buf.get(), bufSize, "0123456789\n", realBufSize)) { EXPECT_TRUE(false); return; } BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - bytraceParser.ParseTraceDataSegment(std::move(buf), bufSize); + bytraceParser.ParseTraceDataSegment(std::move(buf), realBufSize); bytraceParser.WaitForParserEnd(); stream_.traceDataCache_->ExportDatabase(dbPath_); EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); @@ -118,15 +118,16 @@ HWTEST_F(BytraceParserTest, ParseInvalidData, TestSize.Level1) */ HWTEST_F(BytraceParserTest, ParseComment, TestSize.Level1) { - TS_LOGI("test1-4"); + TS_LOGI("test2-4"); constexpr uint32_t bufSize = 1024; auto buf = std::make_unique(bufSize); - if (memcpy_s(buf.get(), bufSize, "TRACE: \n# tracer: nop \n# \n", strlen("TRACE: \n# tracer: nop \n# \n"))) { + auto realBufSize = strlen("TRACE: \n# tracer: nop \n# \n"); + if (memcpy_s(buf.get(), bufSize, "TRACE: \n# tracer: nop \n# \n", realBufSize)) { EXPECT_TRUE(false); return; } BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - bytraceParser.ParseTraceDataSegment(std::move(buf), bufSize); + bytraceParser.ParseTraceDataSegment(std::move(buf), realBufSize); bytraceParser.WaitForParserEnd(); stream_.traceDataCache_->ExportDatabase(dbPath_); EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); @@ -142,15 +143,16 @@ HWTEST_F(BytraceParserTest, ParseComment, TestSize.Level1) */ HWTEST_F(BytraceParserTest, ParseInvalidLines, TestSize.Level1) { - TS_LOGI("test1-5"); + TS_LOGI("test2-5"); constexpr uint32_t bufSize = 1024; auto buf = std::make_unique(bufSize); - if (memcpy_s(buf.get(), bufSize, "\nafafda\n", strlen("\nafafda\n"))) { + auto realBufSize = strlen(" \nafafda\n"); + if (memcpy_s(buf.get(), bufSize, " \nafafda\n", realBufSize)) { EXPECT_TRUE(false); return; } BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - bytraceParser.ParseTraceDataSegment(std::move(buf), bufSize); + bytraceParser.ParseTraceDataSegment(std::move(buf), realBufSize); bytraceParser.WaitForParserEnd(); stream_.traceDataCache_->ExportDatabase(dbPath_); EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); @@ -166,10 +168,10 @@ HWTEST_F(BytraceParserTest, ParseInvalidLines, TestSize.Level1) */ HWTEST_F(BytraceParserTest, ParseNormal, TestSize.Level1) { - TS_LOGI("test1-6"); + TS_LOGI("test2-6"); std::string str( "ACCS0-2716 ( 2519) [000] ...1 168758.662861: binder_transaction: \ - transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3\n"); + transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3 \n"); BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); bytraceParser.ParseTraceDataItem(str); bytraceParser.WaitForParserEnd(); @@ -186,10 +188,10 @@ HWTEST_F(BytraceParserTest, ParseNormal, TestSize.Level1) */ HWTEST_F(BytraceParserTest, LineParser_abnormal_pid_err, TestSize.Level1) { - TS_LOGI("test1-7"); + TS_LOGI("test2-7"); std::string str( "ACCS0-27X6 ( 2519) [000] ...1 168758.662861: binder_transaction: \ - transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3\n"); + transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3 \n"); BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); bytraceParser.ParseTraceDataItem(str); bytraceParser.WaitForParserEnd(); @@ -206,10 +208,10 @@ HWTEST_F(BytraceParserTest, LineParser_abnormal_pid_err, TestSize.Level1) */ HWTEST_F(BytraceParserTest, LineParserWithInvalidCpu, TestSize.Level1) { - TS_LOGI("test1-8"); + TS_LOGI("test2-8"); std::string str( "ACCS0-2716 ( 2519) [00X] ...1 168758.662861: binder_transaction: \ - transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3\n"); + transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3 \n"); BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); bytraceParser.ParseTraceDataItem(str); bytraceParser.WaitForParserEnd(); @@ -226,10 +228,10 @@ HWTEST_F(BytraceParserTest, LineParserWithInvalidCpu, TestSize.Level1) */ HWTEST_F(BytraceParserTest, LineParserWithInvalidTs, TestSize.Level1) { - TS_LOGI("test1-9"); + TS_LOGI("test2-9"); std::string str( "ACCS0-2716 ( 2519) [000] ...1 168758.662X61: binder_transaction: \ - transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3\n"); + transaction=25137708 dest_node=4336 dest_proc=924 dest_thread=0 reply=0 flags=0x10 code=0x3 \n"); BytraceParser bytraceParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); bytraceParser.ParseTraceDataItem(str); bytraceParser.WaitForParserEnd(); diff --git a/host/trace_streamer/test/unittest/clock_filter_test.cpp b/host/trace_streamer/test/unittest/clock_filter_test.cpp old mode 100644 new mode 100755 index 833a3301a2ef1f6b3709d769953510e7fe8cdd35..d02bdb721d1f863ab15c4d7e7300da31d0cb7409 --- a/host/trace_streamer/test/unittest/clock_filter_test.cpp +++ b/host/trace_streamer/test/unittest/clock_filter_test.cpp @@ -45,7 +45,7 @@ public: */ HWTEST_F(ClockFilterTest, ConvertBoottimeToMonitonicTime, TestSize.Level1) { - TS_LOGI("test2-1"); + TS_LOGI("test3-1"); uint64_t tsBoottime = 100; uint64_t tsMonotonicTime = 200; std::vector snapShot0; @@ -59,13 +59,13 @@ HWTEST_F(ClockFilterTest, ConvertBoottimeToMonitonicTime, TestSize.Level1) } /** - * @tc.name: ConvertBoottimeToMonitonicTime + * @tc.name: ConvertBoottimeToMonitonicTimeTwice * @tc.desc: convert twice Boottime to MonitonicTime * @tc.type: FUNC */ HWTEST_F(ClockFilterTest, ConvertBoottimeToMonitonicTimeTwice, TestSize.Level1) { - TS_LOGI("test2-2"); + TS_LOGI("test3-2"); uint64_t tsBoottime = 100; uint64_t tsMonotonicTime = 200; std::vector snapShot0; @@ -82,13 +82,13 @@ HWTEST_F(ClockFilterTest, ConvertBoottimeToMonitonicTimeTwice, TestSize.Level1) } /** - * @tc.name: ConvertBoottimeToMonitonicTime - * @tc.desc: convert Boottime to MonitonicTime twice + * @tc.name: ConvertTimestampInvalid + * @tc.desc: Convert timestamp invalid * @tc.type: FUNC */ HWTEST_F(ClockFilterTest, ConvertTimestampInvalid, TestSize.Level1) { - TS_LOGI("test2-4"); + TS_LOGI("test3-3"); uint64_t tsBoottime = 100; uint64_t tsMonotonicTime = 200; std::vector snapShot0; @@ -114,7 +114,7 @@ HWTEST_F(ClockFilterTest, ConvertTimestampInvalid, TestSize.Level1) */ HWTEST_F(ClockFilterTest, ConvertTimestampBoottimeToRealtime, TestSize.Level1) { - TS_LOGI("test2-5"); + TS_LOGI("test3-4"); uint64_t tsBoottime = 100; uint64_t tsRealTime = 300; std::vector snapShot0; @@ -140,7 +140,7 @@ HWTEST_F(ClockFilterTest, ConvertTimestampBoottimeToRealtime, TestSize.Level1) */ HWTEST_F(ClockFilterTest, ConvertBoottimeToRealtimeTwiceWithTwoSnapShot, TestSize.Level1) { - TS_LOGI("test2-6"); + TS_LOGI("test3-5"); uint64_t tsBoottime = 100; uint64_t tsRealTime = 300; std::vector snapShot0; @@ -169,7 +169,7 @@ HWTEST_F(ClockFilterTest, ConvertBoottimeToRealtimeTwiceWithTwoSnapShot, TestSiz */ HWTEST_F(ClockFilterTest, ConvertBoottimeToRealtimeWithSingleSnapShot, TestSize.Level1) { - TS_LOGI("test2-7"); + TS_LOGI("test3-6"); uint64_t tsBoottime = 100; uint64_t tsRealTime = 300; std::vector snapShot0; @@ -192,7 +192,7 @@ HWTEST_F(ClockFilterTest, ConvertBoottimeToRealtimeWithSingleSnapShot, TestSize. */ HWTEST_F(ClockFilterTest, ConvertRealtimeToBoottime, TestSize.Level1) { - TS_LOGI("test2-8"); + TS_LOGI("test3-7"); uint64_t tsBoottime = 100; uint64_t tsRealTime = 300; std::vector snapShot0; @@ -211,7 +211,7 @@ HWTEST_F(ClockFilterTest, ConvertRealtimeToBoottime, TestSize.Level1) */ HWTEST_F(ClockFilterTest, ConvertRealtimeToBoottimeTwice, TestSize.Level1) { - TS_LOGI("test2-8"); + TS_LOGI("test3-8"); uint64_t tsBoottime = 100; uint64_t tsRealTime = 300; std::vector snapShot0; @@ -233,7 +233,7 @@ HWTEST_F(ClockFilterTest, ConvertRealtimeToBoottimeTwice, TestSize.Level1) */ HWTEST_F(ClockFilterTest, ConvertRealtimeToBoottimeTwiceWithTwoSnapshot, TestSize.Level1) { - TS_LOGI("test2-9"); + TS_LOGI("test3-9"); uint64_t tsBoottime = 100; uint64_t tsRealTime = 300; std::vector snapShot0; @@ -262,7 +262,7 @@ HWTEST_F(ClockFilterTest, ConvertRealtimeToBoottimeTwiceWithTwoSnapshot, TestSiz */ HWTEST_F(ClockFilterTest, ConvertTimestamp, TestSize.Level1) { - TS_LOGI("test2-10"); + TS_LOGI("test3-10"); uint64_t tsBoottime = 100; uint64_t tsMonotonicTime = 200; uint64_t tsRealTime = 300; @@ -323,7 +323,7 @@ HWTEST_F(ClockFilterTest, ConvertTimestamp, TestSize.Level1) */ HWTEST_F(ClockFilterTest, ConvertToPrimary, TestSize.Level1) { - TS_LOGI("test2-11"); + TS_LOGI("test3-11"); std::vector snapShot0; uint64_t tsBoottime = 100; uint64_t tsRealTime = 300; @@ -351,7 +351,7 @@ HWTEST_F(ClockFilterTest, ConvertToPrimary, TestSize.Level1) */ HWTEST_F(ClockFilterTest, ConvertToPrimaryTwice, TestSize.Level1) { - TS_LOGI("test2-11"); + TS_LOGI("test3-12"); std::vector snapShot0; uint64_t tsBoottime = 100; uint64_t tsRealTime = 300; @@ -379,7 +379,7 @@ HWTEST_F(ClockFilterTest, ConvertToPrimaryTwice, TestSize.Level1) */ HWTEST_F(ClockFilterTest, ConvertToPrimaryTimestampLessThanSnapShop, TestSize.Level1) { - TS_LOGI("test2-13"); + TS_LOGI("test3-13"); std::vector snapShot0; uint64_t tsBoottime = 100; uint64_t tsRealTime = 300; @@ -400,7 +400,7 @@ HWTEST_F(ClockFilterTest, ConvertToPrimaryTimestampLessThanSnapShop, TestSize.Le */ HWTEST_F(ClockFilterTest, ConvertMonotonicTimeToPrimaryTwice, TestSize.Level1) { - TS_LOGI("test2-14"); + TS_LOGI("test3-14"); std::vector snapShot0; uint64_t tsMonotonicTime = 200; uint64_t tsRealTimeCoarseTime = 400; @@ -424,7 +424,7 @@ HWTEST_F(ClockFilterTest, ConvertMonotonicTimeToPrimaryTwice, TestSize.Level1) */ HWTEST_F(ClockFilterTest, ConvertToPrimaryTwiceWithTwoSnapshop, TestSize.Level1) { - TS_LOGI("test2-15"); + TS_LOGI("test3-15"); std::vector snapShot0; uint64_t tsMonotonicTime = 200; uint64_t tsRealTimeCoarseTime = 400; @@ -457,7 +457,7 @@ HWTEST_F(ClockFilterTest, ConvertToPrimaryTwiceWithTwoSnapshop, TestSize.Level1) */ HWTEST_F(ClockFilterTest, MutiTimeTypeConvertWithMutiSnapshop, TestSize.Level1) { - TS_LOGI("test2-13"); + TS_LOGI("test3-16"); std::vector snapShot0; uint64_t tsBoottime = 100; uint64_t tsMonotonicTime = 200; diff --git a/host/trace_streamer/test/unittest/cpu_filter_test.cpp b/host/trace_streamer/test/unittest/cpu_filter_test.cpp old mode 100644 new mode 100755 index 3239bf9937c20f573bdaf49c95b9a96b5d9832fe..459ad7b54900d1692674e4dd181e1ba233004986 --- a/host/trace_streamer/test/unittest/cpu_filter_test.cpp +++ b/host/trace_streamer/test/unittest/cpu_filter_test.cpp @@ -17,6 +17,7 @@ #include #include "cpu_filter.h" +#include "process_filter.h" #include "ts_common.h" using namespace testing::ext; @@ -28,6 +29,7 @@ public: void SetUp() { streamFilters_.cpuFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); + streamFilters_.processFilter_ = std::make_unique(&traceDataCache_, &streamFilters_); } void TearDown() {} @@ -44,16 +46,15 @@ public: */ HWTEST_F(CpuFilterTest, CpufilterInsertWakeupTest, TestSize.Level1) { - TS_LOGI("test3-1"); + TS_LOGI("test4-1"); /* InsertWakeupEvent ts, internalTid */ uint64_t ts1 = 168758662877000; uint64_t itid = 1; streamFilters_.cpuFilter_->InsertWakeupEvent(ts1, itid); // 1st waking - streamFilters_.cpuFilter_->FinishCpuEvent(); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itid) == INVALID_UINT64); - EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itid) == TASK_INVALID); - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 0); // 0 thread state only + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itid) == 0); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itid) == TASK_RUNNABLE); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 1); // 0 thread state only } /** @@ -63,7 +64,7 @@ HWTEST_F(CpuFilterTest, CpufilterInsertWakeupTest, TestSize.Level1) */ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTest, TestSize.Level1) { - TS_LOGI("test3-2"); + TS_LOGI("test4-2"); uint64_t ts1 = 168758662919000; uint64_t itidPre = 2; uint64_t prePior = 120; @@ -73,7 +74,6 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTest, TestSize.Level1) streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, nextPior); // 1st switch - streamFilters_.cpuFilter_->FinishCpuEvent(); printf("state of pre itid: %llu\n", streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre)); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); @@ -89,7 +89,7 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTest, TestSize.Level1) */ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchFromZeroThread, TestSize.Level1) { - TS_LOGI("test3-2-2"); + TS_LOGI("test4-3"); uint64_t ts1 = 168758662919000; uint64_t itidPre = 0; uint64_t prePior = 120; @@ -99,7 +99,6 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchFromZeroThread, TestSize.Level1) streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, nextPior); // 1st switch - streamFilters_.cpuFilter_->FinishCpuEvent(); printf("state of pre itid: %llu\n", streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre)); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INVALID); @@ -115,7 +114,7 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchFromZeroThread, TestSize.Level1) */ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchToZeroThread, TestSize.Level1) { - TS_LOGI("test3-2-3"); + TS_LOGI("test4-4"); uint64_t ts1 = 168758662919000; uint64_t itidPre = 2; uint64_t prePior = 120; @@ -125,7 +124,6 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchToZeroThread, TestSize.Level1) streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, nextPior); // 1st switch - streamFilters_.cpuFilter_->FinishCpuEvent(); printf("state of pre itid: %llu\n", streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre)); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); @@ -141,7 +139,7 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchToZeroThread, TestSize.Level1) */ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchDoubleThread, TestSize.Level1) { - TS_LOGI("test3-3"); + TS_LOGI("test4-5"); uint64_t ts1 = 168758662919000; uint64_t itidPre = 2; uint64_t prePior = 120; @@ -151,7 +149,6 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchDoubleThread, TestSize.Level1) streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, nextPior); // 1st switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); @@ -165,9 +162,8 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchDoubleThread, TestSize.Level1) cpu = 0; itidNext = 4; nextPior = 120; - streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_RUNNABLE, itidNext, + streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, nextPior); // 2nd switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 2); @@ -182,7 +178,7 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchDoubleThread, TestSize.Level1) */ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchThreeThread, TestSize.Level1) { - TS_LOGI("test3-3-2"); + TS_LOGI("test4-6"); uint64_t ts1 = 168758662919000; uint64_t itidPre = 2; uint64_t prePior = 120; @@ -192,7 +188,6 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchThreeThread, TestSize.Level1) streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, nextPior); // 1st switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); @@ -208,7 +203,6 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchThreeThread, TestSize.Level1) nextPior = 120; streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_RUNNABLE, itidNext, nextPior); // 2nd switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 2); @@ -223,7 +217,7 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchThreeThread, TestSize.Level1) */ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTestZero, TestSize.Level1) { - TS_LOGI("test3-3-3"); + TS_LOGI("test4-7"); uint64_t ts1 = 168758662919000; uint64_t itidPre = 2; uint64_t prePior = 120; @@ -233,7 +227,6 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTestZero, TestSize.Level1) streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_INTERRUPTIBLE, itidNext, nextPior); // 1st switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidPre) == TASK_INTERRUPTIBLE); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); @@ -248,7 +241,6 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTestZero, TestSize.Level1) nextPior = 120; streamFilters_.cpuFilter_->InsertSwitchEvent(ts1, cpu, itidPre, prePior, TASK_RUNNABLE, itidNext, nextPior); // 2nd switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itidNext) == TASK_RUNNING); EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itidNext) == 2); @@ -260,18 +252,17 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTestZero, TestSize.Level1) * @tc.desc: Test CpuFilter insert Waking Event * @tc.type: FUNC */ -HWTEST_F(CpuFilterTest, CpufiltertWakeupTest, TestSize.Level1) +HWTEST_F(CpuFilterTest, CpufiltertWakeingTest, TestSize.Level1) { - TS_LOGI("test3-5"); + TS_LOGI("test4-8"); uint64_t ts1 = 168758662919000; uint64_t itid = 2; streamFilters_.cpuFilter_->InsertWakeupEvent(ts1, itid); - streamFilters_.cpuFilter_->FinishCpuEvent(); - EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itid) == TASK_INVALID); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itid) == INVALID_UINT64); - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 0); // 0 thread state + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itid) == TASK_RUNNABLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itid) == 0); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 1); // 0 thread state } /** @@ -281,20 +272,18 @@ HWTEST_F(CpuFilterTest, CpufiltertWakeupTest, TestSize.Level1) */ HWTEST_F(CpuFilterTest, CpufiltertWakingTwice, TestSize.Level1) { - TS_LOGI("test3-6"); + TS_LOGI("test4-9"); uint64_t ts1 = 168758662919000; uint64_t itid = 2; streamFilters_.cpuFilter_->InsertWakeupEvent(ts1, itid); - streamFilters_.cpuFilter_->FinishCpuEvent(); ts1 = 168758662929000; itid = 4; streamFilters_.cpuFilter_->InsertWakeupEvent(ts1, itid); - streamFilters_.cpuFilter_->FinishCpuEvent(); - EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itid) == TASK_INVALID); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itid) == INVALID_UINT64); - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 0); // 0 thread state + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(itid) == TASK_RUNNABLE); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(itid) == 1); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 2); // 0 thread state } /** @@ -304,26 +293,23 @@ HWTEST_F(CpuFilterTest, CpufiltertWakingTwice, TestSize.Level1) */ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTestFull, TestSize.Level1) { - TS_LOGI("test3-7"); + TS_LOGI("test4-10"); /* InsertWakeupEvent ts, internalTid */ /* InsertSwitchEvent ts, cpu, prevPid, prevPior, prevState, nextPid, nextPior */ streamFilters_.cpuFilter_->InsertWakeupEvent(168758662877000, 1); // 1st waking - streamFilters_.cpuFilter_->FinishCpuEvent(); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(1) == INVALID_UINT64); - EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(1) == TASK_INVALID); - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 0); // 0 thread state only + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(1) == 0); + EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(1) == TASK_RUNNABLE); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 1); // 0 thread state only streamFilters_.cpuFilter_->InsertSwitchEvent(168758662919000, 0, 1, 120, TASK_INTERRUPTIBLE, 2, 124); // 1st switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(1) == TASK_INTERRUPTIBLE); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(2) == TASK_RUNNING); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(2) == 0); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(2) == 1); // 2 thread state, the waking event add a runnable state EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 3); streamFilters_.cpuFilter_->InsertSwitchEvent(168758663017000, 0, 0, 120, TASK_RUNNABLE, 4, 120); // 2nd switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(4) == TASK_RUNNING); EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(4) == 3); @@ -332,39 +318,35 @@ HWTEST_F(CpuFilterTest, CpufilterInsertSwitchTestFull, TestSize.Level1) streamFilters_.cpuFilter_->InsertWakeupEvent(168758663078000, 0); // 2nd waking streamFilters_.cpuFilter_->InsertWakeupEvent(168758663092000, 0); // 3rd waking - streamFilters_.cpuFilter_->FinishCpuEvent(); streamFilters_.cpuFilter_->InsertSwitchEvent(168758663107000, 0, 2, 124, TASK_RUNNABLE, 5, 98); // 3rd switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(5) == TASK_RUNNING); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(2) == TASK_RUNNABLE); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(5) == 4); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(2) == 5); - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 6); // 6 thread state + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(5) == 6); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(2) == 7); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 8); // 6 thread state streamFilters_.cpuFilter_->InsertSwitchEvent(168758663126000, 0, 5, 98, TASK_INTERRUPTIBLE, 2, 124); // 4th switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(2) == TASK_RUNNING); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(5) == TASK_INTERRUPTIBLE); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(2) == 6); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(5) == 7); - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 8); // 8 thread state + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(2) == 8); + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(5) == 9); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 10); // 8 thread state streamFilters_.cpuFilter_->InsertSwitchEvent(168758663136000, 3, 5, 120, TASK_RUNNABLE, 6, 120); // 5th switch - streamFilters_.cpuFilter_->FinishCpuEvent(); EXPECT_TRUE(streamFilters_.cpuFilter_->StateOfInternalTidInStateTable(6) == TASK_RUNNING); - EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(6) == 8); - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 10); // 10 thread state + EXPECT_TRUE(streamFilters_.cpuFilter_->RowOfInternalTidInStateTable(6) == 10); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->Size() == 12); // 10 thread state // after 3rd switch - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[0] == 168758663107000 - 168758662919000); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[1] == 168758663107000 - 168758662919000); // after 4th switch - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[4] == 168758663126000 - 168758663107000); - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[5] == 168758663126000 - 168758663107000); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[6] == 168758663126000 - 168758663107000); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[7] == 168758663126000 - 168758663107000); // after 5th switch - EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[7] == 168758663136000 - 168758663126000); + EXPECT_TRUE(traceDataCache_.GetThreadStateData()->DursData()[9] == 168758663136000 - 168758663126000); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/ebpf_file_system_test.cpp b/host/trace_streamer/test/unittest/ebpf_file_system_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..1cd82f61a2eeec9868d753f18b2cee16d6edad72 --- /dev/null +++ b/host/trace_streamer/test/unittest/ebpf_file_system_test.cpp @@ -0,0 +1,510 @@ +/* + * 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. + */ + +#include +#include + +#include "ebpf_data_parser.h" +#include "ebpf_stdtype.h" +#include "process_filter.h" +#include "trace_streamer_selector.h" +#include "ts_common.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +using namespace SysTuning::EbpfStdtype; +namespace SysTuning { +namespace TraceStreamer { +class EbpfFileSystemTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +const uint32_t PID_01 = 32; +const uint32_t TID_01 = 12; +const uint32_t PID_02 = 33; +const uint32_t TID_02 = 13; +const uint64_t START_TIME_01 = 1725645867369; +const uint64_t END_TIME_01 = 1725645967369; +const uint64_t START_TIME_02 = 1725645867369; +const uint64_t END_TIME_02 = 1725645967369; +const int32_t RET_01 = 8; +const int32_t RET_02 = -1; +const uint16_t IPS_NUM_00 = 0; +const uint16_t IPS_NUM_01 = 1; +const uint16_t IPS_NUM_02 = 2; +const uint64_t ARGS_01[ARGS_MAX] = {101, 102, 103, 104}; +const uint64_t ARGS_02[ARGS_MAX] = {201, 202, 203, 204}; +const char PROCESS_NAME_01[MAX_PROCESS_NAME_SZIE] = "process01"; +const char PROCESS_NAME_02[MAX_PROCESS_NAME_SZIE] = "process02"; +const uint64_t IPS_01[IPS_NUM_01] = {0x100000000}; +const uint64_t IPS_02[IPS_NUM_02] = {0x100000000, 0x100000001}; + +/** + * @tc.name: ParseFileSystemWithTypeOpen + * @tc.desc: Test parse Ebpf data has one file system data with type open and no ips + * @tc.type: FUNC + */ +HWTEST_F(EbpfFileSystemTest, ParseFileSystemWithTypeOpen, TestSize.Level1) +{ + TS_LOGI("test30-1"); + + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + + FsFixedHeader fsFixedHeader; + fsFixedHeader.pid = PID_01; + fsFixedHeader.tid = TID_01; + fsFixedHeader.startTime = START_TIME_01; + fsFixedHeader.endTime = END_TIME_01; + fsFixedHeader.ret = RET_01; + fsFixedHeader.nrUserIPs = IPS_NUM_00; + fsFixedHeader.type = SYS_OPENAT2; + for (auto i = 0; i < ARGS_MAX; i++) { + fsFixedHeader.args[i] = ARGS_01[i]; + } + strncpy_s(fsFixedHeader.processName, MAX_PROCESS_NAME_SZIE, PROCESS_NAME_01, MAX_PROCESS_NAME_SZIE); + + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(fsFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_FS; + + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&fsFixedHeader), + reinterpret_cast(&fsFixedHeader + 1)); + + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(parser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(parser->reader_->GetFileSystemEventMap().size()); + parser->ParseFileSystemEvent(); + parser->Finish(); + EXPECT_TRUE(parser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstFileSystemSample().CallChainIds()[0]; + EXPECT_EQ(callChainId, INVALID_UINT64); + auto type = stream_.traceDataCache_->GetConstFileSystemSample().Types()[0]; + EXPECT_EQ(type, OPEN); + auto startTs = stream_.traceDataCache_->GetConstFileSystemSample().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME_01); + auto endTs = stream_.traceDataCache_->GetConstFileSystemSample().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME_01); + auto dur = stream_.traceDataCache_->GetConstFileSystemSample().Durs()[0]; + EXPECT_EQ(dur, END_TIME_01 - START_TIME_01); + auto ExpectReturnValue = parser->ConvertToHexTextIndex(RET_01); + auto returnValue = stream_.traceDataCache_->GetConstFileSystemSample().ReturnValues()[0]; + EXPECT_EQ(returnValue, ExpectReturnValue); + auto errorCode = stream_.traceDataCache_->GetConstFileSystemSample().ErrorCodes()[0]; + EXPECT_EQ(errorCode, INVALID_UINT64); + auto fd = stream_.traceDataCache_->GetConstFileSystemSample().Fds()[0]; + EXPECT_EQ(fd, RET_01); + auto fileId = stream_.traceDataCache_->GetConstFileSystemSample().FileIds()[0]; + EXPECT_EQ(fileId, INVALID_UINT64); + auto size = stream_.traceDataCache_->GetConstFileSystemSample().Sizes()[0]; + EXPECT_EQ(size, MAX_SIZE_T); + auto i = 0; + auto ExpectFirstArg = parser->ConvertToHexTextIndex(ARGS_01[i++]); + auto firstArg = stream_.traceDataCache_->GetConstFileSystemSample().FirstArguments()[0]; + EXPECT_EQ(firstArg, ExpectFirstArg); + auto ExpectSecondArg = parser->ConvertToHexTextIndex(ARGS_01[i++]); + auto secondArg = stream_.traceDataCache_->GetConstFileSystemSample().SecondArguments()[0]; + EXPECT_EQ(secondArg, ExpectSecondArg); + auto ExpectThirdArg = parser->ConvertToHexTextIndex(ARGS_01[i++]); + auto thirdArg = stream_.traceDataCache_->GetConstFileSystemSample().ThirdArguments()[0]; + EXPECT_EQ(thirdArg, ExpectThirdArg); + auto ExpectFourthArg = parser->ConvertToHexTextIndex(ARGS_01[i]); + auto fourthArg = stream_.traceDataCache_->GetConstFileSystemSample().FourthArguments()[0]; + EXPECT_EQ(fourthArg, ExpectFourthArg); +} + +/** + * @tc.name: ParseFileSystemWithTypeClose + * @tc.desc: Test parse Ebpf data has one file system data with type close and no ips and return value little to zero + * @tc.type: FUNC + */ +HWTEST_F(EbpfFileSystemTest, ParseFileSystemWithTypeClose, TestSize.Level1) +{ + TS_LOGI("test30-2"); + + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + + FsFixedHeader fsFixedHeader; + fsFixedHeader.pid = PID_02; + fsFixedHeader.tid = TID_02; + fsFixedHeader.startTime = START_TIME_02; + fsFixedHeader.endTime = END_TIME_02; + fsFixedHeader.ret = RET_02; + fsFixedHeader.nrUserIPs = IPS_NUM_00; + fsFixedHeader.type = SYS_CLOSE; + for (auto i = 0; i < ARGS_MAX; i++) { + fsFixedHeader.args[i] = ARGS_02[i]; + } + strncpy_s(fsFixedHeader.processName, MAX_PROCESS_NAME_SZIE, PROCESS_NAME_02, MAX_PROCESS_NAME_SZIE); + + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(fsFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_FS; + + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&fsFixedHeader), + reinterpret_cast(&fsFixedHeader + 1)); + + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(parser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(parser->reader_->GetFileSystemEventMap().size()); + parser->ParseFileSystemEvent(); + parser->Finish(); + EXPECT_TRUE(parser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstFileSystemSample().CallChainIds()[0]; + EXPECT_EQ(callChainId, INVALID_UINT64); + auto type = stream_.traceDataCache_->GetConstFileSystemSample().Types()[0]; + EXPECT_EQ(type, CLOSE); + auto startTs = stream_.traceDataCache_->GetConstFileSystemSample().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME_02); + auto endTs = stream_.traceDataCache_->GetConstFileSystemSample().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME_02); + auto dur = stream_.traceDataCache_->GetConstFileSystemSample().Durs()[0]; + EXPECT_EQ(dur, END_TIME_02 - START_TIME_02); + auto ExpectReturnValue = parser->ConvertToHexTextIndex(0); + auto returnValue = stream_.traceDataCache_->GetConstFileSystemSample().ReturnValues()[0]; + EXPECT_EQ(returnValue, ExpectReturnValue); + auto ExpectErrorValue = parser->ConvertToHexTextIndex(-RET_02); + auto errorCode = stream_.traceDataCache_->GetConstFileSystemSample().ErrorCodes()[0]; + EXPECT_EQ(errorCode, ExpectErrorValue); + auto fd = stream_.traceDataCache_->GetConstFileSystemSample().Fds()[0]; + EXPECT_EQ(fd, ARGS_02[1]); + auto fileId = stream_.traceDataCache_->GetConstFileSystemSample().FileIds()[0]; + EXPECT_EQ(fileId, INVALID_UINT64); + auto size = stream_.traceDataCache_->GetConstFileSystemSample().Sizes()[0]; + EXPECT_EQ(size, MAX_SIZE_T); + auto i = 0; + auto ExpectFirstArg = parser->ConvertToHexTextIndex(ARGS_02[i++]); + auto firstArg = stream_.traceDataCache_->GetConstFileSystemSample().FirstArguments()[0]; + EXPECT_EQ(firstArg, ExpectFirstArg); + auto ExpectSecondArg = parser->ConvertToHexTextIndex(ARGS_02[i++]); + auto secondArg = stream_.traceDataCache_->GetConstFileSystemSample().SecondArguments()[0]; + EXPECT_EQ(secondArg, ExpectSecondArg); + auto ExpectThirdArg = parser->ConvertToHexTextIndex(ARGS_02[i++]); + auto thirdArg = stream_.traceDataCache_->GetConstFileSystemSample().ThirdArguments()[0]; + EXPECT_EQ(thirdArg, ExpectThirdArg); + auto ExpectFourthArg = parser->ConvertToHexTextIndex(ARGS_02[i]); + auto fourthArg = stream_.traceDataCache_->GetConstFileSystemSample().FourthArguments()[0]; + EXPECT_EQ(fourthArg, ExpectFourthArg); +} + +/** + * @tc.name: ParseFileSystemWithTypeRead + * @tc.desc: Test parse Ebpf data has one file system data with type read and no ips + * @tc.type: FUNC + */ +HWTEST_F(EbpfFileSystemTest, ParseFileSystemWithTypeRead, TestSize.Level1) +{ + TS_LOGI("test30-3"); + + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + + FsFixedHeader fsFixedHeader; + fsFixedHeader.pid = PID_01; + fsFixedHeader.tid = TID_01; + fsFixedHeader.startTime = START_TIME_01; + fsFixedHeader.endTime = END_TIME_01; + fsFixedHeader.ret = RET_01; + fsFixedHeader.nrUserIPs = IPS_NUM_00; + fsFixedHeader.type = SYS_READ; + for (auto i = 0; i < ARGS_MAX; i++) { + fsFixedHeader.args[i] = ARGS_01[i]; + } + strncpy_s(fsFixedHeader.processName, MAX_PROCESS_NAME_SZIE, PROCESS_NAME_01, MAX_PROCESS_NAME_SZIE); + + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(fsFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_FS; + + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&fsFixedHeader), + reinterpret_cast(&fsFixedHeader + 1)); + + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(parser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(parser->reader_->GetFileSystemEventMap().size()); + parser->ParseFileSystemEvent(); + parser->Finish(); + EXPECT_TRUE(parser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstFileSystemSample().CallChainIds()[0]; + EXPECT_EQ(callChainId, INVALID_UINT64); + auto type = stream_.traceDataCache_->GetConstFileSystemSample().Types()[0]; + EXPECT_EQ(type, READ); + auto startTs = stream_.traceDataCache_->GetConstFileSystemSample().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME_01); + auto endTs = stream_.traceDataCache_->GetConstFileSystemSample().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME_01); + auto dur = stream_.traceDataCache_->GetConstFileSystemSample().Durs()[0]; + EXPECT_EQ(dur, END_TIME_01 - START_TIME_01); + auto ExpectReturnValue = parser->ConvertToHexTextIndex(RET_01); + auto returnValue = stream_.traceDataCache_->GetConstFileSystemSample().ReturnValues()[0]; + EXPECT_EQ(returnValue, ExpectReturnValue); + auto errorCode = stream_.traceDataCache_->GetConstFileSystemSample().ErrorCodes()[0]; + EXPECT_EQ(errorCode, INVALID_UINT64); + auto fd = stream_.traceDataCache_->GetConstFileSystemSample().Fds()[0]; + EXPECT_EQ(fd, ARGS_01[0]); + auto fileId = stream_.traceDataCache_->GetConstFileSystemSample().FileIds()[0]; + EXPECT_EQ(fileId, INVALID_UINT64); + auto size = stream_.traceDataCache_->GetConstFileSystemSample().Sizes()[0]; + EXPECT_EQ(size, RET_01); + auto i = 0; + auto ExpectFirstArg = parser->ConvertToHexTextIndex(ARGS_01[i++]); + auto firstArg = stream_.traceDataCache_->GetConstFileSystemSample().FirstArguments()[0]; + EXPECT_EQ(firstArg, ExpectFirstArg); + auto ExpectSecondArg = parser->ConvertToHexTextIndex(ARGS_01[i++]); + auto secondArg = stream_.traceDataCache_->GetConstFileSystemSample().SecondArguments()[0]; + EXPECT_EQ(secondArg, ExpectSecondArg); + auto ExpectThirdArg = parser->ConvertToHexTextIndex(ARGS_01[i++]); + auto thirdArg = stream_.traceDataCache_->GetConstFileSystemSample().ThirdArguments()[0]; + EXPECT_EQ(thirdArg, ExpectThirdArg); + auto ExpectFourthArg = parser->ConvertToHexTextIndex(ARGS_01[i]); + auto fourthArg = stream_.traceDataCache_->GetConstFileSystemSample().FourthArguments()[0]; + EXPECT_EQ(fourthArg, ExpectFourthArg); +} + +/** + * @tc.name: ParseFileSystemWithTypeWrite + * @tc.desc: Test parse Ebpf data has one file system data with type read and no ips + * @tc.type: FUNC + */ +HWTEST_F(EbpfFileSystemTest, ParseFileSystemWithTypeWrite, TestSize.Level1) +{ + TS_LOGI("test30-4"); + + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + + FsFixedHeader fsFixedHeader; + fsFixedHeader.pid = PID_02; + fsFixedHeader.tid = TID_02; + fsFixedHeader.startTime = START_TIME_02; + fsFixedHeader.endTime = END_TIME_02; + fsFixedHeader.ret = RET_02; + fsFixedHeader.nrUserIPs = IPS_NUM_00; + fsFixedHeader.type = SYS_WRITE; + for (auto i = 0; i < ARGS_MAX; i++) { + fsFixedHeader.args[i] = ARGS_02[i]; + } + strncpy_s(fsFixedHeader.processName, MAX_PROCESS_NAME_SZIE, PROCESS_NAME_02, MAX_PROCESS_NAME_SZIE); + + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(fsFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_FS; + + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&fsFixedHeader), + reinterpret_cast(&fsFixedHeader + 1)); + + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(parser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(parser->reader_->GetFileSystemEventMap().size()); + parser->ParseFileSystemEvent(); + parser->Finish(); + EXPECT_TRUE(parser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstFileSystemSample().CallChainIds()[0]; + EXPECT_EQ(callChainId, INVALID_UINT64); + auto type = stream_.traceDataCache_->GetConstFileSystemSample().Types()[0]; + EXPECT_EQ(type, WRITE); + auto startTs = stream_.traceDataCache_->GetConstFileSystemSample().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME_02); + auto endTs = stream_.traceDataCache_->GetConstFileSystemSample().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME_02); + auto dur = stream_.traceDataCache_->GetConstFileSystemSample().Durs()[0]; + EXPECT_EQ(dur, END_TIME_02 - START_TIME_02); + auto ExpectReturnValue = parser->ConvertToHexTextIndex(0); + auto returnValue = stream_.traceDataCache_->GetConstFileSystemSample().ReturnValues()[0]; + EXPECT_EQ(returnValue, ExpectReturnValue); + auto errorCode = stream_.traceDataCache_->GetConstFileSystemSample().ErrorCodes()[0]; + auto ExpectErrorValue = parser->ConvertToHexTextIndex(-RET_02); + EXPECT_EQ(errorCode, ExpectErrorValue); + auto fd = stream_.traceDataCache_->GetConstFileSystemSample().Fds()[0]; + EXPECT_EQ(fd, ARGS_02[0]); + auto fileId = stream_.traceDataCache_->GetConstFileSystemSample().FileIds()[0]; + EXPECT_EQ(fileId, INVALID_UINT64); + auto size = stream_.traceDataCache_->GetConstFileSystemSample().Sizes()[0]; + EXPECT_EQ(size, MAX_SIZE_T); + auto i = 0; + auto ExpectFirstArg = parser->ConvertToHexTextIndex(ARGS_02[i++]); + auto firstArg = stream_.traceDataCache_->GetConstFileSystemSample().FirstArguments()[0]; + EXPECT_EQ(firstArg, ExpectFirstArg); + auto ExpectSecondArg = parser->ConvertToHexTextIndex(ARGS_02[i++]); + auto secondArg = stream_.traceDataCache_->GetConstFileSystemSample().SecondArguments()[0]; + EXPECT_EQ(secondArg, ExpectSecondArg); + auto ExpectThirdArg = parser->ConvertToHexTextIndex(ARGS_02[i++]); + auto thirdArg = stream_.traceDataCache_->GetConstFileSystemSample().ThirdArguments()[0]; + EXPECT_EQ(thirdArg, ExpectThirdArg); + auto ExpectFourthArg = parser->ConvertToHexTextIndex(ARGS_02[i]); + auto fourthArg = stream_.traceDataCache_->GetConstFileSystemSample().FourthArguments()[0]; + EXPECT_EQ(fourthArg, ExpectFourthArg); +} + +/** + * @tc.name: ParseFileSystemWithErrorType + * @tc.desc: Test parse Ebpf data has one file system data with error type and no ips + * @tc.type: FUNC + */ +HWTEST_F(EbpfFileSystemTest, ParseFileSystemWithErrorType, TestSize.Level1) +{ + TS_LOGI("test30-5"); + + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + + FsFixedHeader fsFixedHeader; + fsFixedHeader.pid = PID_01; + fsFixedHeader.tid = TID_01; + fsFixedHeader.startTime = START_TIME_01; + fsFixedHeader.endTime = END_TIME_01; + fsFixedHeader.ret = RET_01; + fsFixedHeader.nrUserIPs = IPS_NUM_00; + fsFixedHeader.type = 0; + for (auto i = 0; i < ARGS_MAX; i++) { + fsFixedHeader.args[i] = ARGS_01[i]; + } + strncpy_s(fsFixedHeader.processName, MAX_PROCESS_NAME_SZIE, PROCESS_NAME_01, MAX_PROCESS_NAME_SZIE); + + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(fsFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_FS; + + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&fsFixedHeader), + reinterpret_cast(&fsFixedHeader + 1)); + + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(parser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(parser->reader_->GetFileSystemEventMap().size()); + parser->ParseFileSystemEvent(); + parser->Finish(); + EXPECT_TRUE(parser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + EXPECT_FALSE(stream_.traceDataCache_->GetConstFileSystemSample().Size()); +} + +/** + * @tc.name: ParseFileSystemWithIPsButNoSymTable + * @tc.desc: Test parse Ebpf data has one file system data with ips but no maps + * @tc.type: FUNC + */ +HWTEST_F(EbpfFileSystemTest, ParseFileSystemWithIPsButNoMaps, TestSize.Level1) +{ + TS_LOGI("test30-6"); + + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + + FsFixedHeader fsFixedHeader; + fsFixedHeader.pid = PID_01; + fsFixedHeader.tid = TID_01; + fsFixedHeader.startTime = START_TIME_01; + fsFixedHeader.endTime = END_TIME_01; + fsFixedHeader.ret = RET_01; + fsFixedHeader.nrUserIPs = IPS_NUM_02; + fsFixedHeader.type = SYS_OPENAT2; + for (auto i = 0; i < ARGS_MAX; i++) { + fsFixedHeader.args[i] = ARGS_01[i]; + } + strncpy_s(fsFixedHeader.processName, MAX_PROCESS_NAME_SZIE, PROCESS_NAME_01, MAX_PROCESS_NAME_SZIE); + + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(fsFixedHeader) + IPS_NUM_02 * sizeof(uint64_t); + ebpfTypeAndLength.type = ITEM_EVENT_FS; + + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&fsFixedHeader), + reinterpret_cast(&fsFixedHeader + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(IPS_02), + reinterpret_cast(&IPS_02 + 1)); + + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(parser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(parser->reader_->GetFileSystemEventMap().size()); + parser->ParseFileSystemEvent(); + parser->Finish(); + EXPECT_TRUE(parser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstFileSystemSample().CallChainIds()[0]; + EXPECT_EQ(callChainId, 0); + auto callStackFirstLevelCallChainId = stream_.traceDataCache_->GetConstEbpfCallStackData().CallChainIds()[0]; + EXPECT_EQ(callStackFirstLevelCallChainId, 0); + auto callStackSecondLevelCallChainId = stream_.traceDataCache_->GetConstEbpfCallStackData().CallChainIds()[1]; + EXPECT_EQ(callStackSecondLevelCallChainId, 0); + auto callStackFirstLevelDepth = stream_.traceDataCache_->GetConstEbpfCallStackData().Depths()[0]; + EXPECT_EQ(callStackFirstLevelDepth, 0); + auto callStackSecondLevelDepth = stream_.traceDataCache_->GetConstEbpfCallStackData().Depths()[1]; + EXPECT_EQ(callStackSecondLevelDepth, 1); + auto ExpectCallStackFirstLevelIp = parser->ConvertToHexTextIndex(IPS_02[1]); + auto callStackFirstLevelIp = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[0]; + EXPECT_EQ(callStackFirstLevelIp, ExpectCallStackFirstLevelIp); + auto ExpectCallStackSecondLevelIp = parser->ConvertToHexTextIndex(IPS_02[0]); + auto callStackSecondLevelIp = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[1]; + EXPECT_EQ(callStackSecondLevelIp, ExpectCallStackSecondLevelIp); + auto callStackFirstLevelSymbolId = stream_.traceDataCache_->GetConstEbpfCallStackData().SymbolIds()[0]; + EXPECT_EQ(callStackFirstLevelSymbolId, INVALID_UINT64); + auto callStackSecondLevelSymbolId = stream_.traceDataCache_->GetConstEbpfCallStackData().SymbolIds()[1]; + EXPECT_EQ(callStackSecondLevelSymbolId, INVALID_UINT64); + auto callStackFirstLevelFilePathIds = stream_.traceDataCache_->GetConstEbpfCallStackData().FilePathIds()[0]; + EXPECT_EQ(callStackFirstLevelFilePathIds, INVALID_UINT64); + auto callStackSecondLevelFilePathIds = stream_.traceDataCache_->GetConstEbpfCallStackData().FilePathIds()[1]; + EXPECT_EQ(callStackSecondLevelFilePathIds, INVALID_UINT64); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/ebpf_parser_test.cpp b/host/trace_streamer/test/unittest/ebpf_parser_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..f53250add0d7b97eb60565f6500a73a106fcf976 --- /dev/null +++ b/host/trace_streamer/test/unittest/ebpf_parser_test.cpp @@ -0,0 +1,159 @@ +/* + * 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. + */ + +#include +#include + +#include "ebpf_data_parser.h" +#include "ebpf_stdtype.h" +#include "htrace_file_header.h" +#include "process_filter.h" +#include "trace_streamer_selector.h" +#include "ts_common.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +using namespace SysTuning::EbpfStdtype; +namespace SysTuning { +namespace TraceStreamer { +const std::string COMMAND_LINE = "hiebpf --events ptrace --duration 50"; +const uint64_t EPBF_ERROR_MAGIC = 0x12345678; +const uint32_t EPBF_ERROR_HEAD_SIZE = 0; +class EbpfParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: EbpfDataOnlyEbpfHeadWithErrorMagic + * @tc.desc: Test parse Ebpf data with only ebpf head but no command line + * @tc.type: FUNC + */ +HWTEST_F(EbpfParserTest, EbpfDataOnlyEbpfHeadWithErrorMagic, TestSize.Level1) +{ + TS_LOGI("test29-1"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.magic = EPBF_ERROR_MAGIC; + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_FALSE(parser->Init(dequeBuffer, dequeBuffer.size())); +} + +/** + * @tc.name: EbpfDataOnlyEbpfHeadWithErrorSize + * @tc.desc: Test parse Ebpf data with only ebpf head but no command line + * @tc.type: FUNC + */ +HWTEST_F(EbpfParserTest, EbpfDataOnlyEbpfHeadWithErrorSize, TestSize.Level1) +{ + TS_LOGI("test29-2"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.headSize = EPBF_ERROR_HEAD_SIZE; + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_FALSE(parser->Init(dequeBuffer, dequeBuffer.size())); +} + +/** + * @tc.name: EbpfDataEbpfHeadWithNormalData + * @tc.desc: Test parse Ebpf data with normal data + * @tc.type: FUNC + */ +HWTEST_F(EbpfParserTest, EbpfDataEbpfHeadWithNormalData, TestSize.Level1) +{ + TS_LOGI("test29-3"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = 0; + ebpfHeader.header.headSize = EbpfDataHeader::EBPF_DATA_HEADER_SIZE; + + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(parser->Init(dequeBuffer, dequeBuffer.size())); + parser->Finish(); + EXPECT_EQ(parser->reader_->ebpfDataHeader_->header.clock, EBPF_CLOCK_BOOTTIME); + EXPECT_EQ(parser->reader_->ebpfDataHeader_->header.cmdLineLen, 0); + EXPECT_EQ(parser->reader_->ebpfDataHeader_->header.headSize, EbpfDataHeader::EBPF_DATA_HEADER_SIZE); +} + +/** + * @tc.name: EbpfDataWithOnlyEbpfHeadNoCommandLine + * @tc.desc: Test parse Ebpf data with only ebpf head but no command line + * @tc.type: FUNC + */ +HWTEST_F(EbpfParserTest, EbpfDataWithOnlyEbpfHeadNoCommandLine, TestSize.Level1) +{ + TS_LOGI("test29-4"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = 0; + + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + EXPECT_TRUE(parser->Init(dequeBuffer, dequeBuffer.size())); + parser->Finish(); + EXPECT_TRUE(parser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); +} + +/** + * @tc.name: EbpfDataEbpfHeadHasProcessName + * @tc.desc: Test parse Ebpf data with only ebpf head + * @tc.type: FUNC + */ +HWTEST_F(EbpfParserTest, EbpfDataEbpfHeadHasProcessName, TestSize.Level1) +{ + TS_LOGI("test29-5"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = COMMAND_LINE.length(); + strncpy_s(ebpfHeader.cmdline, EbpfDataHeader::EBPF_COMMAND_MAX_SIZE, COMMAND_LINE.c_str(), + EbpfDataHeader::EBPF_COMMAND_MAX_SIZE); + + std::deque dequeBuffer = {}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + std::unique_ptr parser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + EXPECT_TRUE(parser->Init(dequeBuffer, dequeBuffer.size())); + parser->Finish(); + EXPECT_TRUE(parser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + EXPECT_TRUE(parser->reader_->ebpfDataHeader_->header.cmdLineLen == COMMAND_LINE.length()); + EXPECT_STREQ(parser->reader_->ebpfDataHeader_->cmdline, COMMAND_LINE.c_str()); +} + +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/event_parser_test.cpp b/host/trace_streamer/test/unittest/event_parser_test.cpp old mode 100644 new mode 100755 index 56a87765d3f760129c8b4fb464f2aef9368a6eef..e697689bb104b1ed8f9ed9301cd9b7afe8ba5d0d --- a/host/trace_streamer/test/unittest/event_parser_test.cpp +++ b/host/trace_streamer/test/unittest/event_parser_test.cpp @@ -23,11 +23,13 @@ #include "parser/bytrace_parser/bytrace_event_parser.h" #include "parser/bytrace_parser/bytrace_parser.h" #include "parser/common_types.h" -#include "securec.h" +#include "string_help.h" #include "trace_streamer_selector.h" using namespace testing::ext; using namespace SysTuning::TraceStreamer; +using namespace SysTuning::base; + namespace SysTuning { namespace TraceStreamer { const uint32_t G_BUF_SIZE = 1024; @@ -48,7 +50,7 @@ public: public: TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "/data/resource/out.db"; + const std::string dbPath_ = "data/resource/out.db"; }; /** @@ -58,7 +60,7 @@ public: */ HWTEST_F(EventParserTest, ParseLine, TestSize.Level1) { - TS_LOGI("test4-1"); + TS_LOGI("test5-1"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; @@ -67,18 +69,14 @@ HWTEST_F(EventParserTest, ParseLine, TestSize.Level1) bytraceLine.pidStr = "12"; bytraceLine.tGidStr = "12"; bytraceLine.eventName = "sched_switch"; - ArgsMap args; - args.insert(std::make_pair("prev_comm", "ACCS0")); - args.insert(std::make_pair("prev_pid", "2716")); - args.insert(std::make_pair("prev_prio", "120")); - args.insert(std::make_pair("prev_state", "R")); - args.insert(std::make_pair("next_comm", "kworker/0:0")); - args.insert(std::make_pair("next_pid", "8326")); - args.insert(std::make_pair("next_prio", "120")); + bytraceLine.argsStr = + "prev_comm=ACCS0 prev_pid=2716 prev_prio=120 \ + prev_state=R ==> next_comm=kworker/0:0 next_pid=8326 next_prio=120"; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - int result = eventParser.ParseDataItem(bytraceLine, args, 2519); - EXPECT_EQ(result, true); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.ParseDataItem(bytraceLine); + eventParser.FilterAllEvents(); + EXPECT_EQ(0, + stream_.traceDataCache_->GetStatAndInfo()->GetValue(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_DATA_INVALID)); auto readStatIndex = stream_.traceDataCache_->GetConstSchedSliceData().EndStatesData()[0]; EXPECT_EQ(TASK_RUNNABLE, readStatIndex); auto realTimeStamp = stream_.traceDataCache_->GetConstSchedSliceData().TimeStamData()[0]; @@ -94,7 +92,7 @@ HWTEST_F(EventParserTest, ParseLine, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseLineNotEnoughArgs, TestSize.Level1) { - TS_LOGI("test4-1"); + TS_LOGI("test5-2"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; @@ -103,18 +101,13 @@ HWTEST_F(EventParserTest, ParseLineNotEnoughArgs, TestSize.Level1) bytraceLine.pidStr = "12"; bytraceLine.tGidStr = "12"; bytraceLine.eventName = "sched_switch"; - ArgsMap args; - args.insert(std::make_pair("prev_prio", "120")); - args.insert(std::make_pair("prev_state", "R")); - args.insert(std::make_pair("next_comm", "kworker/0:0")); - args.insert(std::make_pair("next_pid", "8326")); - args.insert(std::make_pair("next_prio", "120")); + bytraceLine.argsStr = "prev_state=R ==> next_comm=kworker/0:0 next_pid=8326 next_prio=120"; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - int result = eventParser.ParseDataItem(bytraceLine, args, 2519); - - EXPECT_EQ(result, false); + eventParser.ParseDataItem(bytraceLine); + eventParser.FilterAllEvents(); + EXPECT_EQ(1, + stream_.traceDataCache_->GetStatAndInfo()->GetValue(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_DATA_INVALID)); } - /** * @tc.name: ParseLineUnCognizableEventname * @tc.desc: Parse a UnCognizable Eventname event in bytrace format @@ -122,7 +115,7 @@ HWTEST_F(EventParserTest, ParseLineNotEnoughArgs, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseLineUnCognizableEventname, TestSize.Level1) { - TS_LOGI("test4-2"); + TS_LOGI("test5-3"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; @@ -131,18 +124,13 @@ HWTEST_F(EventParserTest, ParseLineUnCognizableEventname, TestSize.Level1) bytraceLine.pidStr = "12"; bytraceLine.tGidStr = "12"; bytraceLine.eventName = "ThisEventNameDoNotExist"; // UnRecognizable event name - ArgsMap args; - args.insert(std::make_pair("prev_comm", "ACCS0")); - args.insert(std::make_pair("prev_pid", "2716")); - args.insert(std::make_pair("prev_prio", "120")); - args.insert(std::make_pair("prev_state", "R")); - args.insert(std::make_pair("next_comm", "kworker/0:0")); - args.insert(std::make_pair("next_pid", "8326")); - args.insert(std::make_pair("next_prio", "120")); + bytraceLine.argsStr = + "prev_comm=ACCS0 prev_pid=2716 prev_prio=120 \ + prev_state=R ==> next_comm=kworker/0:0 next_pid=8326 next_prio=120"; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - int result = eventParser.ParseDataItem(bytraceLine, args, 2519); - - EXPECT_EQ(result, false); + eventParser.ParseDataItem(bytraceLine); + eventParser.FilterAllEvents(); + EXPECT_EQ(1, stream_.traceDataCache_->GetStatAndInfo()->GetValue(TRACE_EVENT_OTHER, STAT_EVENT_NOTSUPPORTED)); } /** @@ -152,7 +140,7 @@ HWTEST_F(EventParserTest, ParseLineUnCognizableEventname, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedSwitchNoArgs, TestSize.Level1) { - TS_LOGI("test4-4"); + TS_LOGI("test5-4"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; @@ -161,11 +149,11 @@ HWTEST_F(EventParserTest, ParseSchedSwitchNoArgs, TestSize.Level1) bytraceLine.pidStr = "12"; bytraceLine.tGidStr = "12"; bytraceLine.eventName = "sched_switch"; - ArgsMap args; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - int result = eventParser.ParseDataItem(bytraceLine, args, 2519); - - EXPECT_EQ(result, false); + eventParser.ParseDataItem(bytraceLine); + eventParser.FilterAllEvents(); + EXPECT_EQ(1, + stream_.traceDataCache_->GetStatAndInfo()->GetValue(TRACE_EVENT_SCHED_SWITCH, STAT_EVENT_DATA_INVALID)); } /** @@ -175,7 +163,7 @@ HWTEST_F(EventParserTest, ParseSchedSwitchNoArgs, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedWakeupNoArgs, TestSize.Level1) { - TS_LOGI("test4-4"); + TS_LOGI("test5-5"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; @@ -184,11 +172,11 @@ HWTEST_F(EventParserTest, ParseSchedWakeupNoArgs, TestSize.Level1) bytraceLine.pidStr = "12"; bytraceLine.tGidStr = "12"; bytraceLine.eventName = "sched_wakeup"; - ArgsMap args; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - int result = eventParser.ParseDataItem(bytraceLine, args, 2519); - - EXPECT_EQ(result, false); + eventParser.ParseDataItem(bytraceLine); + eventParser.FilterAllEvents(); + EXPECT_EQ(1, + stream_.traceDataCache_->GetStatAndInfo()->GetValue(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_DATA_INVALID)); } /** @@ -198,7 +186,7 @@ HWTEST_F(EventParserTest, ParseSchedWakeupNoArgs, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseTracingMarkWriteC, TestSize.Level1) { - TS_LOGI("test4-7"); + TS_LOGI("test5-6"); const uint8_t str[] = "ACCS0-2716 ( 2519) [000] ...1 174330.284808: tracing_mark_write: C|2519|Heap size (KB)|2906\n"; @@ -223,7 +211,7 @@ HWTEST_F(EventParserTest, ParseTracingMarkWriteC, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseTracingMarkWriteBE, TestSize.Level1) { - TS_LOGI("test4-8"); + TS_LOGI("test5-7"); const uint8_t str[] = "system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|Choreographer#doFrame\n \ system - 1298(1298)[001]... 1 174330.287622 : tracing_mark_write : E | 1298\n"; // E | 1298 wrong format @@ -249,7 +237,7 @@ HWTEST_F(EventParserTest, ParseTracingMarkWriteBE, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseTracingMarkWriteSF, TestSize.Level1) { - TS_LOGI("test4-9"); + TS_LOGI("test5-8"); const uint8_t str[] = "system-1298 ( 1298) [001] ...1 174330.287478: tracing_mark_write: S|1298|animator:\ @@ -277,7 +265,7 @@ HWTEST_F(EventParserTest, ParseTracingMarkWriteSF, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseTracingMarkWriteErrorPoint, TestSize.Level1) { - TS_LOGI("test4-10"); + TS_LOGI("test5-9"); const uint8_t str[] = "system-1298 ( 1298) [001] ...1 174330.287478: tracing_mark_write: G|1298|animator: \ translateX|18888109\n system-1298(1298)[001]... 1 174330.287514 : tracing_mark_write : \ @@ -304,7 +292,7 @@ HWTEST_F(EventParserTest, ParseTracingMarkWriteErrorPoint, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseCpuIdle, TestSize.Level1) { - TS_LOGI("test4-14"); + TS_LOGI("test5-10"); const uint8_t str[] = "-0 (-----) [003] d..2 174330.280761: cpu_idle: state=2 cpu_id=3\n"; auto buf = std::make_unique(G_BUF_SIZE); if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { @@ -327,7 +315,7 @@ HWTEST_F(EventParserTest, ParseCpuIdle, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseIrqHandlerEntry, TestSize.Level1) { - TS_LOGI("test4-15"); + TS_LOGI("test5-11"); const uint8_t str[] = "ACCS0-2716 ( 2519) [000] d.h1 174330.280362: irq_handler_entry: irq=19 name=408000.qcom,cpu-bwmon\n"; auto buf = std::make_unique(G_BUF_SIZE); @@ -351,9 +339,8 @@ HWTEST_F(EventParserTest, ParseIrqHandlerEntry, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseIrqHandlerExit, TestSize.Level1) { - TS_LOGI("test4-16"); - const uint8_t str[] = - "ACCS0-2716 ( 2519) [000] d.h1 174330.280382: irq_handler_exit: irq=19 ret=handled\n"; + TS_LOGI("test5-12"); + const uint8_t str[] = "ACCS0-2716 ( 2519) [000] d.h1 174330.280382: irq_handler_exit: irq=19 ret=handled\n"; auto buf = std::make_unique(G_BUF_SIZE); if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { EXPECT_TRUE(false); @@ -375,7 +362,7 @@ HWTEST_F(EventParserTest, ParseIrqHandlerExit, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedWaking, TestSize.Level1) { - TS_LOGI("test4-17"); + TS_LOGI("test5-13"); const uint8_t str[] = "ACCS0-2716 ( 2519) [000] d..5 174330.280567: sched_waking: \ comm=Binder:924_6 pid=1332 prio=120 target_cpu=000\n"; @@ -399,7 +386,7 @@ HWTEST_F(EventParserTest, ParseSchedWaking, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedWakeup, TestSize.Level1) { - TS_LOGI("test4-18"); + TS_LOGI("test5-14"); const uint8_t str[] = "ACCS0-2716 ( 2519) [000] d..6 174330.280575: sched_wakeup: \ comm=Binder:924_6 pid=1332 prio=120 target_cpu=000\n"; @@ -424,7 +411,7 @@ HWTEST_F(EventParserTest, ParseSchedWakeup, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseTraceEventClockSync, TestSize.Level1) { - TS_LOGI("test4-19"); + TS_LOGI("test5-15"); const uint8_t str[] = "sampletrace-12728 (12728) [003] ...1 174330.280300: tracing_mark_write: \ trace_event_clock_sync:parent_ts=23139.998047\n"; @@ -449,7 +436,7 @@ HWTEST_F(EventParserTest, ParseTraceEventClockSync, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedSwitch, TestSize.Level1) { - TS_LOGI("test4-27"); + TS_LOGI("test5-16"); const uint8_t str[] = "ACCS0-2716 ( 2519) [000] d..3 174330.289220: sched_switch: prev_comm=ACCS0 prev_pid=2716 prev_prio=120 \ prev_state=R+ ==> next_comm=Binder:924_6 next_pid=1332 next_prio=120\n"; @@ -474,7 +461,7 @@ HWTEST_F(EventParserTest, ParseSchedSwitch, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseTaskRename, TestSize.Level1) { - TS_LOGI("test4-28"); + TS_LOGI("test5-17"); const uint8_t str[] = "<...>-2093 (-----) [001] ...2 174332.792290: task_rename: pid=12729 oldcomm=perfd \ newcomm=POSIX timer 249 oom_score_adj=-1000\n"; @@ -499,7 +486,7 @@ HWTEST_F(EventParserTest, ParseTaskRename, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseTaskNewtask, TestSize.Level1) { - TS_LOGI("test4-29"); + TS_LOGI("test5-18"); const uint8_t str[] = "<...>-2 (-----) [003] ...1 174332.825588: task_newtask: pid=12730 \ comm=kthreadd clone_flags=800711 oom_score_adj=0\n"; @@ -514,7 +501,7 @@ HWTEST_F(EventParserTest, ParseTaskNewtask, TestSize.Level1) EXPECT_EQ(bytraceParser.ParsedTraceValidLines(), static_cast(1)); stream_.traceDataCache_->ExportDatabase(dbPath_); - EXPECT_TRUE(access(dbPath_.c_str(), F_OK) == 0); + EXPECT_EQ(access(dbPath_.c_str(), F_OK), 0); } /** @@ -524,7 +511,7 @@ HWTEST_F(EventParserTest, ParseTaskNewtask, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseWorkqueueExecuteStart, TestSize.Level1) { - TS_LOGI("test4-30"); + TS_LOGI("test5-19"); const uint8_t str[] = "<...>-12180 (-----) [001] ...1 174332.827595: workqueue_execute_start: \ work struct 0000000000000000: function pm_runtime_work\n"; @@ -549,7 +536,7 @@ HWTEST_F(EventParserTest, ParseWorkqueueExecuteStart, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseWorkqueueExecuteEnd, TestSize.Level1) { - TS_LOGI("test4-31"); + TS_LOGI("test5-20"); const uint8_t str[] = "<...>-12180 (-----) [001] ...1 174332.828056: workqueue_execute_end: work struct 0000000000000000\n"; auto buf = std::make_unique(G_BUF_SIZE); @@ -573,10 +560,10 @@ HWTEST_F(EventParserTest, ParseWorkqueueExecuteEnd, TestSize.Level1) */ HWTEST_F(EventParserTest, ParsDistribute, TestSize.Level1) { - TS_LOGI("test4-31-1"); + TS_LOGI("test5-21"); const uint8_t str[] = "system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|[8b00e96b2,2,1]:C$#decodeFrame$#" - "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \ + "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466}\n \ system - 1298(1298)[001]... 1 174330.287622 : tracing_mark_write : E | 1298 \n"; auto buf = std::make_unique(G_BUF_SIZE); if (memcpy_s(buf.get(), G_BUF_SIZE, str, sizeof(str))) { @@ -604,7 +591,7 @@ HWTEST_F(EventParserTest, ParsDistribute, TestSize.Level1) */ HWTEST_F(EventParserTest, ParsPairsOfDistributeEvent, TestSize.Level1) { - TS_LOGI("test4-31-2"); + TS_LOGI("test5-22"); const uint8_t str[] = "system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|[8b00e96b2,2,1]:C$#decodeFrame$#" "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \ @@ -642,7 +629,7 @@ HWTEST_F(EventParserTest, ParsPairsOfDistributeEvent, TestSize.Level1) */ HWTEST_F(EventParserTest, ParsDistributeWithNoFlag, TestSize.Level1) { - TS_LOGI("test4-31-3"); + TS_LOGI("test5-23"); const uint8_t str[] = "system-1298 ( 1298) [001] ...1 174330.287420: tracing_mark_write: B|1298|[8b00e96b2,2,1]$#decodeFrame$#" "{\"Process\":\"DecodeVideoFrame\",\"frameTimestamp\":37313484466} \ @@ -673,7 +660,7 @@ HWTEST_F(EventParserTest, ParsDistributeWithNoFlag, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedSwitchByInitParam, TestSize.Level1) { - TS_LOGI("test4-32"); + TS_LOGI("test5-24"); BytraceLine bytraceLine; static std::unordered_map args{{"prev_comm", "ACCS0"}, {"next_comm", "HeapTaskDaemon"}, {"prev_prio", "120"}, {"next_prio", "124"}, @@ -692,7 +679,7 @@ HWTEST_F(EventParserTest, ParseSchedSwitchByInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedSwitchByAbnormalInitParam, TestSize.Level1) { - TS_LOGI("test4-33"); + TS_LOGI("test5-25"); BytraceLine bytraceLine; static std::unordered_map args{{"prev_comm", "ACCS0"}, {"next_comm", "HeapTaskDaemon"}, {"prev_prio", ""}, {"next_prio", ""}, @@ -709,9 +696,9 @@ HWTEST_F(EventParserTest, ParseSchedSwitchByAbnormalInitParam, TestSize.Level1) * @tc.desc: Parse a TaskRename event * @tc.type: FUNC */ -HWTEST_F(EventParserTest, ParseTaskRenameByInitParam, TestSize.Level1) +HWTEST_F(EventParserTest, ParseTaskRenameEventByInitParam, TestSize.Level1) { - TS_LOGI("test4-34"); + TS_LOGI("test5-26"); BytraceLine bytraceLine; static std::unordered_map args{{"newcomm", "POSIX"}, {"pid", "8542"}}; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); @@ -727,7 +714,7 @@ HWTEST_F(EventParserTest, ParseTaskRenameByInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseTaskNewtaskByInitParam, TestSize.Level1) { - TS_LOGI("test4-35"); + TS_LOGI("test5-27"); BytraceLine bytraceLine; bytraceLine.tGidStr = "12"; static std::unordered_map args{{"comm", "POSIX"}, {"pid", "8542"}, {"clone_flags", "1"}}; @@ -744,14 +731,14 @@ HWTEST_F(EventParserTest, ParseTaskNewtaskByInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseTracingMarkWriteByInitParam, TestSize.Level1) { - TS_LOGI("test4-36"); + TS_LOGI("test5-28"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; - bytraceLine.argsStr = "vec=9 [action=RCU]"; + bytraceLine.argsStr = "B|924|FullSuspendCheck"; static std::unordered_map args{}; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - int result = eventParser.TracingMarkWriteEvent(args, bytraceLine); + int result = eventParser.TracingMarkWriteOrPrintEvent(args, bytraceLine); EXPECT_EQ(result, true); } @@ -763,7 +750,7 @@ HWTEST_F(EventParserTest, ParseTracingMarkWriteByInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedWakeupByInitParam, TestSize.Level1) { - TS_LOGI("test4-37"); + TS_LOGI("test5-29"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; @@ -781,7 +768,7 @@ HWTEST_F(EventParserTest, ParseSchedWakeupByInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedWakeupByAbromalInitParam, TestSize.Level1) { - TS_LOGI("test4-38"); + TS_LOGI("test5-30"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; @@ -799,11 +786,12 @@ HWTEST_F(EventParserTest, ParseSchedWakeupByAbromalInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedWakingByInitParam, TestSize.Level1) { - TS_LOGI("test4-39"); + TS_LOGI("test5-31"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; - static std::unordered_map args{{"pid", "1200"}, {"target_cpu", "1"}}; + static std::unordered_map args{ + {"prio", "120"}, {"comm", "thread1"}, {"pid", "1200"}, {"target_cpu", "1"}}; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int result = eventParser.SchedWakingEvent(args, bytraceLine); @@ -817,11 +805,12 @@ HWTEST_F(EventParserTest, ParseSchedWakingByInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseSchedWakingByAbnormalInitParam, TestSize.Level1) { - TS_LOGI("test4-40"); + TS_LOGI("test5-32"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1; - static std::unordered_map args{{"pid", ""}, {"target_cpu", "1"}}; + static std::unordered_map args { + {"prio", "120"}, {"comm", "thread1"}, {"pid", ""}, {"target_cpu", "1"}}; BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int result = eventParser.SchedWakingEvent(args, bytraceLine); @@ -835,7 +824,7 @@ HWTEST_F(EventParserTest, ParseSchedWakingByAbnormalInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseCpuIdleByInitParam, TestSize.Level1) { - TS_LOGI("test4-41"); + TS_LOGI("test5-33"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.eventName = "POSIX"; @@ -853,7 +842,7 @@ HWTEST_F(EventParserTest, ParseCpuIdleByInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseCpuIdleByAbnormalInitParam, TestSize.Level1) { - TS_LOGI("test4-42"); + TS_LOGI("test5-34"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.eventName = "POSIX"; @@ -871,7 +860,7 @@ HWTEST_F(EventParserTest, ParseCpuIdleByAbnormalInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseCpuFrequencyNormal, TestSize.Level1) { - TS_LOGI("test4-44"); + TS_LOGI("test5-35"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.eventName = "POSIX"; @@ -889,7 +878,7 @@ HWTEST_F(EventParserTest, ParseCpuFrequencyNormal, TestSize.Level1) */ HWTEST_F(EventParserTest, ParseCpuFrequencyByAbnormalInitEmptyCpuId, TestSize.Level1) { - TS_LOGI("test4-45"); + TS_LOGI("test5-36"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.eventName = "POSIX"; @@ -907,7 +896,7 @@ HWTEST_F(EventParserTest, ParseCpuFrequencyByAbnormalInitEmptyCpuId, TestSize.Le */ HWTEST_F(EventParserTest, ParseCpuFrequencyByAbnormalInitEmptyStateValue, TestSize.Level1) { - TS_LOGI("test4-46"); + TS_LOGI("test5-37"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.eventName = "POSIX"; @@ -925,7 +914,7 @@ HWTEST_F(EventParserTest, ParseCpuFrequencyByAbnormalInitEmptyStateValue, TestSi */ HWTEST_F(EventParserTest, ParseWorkqueueExecuteStartByInitParam, TestSize.Level1) { - TS_LOGI("test4-47"); + TS_LOGI("test5-38"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1355; @@ -944,7 +933,7 @@ HWTEST_F(EventParserTest, ParseWorkqueueExecuteStartByInitParam, TestSize.Level1 */ HWTEST_F(EventParserTest, ParseWorkqueueExecuteEndByInitParam, TestSize.Level1) { - TS_LOGI("test4-48"); + TS_LOGI("test5-39"); BytraceLine bytraceLine; bytraceLine.ts = 1616439852302; bytraceLine.pid = 1355; @@ -952,7 +941,7 @@ HWTEST_F(EventParserTest, ParseWorkqueueExecuteEndByInitParam, TestSize.Level1) BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int result = eventParser.WorkqueueExecuteEndEvent(args, bytraceLine); - EXPECT_EQ(result, false); + EXPECT_EQ(result, true); } /** @@ -963,7 +952,7 @@ HWTEST_F(EventParserTest, ParseWorkqueueExecuteEndByInitParam, TestSize.Level1) */ HWTEST_F(EventParserTest, CheckTracePoint, TestSize.Level1) { - TS_LOGI("test4-49"); + TS_LOGI("test5-40"); std::string str("B|924|FullSuspendCheck"); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int result = eventParser.printEventParser_.CheckTracePoint(str); @@ -978,7 +967,7 @@ HWTEST_F(EventParserTest, CheckTracePoint, TestSize.Level1) */ HWTEST_F(EventParserTest, CheckTracePointEmptyString, TestSize.Level1) { - TS_LOGI("test4-50"); + TS_LOGI("test5-41"); std::string str(""); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int result = eventParser.printEventParser_.CheckTracePoint(str); @@ -993,7 +982,7 @@ HWTEST_F(EventParserTest, CheckTracePointEmptyString, TestSize.Level1) */ HWTEST_F(EventParserTest, CheckTracePointNoSplit, TestSize.Level1) { - TS_LOGI("test4-51"); + TS_LOGI("test5-42"); std::string str("trace_event_clock_sync"); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int result = eventParser.printEventParser_.CheckTracePoint(str); @@ -1008,7 +997,7 @@ HWTEST_F(EventParserTest, CheckTracePointNoSplit, TestSize.Level1) */ HWTEST_F(EventParserTest, CheckTracePointMultiType, TestSize.Level1) { - TS_LOGI("test4-52"); + TS_LOGI("test5-43"); std::string str("BECSF|924|FullSuspendCheck"); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int result = eventParser.printEventParser_.CheckTracePoint(str); @@ -1023,7 +1012,7 @@ HWTEST_F(EventParserTest, CheckTracePointMultiType, TestSize.Level1) */ HWTEST_F(EventParserTest, CheckTracePointCheckSingleCharacter, TestSize.Level1) { - TS_LOGI("test4-53"); + TS_LOGI("test5-44"); std::string str("X"); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int result = eventParser.printEventParser_.CheckTracePoint(str); @@ -1038,7 +1027,7 @@ HWTEST_F(EventParserTest, CheckTracePointCheckSingleCharacter, TestSize.Level1) */ HWTEST_F(EventParserTest, CheckTracePointCheckErrorSplit, TestSize.Level1) { - TS_LOGI("test4-54"); + TS_LOGI("test5-45"); std::string str("B&924|FullSuspendCheck"); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); int result = eventParser.printEventParser_.CheckTracePoint(str); @@ -1053,7 +1042,7 @@ HWTEST_F(EventParserTest, CheckTracePointCheckErrorSplit, TestSize.Level1) */ HWTEST_F(EventParserTest, GetTracePoint, TestSize.Level1) { - TS_LOGI("test4-55"); + TS_LOGI("test5-46"); TracePoint point; std::string str("B|924|SuspendThreadByThreadId suspended Binder:924_8 id=39"); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); @@ -1069,7 +1058,7 @@ HWTEST_F(EventParserTest, GetTracePoint, TestSize.Level1) */ HWTEST_F(EventParserTest, GetTracePointParseEmptyString, TestSize.Level1) { - TS_LOGI("test4-56"); + TS_LOGI("test5-47"); TracePoint point; std::string str(""); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); @@ -1085,7 +1074,7 @@ HWTEST_F(EventParserTest, GetTracePointParseEmptyString, TestSize.Level1) */ HWTEST_F(EventParserTest, GetTracePointParseErrorSubEventType, TestSize.Level1) { - TS_LOGI("test4-57"); + TS_LOGI("test5-48"); TracePoint point; std::string str("X|924|SuspendThreadByThreadId suspended Binder:924_8 id=39"); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); @@ -1101,7 +1090,7 @@ HWTEST_F(EventParserTest, GetTracePointParseErrorSubEventType, TestSize.Level1) */ HWTEST_F(EventParserTest, GetThreadGroupId, TestSize.Level1) { - TS_LOGI("test4-58"); + TS_LOGI("test5-49"); size_t length{0}; std::string str("E|924"); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); @@ -1117,7 +1106,7 @@ HWTEST_F(EventParserTest, GetThreadGroupId, TestSize.Level1) */ HWTEST_F(EventParserTest, GetThreadGroupIdParseErrorPid, TestSize.Level1) { - TS_LOGI("test4-59"); + TS_LOGI("test5-50"); size_t length{0}; std::string str("E|abc"); BytraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); @@ -1133,7 +1122,7 @@ HWTEST_F(EventParserTest, GetThreadGroupIdParseErrorPid, TestSize.Level1) */ HWTEST_F(EventParserTest, HandlerB, TestSize.Level1) { - TS_LOGI("test4-60"); + TS_LOGI("test5-51"); size_t length{3}; TracePoint outPoint; std::string str("B|924|HID::ISensors::batch::client"); @@ -1144,13 +1133,13 @@ HWTEST_F(EventParserTest, HandlerB, TestSize.Level1) } /** - * @tc.name: HandlerB + * @tc.name: HandlerBAbnormal * @tc.desc: Test HandlerBAbnormal interface using Abnormal format * @tc.type: FUNC */ HWTEST_F(EventParserTest, HandlerBAbnormal, TestSize.Level1) { - TS_LOGI("test4-61"); + TS_LOGI("test5-52"); size_t length{3}; TracePoint outPoint; std::string str("B|924|"); @@ -1167,7 +1156,7 @@ HWTEST_F(EventParserTest, HandlerBAbnormal, TestSize.Level1) */ HWTEST_F(EventParserTest, HandlerCsf, TestSize.Level1) { - TS_LOGI("test4-62"); + TS_LOGI("test5-53"); size_t length{4}; TracePoint outPoint; std::string str("C|2519|Heap size (KB)|2363"); @@ -1184,7 +1173,7 @@ HWTEST_F(EventParserTest, HandlerCsf, TestSize.Level1) */ HWTEST_F(EventParserTest, HandlerCsfParseEmptyString, TestSize.Level1) { - TS_LOGI("test4-63"); + TS_LOGI("test5-54"); size_t length{4}; TracePoint outPoint; std::string str(""); @@ -1201,7 +1190,7 @@ HWTEST_F(EventParserTest, HandlerCsfParseEmptyString, TestSize.Level1) */ HWTEST_F(EventParserTest, HandlerCsfParseErrorFormate, TestSize.Level1) { - TS_LOGI("test4-64"); + TS_LOGI("test5-55"); size_t length{4}; TracePoint outPoint; std::string str("C|2519|Heap size (KB)|"); diff --git a/host/trace_streamer/test/unittest/filter_filter_test.cpp b/host/trace_streamer/test/unittest/filter_filter_test.cpp old mode 100644 new mode 100755 index 732dbb00c1596c478c50eb61310c583d807d5503..6a311c254c6e6b763f87b0179cff8fbcd161863b --- a/host/trace_streamer/test/unittest/filter_filter_test.cpp +++ b/host/trace_streamer/test/unittest/filter_filter_test.cpp @@ -45,7 +45,7 @@ public: */ HWTEST_F(FilterFilterTest, AddCpuCounterFilter, TestSize.Level1) { - TS_LOGI("test5-1"); + TS_LOGI("test6-1"); uint32_t filterId = streamFilters_.filterFilter_->AddFilter("cpu_counter_filter", "cpu1", 1); EXPECT_EQ(filterId, static_cast(0)); @@ -57,13 +57,13 @@ HWTEST_F(FilterFilterTest, AddCpuCounterFilter, TestSize.Level1) } /** - * @tc.name: AddCpuCounterFilter + * @tc.name: AddThreadFilter * @tc.desc: Add thread_counter_filter & thread_filter through AddFilter interface * @tc.type: FUNC */ HWTEST_F(FilterFilterTest, AddThreadFilter, TestSize.Level1) { - TS_LOGI("test5-2"); + TS_LOGI("test6-2"); uint32_t threadFilterId = streamFilters_.filterFilter_->AddFilter("thread_counter_filter", "threadCount1", 1); EXPECT_EQ(threadFilterId, static_cast(0)); diff --git a/host/trace_streamer/test/unittest/hidump_parser_test.cpp b/host/trace_streamer/test/unittest/hidump_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89d252ca08c74311a1285423894fc23dc669f4df --- /dev/null +++ b/host/trace_streamer/test/unittest/hidump_parser_test.cpp @@ -0,0 +1,160 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "htrace_hidump_parser.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HidumpParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() + { + if (access(dbPath_.c_str(), F_OK) == 0) { + remove(dbPath_.c_str()); + } + } + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; + const std::string dbPath_ = "data/resource/out.db"; +}; + +/** + * @tc.name: ParseEmptyHidumpInfo + * @tc.desc: Parse an empty HidumpInfo + * @tc.type: FUNC + */ +HWTEST_F(HidumpParserTest, ParseEmptyHidumpInfo, TestSize.Level1) +{ + TS_LOGI("test7-1"); + HidumpInfo hidumpInfo; + HtraceHidumpParser htraceHidumpParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceHidumpParser.Parse(hidumpInfo); + auto size = stream_.traceDataCache_->GetConstHidumpData().Size(); + EXPECT_EQ(0, size); +} + +/** + * @tc.name: ParseLegalHidumpInfo + * @tc.desc: Parse a legal HidumpInfo + * @tc.type: FUNC + */ +HWTEST_F(HidumpParserTest, ParseLegalHidumpInfo, TestSize.Level1) +{ + TS_LOGI("test7-2"); + const uint32_t FPS = 120; + const uint32_t TV_SEC = 16326755; + const uint32_t TV_NSEC = 39656070; + + FpsData_TimeSpec timeSpec; + timeSpec.set_tv_nsec(TV_NSEC); + timeSpec.set_tv_sec(TV_SEC); + + HidumpInfo* hidumpInfo = new HidumpInfo(); + auto fpsData = hidumpInfo->add_fps_event(); + fpsData->set_fps(FPS); + fpsData->set_allocated_time(&timeSpec); + + HtraceHidumpParser htraceHidumpParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceHidumpParser.Parse(*hidumpInfo); + + auto Fps = stream_.traceDataCache_->GetConstHidumpData().Fpss()[0]; + EXPECT_EQ(FPS, Fps); + auto TimeSpec = stream_.traceDataCache_->GetConstHidumpData().TimeStamData()[0]; + EXPECT_EQ((TV_NSEC + TV_SEC * SEC_TO_NS), TimeSpec); + auto Size = stream_.traceDataCache_->GetConstHidumpData().Size(); + EXPECT_EQ(1, Size); +} + +/** + * @tc.name: ParseMultipleReasonableHidumpInfo + * @tc.desc: parse multiple reasonable HidumpInfo + * @tc.type: FUNC + */ +HWTEST_F(HidumpParserTest, ParseMultipleReasonableHidumpInfo, TestSize.Level1) +{ + TS_LOGI("test7-3"); + const uint32_t FPS_00 = 120; + const uint32_t TV_SEC_00 = 1632675525; + const uint32_t TV_NSEC_00 = 996560700; + FpsData_TimeSpec timeSpecFirst; + timeSpecFirst.set_tv_nsec(TV_NSEC_00); + timeSpecFirst.set_tv_sec(TV_SEC_00); + + const uint32_t FPS_01 = 60; + const uint32_t TV_SEC_01 = 1632675525; + const uint32_t TV_NSEC_01 = 996560700; + FpsData_TimeSpec timeSpecSecond; + timeSpecSecond.set_tv_nsec(TV_NSEC_01); + timeSpecSecond.set_tv_sec(TV_SEC_01); + + const uint32_t FPS_02 = 90; + const uint32_t TV_SEC_02 = 1632688888; + const uint32_t TV_NSEC_02 = 996588888; + FpsData_TimeSpec timeSpecThird; + timeSpecThird.set_tv_nsec(TV_NSEC_02); + timeSpecThird.set_tv_sec(TV_SEC_02); + + HidumpInfo* hidumpInfo = new HidumpInfo(); + auto fpsDataFirst = hidumpInfo->add_fps_event(); + fpsDataFirst->set_fps(FPS_00); + fpsDataFirst->set_allocated_time(&timeSpecFirst); + + auto fpsDataSecond = hidumpInfo->add_fps_event(); + fpsDataSecond->set_fps(FPS_01); + fpsDataSecond->set_allocated_time(&timeSpecSecond); + + auto fpsDataThird = hidumpInfo->add_fps_event(); + fpsDataThird->set_fps(FPS_02); + fpsDataThird->set_allocated_time(&timeSpecThird); + + HtraceHidumpParser htraceHidumpParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceHidumpParser.Parse(*hidumpInfo); + + auto Fps_00 = stream_.traceDataCache_->GetConstHidumpData().Fpss()[0]; + auto Fps_01 = stream_.traceDataCache_->GetConstHidumpData().Fpss()[1]; + auto Fps_02 = stream_.traceDataCache_->GetConstHidumpData().Fpss()[2]; + EXPECT_EQ(FPS_00, Fps_00); + EXPECT_EQ(FPS_01, Fps_01); + EXPECT_EQ(FPS_02, Fps_02); + + auto TimeSpec_00 = stream_.traceDataCache_->GetConstHidumpData().TimeStamData()[0]; + auto TimeSpec_01 = stream_.traceDataCache_->GetConstHidumpData().TimeStamData()[1]; + auto TimeSpec_02 = stream_.traceDataCache_->GetConstHidumpData().TimeStamData()[2]; + EXPECT_EQ((TV_NSEC_00 + TV_SEC_00 * SEC_TO_NS), TimeSpec_00); + EXPECT_EQ((TV_NSEC_01 + TV_SEC_01 * SEC_TO_NS), TimeSpec_01); + EXPECT_EQ((TV_NSEC_02 + TV_SEC_02 * SEC_TO_NS), TimeSpec_02); + + auto Size = stream_.traceDataCache_->GetConstHidumpData().Size(); + EXPECT_EQ(3, Size); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/hilog_parser_test.cpp b/host/trace_streamer/test/unittest/hilog_parser_test.cpp index 69f71d6495d54aa32e0ec76bdc87c80b1cc8aecb..e4bcd81ee55eea84f921f221da5de5acf409f82a 100644 --- a/host/trace_streamer/test/unittest/hilog_parser_test.cpp +++ b/host/trace_streamer/test/unittest/hilog_parser_test.cpp @@ -42,12 +42,13 @@ public: }; /** - * @tc.name: HilogParseWithoutHilogLine + * @tc.name: ParseHilogInfoWithoutHilogLine * @tc.desc: Parse a HilogInfo that does not contain any hiloglines * @tc.type: FUNC */ HWTEST_F(HilogParserTest, ParseHilogInfoWithoutHilogLine, TestSize.Level1) { + TS_LOGI("test8-1"); HilogInfo* hilogInfo = new HilogInfo(); HtraceHiLogParser htraceHiLogParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); htraceHiLogParser.Parse(*hilogInfo); @@ -62,6 +63,7 @@ HWTEST_F(HilogParserTest, ParseHilogInfoWithoutHilogLine, TestSize.Level1) */ HWTEST_F(HilogParserTest, ParseHilogInfoWithOneHilogLine, TestSize.Level1) { + TS_LOGI("test8-2"); const uint64_t TV_SEC = 1632675525; const uint64_t TV_NSEC = 996560700; const std::string LOG_TAG = "HwMSDPMovementService"; @@ -127,6 +129,7 @@ HWTEST_F(HilogParserTest, ParseHilogInfoWithOneHilogLine, TestSize.Level1) */ HWTEST_F(HilogParserTest, ParseHilogInfoWithMultipleHilogLine, TestSize.Level1) { + TS_LOGI("test8-3"); const uint64_t TV_SEC_01 = 1632675525; const uint64_t TV_NSEC_01 = 996560700; const uint32_t PID_01 = 2716; @@ -236,6 +239,7 @@ HWTEST_F(HilogParserTest, ParseHilogInfoWithMultipleHilogLine, TestSize.Level1) */ HWTEST_F(HilogParserTest, ParseHilogInfoWithErrLevelHilogLine, TestSize.Level1) { + TS_LOGI("test8-4"); const uint64_t TV_SEC = 1632675525; const uint64_t TV_NSEC = 996560700; const std::string LOG_TAG = "HwMSDPMovementService"; @@ -275,6 +279,7 @@ HWTEST_F(HilogParserTest, ParseHilogInfoWithErrLevelHilogLine, TestSize.Level1) */ HWTEST_F(HilogParserTest, ParseHilogInfoLostHilogLine, TestSize.Level1) { + TS_LOGI("test8-5"); const uint64_t TV_SEC = 1632675525; const uint64_t TV_NSEC = 996560700; const std::string LOG_TAG = "HwMSDPMovementService"; @@ -314,6 +319,7 @@ HWTEST_F(HilogParserTest, ParseHilogInfoLostHilogLine, TestSize.Level1) */ HWTEST_F(HilogParserTest, ParseHilogInfoHasDuplicateHilogLine, TestSize.Level1) { + TS_LOGI("test8-6"); const uint64_t TV_SEC = 1632675525; const uint64_t TV_NSEC = 996560700; const std::string LOG_TAG = "HwMSDPMovementService"; diff --git a/host/trace_streamer/test/unittest/hisys_event_parser_test.cpp b/host/trace_streamer/test/unittest/hisys_event_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..49c76d4b36fb62468947d74856474de457f6b575 --- /dev/null +++ b/host/trace_streamer/test/unittest/hisys_event_parser_test.cpp @@ -0,0 +1,184 @@ +/* + * 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. + */ + +#include +#include + +#include "htrace_hisysevent_parser.h" +#include "string_to_numerical.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class HtraceHisysEventParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; +namespace base { + auto num0 = SysTuning::base::number(15, SysTuning::base::INTEGER_RADIX_TYPE_DEC); + auto num1 = SysTuning::base::number(15, SysTuning::base::INTEGER_RADIX_TYPE_HEX); +} // namespace base +/** + * @tc.name: ParseNoArray + * @tc.desc: Parse a piece of data without array + * @tc.type: FUNC + */ +HWTEST_F(HtraceHisysEventParserTest, ParseNoArray, TestSize.Level1) +{ + TS_LOGI("test9-1"); + std::string jsMessage = + "{\"domain_\":\"POWERTHERMAL\",\"name_\":\"POWER_IDE_BATTERY\",\"type_\":1,\"time_\":22611696002,\"tz_\":\"+"\ + "0000\",\"pid_\":722,\"tid_\":3462,\"uid_\":1201,\"START_TIME\":22611696002,\"END_TIME\":23617705010,\"GAS_"\ + "GAUGE\":124,\"LEVEL\":33,\"SCREEN\":11,\"CHARGE\":21,\"CURRENT\":-404,\"CAPACITY\":9898,\"level_\":\"MINOR\","\ + "\"id_\":\"16494176919818340149\",\"info_\":\"\"}"; + HtraceHisyseventParser::json jMessage; + HtraceHisyseventParser::JsonData jData; + size_t maxArraySize = 0; + uint64_t serial = 1; + std::vector noArrayIndex; + std::vector arrayIndex; + std::stringstream ss; + ss<>jMessage; + HtraceHisyseventParser HisysEvent(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + HisysEvent.JGetData(jMessage, jData, maxArraySize, noArrayIndex, arrayIndex); + EXPECT_TRUE(jData.eventSource == "POWER_IDE_BATTERY"); + EXPECT_EQ(jData.timestamp, 22611696002); + EXPECT_EQ(maxArraySize, 0); + EXPECT_EQ(noArrayIndex.size(), 17); + EXPECT_EQ(arrayIndex.size(), 0); + DataIndex eventSourceIndex = stream_.traceDataCache_->GetDataIndex(jData.eventSource); + HisysEvent.CommonDataParser(jData, eventSourceIndex, serial); + auto size = stream_.traceDataCache_->GetConstSyseventMeasureData().Size(); + EXPECT_EQ(size, 17); + auto anticipate = stream_.traceDataCache_->GetConstSyseventMeasureData().Serial()[0]; + EXPECT_EQ(anticipate, serial); + EXPECT_TRUE(base::num0 == "15"); + EXPECT_TRUE(base::num1 == "f"); +} +/** + * @tc.name: ParseHaveArrayData + * @tc.desc: Parse a piece of data with array + * @tc.type: FUNC + */ +HWTEST_F(HtraceHisysEventParserTest, ParseHaveArrayData, TestSize.Level1) +{ + TS_LOGI("test9-2"); + std::string jsMessage = + "{\"domain_\":\"POWERTHERMAL\",\"name_\":\"POWER_IDE_WIFISCAN\",\"type_\":2,\"time_\":16611696002,\"tz_\":\"+"\ + "0000\",\"pid_\":722,\"tid_\":17827,\"uid_\":1201,\"START_TIME\":1661783047454,\"END_TIME\":1661783050455,"\ + "\"COUNT\":1,\"APPNAME\":[\"com.ohos.settings\",\"com.ohos.settings_js\",\"com.ohos.settings_app\"],"\ + "\"FOREGROUND_COUNT\":[43,41,65],\"FOREGROUND_ENERGY\":[120,134,532],\"BACKGROUND_COUNT\":[27,856,378],"\ + "\"BACKGROUND_ENERGY\":[638,65,12],\"SCREEN_ON_COUNT\":[23,558,75],\"SCREEN_ON_ENERGY\":[552,142,120],\"SCREEN_"\ + "OFF_COUNT\":[78,354,21],\"SCREEN_OFF_ENERGY\":[352,65,436],\"level_\":\"MINOR\",\"id_\":"\ + "\"17560016619580787102\",\"info_\":\"\"}"; + HtraceHisyseventParser::json jMessage; + HtraceHisyseventParser::JsonData jData; + size_t maxArraySize = 0; + uint64_t serial = 1; + std::vector noArrayIndex; + std::vector arrayIndex; + std::stringstream ss; + ss<>jMessage; + HtraceHisyseventParser HisysEvent(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + HisysEvent.JGetData(jMessage, jData, maxArraySize, noArrayIndex, arrayIndex); + EXPECT_TRUE(jData.eventSource == "POWER_IDE_WIFISCAN"); + EXPECT_EQ(jData.timestamp, 16611696002); + EXPECT_EQ(maxArraySize, 3); + EXPECT_EQ(noArrayIndex.size(), 12); + EXPECT_EQ(arrayIndex.size(), 9); + DataIndex eventSourceIndex = stream_.traceDataCache_->GetDataIndex(jData.eventSource); + HisysEvent.NoArrayDataParse(jData, noArrayIndex, eventSourceIndex, serial); + HisysEvent.ArrayDataParse(jData, arrayIndex, eventSourceIndex, maxArraySize, serial); + auto size = stream_.traceDataCache_->GetConstSyseventMeasureData().Size(); + EXPECT_EQ(size, (9 * 3 + 12)); + auto anticipate = stream_.traceDataCache_->GetConstSyseventMeasureData().Serial()[0]; + EXPECT_EQ(anticipate, serial); +} +/** + * @tc.name: MixedDataAnalysis + * @tc.desc: Mixed data analysis + * @tc.type: FUNC + */ +HWTEST_F(HtraceHisysEventParserTest, MixedDataAnalysis, TestSize.Level1) +{ + TS_LOGI("test9-3"); + std::string jsMessage1 = + "{\"domain_\":\"POWERTHERMAL\",\"name_\":\"POWER_IDE_BATTERY\",\"type_\":1,\"time_\":22611696002,\"tz_\":\"+"\ + "0000\",\"pid_\":722,\"tid_\":3462,\"uid_\":1201,\"START_TIME\":22611696002,\"END_TIME\":23617705010,\"GAS_"\ + "GAUGE\":124,\"LEVEL\":33,\"SCREEN\":11,\"CHARGE\":21,\"CURRENT\":-404,\"CAPACITY\":9898,\"level_\":\"MINOR\","\ + "\"id_\":\"16494176919818340149\",\"info_\":\"\"}"; + std::string jsMessage2 = + "{\"domain_\":\"POWERTHERMAL\",\"name_\":\"POWER_IDE_WIFISCAN\",\"type_\":2,\"time_\":16611696002,\"tz_\":\"+"\ + "0000\",\"pid_\":722,\"tid_\":17827,\"uid_\":1201,\"START_TIME\":1661783047454,\"END_TIME\":1661783050455,"\ + "\"COUNT\":1,\"APPNAME\":[\"com.ohos.settings\",\"com.ohos.settings_js\",\"com.ohos.settings_app\"],"\ + "\"FOREGROUND_COUNT\":[43,41,65],\"FOREGROUND_ENERGY\":[120,134,532],\"BACKGROUND_COUNT\":[27,856,378],"\ + "\"BACKGROUND_ENERGY\":[638,65,12],\"SCREEN_ON_COUNT\":[23,558,75],\"SCREEN_ON_ENERGY\":[552,142,120],\"SCREEN_"\ + "OFF_COUNT\":[78,354,21],\"SCREEN_OFF_ENERGY\":[352,65,436],\"level_\":\"MINOR\",\"id_\":"\ + "\"17560016619580787102\",\"info_\":\"\"}"; + std::vector jsMessage; + jsMessage.push_back(jsMessage1); + jsMessage.push_back(jsMessage2); + uint64_t serial = 1; + for (auto i = jsMessage.begin(); i != jsMessage.end(); i++) { + HtraceHisyseventParser::json jMessage; + HtraceHisyseventParser::JsonData jData; + size_t maxArraySize = 0; + std::vector noArrayIndex; + std::vector arrayIndex; + std::stringstream ss; + ss << *i; + ss >> jMessage; + HtraceHisyseventParser HisysEvent(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + HisysEvent.JGetData(jMessage, jData, maxArraySize, noArrayIndex, arrayIndex); + if (jData.eventSource == "POWER_IDE_WIFISCAN") { + EXPECT_TRUE(jData.eventSource == "POWER_IDE_WIFISCAN"); + EXPECT_EQ(jData.timestamp, 16611696002); + EXPECT_EQ(maxArraySize, 3); + EXPECT_EQ(noArrayIndex.size(), 12); + EXPECT_EQ(arrayIndex.size(), 9); + } else { + EXPECT_TRUE(jData.eventSource == "POWER_IDE_BATTERY"); + EXPECT_EQ(jData.timestamp, 22611696002); + EXPECT_EQ(maxArraySize, 0); + EXPECT_EQ(noArrayIndex.size(), 17); + EXPECT_EQ(arrayIndex.size(), 0); + } + DataIndex eventSourceIndex = stream_.traceDataCache_->GetDataIndex(jData.eventSource); + if (maxArraySize) { + HisysEvent.NoArrayDataParse(jData, noArrayIndex, eventSourceIndex, serial); + HisysEvent.ArrayDataParse(jData, arrayIndex, eventSourceIndex, maxArraySize, serial); + } else { + HisysEvent.CommonDataParser(jData, eventSourceIndex, serial); + } + } + auto size = stream_.traceDataCache_->GetConstSyseventMeasureData().Size(); + EXPECT_EQ(size, 17 + (9 * 3 + 12)); + auto anticipate = stream_.traceDataCache_->GetConstSyseventMeasureData().Serial()[0]; + EXPECT_EQ(anticipate, serial); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/htrace_binder_event_test.cpp b/host/trace_streamer/test/unittest/htrace_binder_event_test.cpp index 32c7c9e982e042c896c0cdb6883ea543e6852c63..d496226d614e714232053be570eca88a8aeb8343 100644 --- a/host/trace_streamer/test/unittest/htrace_binder_event_test.cpp +++ b/host/trace_streamer/test/unittest/htrace_binder_event_test.cpp @@ -47,6 +47,7 @@ public: */ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReply, TestSize.Level1) { + TS_LOGI("test10-1"); std::string appName = "app1"; int64_t ts1 = 100; uint32_t tid1 = 1; @@ -78,7 +79,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReply, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 7); @@ -91,7 +92,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReply, TestSize.Level1) */ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceive, TestSize.Level1) { - TS_LOGI("test9-2"); + TS_LOGI("test10-2"); std::string appName = "app1"; int64_t ts1 = 100; uint32_t tid1 = 1; @@ -123,7 +124,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceive, TestSize. HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 7); @@ -142,7 +143,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceive, TestSize. binderReceivedEvent->set_debug_id(transactionId1); ftraceEvent2->set_allocated_binder_transaction_received_format(binderReceivedEvent); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); @@ -156,6 +157,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceive, TestSize. */ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, TestSize.Level1) { + TS_LOGI("test10-3"); int64_t ts1 = 100; std::string appName = "app1"; uint32_t tid1 = 1; @@ -187,7 +189,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 7); @@ -208,7 +210,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, ftraceEvent2->set_comm(appName); ftraceEvent2->set_allocated_binder_transaction_alloc_buf_format(binderAllocEvent); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 9); ts1 = 200; @@ -226,7 +228,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, binderReceivedEvent->set_debug_id(transactionId1); ftraceEvent3->set_allocated_binder_transaction_received_format(binderReceivedEvent); eventParser.ParseDataItem(&ftraceCpuDetail3, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); @@ -240,7 +242,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveWithAlloc, */ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveNotmatch, TestSize.Level1) { - TS_LOGI("test9-4"); + TS_LOGI("test10-4"); std::string appName = "app1"; int64_t ts1 = 100; uint32_t tid1 = 1; @@ -272,7 +274,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveNotmatch, T HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); ts1 = 200; @@ -291,7 +293,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveNotmatch, T binderReceivedEvent->set_debug_id(transactionId2); ftraceEvent2->set_allocated_binder_transaction_received_format(binderReceivedEvent); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); } @@ -303,7 +305,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNeedReplyAndReceiveNotmatch, T */ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNoNeedReply, TestSize.Level1) { - TS_LOGI("test9-5"); + TS_LOGI("test10-5"); std::string appName = "app1"; int64_t ts1 = 100; uint32_t tid1 = 1; @@ -335,7 +337,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNoNeedReply, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); } @@ -346,7 +348,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterNoNeedReply, TestSize.Level1) */ HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilter, TestSize.Level1) { - TS_LOGI("test9-6"); + TS_LOGI("test10-6"); std::string appName = "app1"; int64_t ts1 = 100; uint32_t tid1 = 1; @@ -378,7 +380,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilter, TestSiz HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); ts1 = 200; @@ -396,10 +398,10 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilter, TestSiz binderReceivedEvent->set_debug_id(transactionId1); ftraceEvent2->set_allocated_binder_transaction_received_format(binderReceivedEvent); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[1] == 0); } /** @@ -409,7 +411,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilter, TestSiz */ HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilterNotmatch, TestSize.Level1) { - TS_LOGI("test9-7"); + TS_LOGI("test10-7"); std::string appName = "app1"; int64_t ts1 = 100; uint32_t tid1 = 1; @@ -441,7 +443,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilterNotmatch, HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); ts1 = 200; @@ -460,7 +462,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilterNotmatch, binderReceivedEvent->set_debug_id(transactionId2); ftraceEvent2->set_allocated_binder_transaction_received_format(binderReceivedEvent); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); } @@ -472,7 +474,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderNoneedReplyAndReceivefilterNotmatch, */ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterWrongReply, TestSize.Level1) { - TS_LOGI("test9-8"); + TS_LOGI("test10-8"); std::string appName = "app1"; int64_t ts1 = 100; uint32_t tid1 = 1; @@ -504,8 +506,7 @@ HWTEST_F(HtraceBinderEventTest, BinderSenderfilterWrongReply, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); - stream_.streamFilters_->binderFilter_->FinishBinderEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 0); EXPECT_TRUE(stream_.traceDataCache_->GetConstArgSetData().Size() == 0); } diff --git a/host/trace_streamer/test/unittest/htrace_cpu_data_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_cpu_data_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0217877a664dd851e52c27ee217395127c957248 --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_cpu_data_parser_test.cpp @@ -0,0 +1,312 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "htrace_cpu_data_parser.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HtraceCpuDataParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() const{} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: ParseHtraceWithoutCpuDataData + * @tc.desc: Parse a cpu that does not contain any cpudata + * @tc.type: FUNC + */ +HWTEST_F(HtraceCpuDataParserTest, ParseHtraceWithoutCpuData, TestSize.Level1) +{ + TS_LOGI("test11-1"); + uint64_t ts = 100; + auto cpuData = std::make_unique(); + HtraceCpuDataParser htraceCpuDataParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceCpuDataParser.Parse(*cpuData, ts); + auto size = stream_.traceDataCache_->GetConstCpuUsageInfoData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseHtraceWithOneCpuData + * @tc.desc: Parse a cpu with one cpudata + * @tc.type: FUNC + */ +HWTEST_F(HtraceCpuDataParserTest, ParseHtraceWithOneCpuData, TestSize.Level1) +{ + TS_LOGI("test11-2"); + uint64_t ts = 102; + const uint64_t TOTAL_LOAD = 2; + const uint64_t USER_LOAD = 42; + const uint64_t SYSTEM_LOAD = 32; + const uint64_t PROCESS_NUM = 202; + + auto cpuDataInfo(std::make_unique()); + cpuDataInfo->set_total_load(TOTAL_LOAD); + cpuDataInfo->set_user_load(USER_LOAD); + cpuDataInfo->set_sys_load(SYSTEM_LOAD); + cpuDataInfo->set_process_num(PROCESS_NUM); + + HtraceCpuDataParser htraceCpuDataParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceCpuDataParser.Parse(*cpuDataInfo, ts); + htraceCpuDataParser.Finish(); + auto size = stream_.traceDataCache_->GetConstCpuUsageInfoData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseHtraceWithTwoCpuData + * @tc.desc: Parse a cpu with two cpudata + * @tc.type: FUNC + */ +HWTEST_F(HtraceCpuDataParserTest, ParseHtraceWithTwoCpuData, TestSize.Level1) +{ + TS_LOGI("test11-3"); + uint64_t ts = 103; + const uint64_t TOTALLOAD_01 = 2; + const uint64_t USERLOAD_01 = 42; + const uint64_t SYSTEMLOAD_01 = 32; + const uint64_t PROCESS_NUM_01 = 202; + + const uint64_t TOTALLOAD_02 = 3; + const uint64_t USERLOAD_02 = 43; + const uint64_t SYSTEMLOAD_02 = 33; + const uint64_t PROCESS_NUM_02 = 203; + + CpuUsageInfo* cpuUsageInfo01 = new CpuUsageInfo(); + auto cpuDataInfo01(std::make_unique()); + cpuDataInfo01->set_allocated_cpu_usage_info(cpuUsageInfo01); + cpuDataInfo01->set_total_load(TOTALLOAD_01); + cpuDataInfo01->set_user_load(USERLOAD_01); + cpuDataInfo01->set_sys_load(SYSTEMLOAD_01); + cpuDataInfo01->set_process_num(PROCESS_NUM_01); + + HtraceCpuDataParser htraceCpuDataParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceCpuDataParser.Parse(*cpuDataInfo01, ts); + + CpuUsageInfo* cpuUsageInfo02 = new CpuUsageInfo(); + auto cpuDataInfo02(std::make_unique()); + cpuDataInfo02->set_allocated_cpu_usage_info(cpuUsageInfo02); + cpuDataInfo02->set_total_load(TOTALLOAD_02); + cpuDataInfo02->set_user_load(USERLOAD_02); + cpuDataInfo02->set_sys_load(SYSTEMLOAD_02); + cpuDataInfo02->set_process_num(PROCESS_NUM_02); + + htraceCpuDataParser.Parse(*cpuDataInfo02, ts); + htraceCpuDataParser.Finish(); + + auto size = stream_.traceDataCache_->GetConstCpuUsageInfoData().Size(); + EXPECT_EQ(1, size); + + auto totalLoad = stream_.traceDataCache_->GetConstCpuUsageInfoData().TotalLoad()[0]; + EXPECT_EQ(totalLoad, TOTALLOAD_02); + + auto userLoad = stream_.traceDataCache_->GetConstCpuUsageInfoData().UserLoad()[0]; + EXPECT_EQ(userLoad, USERLOAD_02); + + auto systemLoad = stream_.traceDataCache_->GetConstCpuUsageInfoData().SystemLoad()[0]; + EXPECT_EQ(systemLoad, SYSTEMLOAD_02); +} + +/** + * @tc.name: ParseHtraceWithThreeCpuData + * @tc.desc: Parse a cpu with Three cpudata + * @tc.type: FUNC + */ +HWTEST_F(HtraceCpuDataParserTest, ParseHtraceWithThreeCpuData, TestSize.Level1) +{ + TS_LOGI("test11-4"); + uint64_t ts = 104; + const uint64_t TOTALLOAD_01 = 4; + const uint64_t USERLOAD_01 = 44; + const uint64_t SYSTEMLOAD_01 = 34; + const uint64_t PROCESS_NUM_01 = 204; + + const uint64_t TOTALLOAD_02 = 5; + const uint64_t USERLOAD_02 = 45; + const uint64_t SYSTEMLOAD_02 = 35; + const uint64_t PROCESS_NUM_02 = 205; + + const uint64_t TOTALLOAD_03 = 6; + const uint64_t USERLOAD_03 = 46; + const uint64_t SYSTEMLOAD_03 = 36; + const uint64_t PROCESS_NUM_03 = 206; + + CpuUsageInfo* cpuUsageInfo01 = new CpuUsageInfo(); + auto cpuDataInfo01(std::make_unique()); + cpuDataInfo01->set_allocated_cpu_usage_info(cpuUsageInfo01); + cpuDataInfo01->set_total_load(TOTALLOAD_01); + cpuDataInfo01->set_user_load(USERLOAD_01); + cpuDataInfo01->set_sys_load(SYSTEMLOAD_01); + cpuDataInfo01->set_process_num(PROCESS_NUM_01); + + HtraceCpuDataParser htraceCpuDataParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceCpuDataParser.Parse(*cpuDataInfo01, ts); + + CpuUsageInfo* cpuUsageInfo02 = new CpuUsageInfo(); + auto cpuDataInfo02(std::make_unique()); + cpuDataInfo02->set_allocated_cpu_usage_info(cpuUsageInfo02); + cpuDataInfo02->set_total_load(TOTALLOAD_02); + cpuDataInfo02->set_user_load(USERLOAD_02); + cpuDataInfo02->set_sys_load(SYSTEMLOAD_02); + cpuDataInfo02->set_process_num(PROCESS_NUM_02); + + htraceCpuDataParser.Parse(*cpuDataInfo02, ts); + + CpuUsageInfo* cpuUsageInfo03 = new CpuUsageInfo(); + auto cpuDataInfo03(std::make_unique()); + cpuDataInfo03->set_allocated_cpu_usage_info(cpuUsageInfo03); + cpuDataInfo03->set_total_load(TOTALLOAD_03); + cpuDataInfo03->set_user_load(USERLOAD_03); + cpuDataInfo03->set_sys_load(SYSTEMLOAD_03); + cpuDataInfo03->set_process_num(PROCESS_NUM_03); + + htraceCpuDataParser.Parse(*cpuDataInfo03, ts); + htraceCpuDataParser.Finish(); + + auto size = stream_.traceDataCache_->GetConstCpuUsageInfoData().Size(); + EXPECT_EQ(2, size); + + auto totalLoadFirst = stream_.traceDataCache_->GetConstCpuUsageInfoData().TotalLoad()[0]; + auto totalLoadSecond = stream_.traceDataCache_->GetConstCpuUsageInfoData().TotalLoad()[1]; + EXPECT_EQ(totalLoadFirst, TOTALLOAD_02); + EXPECT_EQ(totalLoadSecond, TOTALLOAD_03); + + auto userLoadFirst = stream_.traceDataCache_->GetConstCpuUsageInfoData().UserLoad()[0]; + auto userLoadSecond = stream_.traceDataCache_->GetConstCpuUsageInfoData().UserLoad()[1]; + EXPECT_EQ(userLoadFirst, USERLOAD_02); + EXPECT_EQ(userLoadSecond, USERLOAD_03); + + auto systemLoadFirst = stream_.traceDataCache_->GetConstCpuUsageInfoData().SystemLoad()[0]; + auto systemLoadSecond = stream_.traceDataCache_->GetConstCpuUsageInfoData().SystemLoad()[1]; + EXPECT_EQ(systemLoadFirst, SYSTEMLOAD_02); + EXPECT_EQ(systemLoadSecond, SYSTEMLOAD_03); +} + +/** + * @tc.name: ParseHtraceWithMultipleCpuData + * @tc.desc: Parse a CpuData with Multiple CpuData + * @tc.type: FUNC + */ +HWTEST_F(HtraceCpuDataParserTest, ParseHtraceWithMultipleCpuData, TestSize.Level1) +{ + TS_LOGI("test11-5"); + uint64_t ts = 104; + const uint64_t TOTALLOAD_01 = 4; + const uint64_t USERLOAD_01 = 44; + const uint64_t SYSTEMLOAD_01 = 34; + const uint64_t PROCESS_NUM_01 = 204; + + const uint64_t TOTALLOAD_02 = 5; + const uint64_t USERLOAD_02 = 45; + const uint64_t SYSTEMLOAD_02 = 35; + const uint64_t PROCESS_NUM_02 = 205; + + const uint64_t TOTALLOAD_03 = 6; + const uint64_t USERLOAD_03 = 46; + const uint64_t SYSTEMLOAD_03 = 36; + const uint64_t PROCESS_NUM_03 = 206; + + const uint64_t TOTALLOAD_04 = 6; + const uint64_t USERLOAD_04 = 46; + const uint64_t SYSTEMLOAD_04 = 36; + const uint64_t PROCESS_NUM_04 = 206; + + CpuUsageInfo* cpuUsageInfo01 = new CpuUsageInfo(); + auto cpuDataInfo01(std::make_unique()); + cpuDataInfo01->set_allocated_cpu_usage_info(cpuUsageInfo01); + cpuDataInfo01->set_total_load(TOTALLOAD_01); + cpuDataInfo01->set_user_load(USERLOAD_01); + cpuDataInfo01->set_sys_load(SYSTEMLOAD_01); + cpuDataInfo01->set_process_num(PROCESS_NUM_01); + + HtraceCpuDataParser htraceCpuDataParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceCpuDataParser.Parse(*cpuDataInfo01, ts); + + CpuUsageInfo* cpuUsageInfo02 = new CpuUsageInfo(); + auto cpuDataInfo02(std::make_unique()); + cpuDataInfo02->set_allocated_cpu_usage_info(cpuUsageInfo02); + cpuDataInfo02->set_total_load(TOTALLOAD_02); + cpuDataInfo02->set_user_load(USERLOAD_02); + cpuDataInfo02->set_sys_load(SYSTEMLOAD_02); + cpuDataInfo02->set_process_num(PROCESS_NUM_02); + + htraceCpuDataParser.Parse(*cpuDataInfo02, ts); + + CpuUsageInfo* cpuUsageInfo03 = new CpuUsageInfo(); + auto cpuDataInfo03(std::make_unique()); + cpuDataInfo03->set_allocated_cpu_usage_info(cpuUsageInfo03); + cpuDataInfo03->set_total_load(TOTALLOAD_03); + cpuDataInfo03->set_user_load(USERLOAD_03); + cpuDataInfo03->set_sys_load(SYSTEMLOAD_03); + cpuDataInfo03->set_process_num(PROCESS_NUM_03); + + htraceCpuDataParser.Parse(*cpuDataInfo03, ts); + + CpuUsageInfo* cpuUsageInfo04 = new CpuUsageInfo(); + auto cpuDataInfo04(std::make_unique()); + cpuDataInfo04->set_allocated_cpu_usage_info(cpuUsageInfo04); + cpuDataInfo04->set_total_load(TOTALLOAD_04); + cpuDataInfo04->set_user_load(USERLOAD_04); + cpuDataInfo04->set_sys_load(SYSTEMLOAD_04); + cpuDataInfo04->set_process_num(PROCESS_NUM_04); + + htraceCpuDataParser.Parse(*cpuDataInfo04, ts); + htraceCpuDataParser.Finish(); + + auto size = stream_.traceDataCache_->GetConstCpuUsageInfoData().Size(); + EXPECT_EQ(3, size); + + auto totalLoadFirst = stream_.traceDataCache_->GetConstCpuUsageInfoData().TotalLoad()[0]; + auto totalLoadSecond = stream_.traceDataCache_->GetConstCpuUsageInfoData().TotalLoad()[1]; + auto totalLoadThird = stream_.traceDataCache_->GetConstCpuUsageInfoData().TotalLoad()[2]; + EXPECT_EQ(totalLoadFirst, TOTALLOAD_02); + EXPECT_EQ(totalLoadSecond, TOTALLOAD_03); + EXPECT_EQ(totalLoadThird, TOTALLOAD_04); + + auto userLoadFirst = stream_.traceDataCache_->GetConstCpuUsageInfoData().UserLoad()[0]; + auto userLoadSecond = stream_.traceDataCache_->GetConstCpuUsageInfoData().UserLoad()[1]; + auto userLoadThird = stream_.traceDataCache_->GetConstCpuUsageInfoData().UserLoad()[2]; + EXPECT_EQ(userLoadFirst, USERLOAD_02); + EXPECT_EQ(userLoadSecond, USERLOAD_03); + EXPECT_EQ(userLoadThird, USERLOAD_04); + + auto systemLoadFirst = stream_.traceDataCache_->GetConstCpuUsageInfoData().SystemLoad()[0]; + auto systemLoadSecond = stream_.traceDataCache_->GetConstCpuUsageInfoData().SystemLoad()[1]; + auto systemLoadThird = stream_.traceDataCache_->GetConstCpuUsageInfoData().SystemLoad()[2]; + EXPECT_EQ(systemLoadFirst, SYSTEMLOAD_02); + EXPECT_EQ(systemLoadSecond, SYSTEMLOAD_03); + EXPECT_EQ(systemLoadThird, SYSTEMLOAD_04); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/htrace_cpu_detail_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_cpu_detail_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08c4b7ac8494e5c22820318b04ff9cf99fd78d5c --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_cpu_detail_parser_test.cpp @@ -0,0 +1,155 @@ +/* + * 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. + */ + +#include +#include + +#include "htrace_cpu_detail_parser.h" +#include "htrace_event_parser.h" +#include "power.pb.h" +#include "stat_filter.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HtraceCpuDetailParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() const{} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: ParseCpudetaulNoEvents + * @tc.desc: Parse a cpudetaul with no events + * @tc.type: FUNC + */ +HWTEST_F(HtraceCpuDetailParserTest, ParseCpudetaulNoEvents, TestSize.Level1) +{ + TS_LOGI("test12-1"); + TracePluginResult tracePacket; + FtraceCpuDetailMsg* cpuDetail = tracePacket.add_ftrace_cpu_detail(); + + HtraceCpuDetailParser htraceCpuDetailParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceCpuDetailParser.Parse(&tracePacket, TS_CLOCK_REALTIME); + htraceCpuDetailParser.FilterAllEvents(); + auto size = tracePacket.ftrace_cpu_detail_size(); + auto eventSize = cpuDetail->event_size(); + EXPECT_EQ(size, 1); + EXPECT_EQ(eventSize, 0); +} +/** + * @tc.name: ParseHtraceWithoutCpuDetailData + * @tc.desc: Parse a cpu that does not contain any cpudetail + * @tc.type: FUNC + */ +HWTEST_F(HtraceCpuDetailParserTest, ParseHtraceWithoutCpuDetailData, TestSize.Level1) +{ + TS_LOGI("test12-2"); + TracePluginResult tracePacket; + FtraceCpuDetailMsg* cpuDetail = tracePacket.add_ftrace_cpu_detail(); + auto event = cpuDetail->add_event(); + + HtraceCpuDetailParser htraceCpuDetailParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceCpuDetailParser.Parse(&tracePacket, TS_CLOCK_REALTIME); + htraceCpuDetailParser.FilterAllEvents(); + auto size = tracePacket.ftrace_cpu_detail_size(); + auto eventSize = cpuDetail->event_size(); + EXPECT_EQ(size, 1); + EXPECT_EQ(eventSize, 1); +} +/** + * @tc.name: ParseHtraceCpuDetailData + * @tc.desc: Parse a cpudetail data + * @tc.type: FUNC + */ +HWTEST_F(HtraceCpuDetailParserTest, ParseHtraceCpuDetailData, TestSize.Level1) +{ + TS_LOGI("test12-3"); + TracePluginResult tracePacket; + FtraceCpuDetailMsg* cpuDetail = tracePacket.add_ftrace_cpu_detail(); + auto event = cpuDetail->add_event(); + cpuDetail->set_cpu(1); + event->set_timestamp(1501983446213000000); + event->set_tgid(1); + CpuFrequencyFormat* freq = new CpuFrequencyFormat(); + freq->set_cpu_id(1); + freq->set_state(1500); + event->set_allocated_cpu_frequency_format(freq); + + HtraceCpuDetailParser htraceCpuDetailParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceCpuDetailParser.Parse(&tracePacket, TS_CLOCK_REALTIME); + htraceCpuDetailParser.FilterAllEvents(); + auto size = tracePacket.ftrace_cpu_detail_size(); + auto eventSize = cpuDetail->event_size(); + auto state = stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0]; + EXPECT_EQ(size, 1); + EXPECT_EQ(eventSize, 1); + EXPECT_EQ(state, 1500); +} +/** + * @tc.name: ParseMultipleCpuDetailData + * @tc.desc: Parse multiple cpudetail data + * @tc.type: FUNC + */ +HWTEST_F(HtraceCpuDetailParserTest, ParseMultipleCpuDetailData, TestSize.Level1) +{ + TS_LOGI("test12-4"); + TracePluginResult tracePacket; + FtraceCpuDetailMsg* cpuDetail = tracePacket.add_ftrace_cpu_detail(); + auto event = cpuDetail->add_event(); + cpuDetail->set_cpu(1); + event->set_timestamp(1501983446213000000); + event->set_tgid(1); + CpuFrequencyFormat* freq0 = new CpuFrequencyFormat(); + freq0->set_cpu_id(1); + freq0->set_state(1500); + event->set_allocated_cpu_frequency_format(freq0); + + cpuDetail = tracePacket.add_ftrace_cpu_detail(); + event = cpuDetail->add_event(); + cpuDetail->set_cpu(1); + event->set_timestamp(1501983446213000000); + event->set_tgid(1); + CpuFrequencyFormat* freq1 = new CpuFrequencyFormat(); + freq1->set_cpu_id(2); + freq1->set_state(3000); + event->set_allocated_cpu_frequency_format(freq1); + + HtraceCpuDetailParser htraceCpuDetailParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceCpuDetailParser.Parse(&tracePacket, TS_CLOCK_REALTIME); + htraceCpuDetailParser.FilterAllEvents(); + auto size = tracePacket.ftrace_cpu_detail_size(); + auto eventSize = cpuDetail->event_size(); + auto state0 = stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0]; + auto cpuId0 = stream_.traceDataCache_->GetConstMeasureData().FilterIdData()[0]; + auto state1 = stream_.traceDataCache_->GetConstMeasureData().ValuesData()[1]; + auto cpuId1 = stream_.traceDataCache_->GetConstMeasureData().FilterIdData()[1]; + EXPECT_EQ(size, 2); + EXPECT_EQ(eventSize, 1); + EXPECT_EQ(state0, 1500); + EXPECT_EQ(state1, 3000); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/htrace_diskio_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_diskio_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1050e85a25db42eb9b573c3b8d93cf213858916b --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_diskio_parser_test.cpp @@ -0,0 +1,330 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "htrace_disk_io_parser.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HtracediskioParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: ParseHtracediskioWithoutDiskioData + * @tc.desc: Parse a diskio that does not contain any DiskioData + * @tc.type: FUNC + */ +HWTEST_F(HtracediskioParserTest, ParseHtracediskioWithoutDiskioData, TestSize.Level1) +{ + TS_LOGI("test13-1"); + uint64_t ts = 100; + auto diskioData = std::make_unique(); + HtraceDiskIOParser htraceDiskIOParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceDiskIOParser.Parse(*diskioData, ts); + auto size = stream_.traceDataCache_->GetConstDiskIOData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseHtracediskioWithOneDiskioData + * @tc.desc: Parse a diskio with one DiskioData + * @tc.type: FUNC + */ +HWTEST_F(HtracediskioParserTest, ParseHtracediskioWithOneDiskioData, TestSize.Level1) +{ + TS_LOGI("test13-2"); + uint64_t ts = 100; + const uint64_t RD = 100; + const uint64_t WR = 101; + const uint64_t RDPERSEC = 102; + const uint64_t WRPERSEC = 103; + StatsData* statsData = new StatsData(); + auto ioStatData = statsData->add_statsinfo(); + ioStatData->set_rd_kb(RD); + ioStatData->set_wr_kb(WR); + ioStatData->set_rd_per_sec(RDPERSEC); + ioStatData->set_wr_per_sec(WRPERSEC); + + auto diskioData(std::make_unique()); + diskioData->set_allocated_statsdata(statsData); + + HtraceDiskIOParser htraceDiskioParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceDiskioParser.Parse(*diskioData, ts); + htraceDiskioParser.Finish(); + auto size = stream_.traceDataCache_->GetConstDiskIOData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseHtracediskioWithTwoDiskioData + * @tc.desc: Parse a diskio with two DiskioData + * @tc.type: FUNC + */ +HWTEST_F(HtracediskioParserTest, ParseHtracediskioWithTwoDiskioData, TestSize.Level1) +{ + TS_LOGI("test13-3"); + uint64_t ts = 100; + const uint64_t RD_01 = 100; + const uint64_t WR_01 = 101; + const uint64_t RDPERSEC_01 = 102; + const uint64_t WRPERSEC_01 = 103; + + const uint64_t RD_02 = 104; + const uint64_t WR_02 = 105; + const uint64_t RDPERSEC_02 = 106; + const uint64_t WRPERSEC_02 = 107; + + StatsData* statsDataFirst = new StatsData(); + auto ioStatDatafirst = statsDataFirst->add_statsinfo(); + ioStatDatafirst->set_rd_kb(RD_01); + ioStatDatafirst->set_wr_kb(WR_01); + ioStatDatafirst->set_rd_per_sec(RDPERSEC_01); + ioStatDatafirst->set_wr_per_sec(WRPERSEC_01); + + auto diskioData = std::make_unique(); + diskioData->set_allocated_statsdata(statsDataFirst); + + HtraceDiskIOParser htraceProcessParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceProcessParser.Parse(*diskioData, ts); + + StatsData* statsDataSecond = new StatsData(); + auto ioStatDataSecond = statsDataSecond->add_statsinfo(); + ioStatDataSecond->set_rd_kb(RD_02); + ioStatDataSecond->set_wr_kb(WR_02); + ioStatDataSecond->set_rd_per_sec(RDPERSEC_02); + ioStatDataSecond->set_wr_per_sec(WRPERSEC_02); + diskioData->set_allocated_statsdata(statsDataSecond); + + htraceProcessParser.Parse(*diskioData, ts); + htraceProcessParser.Finish(); + auto size = stream_.traceDataCache_->GetConstDiskIOData().Size(); + EXPECT_EQ(1, size); + + auto rdCountPerSecFirst = stream_.traceDataCache_->GetConstDiskIOData().RdCountPerSecDatas()[0]; + EXPECT_EQ(rdCountPerSecFirst, RDPERSEC_02); + + auto wrCountPerSecFirst = stream_.traceDataCache_->GetConstDiskIOData().WrCountPerSecDatas()[0]; + EXPECT_EQ(wrCountPerSecFirst, WRPERSEC_02); + + auto rdCountDatasFirst = stream_.traceDataCache_->GetConstDiskIOData().RdCountDatas()[0]; + EXPECT_EQ(rdCountDatasFirst, RD_02); + + auto wrCountDatasFirst = stream_.traceDataCache_->GetConstDiskIOData().WrCountDatas()[0]; + EXPECT_EQ(wrCountDatasFirst, WR_02); +} + +/** + * @tc.name: ParseHtracediskioWithThreeDiskioData + * @tc.desc: Parse a diskio with Three DiskioData + * @tc.type: FUNC + */ +HWTEST_F(HtracediskioParserTest, ParseHtracediskioWithThreeDiskioData, TestSize.Level1) +{ + TS_LOGI("test13-4"); + uint64_t ts = 100; + const uint64_t RD_01 = 100; + const uint64_t WR_01 = 101; + const uint64_t RDPERSEC_01 = 102; + const uint64_t WRPERSEC_01 = 103; + + const uint64_t RD_02 = 104; + const uint64_t WR_02 = 105; + const uint64_t RDPERSEC_02 = 106; + const uint64_t WRPERSEC_02 = 107; + + const uint64_t RD_03 = 108; + const uint64_t WR_03 = 109; + const uint64_t RDPERSEC_03 = 110; + const uint64_t WRPERSEC_03 = 111; + + StatsData* statsDataFirst = new StatsData(); + auto ioStatDatafirst = statsDataFirst->add_statsinfo(); + ioStatDatafirst->set_rd_kb(RD_01); + ioStatDatafirst->set_wr_kb(WR_01); + ioStatDatafirst->set_rd_per_sec(RDPERSEC_01); + ioStatDatafirst->set_wr_per_sec(WRPERSEC_01); + + auto diskioData = std::make_unique(); + diskioData->set_allocated_statsdata(statsDataFirst); + + HtraceDiskIOParser htraceProcessParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceProcessParser.Parse(*diskioData, ts); + + StatsData* statsDataSecond = new StatsData(); + auto ioStatDataSecond = statsDataSecond->add_statsinfo(); + ioStatDataSecond->set_rd_kb(RD_02); + ioStatDataSecond->set_wr_kb(WR_02); + ioStatDataSecond->set_rd_per_sec(RDPERSEC_02); + ioStatDataSecond->set_wr_per_sec(WRPERSEC_02); + diskioData->set_allocated_statsdata(statsDataSecond); + + htraceProcessParser.Parse(*diskioData, ts); + + StatsData* statsDataThird = new StatsData(); + auto ioStatDataThird = statsDataThird->add_statsinfo(); + ioStatDataThird->set_rd_kb(RD_03); + ioStatDataThird->set_wr_kb(WR_03); + ioStatDataThird->set_rd_per_sec(RDPERSEC_03); + ioStatDataThird->set_wr_per_sec(WRPERSEC_03); + diskioData->set_allocated_statsdata(statsDataThird); + htraceProcessParser.Parse(*diskioData, ts); + htraceProcessParser.Finish(); + auto size = stream_.traceDataCache_->GetConstDiskIOData().Size(); + EXPECT_EQ(2, size); + + auto rdCountPerSecFirst = stream_.traceDataCache_->GetConstDiskIOData().RdCountPerSecDatas()[0]; + auto rdCountPerSecSecond = stream_.traceDataCache_->GetConstDiskIOData().RdCountPerSecDatas()[1]; + EXPECT_EQ(rdCountPerSecFirst, RDPERSEC_02); + EXPECT_EQ(rdCountPerSecSecond, RDPERSEC_03); + + auto wrCountPerSecFirst = stream_.traceDataCache_->GetConstDiskIOData().WrCountPerSecDatas()[0]; + auto wrCountPerSecSecond = stream_.traceDataCache_->GetConstDiskIOData().WrCountPerSecDatas()[1]; + EXPECT_EQ(wrCountPerSecFirst, WRPERSEC_02); + EXPECT_EQ(wrCountPerSecSecond, WRPERSEC_03); + + auto rdCountDatasFirst = stream_.traceDataCache_->GetConstDiskIOData().RdCountDatas()[0]; + auto rdCountDatasSecond = stream_.traceDataCache_->GetConstDiskIOData().RdCountDatas()[1]; + EXPECT_EQ(rdCountDatasFirst, RD_02); + EXPECT_EQ(rdCountDatasSecond, RD_03); + + auto wrCountDatasFirst = stream_.traceDataCache_->GetConstDiskIOData().WrCountDatas()[0]; + auto wrCountDatasSecond = stream_.traceDataCache_->GetConstDiskIOData().WrCountDatas()[1]; + EXPECT_EQ(wrCountDatasFirst, WR_02); + EXPECT_EQ(wrCountDatasSecond, WR_03); +} + +/** + * @tc.name: ParseHtracediskioWithMultipleDiskioData + * @tc.desc: Parse a diskio with Multiple DiskioData + * @tc.type: FUNC + */ +HWTEST_F(HtracediskioParserTest, ParseHtracediskioWithMultipleDiskioData, TestSize.Level1) +{ + TS_LOGI("test13-5"); + uint64_t ts = 100; + const uint64_t RD_01 = 100; + const uint64_t WR_01 = 101; + const uint64_t RDPERSEC_01 = 102; + const uint64_t WRPERSEC_01 = 103; + + const uint64_t RD_02 = 104; + const uint64_t WR_02 = 105; + const uint64_t RDPERSEC_02 = 106; + const uint64_t WRPERSEC_02 = 107; + + const uint64_t RD_03 = 108; + const uint64_t WR_03 = 109; + const uint64_t RDPERSEC_03 = 110; + const uint64_t WRPERSEC_03 = 111; + + const uint64_t RD_04 = 112; + const uint64_t WR_04 = 113; + const uint64_t RDPERSEC_04 = 114; + const uint64_t WRPERSEC_04 = 115; + + StatsData* statsDataFirst = new StatsData(); + auto ioStatDatafirst = statsDataFirst->add_statsinfo(); + ioStatDatafirst->set_rd_kb(RD_01); + ioStatDatafirst->set_wr_kb(WR_01); + ioStatDatafirst->set_rd_per_sec(RDPERSEC_01); + ioStatDatafirst->set_wr_per_sec(WRPERSEC_01); + + auto diskioData = std::make_unique(); + diskioData->set_allocated_statsdata(statsDataFirst); + + HtraceDiskIOParser htraceProcessParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceProcessParser.Parse(*diskioData, ts); + + StatsData* statsDataSecond = new StatsData(); + auto ioStatDataSecond = statsDataSecond->add_statsinfo(); + ioStatDataSecond->set_rd_kb(RD_02); + ioStatDataSecond->set_wr_kb(WR_02); + ioStatDataSecond->set_rd_per_sec(RDPERSEC_02); + ioStatDataSecond->set_wr_per_sec(WRPERSEC_02); + diskioData->set_allocated_statsdata(statsDataSecond); + htraceProcessParser.Parse(*diskioData, ts); + + StatsData* statsDataThird = new StatsData(); + auto ioStatDataThird = statsDataThird->add_statsinfo(); + ioStatDataThird->set_rd_kb(RD_03); + ioStatDataThird->set_wr_kb(WR_03); + ioStatDataThird->set_rd_per_sec(RDPERSEC_03); + ioStatDataThird->set_wr_per_sec(WRPERSEC_03); + diskioData->set_allocated_statsdata(statsDataThird); + htraceProcessParser.Parse(*diskioData, ts); + + StatsData* statsDataForth = new StatsData(); + auto ioStatDataForth = statsDataForth->add_statsinfo(); + ioStatDataForth->set_rd_kb(RD_04); + ioStatDataForth->set_wr_kb(WR_04); + ioStatDataForth->set_rd_per_sec(RDPERSEC_04); + ioStatDataForth->set_wr_per_sec(WRPERSEC_04); + diskioData->set_allocated_statsdata(statsDataForth); + htraceProcessParser.Parse(*diskioData, ts); + htraceProcessParser.Finish(); + + auto size = stream_.traceDataCache_->GetConstDiskIOData().Size(); + EXPECT_EQ(3, size); + + auto rdCountPerSecFirst = stream_.traceDataCache_->GetConstDiskIOData().RdCountPerSecDatas()[0]; + auto rdCountPerSecSecond = stream_.traceDataCache_->GetConstDiskIOData().RdCountPerSecDatas()[1]; + auto rdCountPerSecThird = stream_.traceDataCache_->GetConstDiskIOData().RdCountPerSecDatas()[2]; + EXPECT_EQ(rdCountPerSecFirst, RDPERSEC_02); + EXPECT_EQ(rdCountPerSecSecond, RDPERSEC_03); + EXPECT_EQ(rdCountPerSecThird, RDPERSEC_04); + + auto wrCountPerSecFirst = stream_.traceDataCache_->GetConstDiskIOData().WrCountPerSecDatas()[0]; + auto wrCountPerSecSecond = stream_.traceDataCache_->GetConstDiskIOData().WrCountPerSecDatas()[1]; + auto wrCountPerSecThird = stream_.traceDataCache_->GetConstDiskIOData().WrCountPerSecDatas()[2]; + EXPECT_EQ(wrCountPerSecFirst, WRPERSEC_02); + EXPECT_EQ(wrCountPerSecSecond, WRPERSEC_03); + EXPECT_EQ(wrCountPerSecThird, WRPERSEC_04); + + auto rdCountDatasFirst = stream_.traceDataCache_->GetConstDiskIOData().RdCountDatas()[0]; + auto rdCountDatasSecond = stream_.traceDataCache_->GetConstDiskIOData().RdCountDatas()[1]; + auto rdCountDatasThird = stream_.traceDataCache_->GetConstDiskIOData().RdCountDatas()[2]; + EXPECT_EQ(rdCountDatasFirst, RD_02); + EXPECT_EQ(rdCountDatasSecond, RD_03); + EXPECT_EQ(rdCountDatasThird, RD_04); + + auto wrCountDatasFirst = stream_.traceDataCache_->GetConstDiskIOData().WrCountDatas()[0]; + auto wrCountDatasSecond = stream_.traceDataCache_->GetConstDiskIOData().WrCountDatas()[1]; + auto wrCountDatasThird = stream_.traceDataCache_->GetConstDiskIOData().WrCountDatas()[2]; + EXPECT_EQ(wrCountDatasFirst, WR_02); + EXPECT_EQ(wrCountDatasSecond, WR_03); + EXPECT_EQ(wrCountDatasThird, WR_04); +} +} // namespace TraceStreamer +} // namespace SysTuning \ No newline at end of file diff --git a/host/trace_streamer/test/unittest/htrace_event_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_event_parser_test.cpp index 220fe6fa26970e3e68fb0e0ab1d62b5a05af5815..d1b012c283e3aa0aa8d320c12492f5c9bd82cb7a 100644 --- a/host/trace_streamer/test/unittest/htrace_event_parser_test.cpp +++ b/host/trace_streamer/test/unittest/htrace_event_parser_test.cpp @@ -21,6 +21,7 @@ #include "cpu_filter.h" #include "htrace_cpu_detail_parser.h" #include "parser/common_types.h" +#include "src/filter/symbols_filter.h" #include "trace_streamer_filters.h" #include "trace_streamer_selector.h" @@ -55,6 +56,7 @@ public: */ HWTEST_F(HtraceEventParserTest, ParseSchedSwitchEvent, TestSize.Level1) { + TS_LOGI("test14-1"); SchedSwitchFormat* event = new SchedSwitchFormat(); event->set_prev_prio(PRIORITY_01); event->set_next_prio(PRIORITY_02); @@ -76,7 +78,7 @@ HWTEST_F(HtraceEventParserTest, ParseSchedSwitchEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); EXPECT_TRUE(1); auto realTimeStamp = stream_.traceDataCache_->GetConstSchedSliceData().TimeStamData()[0]; EXPECT_TRUE(TIMESTAMP == realTimeStamp); @@ -91,13 +93,14 @@ HWTEST_F(HtraceEventParserTest, ParseSchedSwitchEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseFtraceCpuDetailMsgHasNoEvent, TestSize.Level1) { + TS_LOGI("test14-2"); FtraceCpuDetailMsg ftraceCpuDetail; ftraceCpuDetail.set_cpu(0); ftraceCpuDetail.set_overwrite(0); HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_OTHER, STAT_EVENT_DATA_LOST); EXPECT_TRUE(0 == eventCount); @@ -110,6 +113,7 @@ HWTEST_F(HtraceEventParserTest, ParseFtraceCpuDetailMsgHasNoEvent, TestSize.Leve */ HWTEST_F(HtraceEventParserTest, ParseFtraceCpuDetailMsgOverwriteTrue, TestSize.Level1) { + TS_LOGI("test14-3"); SchedSwitchFormat* event = new SchedSwitchFormat(); event->set_prev_prio(PRIORITY_01); event->set_next_prio(PRIORITY_02); @@ -131,7 +135,7 @@ HWTEST_F(HtraceEventParserTest, ParseFtraceCpuDetailMsgOverwriteTrue, TestSize.L HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_OTHER, STAT_EVENT_DATA_LOST); EXPECT_TRUE(1 == eventCount); } @@ -143,6 +147,7 @@ HWTEST_F(HtraceEventParserTest, ParseFtraceCpuDetailMsgOverwriteTrue, TestSize.L */ HWTEST_F(HtraceEventParserTest, ParseTaskRenameEvent, TestSize.Level1) { + TS_LOGI("test14-4"); TaskRenameFormat* taskRenameEvent = new TaskRenameFormat(); taskRenameEvent->set_pid(PID_01); taskRenameEvent->set_oldcomm(THREAD_NAME_01); @@ -161,7 +166,7 @@ HWTEST_F(HtraceEventParserTest, ParseTaskRenameEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_TASK_RENAME, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -174,6 +179,7 @@ HWTEST_F(HtraceEventParserTest, ParseTaskRenameEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseTaskNewtaskEvent, TestSize.Level1) { + TS_LOGI("test14-5"); TaskNewtaskFormat* newTaskEvent = new TaskNewtaskFormat(); newTaskEvent->set_pid(PID_01); newTaskEvent->set_comm(THREAD_NAME_01); @@ -192,7 +198,7 @@ HWTEST_F(HtraceEventParserTest, ParseTaskNewtaskEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_TASK_NEWTASK, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -205,6 +211,7 @@ HWTEST_F(HtraceEventParserTest, ParseTaskNewtaskEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseSchedWakeupEvent, TestSize.Level1) { + TS_LOGI("test14-6"); SchedWakeupFormat* wakeupEvent = new SchedWakeupFormat(); wakeupEvent->set_comm(THREAD_NAME_01); wakeupEvent->set_pid(PRIORITY_02); @@ -223,7 +230,7 @@ HWTEST_F(HtraceEventParserTest, ParseSchedWakeupEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SCHED_WAKEUP, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -236,6 +243,7 @@ HWTEST_F(HtraceEventParserTest, ParseSchedWakeupEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseSchedWakingEvent, TestSize.Level1) { + TS_LOGI("test14-7"); SchedWakingFormat* wakingEvent = new SchedWakingFormat(); wakingEvent->set_comm(THREAD_NAME_01); wakingEvent->set_pid(PRIORITY_02); @@ -254,7 +262,7 @@ HWTEST_F(HtraceEventParserTest, ParseSchedWakingEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SCHED_WAKING, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -267,6 +275,7 @@ HWTEST_F(HtraceEventParserTest, ParseSchedWakingEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseCpuIdleEvent, TestSize.Level1) { + TS_LOGI("test14-8"); CpuIdleFormat* cpuIdleEvent = new CpuIdleFormat(); cpuIdleEvent->set_cpu_id(0); cpuIdleEvent->set_state(1); @@ -283,7 +292,7 @@ HWTEST_F(HtraceEventParserTest, ParseCpuIdleEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CPU_IDLE, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -296,6 +305,7 @@ HWTEST_F(HtraceEventParserTest, ParseCpuIdleEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseCpuFrequencyEvent, TestSize.Level1) { + TS_LOGI("test14-9"); CpuFrequencyFormat* cpuFrequencyEvent = new CpuFrequencyFormat(); cpuFrequencyEvent->set_cpu_id(0); cpuFrequencyEvent->set_state(1); @@ -312,7 +322,7 @@ HWTEST_F(HtraceEventParserTest, ParseCpuFrequencyEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CPU_FREQUENCY, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -325,6 +335,9 @@ HWTEST_F(HtraceEventParserTest, ParseCpuFrequencyEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseWorkqueueExecuteStartEvent, TestSize.Level1) { + TS_LOGI("test14-10"); + stream_.streamFilters_->symbolsFilter_->RegisterFunc(1, 1); + auto funcNum = stream_.streamFilters_->symbolsFilter_->GetFunc(1); WorkqueueExecuteStartFormat* workqueueExecuteStartEvent = new WorkqueueExecuteStartFormat(); workqueueExecuteStartEvent->set_work(0); workqueueExecuteStartEvent->set_function(1); @@ -341,7 +354,7 @@ HWTEST_F(HtraceEventParserTest, ParseWorkqueueExecuteStartEvent, TestSize.Level1 HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_WORKQUEUE_EXECUTE_START, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -354,6 +367,7 @@ HWTEST_F(HtraceEventParserTest, ParseWorkqueueExecuteStartEvent, TestSize.Level1 */ HWTEST_F(HtraceEventParserTest, ParseWorkqueueExecuteEndEvent, TestSize.Level1) { + TS_LOGI("test14-11"); WorkqueueExecuteEndFormat* workqueueExecuteEndEvent = new WorkqueueExecuteEndFormat(); workqueueExecuteEndEvent->set_work(0); @@ -369,7 +383,7 @@ HWTEST_F(HtraceEventParserTest, ParseWorkqueueExecuteEndEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_WORKQUEUE_EXECUTE_END, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -382,6 +396,7 @@ HWTEST_F(HtraceEventParserTest, ParseWorkqueueExecuteEndEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseClockDisableEvent, TestSize.Level1) { + TS_LOGI("test14-12"); ClockDisableFormat* clockDisableEvent = new ClockDisableFormat(); clockDisableEvent->set_name(THREAD_NAME_02); clockDisableEvent->set_cpu_id(0); @@ -399,7 +414,7 @@ HWTEST_F(HtraceEventParserTest, ParseClockDisableEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLOCK_DISABLE, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -412,6 +427,7 @@ HWTEST_F(HtraceEventParserTest, ParseClockDisableEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseClockEnableEvent, TestSize.Level1) { + TS_LOGI("test14-13"); ClockEnableFormat* clockEnableEvent = new ClockEnableFormat(); clockEnableEvent->set_name(THREAD_NAME_02); clockEnableEvent->set_cpu_id(0); @@ -429,7 +445,7 @@ HWTEST_F(HtraceEventParserTest, ParseClockEnableEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLOCK_ENABLE, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -442,6 +458,7 @@ HWTEST_F(HtraceEventParserTest, ParseClockEnableEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseClockSetRateEvent, TestSize.Level1) { + TS_LOGI("test14-14"); ClockSetRateFormat* clockSetRateEvent = new ClockSetRateFormat(); clockSetRateEvent->set_name(THREAD_NAME_02); clockSetRateEvent->set_cpu_id(0); @@ -459,7 +476,7 @@ HWTEST_F(HtraceEventParserTest, ParseClockSetRateEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLOCK_SET_RATE, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -472,6 +489,7 @@ HWTEST_F(HtraceEventParserTest, ParseClockSetRateEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseClkDisableEvent, TestSize.Level1) { + TS_LOGI("test14-15"); ClkDisableFormat* clkDisableEvent = new ClkDisableFormat(); clkDisableEvent->set_name(THREAD_NAME_02); @@ -487,7 +505,7 @@ HWTEST_F(HtraceEventParserTest, ParseClkDisableEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLK_DISABLE, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -500,6 +518,7 @@ HWTEST_F(HtraceEventParserTest, ParseClkDisableEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseClkEnableEvent, TestSize.Level1) { + TS_LOGI("test14-16"); ClkEnableFormat* clkEnableEvent = new ClkEnableFormat(); clkEnableEvent->set_name(THREAD_NAME_02); @@ -515,6 +534,7 @@ HWTEST_F(HtraceEventParserTest, ParseClkEnableEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLK_ENABLE, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -527,6 +547,7 @@ HWTEST_F(HtraceEventParserTest, ParseClkEnableEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseClkSetRateEvent, TestSize.Level1) { + TS_LOGI("test14-17"); ClkSetRateFormat* clkSetRateEvent = new ClkSetRateFormat(); clkSetRateEvent->set_name(THREAD_NAME_02); clkSetRateEvent->set_rate(1); @@ -543,7 +564,7 @@ HWTEST_F(HtraceEventParserTest, ParseClkSetRateEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_CLK_SET_RATE, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -556,6 +577,7 @@ HWTEST_F(HtraceEventParserTest, ParseClkSetRateEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseSysEnterEvent, TestSize.Level1) { + TS_LOGI("test14-18"); SysEnterFormat* sysEnterEvent = new SysEnterFormat(); sysEnterEvent->set_id(1); sysEnterEvent->set_args(THREAD_NAME_02); @@ -572,7 +594,7 @@ HWTEST_F(HtraceEventParserTest, ParseSysEnterEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); @@ -584,6 +606,7 @@ HWTEST_F(HtraceEventParserTest, ParseSysEnterEvent, TestSize.Level1) */ HWTEST_F(HtraceEventParserTest, ParseSystemExitEvent, TestSize.Level1) { + TS_LOGI("test14-19"); SysExitFormat* sysExitEvent = new SysExitFormat(); sysExitEvent->set_id(1); sysExitEvent->set_ret(1); @@ -600,7 +623,7 @@ HWTEST_F(HtraceEventParserTest, ParseSystemExitEvent, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - stream_.streamFilters_->cpuFilter_->FinishCpuEvent(); + eventParser.FilterAllEvents(); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SYS_EXIT, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); diff --git a/host/trace_streamer/test/unittest/htrace_irq_event_test.cpp b/host/trace_streamer/test/unittest/htrace_irq_event_test.cpp index 79c265ace264f43c8fd5a5953cc22ba5815a3174..c81ebd6fd8b7587cbeb4e996f6dd09d151ee7d59 100644 --- a/host/trace_streamer/test/unittest/htrace_irq_event_test.cpp +++ b/host/trace_streamer/test/unittest/htrace_irq_event_test.cpp @@ -47,7 +47,7 @@ public: */ HWTEST_F(HtraceIrqEventTest, IrqHandlerEntryTest, TestSize.Level1) { - TS_LOGI("test10-1"); + TS_LOGI("test15-1"); int64_t ts1 = 100; uint32_t cpu1 = 1; std::string appName = "app1"; @@ -68,7 +68,9 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEntryTest, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); + eventParser.Clear(); } /** @@ -78,7 +80,7 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEntryTest, TestSize.Level1) */ HWTEST_F(HtraceIrqEventTest, IrqHandlerEntryTestNotMatch, TestSize.Level1) { - TS_LOGI("test10-2"); + TS_LOGI("test15-2"); int64_t ts1 = 120; uint32_t cpu1 = 1; std::string appName = "app1"; @@ -99,7 +101,8 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEntryTestNotMatch, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); ts1 = 110; IrqHandlerEntryFormat* irqHandlerEvent2 = new IrqHandlerEntryFormat(); irqHandlerEvent2->set_irq(irq); @@ -114,11 +117,13 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEntryTestNotMatch, TestSize.Level1) ftraceEvent2->set_comm(appName); ftraceEvent2->set_allocated_irq_handler_entry_format(irqHandlerEvent2); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 2); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_DATA_LOST); EXPECT_TRUE(1 == eventCount); + eventParser.Clear(); } /** @@ -128,7 +133,7 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEntryTestNotMatch, TestSize.Level1) */ HWTEST_F(HtraceIrqEventTest, IrqHandlerExitTestEmpty, TestSize.Level1) { - TS_LOGI("test10-3"); + TS_LOGI("test15-3"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t ret = 1; @@ -151,10 +156,12 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerExitTestEmpty, TestSize.Level1) HtraceEventParser eventParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 0); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 0); auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_NOTMATCH); EXPECT_TRUE(1 == eventCount); + eventParser.Clear(); } /** @@ -164,7 +171,7 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerExitTestEmpty, TestSize.Level1) */ HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTest, TestSize.Level1) { - TS_LOGI("test10-4"); + TS_LOGI("test15-4"); int64_t ts1 = 100; uint32_t cpu1 = 1; std::string appName = "app1"; @@ -185,7 +192,8 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTest, TestSize.Level1) ftraceEvent->set_comm(appName); ftraceEvent->set_allocated_irq_handler_entry_format(irqHandlerEvent); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); uint32_t ret = 1; // 1 for handled, else for unhandled IrqHandlerExitFormat* irqHandlerExitEvent = new IrqHandlerExitFormat(); @@ -202,9 +210,11 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTest, TestSize.Level1) ftraceEvent2->set_allocated_irq_handler_exit_format(irqHandlerExitEvent); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); + eventParser.FilterAllEvents(); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().ArgSetIdsData()[0] == 0); + eventParser.Clear(); } /** @@ -214,7 +224,7 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTest, TestSize.Level1) */ HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTestTwice, TestSize.Level1) { - TS_LOGI("test10-4-2"); + TS_LOGI("test15-5"); int64_t ts1 = 100; uint32_t cpu1 = 1; std::string appName = "app1"; @@ -235,7 +245,8 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTestTwice, TestSize.Level1) ftraceEvent->set_comm(appName); ftraceEvent->set_allocated_irq_handler_entry_format(irqHandlerEvent); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); uint32_t ret = 1; // 1 for handled, else for unhandled cpu1 = 2; ts1 = 150; @@ -254,7 +265,8 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTestTwice, TestSize.Level1) ftraceEvent2->set_allocated_irq_handler_exit_format(irqHandlerExitEvent); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); EXPECT_TRUE(stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_NOTMATCH) == 1); cpu1 = 1; @@ -274,8 +286,10 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTestTwice, TestSize.Level1) ftraceEvent3->set_allocated_irq_handler_exit_format(irqHandlerExitEvent2); eventParser.ParseDataItem(&ftraceCpuDetail3, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().ArgSetIdsData()[0] == 0); + eventParser.Clear(); } /** @@ -285,7 +299,7 @@ HWTEST_F(HtraceIrqEventTest, IrqHandlerEnterAndExitTestTwice, TestSize.Level1) */ HWTEST_F(HtraceIrqEventTest, SoftIrqEntryTest, TestSize.Level1) { - TS_LOGI("test10-6"); + TS_LOGI("test15-6"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; @@ -305,7 +319,9 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqEntryTest, TestSize.Level1) ftraceEvent->set_comm(appName); ftraceEvent->set_allocated_softirq_entry_format(softirqEntryEvent); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); + eventParser.Clear(); } /** @@ -315,7 +331,7 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqEntryTest, TestSize.Level1) */ HWTEST_F(HtraceIrqEventTest, SoftIrqEntryNotMatch, TestSize.Level1) { - TS_LOGI("test10-7"); + TS_LOGI("test15-7"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; @@ -335,7 +351,8 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqEntryNotMatch, TestSize.Level1) ftraceEvent->set_comm(appName); ftraceEvent->set_allocated_softirq_entry_format(softirqEntryEvent); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); ts1 = 150; SoftirqEntryFormat* softirqEntryEvent2 = new SoftirqEntryFormat(); @@ -350,9 +367,11 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqEntryNotMatch, TestSize.Level1) ftraceEvent2->set_comm(appName); ftraceEvent2->set_allocated_softirq_entry_format(softirqEntryEvent2); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 2); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 2); EXPECT_TRUE( stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_DATA_LOST) == 1); + eventParser.Clear(); } /** @@ -362,7 +381,7 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqEntryNotMatch, TestSize.Level1) */ HWTEST_F(HtraceIrqEventTest, SoftIrqExitEmptyTest, TestSize.Level1) { - TS_LOGI("test10-8"); + TS_LOGI("test15-8"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; @@ -382,9 +401,11 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqExitEmptyTest, TestSize.Level1) ftraceEvent->set_comm(appName); ftraceEvent->set_allocated_softirq_exit_format(softirqExitEvent); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 0); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 0); EXPECT_TRUE( stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); + eventParser.Clear(); } /** @@ -394,7 +415,7 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqExitEmptyTest, TestSize.Level1) */ HWTEST_F(HtraceIrqEventTest, SoftIrqTest, TestSize.Level1) { - TS_LOGI("test10-9"); + TS_LOGI("test15-9"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; @@ -414,8 +435,10 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqTest, TestSize.Level1) ftraceEvent->set_comm(appName); ftraceEvent->set_allocated_softirq_entry_format(softirqEntryEvent); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); + eventParser.FilterAllEvents(); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); + eventParser.Clear(); ts1 = 150; SoftirqExitFormat* softirqExitEvent = new SoftirqExitFormat(); softirqExitEvent->set_vec(vec); @@ -429,7 +452,9 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqTest, TestSize.Level1) ftraceEvent2->set_comm(appName); ftraceEvent2->set_allocated_softirq_exit_format(softirqExitEvent); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); + eventParser.Clear(); } /** @@ -439,7 +464,7 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqTest, TestSize.Level1) */ HWTEST_F(HtraceIrqEventTest, SoftIrqTestNotMatch, TestSize.Level1) { - TS_LOGI("test10-10"); + TS_LOGI("test15-10"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; @@ -459,7 +484,9 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqTestNotMatch, TestSize.Level1) ftraceEvent->set_comm(appName); ftraceEvent->set_allocated_softirq_entry_format(softirqEntryEvent); eventParser.ParseDataItem(&ftraceCpuDetail, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); + eventParser.Clear(); ts1 = 150; cpu1 = 2; @@ -475,9 +502,11 @@ HWTEST_F(HtraceIrqEventTest, SoftIrqTestNotMatch, TestSize.Level1) ftraceEvent2->set_comm(appName); ftraceEvent2->set_allocated_softirq_exit_format(softirqExitEvent); eventParser.ParseDataItem(&ftraceCpuDetail2, TS_CLOCK_BOOTTIME); - EXPECT_TRUE(stream_.traceDataCache_->GetConstInternalSlicesData().Size() == 1); + eventParser.FilterAllEvents(); + EXPECT_TRUE(stream_.traceDataCache_->GetConstIrqData().Size() == 1); EXPECT_TRUE(stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); + eventParser.Clear(); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/htrace_mem_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_mem_parser_test.cpp old mode 100644 new mode 100755 index 822a0f2f2cf1ceb663419f8bc1e9591658666984..1ac7a4e2d8a1b68fc32c3f6e1aa00b266bdc5768 --- a/host/trace_streamer/test/unittest/htrace_mem_parser_test.cpp +++ b/host/trace_streamer/test/unittest/htrace_mem_parser_test.cpp @@ -45,7 +45,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "/data/resource/out.db"; + const std::string dbPath_ = "data/resource/out.db"; }; /** @@ -55,7 +55,7 @@ public: */ HWTEST_F(HtraceMemParserTest, ParseMemParse, TestSize.Level1) { - TS_LOGI("test7-1"); + TS_LOGI("test16-1"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -85,7 +85,7 @@ HWTEST_F(HtraceMemParserTest, ParseMemParse, TestSize.Level1) */ HWTEST_F(HtraceMemParserTest, ParseMemParseTestMeasureDataSize, TestSize.Level1) { - TS_LOGI("test7-1"); + TS_LOGI("test16-2"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -119,21 +119,22 @@ HWTEST_F(HtraceMemParserTest, ParseMemParseTestMeasureDataSize, TestSize.Level1) EXPECT_TRUE(1 == eventCount); EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessData(1).pid_ == pid); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == MEM_MAX * 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == MEM_MAX * 1); + EXPECT_EQ(stream_.traceDataCache_->GetConstProcessData().size(), 2); for (auto i = 0; i < MEM_MAX; i++) { - if (stream_.traceDataCache_->GetConstMeasureData().filterIdDeque_[i] == + if (stream_.traceDataCache_->GetConstProcessMeasureData().filterIdDeque_[i] == memParser->memNameDictMap_.at(MEM_VM_SIZE)) { - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().valuesDeque_[i] == memKb); - } else if (stream_.traceDataCache_->GetConstMeasureData().filterIdDeque_[i] == + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().valuesDeque_[i] == memKb); + } else if (stream_.traceDataCache_->GetConstProcessMeasureData().filterIdDeque_[i] == memParser->memNameDictMap_.at(MEM_VM_RSS)) { - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().valuesDeque_[i] == memRssKb); - } else if (stream_.traceDataCache_->GetConstMeasureData().filterIdDeque_[i] == + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().valuesDeque_[i] == memRssKb); + } else if (stream_.traceDataCache_->GetConstProcessMeasureData().filterIdDeque_[i] == memParser->memNameDictMap_.at(MEM_VM_ANON)) { - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().valuesDeque_[i] == memAnonKb); - } else if (stream_.traceDataCache_->GetConstMeasureData().filterIdDeque_[i] == + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().valuesDeque_[i] == memAnonKb); + } else if (stream_.traceDataCache_->GetConstProcessMeasureData().filterIdDeque_[i] == memParser->memNameDictMap_.at(MEM_RSS_FILE)) { - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().valuesDeque_[i] == memFileKb); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().valuesDeque_[i] == memFileKb); } } } @@ -145,7 +146,7 @@ HWTEST_F(HtraceMemParserTest, ParseMemParseTestMeasureDataSize, TestSize.Level1) */ HWTEST_F(HtraceMemParserTest, ParseMemParseTestMutiMeasureData, TestSize.Level1) { - TS_LOGI("test7-1"); + TS_LOGI("test16-3"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -198,7 +199,7 @@ HWTEST_F(HtraceMemParserTest, ParseMemParseTestMutiMeasureData, TestSize.Level1) */ HWTEST_F(HtraceMemParserTest, ParseMultiEmptyProcessMemoryInfo, TestSize.Level1) { - TS_LOGI("test7-1"); + TS_LOGI("test16-4"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -225,7 +226,7 @@ HWTEST_F(HtraceMemParserTest, ParseMultiEmptyProcessMemoryInfo, TestSize.Level1) auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_MEMORY, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == MEM_MAX * 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == MEM_MAX * 2); } /** @@ -235,7 +236,7 @@ HWTEST_F(HtraceMemParserTest, ParseMultiEmptyProcessMemoryInfo, TestSize.Level1) */ HWTEST_F(HtraceMemParserTest, ParseEmptyMemoryData, TestSize.Level1) { - TS_LOGI("test7-1"); + TS_LOGI("test16-5"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; diff --git a/host/trace_streamer/test/unittest/htrace_network_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_network_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9d62420c12e67b79f0e3fca6760ec07e3a71643 --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_network_parser_test.cpp @@ -0,0 +1,300 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "htrace_network_parser.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HtraceNetworkParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: ParseHtraceNetworkWithoutNetworkData + * @tc.desc: Parse a Process that does not contain any ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceNetworkParserTest, ParseHtraceNetworkWithoutNetworkData, TestSize.Level1) +{ + TS_LOGI("test17-1"); + uint64_t ts = 100; + auto networkDatas = std::make_unique(); + HtraceNetworkParser htraceProcessParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceProcessParser.Parse(*networkDatas, ts); + auto size = stream_.traceDataCache_->GetConstNetworkData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseHtraceNetworkWithNetworkData + * @tc.desc: Parse a Process with ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceNetworkParserTest, ParseHtraceNetworkWithNetworkData, TestSize.Level1) +{ + TS_LOGI("test17-2"); + uint64_t ts = 100; + const uint64_t DURS = 1999632780; + const uint64_t TX = 712924; + const uint64_t RX = 13535014; + const uint64_t PACKETIN = 11431; + const uint64_t PACKETOUT = 7373; + + auto networkDatas = std::make_unique(); + NetworkSystemData* networkSystemData = new NetworkSystemData(); + networkSystemData->set_rx_bytes(RX); + networkSystemData->set_tx_bytes(TX); + networkSystemData->set_rx_packets(PACKETIN); + networkSystemData->set_tx_packets(PACKETOUT); + networkDatas->set_allocated_network_system_info(networkSystemData); + + HtraceNetworkParser htraceNetworkParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNetworkParser.Parse(*networkDatas, ts); + htraceNetworkParser.Finish(); + auto size = stream_.traceDataCache_->GetConstNetworkData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseHtraceNetworkWithTwoNetworkData + * @tc.desc: Parse a Process with ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceNetworkParserTest, ParseHtraceNetworkWithTwoNetworkData, TestSize.Level1) +{ + TS_LOGI("test17-3"); + uint64_t ts = 100; + auto networkDatas = std::make_unique(); + + const uint64_t DURS_01 = 1999632781; + const uint64_t TX_01 = 712921; + const uint64_t RX_01 = 13535011; + const uint64_t PACKETIN_01 = 11431; + const uint64_t PACKETOUT_01 = 7371; + NetworkSystemData* networkSystemDataFirst = new NetworkSystemData(); + networkSystemDataFirst->set_rx_bytes(RX_01); + networkSystemDataFirst->set_tx_bytes(TX_01); + networkSystemDataFirst->set_rx_packets(PACKETIN_01); + networkSystemDataFirst->set_tx_packets(PACKETOUT_01); + networkDatas->set_allocated_network_system_info(networkSystemDataFirst); + HtraceNetworkParser htraceNetworkParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNetworkParser.Parse(*networkDatas, ts); + + const uint64_t DURS_02 = 1999632782; + const uint64_t TX_02 = 712922; + const uint64_t RX_02 = 13535012; + const uint64_t PACKETIN_02 = 11432; + const uint64_t PACKETOUT_02 = 7372; + NetworkSystemData* networkSystemDataSecond = new NetworkSystemData(); + networkSystemDataSecond->set_rx_bytes(RX_02); + networkSystemDataSecond->set_tx_bytes(TX_02); + networkSystemDataSecond->set_rx_packets(PACKETIN_02); + networkSystemDataSecond->set_tx_packets(PACKETOUT_02); + networkDatas->set_allocated_network_system_info(networkSystemDataSecond); + htraceNetworkParser.Parse(*networkDatas, ts); + htraceNetworkParser.Finish(); + + auto tx = stream_.traceDataCache_->GetConstNetworkData().TxDatas()[0]; + EXPECT_EQ(tx, TX_02); + auto rx = stream_.traceDataCache_->GetConstNetworkData().RxDatas()[0]; + EXPECT_EQ(rx, RX_02); + auto packetIn = stream_.traceDataCache_->GetConstNetworkData().PacketIn()[0]; + EXPECT_EQ(packetIn, PACKETIN_02); + auto packetOut = stream_.traceDataCache_->GetConstNetworkData().PacketOut()[0]; + EXPECT_EQ(packetOut, PACKETOUT_02); +} + +/** + * @tc.name: ParseHtraceNetworkWithThreeNetworkData + * @tc.desc: Parse a Process with ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceNetworkParserTest, ParseHtraceNetworkWithThreeNetworkData, TestSize.Level1) +{ + TS_LOGI("test17-4"); + uint64_t ts = 100; + auto networkDatas = std::make_unique(); + + const uint64_t DURS_01 = 1999632781; + const uint64_t TX_01 = 712921; + const uint64_t RX_01 = 13535011; + const uint64_t PACKETIN_01 = 11431; + const uint64_t PACKETOUT_01 = 7371; + NetworkSystemData* networkSystemDataFirst = new NetworkSystemData(); + networkSystemDataFirst->set_rx_bytes(RX_01); + networkSystemDataFirst->set_tx_bytes(TX_01); + networkSystemDataFirst->set_rx_packets(PACKETIN_01); + networkSystemDataFirst->set_tx_packets(PACKETOUT_01); + networkDatas->set_allocated_network_system_info(networkSystemDataFirst); + HtraceNetworkParser htraceNetworkParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNetworkParser.Parse(*networkDatas, ts); + + const uint64_t DURS_02 = 1999632782; + const uint64_t TX_02 = 712922; + const uint64_t RX_02 = 13535012; + const uint64_t PACKETIN_02 = 11432; + const uint64_t PACKETOUT_02 = 7372; + NetworkSystemData* networkSystemDataSecond = new NetworkSystemData(); + networkSystemDataSecond->set_rx_bytes(RX_02); + networkSystemDataSecond->set_tx_bytes(TX_02); + networkSystemDataSecond->set_rx_packets(PACKETIN_02); + networkSystemDataSecond->set_tx_packets(PACKETOUT_02); + networkDatas->set_allocated_network_system_info(networkSystemDataSecond); + htraceNetworkParser.Parse(*networkDatas, ts); + + const uint64_t DURS_03 = 1999632783; + const uint64_t TX_03 = 712923; + const uint64_t RX_03 = 13535013; + const uint64_t PACKETIN_03 = 11433; + const uint64_t PACKETOUT_03 = 7373; + NetworkSystemData* networkSystemDataThird = new NetworkSystemData(); + networkSystemDataThird->set_rx_bytes(RX_03); + networkSystemDataThird->set_tx_bytes(TX_03); + networkSystemDataThird->set_rx_packets(PACKETIN_03); + networkSystemDataThird->set_tx_packets(PACKETOUT_03); + networkDatas->set_allocated_network_system_info(networkSystemDataThird); + htraceNetworkParser.Parse(*networkDatas, ts); + htraceNetworkParser.Finish(); + + auto txFirst = stream_.traceDataCache_->GetConstNetworkData().TxDatas()[0]; + auto txSecond = stream_.traceDataCache_->GetConstNetworkData().TxDatas()[1]; + EXPECT_EQ(txFirst, TX_02); + EXPECT_EQ(txSecond, TX_03); + auto rxFirst = stream_.traceDataCache_->GetConstNetworkData().RxDatas()[0]; + auto rxSecond = stream_.traceDataCache_->GetConstNetworkData().RxDatas()[1]; + EXPECT_EQ(rxFirst, RX_02); + EXPECT_EQ(rxSecond, RX_03); + auto packetInFirst = stream_.traceDataCache_->GetConstNetworkData().PacketIn()[0]; + auto packetInSecond = stream_.traceDataCache_->GetConstNetworkData().PacketIn()[1]; + EXPECT_EQ(packetInFirst, PACKETIN_02); + EXPECT_EQ(packetInSecond, PACKETIN_03); + auto packetOutFirst = stream_.traceDataCache_->GetConstNetworkData().PacketOut()[0]; + auto packetOutSecond = stream_.traceDataCache_->GetConstNetworkData().PacketOut()[1]; + EXPECT_EQ(packetOutFirst, PACKETOUT_02); + EXPECT_EQ(packetOutSecond, PACKETOUT_03); +} + +/** + * @tc.name: ParseHtraceNetworkWithMultipleNetworkData + * @tc.desc: Parse a Process with ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceNetworkParserTest, ParseHtraceNetworkWithMultipleNetworkData, TestSize.Level1) +{ + TS_LOGI("test17-5"); + uint64_t ts = 100; + auto networkDatas = std::make_unique(); + + const uint64_t DURS_01 = 1999632781; + const uint64_t TX_01 = 712921; + const uint64_t RX_01 = 13535011; + const uint64_t PACKETIN_01 = 11431; + const uint64_t PACKETOUT_01 = 7371; + NetworkSystemData* networkSystemDataFirst = new NetworkSystemData(); + networkSystemDataFirst->set_rx_bytes(RX_01); + networkSystemDataFirst->set_tx_bytes(TX_01); + networkSystemDataFirst->set_rx_packets(PACKETIN_01); + networkSystemDataFirst->set_tx_packets(PACKETOUT_01); + networkDatas->set_allocated_network_system_info(networkSystemDataFirst); + HtraceNetworkParser htraceNetworkParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNetworkParser.Parse(*networkDatas, ts); + + const uint64_t DURS_02 = 1999632782; + const uint64_t TX_02 = 712922; + const uint64_t RX_02 = 13535012; + const uint64_t PACKETIN_02 = 11432; + const uint64_t PACKETOUT_02 = 7372; + NetworkSystemData* networkSystemDataSecond = new NetworkSystemData(); + networkSystemDataSecond->set_rx_bytes(RX_02); + networkSystemDataSecond->set_tx_bytes(TX_02); + networkSystemDataSecond->set_rx_packets(PACKETIN_02); + networkSystemDataSecond->set_tx_packets(PACKETOUT_02); + networkDatas->set_allocated_network_system_info(networkSystemDataSecond); + htraceNetworkParser.Parse(*networkDatas, ts); + + const uint64_t DURS_03 = 1999632783; + const uint64_t TX_03 = 712923; + const uint64_t RX_03 = 13535013; + const uint64_t PACKETIN_03 = 11433; + const uint64_t PACKETOUT_03 = 7373; + NetworkSystemData* networkSystemDataThird = new NetworkSystemData(); + networkSystemDataThird->set_rx_bytes(RX_03); + networkSystemDataThird->set_tx_bytes(TX_03); + networkSystemDataThird->set_rx_packets(PACKETIN_03); + networkSystemDataThird->set_tx_packets(PACKETOUT_03); + networkDatas->set_allocated_network_system_info(networkSystemDataThird); + htraceNetworkParser.Parse(*networkDatas, ts); + + const uint64_t DURS_04 = 1999632784; + const uint64_t TX_04 = 712924; + const uint64_t RX_04 = 13535014; + const uint64_t PACKETIN_04 = 11434; + const uint64_t PACKETOUT_04 = 7374; + NetworkSystemData* networkSystemDataForth = new NetworkSystemData(); + networkSystemDataForth->set_rx_bytes(RX_04); + networkSystemDataForth->set_tx_bytes(TX_04); + networkSystemDataForth->set_rx_packets(PACKETIN_04); + networkSystemDataForth->set_tx_packets(PACKETOUT_04); + networkDatas->set_allocated_network_system_info(networkSystemDataForth); + htraceNetworkParser.Parse(*networkDatas, ts); + htraceNetworkParser.Finish(); + + auto txFirst = stream_.traceDataCache_->GetConstNetworkData().TxDatas()[0]; + auto txSecond = stream_.traceDataCache_->GetConstNetworkData().TxDatas()[1]; + auto txThird = stream_.traceDataCache_->GetConstNetworkData().TxDatas()[2]; + EXPECT_EQ(txFirst, TX_02); + EXPECT_EQ(txSecond, TX_03); + EXPECT_EQ(txThird, TX_04); + auto rxFirst = stream_.traceDataCache_->GetConstNetworkData().RxDatas()[0]; + auto rxSecond = stream_.traceDataCache_->GetConstNetworkData().RxDatas()[1]; + auto rxThird = stream_.traceDataCache_->GetConstNetworkData().RxDatas()[2]; + EXPECT_EQ(rxFirst, RX_02); + EXPECT_EQ(rxSecond, RX_03); + EXPECT_EQ(rxThird, RX_04); + auto packetInFirst = stream_.traceDataCache_->GetConstNetworkData().PacketIn()[0]; + auto packetInSecond = stream_.traceDataCache_->GetConstNetworkData().PacketIn()[1]; + auto packetInThird = stream_.traceDataCache_->GetConstNetworkData().PacketIn()[2]; + EXPECT_EQ(packetInFirst, PACKETIN_02); + EXPECT_EQ(packetInSecond, PACKETIN_03); + EXPECT_EQ(packetInThird, PACKETIN_04); + auto packetOutFirst = stream_.traceDataCache_->GetConstNetworkData().PacketOut()[0]; + auto packetOutSecond = stream_.traceDataCache_->GetConstNetworkData().PacketOut()[1]; + auto packetOutThird = stream_.traceDataCache_->GetConstNetworkData().PacketOut()[2]; + EXPECT_EQ(packetOutFirst, PACKETOUT_02); + EXPECT_EQ(packetOutSecond, PACKETOUT_03); + EXPECT_EQ(packetOutThird, PACKETOUT_04); +} +} // namespace TraceStreamer +} // namespace SysTuning \ No newline at end of file diff --git a/host/trace_streamer/test/unittest/htrace_process_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_process_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f241229a87d0eba51067dab94812def01c86a2b --- /dev/null +++ b/host/trace_streamer/test/unittest/htrace_process_parser_test.cpp @@ -0,0 +1,299 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "htrace_process_parser.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +class HtraceProcessParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: ParseHtraceProcessWithoutProcessData + * @tc.desc: Parse a Process that does not contain any ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceProcessParserTest, ParseHtraceProcessWithoutProcessData, TestSize.Level1) +{ + TS_LOGI("test18-1"); + auto processData = std::make_unique(); + uint64_t ts = 100; + HtraceProcessParser htraceProcessParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceProcessParser.Parse(*processData, ts); + auto size = stream_.traceDataCache_->GetConstLiveProcessData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseHtraceProcessWithProcessData + * @tc.desc: Parse a Process with ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceProcessParserTest, ParseHtraceProcessWithProcessData, TestSize.Level1) +{ + TS_LOGI("test18-2"); + uint64_t ts = 100; + const uint32_t PID = 312; + const string NAME = "resource_schedu"; + const int32_t PPID = 22; + const int32_t UID = 23; + + auto processData = std::make_unique(); + ProcessInfo* processInfo = processData->add_processesinfo(); + processInfo->set_pid(PID); + processInfo->set_name(NAME); + processInfo->set_ppid(PPID); + processInfo->set_uid(UID); + + HtraceProcessParser htraceProcessParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceProcessParser.Parse(*processData, ts); + htraceProcessParser.Finish(); + + auto size = stream_.traceDataCache_->GetConstLiveProcessData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseHtraceProcessWithTwoProcessData + * @tc.desc: Parse a Process with ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceProcessParserTest, ParseHtraceProcessWithTwoProcessData, TestSize.Level1) +{ + TS_LOGI("test18-3"); + uint64_t ts = 100; + const uint32_t PID_01 = 311; + const string NAME_01 = "resource_schedu01"; + const int32_t PPID_01 = 21; + const int32_t UID_01 = 1; + + const uint32_t PID_02 = 312; + const string NAME_02 = "resource_schedu02"; + const int32_t PPID_02 = 22; + const int32_t UID_02 = 2; + + auto processData = std::make_unique(); + ProcessInfo* processInfoFirst = processData->add_processesinfo(); + processInfoFirst->set_pid(PID_01); + processInfoFirst->set_name(NAME_01); + processInfoFirst->set_ppid(PPID_01); + processInfoFirst->set_uid(UID_01); + + ProcessInfo* processInfoSecond = processData->add_processesinfo(); + processInfoSecond->set_pid(PID_02); + processInfoSecond->set_name(NAME_02); + processInfoSecond->set_ppid(PPID_02); + processInfoSecond->set_uid(UID_02); + + HtraceProcessParser htraceProcessParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceProcessParser.Parse(*processData, ts); + htraceProcessParser.Finish(); + + auto size = stream_.traceDataCache_->GetConstLiveProcessData().Size(); + EXPECT_EQ(1, size); + + auto pidFirst = stream_.traceDataCache_->GetConstLiveProcessData().ProcessID()[0]; + EXPECT_EQ(pidFirst, PID_02); + auto processNameFirst = stream_.traceDataCache_->GetConstLiveProcessData().ProcessName()[0]; + EXPECT_EQ(processNameFirst, NAME_02); + auto parentProcessIDFirst = stream_.traceDataCache_->GetConstLiveProcessData().ParentProcessID()[0]; + EXPECT_EQ(parentProcessIDFirst, PPID_02); + auto uidFirst = stream_.traceDataCache_->GetConstLiveProcessData().Uid()[0]; + EXPECT_EQ(uidFirst, UID_02); + auto userNameFirst = stream_.traceDataCache_->GetConstLiveProcessData().UserName()[0]; + EXPECT_EQ(userNameFirst, std::to_string(UID_02)); +} + +/** + * @tc.name: ParseHtraceProcessWithThreeProcessData + * @tc.desc: Parse a Process with ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceProcessParserTest, ParseHtraceProcessWithThreeProcessData, TestSize.Level1) +{ + TS_LOGI("test18-4"); + uint64_t ts = 100; + const uint32_t PID_01 = 311; + const string NAME_01 = "resource_schedu01"; + const int32_t PPID_01 = 21; + const int32_t UID_01 = 1; + + const uint32_t PID_02 = 312; + const string NAME_02 = "resource_schedu02"; + const int32_t PPID_02 = 22; + const int32_t UID_02 = 2; + + const uint32_t PID_03 = 313; + const string NAME_03 = "resource_schedu03"; + const int32_t PPID_03 = 23; + const int32_t UID_03 = 3; + + auto processData = std::make_unique(); + ProcessInfo* processInfoFirst = processData->add_processesinfo(); + processInfoFirst->set_pid(PID_01); + processInfoFirst->set_name(NAME_01); + processInfoFirst->set_ppid(PPID_01); + processInfoFirst->set_uid(UID_01); + + ProcessInfo* processInfoSecond = processData->add_processesinfo(); + processInfoSecond->set_pid(PID_02); + processInfoSecond->set_name(NAME_02); + processInfoSecond->set_ppid(PPID_02); + processInfoSecond->set_uid(UID_02); + + ProcessInfo* processInfoThird = processData->add_processesinfo(); + processInfoThird->set_pid(PID_03); + processInfoThird->set_name(NAME_03); + processInfoThird->set_ppid(PPID_03); + processInfoThird->set_uid(UID_03); + + HtraceProcessParser htraceProcessParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceProcessParser.Parse(*processData, ts); + htraceProcessParser.Finish(); + + auto pidFirst = stream_.traceDataCache_->GetConstLiveProcessData().ProcessID()[0]; + auto pidSecond = stream_.traceDataCache_->GetConstLiveProcessData().ProcessID()[1]; + EXPECT_EQ(pidFirst, PID_02); + EXPECT_EQ(pidSecond, PID_03); + auto processNameFirst = stream_.traceDataCache_->GetConstLiveProcessData().ProcessName()[0]; + auto processNameSecond = stream_.traceDataCache_->GetConstLiveProcessData().ProcessName()[1]; + EXPECT_EQ(processNameFirst, NAME_02); + EXPECT_EQ(processNameSecond, NAME_03); + auto parentProcessIDFirst = stream_.traceDataCache_->GetConstLiveProcessData().ParentProcessID()[0]; + auto parentProcessIDSecond = stream_.traceDataCache_->GetConstLiveProcessData().ParentProcessID()[1]; + EXPECT_EQ(parentProcessIDFirst, PPID_02); + EXPECT_EQ(parentProcessIDSecond, PPID_03); + auto uidFirst = stream_.traceDataCache_->GetConstLiveProcessData().Uid()[0]; + auto uidSecond = stream_.traceDataCache_->GetConstLiveProcessData().Uid()[1]; + EXPECT_EQ(uidFirst, UID_02); + EXPECT_EQ(uidSecond, UID_03); + auto userNameFirst = stream_.traceDataCache_->GetConstLiveProcessData().UserName()[0]; + auto userNameSecond = stream_.traceDataCache_->GetConstLiveProcessData().UserName()[1]; + EXPECT_EQ(userNameFirst, std::to_string(UID_02)); + EXPECT_EQ(userNameSecond, std::to_string(UID_03)); +} + +/** + * @tc.name: ParseHtraceProcessWithMultipleProcessData + * @tc.desc: Parse a Process with ProcessData + * @tc.type: FUNC + */ +HWTEST_F(HtraceProcessParserTest, ParseHtraceProcessWithMultipleProcessData, TestSize.Level1) +{ + TS_LOGI("test18-5"); + uint64_t ts = 100; + const uint32_t PID_01 = 311; + const string NAME_01 = "resource_schedu01"; + const int32_t PPID_01 = 21; + const int32_t UID_01 = 1; + + const uint32_t PID_02 = 312; + const string NAME_02 = "resource_schedu02"; + const int32_t PPID_02 = 22; + const int32_t UID_02 = 2; + + const uint32_t PID_03 = 313; + const string NAME_03 = "resource_schedu03"; + const int32_t PPID_03 = 23; + const int32_t UID_03 = 3; + + const uint32_t PID_04 = 313; + const string NAME_04 = "resource_schedu03"; + const int32_t PPID_04 = 23; + const int32_t UID_04 = 3; + + auto processData = std::make_unique(); + ProcessInfo* processInfoFirst = processData->add_processesinfo(); + processInfoFirst->set_pid(PID_01); + processInfoFirst->set_name(NAME_01); + processInfoFirst->set_ppid(PPID_01); + processInfoFirst->set_uid(UID_01); + + ProcessInfo* processInfoSecond = processData->add_processesinfo(); + processInfoSecond->set_pid(PID_02); + processInfoSecond->set_name(NAME_02); + processInfoSecond->set_ppid(PPID_02); + processInfoSecond->set_uid(UID_02); + + ProcessInfo* processInfoThird = processData->add_processesinfo(); + processInfoThird->set_pid(PID_03); + processInfoThird->set_name(NAME_03); + processInfoThird->set_ppid(PPID_03); + processInfoThird->set_uid(UID_03); + + ProcessInfo* processInfoFour = processData->add_processesinfo(); + processInfoFour->set_pid(PID_04); + processInfoFour->set_name(NAME_04); + processInfoFour->set_ppid(PPID_04); + processInfoFour->set_uid(UID_04); + + HtraceProcessParser htraceProcessParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceProcessParser.Parse(*processData, ts); + htraceProcessParser.Finish(); + + auto pidFirst = stream_.traceDataCache_->GetConstLiveProcessData().ProcessID()[0]; + auto pidSecond = stream_.traceDataCache_->GetConstLiveProcessData().ProcessID()[1]; + auto pidThird = stream_.traceDataCache_->GetConstLiveProcessData().ProcessID()[2]; + EXPECT_EQ(pidFirst, PID_02); + EXPECT_EQ(pidSecond, PID_03); + EXPECT_EQ(pidThird, PID_04); + auto processNameFirst = stream_.traceDataCache_->GetConstLiveProcessData().ProcessName()[0]; + auto processNameSecond = stream_.traceDataCache_->GetConstLiveProcessData().ProcessName()[1]; + auto processNameThird = stream_.traceDataCache_->GetConstLiveProcessData().ProcessName()[2]; + EXPECT_EQ(processNameFirst, NAME_02); + EXPECT_EQ(processNameSecond, NAME_03); + EXPECT_EQ(processNameThird, NAME_04); + auto parentProcessIDFirst = stream_.traceDataCache_->GetConstLiveProcessData().ParentProcessID()[0]; + auto parentProcessIDSecond = stream_.traceDataCache_->GetConstLiveProcessData().ParentProcessID()[1]; + auto parentProcessIDThird = stream_.traceDataCache_->GetConstLiveProcessData().ParentProcessID()[2]; + EXPECT_EQ(parentProcessIDFirst, PPID_02); + EXPECT_EQ(parentProcessIDSecond, PPID_03); + EXPECT_EQ(parentProcessIDThird, PPID_04); + auto uidFirst = stream_.traceDataCache_->GetConstLiveProcessData().Uid()[0]; + auto uidSecond = stream_.traceDataCache_->GetConstLiveProcessData().Uid()[1]; + auto uidThird = stream_.traceDataCache_->GetConstLiveProcessData().Uid()[2]; + EXPECT_EQ(uidFirst, UID_02); + EXPECT_EQ(uidSecond, UID_03); + EXPECT_EQ(uidThird, UID_04); + auto userNameFirst = stream_.traceDataCache_->GetConstLiveProcessData().UserName()[0]; + auto userNameSecond = stream_.traceDataCache_->GetConstLiveProcessData().UserName()[1]; + auto userNameThird = stream_.traceDataCache_->GetConstLiveProcessData().UserName()[2]; + EXPECT_EQ(userNameFirst, std::to_string(UID_02)); + EXPECT_EQ(userNameSecond, std::to_string(UID_03)); + EXPECT_EQ(userNameThird, std::to_string(UID_04)); +} +} // namespace TraceStreamer +} // namespace SysTuning \ No newline at end of file diff --git a/host/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp index 560f22dbe331ca87bcca470a431dd6a7910b8647..e8d09f99487c495efd4577bcbac2ee42cb1d5a9a 100644 --- a/host/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp +++ b/host/trace_streamer/test/unittest/htrace_sys_mem_parser_test.cpp @@ -44,7 +44,7 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "/data/resource/out.db"; + const std::string dbPath_ = "data/resource/out.db"; }; /** @@ -54,9 +54,8 @@ public: */ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseInputEmpty, TestSize.Level1) { - TS_LOGI("test12-1"); + TS_LOGI("test19-1"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); - MemoryData tracePacket; SysMeminfo* mem = tracePacket.add_meminfo(); EXPECT_TRUE(mem != nullptr); @@ -67,6 +66,8 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseInputEmpty, TestSize.Level1) mem->set_value(value); uint64_t timeStamp = 1616439852302; BuiltinClocks clock = TS_CLOCK_REALTIME; + uint64_t zarm = 100; + tracePacket.set_zram(zarm); memParser->Parse(tracePacket, timeStamp, clock); stream_.traceDataCache_->ExportDatabase(dbPath_); @@ -77,8 +78,8 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseInputEmpty, TestSize.Level1) auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_EQ(2, stream_.traceDataCache_->GetConstSysMeasureFilterData().Size()); + EXPECT_EQ(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[0], static_cast(value)); } /** @@ -88,7 +89,7 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseInputEmpty, TestSize.Level1) */ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseNormal, TestSize.Level1) { - TS_LOGI("test12-2"); + TS_LOGI("test19-2"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -107,6 +108,8 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseNormal, TestSize.Level1) mem->set_key(SysMeminfoType::PMEM_MEM_FREE); uint64_t value2 = random(); mem->set_value(value2); + uint64_t zarm = 100; + tracePacket.set_zram(zarm); uint64_t timeStamp = 1616439852302; BuiltinClocks clock = TS_CLOCK_REALTIME; @@ -120,9 +123,9 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseNormal, TestSize.Level1) auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[1] == static_cast(value2)); + EXPECT_EQ(3, stream_.traceDataCache_->GetConstSysMemMeasureData().Size()); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[1] == static_cast(value2)); } /** @@ -132,7 +135,7 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseNormal, TestSize.Level1) */ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseAbnomal, TestSize.Level1) { - TS_LOGI("test12-3"); + TS_LOGI("test19-3"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -151,6 +154,8 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseAbnomal, TestSize.Level1) mem->set_key(static_cast(199999)); // invalid data uint64_t value2 = random(); mem->set_value(value2); + uint64_t zarm = 100; + tracePacket.set_zram(zarm); uint64_t timeStamp = 1616439852302; BuiltinClocks clock = TS_CLOCK_REALTIME; @@ -166,8 +171,8 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseAbnomal, TestSize.Level1) EXPECT_TRUE(1 == eventCount); eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_DATA_INVALID); EXPECT_TRUE(1 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_EQ(2, stream_.traceDataCache_->GetConstSysMemMeasureData().Size()); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[0] == static_cast(value)); } /** @@ -177,7 +182,7 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseAbnomal, TestSize.Level1) */ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseMutiNomal, TestSize.Level1) { - TS_LOGI("test12-4"); + TS_LOGI("test19-4"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -185,7 +190,7 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseMutiNomal, TestSize.Level1) EXPECT_TRUE(mem != nullptr); int size = tracePacket.meminfo_size(); EXPECT_TRUE(size == 1); - mem->set_key(SysMeminfoType::PMEM_CMA_FREE); + mem->set_key(SysMeminfoType::PMEM_KERNEL_RECLAIMABLE); uint64_t value = random(); mem->set_value(value); @@ -204,6 +209,8 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseMutiNomal, TestSize.Level1) mem->set_key(SysMeminfoType::SysMeminfoType_INT_MAX_SENTINEL_DO_NOT_USE_); uint64_t value3 = random(); mem->set_value(value3); + uint64_t zarm = 100; + tracePacket.set_zram(zarm); uint64_t timeStamp = 1616439852302; BuiltinClocks clock = TS_CLOCK_REALTIME; @@ -219,8 +226,8 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseMutiNomal, TestSize.Level1) EXPECT_TRUE(1 == eventCount); eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_DATA_INVALID); EXPECT_TRUE(2 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_EQ(2, stream_.traceDataCache_->GetConstSysMemMeasureData().Size()); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[0] == static_cast(value)); } /** @@ -230,13 +237,13 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseMutiNomal, TestSize.Level1) */ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseWithRandomValue, TestSize.Level1) { - TS_LOGI("test12-5"); + TS_LOGI("test19-5"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; std::map sysMemValueMap_ = {}; - for (auto i = 0; i < SysMeminfoType::PMEM_CMA_FREE + 1; i++) { + for (auto i = 0; i < SysMeminfoType::PMEM_KERNEL_RECLAIMABLE + 1; i++) { uint64_t value = random(); sysMemValueMap_.insert(std::make_pair(static_cast(i), value)); SysMeminfo* mem = tracePacket.add_meminfo(); @@ -260,8 +267,8 @@ HWTEST_F(HtraceSysMemParserTest, ParseSysMemParseWithRandomValue, TestSize.Level auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_MEMORY, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); - for (auto i = 0; i < SysMeminfoType::PMEM_CMA_FREE + 1; i++) { - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[i] == + for (auto i = 0; i < SysMeminfoType::PMEM_KERNEL_RECLAIMABLE + 1; i++) { + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[i] == sysMemValueMap_.at(static_cast(i))); } } diff --git a/host/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp b/host/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp index da4d4064035473b28618a5976efe65ca17cc045f..f089c80a8a63a28036fe0b35a023e73ef9110577 100644 --- a/host/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp +++ b/host/trace_streamer/test/unittest/htrace_sys_vmem_parser_test.cpp @@ -44,17 +44,17 @@ public: public: SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; - const std::string dbPath_ = "/data/resource/out.db"; + const std::string dbPath_ = "data/resource/out.db"; }; /** - * @tc.name: ParseSysMemParseWithRandomValue + * @tc.name: ParseSysVMemParse * @tc.desc: Virtual memory parsing test, input a random reasonable value * @tc.type: FUNC */ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemParse, TestSize.Level1) { - TS_LOGI("test13-1"); + TS_LOGI("test20-1"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -78,8 +78,8 @@ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemParse, TestSize.Level1) auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[0] == static_cast(value)); } /** @@ -89,7 +89,7 @@ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemParse, TestSize.Level1) */ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemNomal, TestSize.Level1) { - TS_LOGI("test13-2"); + TS_LOGI("test20-2"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -122,9 +122,9 @@ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemNomal, TestSize.Level1) auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_RECEIVED); EXPECT_TRUE(1 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[1] == static_cast(value2)); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[1] == static_cast(value2)); } /** @@ -134,7 +134,7 @@ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemNomal, TestSize.Level1) */ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemAbnomal, TestSize.Level1) { - TS_LOGI("test13-3"); + TS_LOGI("test20-3"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -169,8 +169,8 @@ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemAbnomal, TestSize.Level1) eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_DATA_INVALID); EXPECT_TRUE(0 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[0] == static_cast(value)); } /** @@ -180,7 +180,7 @@ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemAbnomal, TestSize.Level1) */ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemWithMutiNomal, TestSize.Level1) { - TS_LOGI("test13-4"); + TS_LOGI("test20-4"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -224,8 +224,8 @@ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemWithMutiNomal, TestSize.Level1) eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SYS_VIRTUAL_MEMORY, STAT_EVENT_DATA_INVALID); EXPECT_TRUE(2 == eventCount); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == static_cast(value)); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[0] == static_cast(value)); } /** @@ -235,7 +235,7 @@ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemWithMutiNomal, TestSize.Level1) */ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemWithRandomValue, TestSize.Level1) { - TS_LOGI("test13-5"); + TS_LOGI("test20-5"); HtraceMemParser* memParser = new HtraceMemParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); MemoryData tracePacket; @@ -267,7 +267,7 @@ HWTEST_F(HtraceSysVMemParserTest, ParseSysVMemWithRandomValue, TestSize.Level1) EXPECT_TRUE(1 == eventCount); for (auto i = 0; i < SysVMeminfoType::VMEMINFO_WORKINGSET_RESTORE + 1; i++) { - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[i] == + EXPECT_TRUE(stream_.traceDataCache_->GetConstSysMemMeasureData().ValuesData()[i] == sysVMemValueMap_.at(static_cast(i))); } } diff --git a/host/trace_streamer/test/unittest/http_server_test.cpp b/host/trace_streamer/test/unittest/http_server_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea8987a2fbe2e8b64da721083df3656b7b97e866 --- /dev/null +++ b/host/trace_streamer/test/unittest/http_server_test.cpp @@ -0,0 +1,348 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "http_server.h" +#include "http_socket.h" +#include "rpc/rpc_server.h" +#include "string_help.h" + +using namespace testing::ext; +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::base; +#define UNUSED(expr) \ + do { \ + static_cast(expr); \ + } while (0) + +const uint32_t MAX_TESET_BUF_SIZE = 1024; +std::string g_parserData = "sugov:0-178 ( 178) [001] .... 28462.257501: cpu_frequency: state=816000 cpu_id=0 \n"; +std::string g_sqlQuery("select * from measure;"); +char g_clientRecvBuf[MAX_TESET_BUF_SIZE] = {0}; +class HttpServerTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} + +public: + TraceStreamerSelector stream_ = {}; +}; + +void ResultCallbackFunc(const std::string result, int num) +{ + // unused + UNUSED(result); +} + +void* HttpServerThread(void* arg) +{ + HttpServer* httpServer = static_cast(arg); + httpServer->Run(); + TS_LOGI("Server thread end"); + pthread_exit(nullptr); +} + +int HttpClient(const char* buf) +{ + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htons(INADDR_ANY); + const uint16_t listenPort = 9001; + addr.sin_port = htons(listenPort); + struct timeval recvTimeout = {1, 100000}; + + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + TS_LOGI("CreateSocket socket error"); + return -1; + } + + int ret = connect(sockfd, (struct sockaddr*)(&addr), sizeof(struct sockaddr)); + if (ret < 0) { + TS_LOGE("Connect error"); + return -1; + } + + ret = send(sockfd, buf, strlen(buf), 0); + if (ret < 0) { + TS_LOGE("Send error"); + return -1; + } + + if (!memset_s(g_clientRecvBuf, strlen(g_clientRecvBuf), 0, strlen(g_clientRecvBuf))) { + TS_LOGE("memset_s error"); + return -1; + } + int index = 0; + ret = setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char*)(&recvTimeout), sizeof(recvTimeout)); + if (ret != 0) { + TS_LOGE("set recv time out error"); + return -1; + } + while (1) { + ret = recv(sockfd, g_clientRecvBuf + index, MAX_TESET_BUF_SIZE, 0); + if (ret < 0) { + TS_LOGE("Recv timeout"); + break; + } + index += ret; + } + return 0; +} + +/** + * @tc.name: HttpCorrectRequest + * @tc.desc: HTTP correct request + * @tc.type: FUNC + */ +HWTEST_F(HttpServerTest, HttpCorrectRequest, TestSize.Level1) +{ + TS_LOGI("test21-1"); + HttpServer httpServer; + RpcServer rpcServer; + pthread_t pthreadId = 0; + int ret = 0; + + ret = rpcServer.ParseData((const uint8_t*)g_parserData.c_str(), g_parserData.length(), ResultCallbackFunc); + ret = rpcServer.ParseDataOver(nullptr, 0, ResultCallbackFunc); + ret = rpcServer.SqlQuery((const uint8_t*)g_sqlQuery.c_str(), g_sqlQuery.length(), ResultCallbackFunc); + + httpServer.RegisterRpcFunction(&rpcServer); + ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer); + if (ret != 0) { + TS_LOGE("Server pthread create fail"); + pthread_exit(nullptr); + } + + sleep(1); + std::string bufToSend = + "GET /sqlquery HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length:\ + 23\r\n\r\nselect * from measure\r\n"; + + ret = HttpClient(bufToSend.c_str()); + if (ret < 0) { + TS_LOGE("Client fail"); + } + httpServer.Exit(); + ret = pthread_join(pthreadId, nullptr); + if (ret != 0) { + TS_LOGE("Server pthread jion fail"); + } + char targetStr[MAX_TESET_BUF_SIZE] = { + "HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Type: application/json\r\nTransfer-Encoding: " + "chunked\r\n\r\n62\r\nok\r\n{\"columns\":[\"type\",\"ts\",\"value\",\"filter_id\"],\"values\":[[\"measure\"," + "28462257501000,816000,0]]}" + "\r\n\r\n0\r\n\r\n"}; + + EXPECT_STREQ(targetStr, g_clientRecvBuf); +} +/** + * @tc.name: OthreAgreement + * @tc.desc: Use http1 1. Agreements other than agreements + * @tc.type: FUNC + */ +HWTEST_F(HttpServerTest, OthreAgreement, TestSize.Level1) +{ + TS_LOGI("test21-2"); + HttpServer httpServer; + RpcServer rpcServer; + pthread_t pthreadId = 0; + int ret = 0; + + httpServer.RegisterRpcFunction(&rpcServer); + ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer); + if (ret != 0) { + TS_LOGE("Server pthread create fail"); + pthread_exit(nullptr); + } + + sleep(1); + std::string bufToSend = + "GET /sqlquery HTTP/0.9\r\nHost: 127.0.0.1\r\nContent-Length:\ + 23\r\n\r\nselect * from measure\r\n"; + + ret = HttpClient(bufToSend.c_str()); + if (ret < 0) { + TS_LOGE("Client fail"); + } + httpServer.Exit(); + ret = pthread_join(pthreadId, nullptr); + if (ret != 0) { + TS_LOGE("Server pthread jion fail"); + } + char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 400 Bad Request\r\nConnection: Keep-Alive\r\n\r\n"}; + EXPECT_STREQ(targetStr, g_clientRecvBuf); +} + +/** + * @tc.name: OthreProtocols + * @tc.desc: Use protocols other than GET and POST + * @tc.type: FUNC + */ +HWTEST_F(HttpServerTest, OthreProtocols, TestSize.Level1) +{ + TS_LOGI("test21-3"); + HttpServer httpServer; + RpcServer rpcServer; + pthread_t pthreadId = 0; + int ret = 0; + + httpServer.RegisterRpcFunction(&rpcServer); + ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer); + if (ret != 0) { + TS_LOGE("Server pthread create fail"); + pthread_exit(nullptr); + } + + sleep(1); + std::string bufToSend = + "HEAD /sqlquery HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length:\ + 23\r\n\r\nselect * from measure\r\n"; + + ret = HttpClient(bufToSend.c_str()); + if (ret < 0) { + TS_LOGE("Client fail"); + } + httpServer.Exit(); + ret = pthread_join(pthreadId, nullptr); + if (ret != 0) { + TS_LOGE("Server pthread jion fail"); + } + char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 405 Method Not Allowed\r\nConnection: Keep-Alive\r\n\r\n"}; + EXPECT_STREQ(targetStr, g_clientRecvBuf); +} + +/** + * @tc.name: RequestLineFormatError + * @tc.desc: Request line format error + * @tc.type: FUNC + */ +HWTEST_F(HttpServerTest, RequestLineFormatError, TestSize.Level1) +{ + TS_LOGI("test21-4"); + HttpServer httpServer; + RpcServer rpcServer; + pthread_t pthreadId = 0; + int ret = 0; + + httpServer.RegisterRpcFunction(&rpcServer); + ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer); + if (ret != 0) { + TS_LOGE("Server pthread create fail"); + pthread_exit(nullptr); + } + + sleep(1); + std::string bufToSend = + "POST /sqlqueryHTTP/0.9\r\nHost: 127.0.0.1\r\nContent-Length:\ + 20\r\n\r\nselect * from meta\r\n"; + + ret = HttpClient(bufToSend.c_str()); + if (ret < 0) { + TS_LOGE("Client fail"); + } + httpServer.Exit(); + ret = pthread_join(pthreadId, nullptr); + if (ret != 0) { + TS_LOGE("Server pthread jion fail"); + } + char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 400 Bad Request\r\nConnection: Keep-Alive\r\n\r\n"}; + EXPECT_STREQ(targetStr, g_clientRecvBuf); +} + +/** + * @tc.name: RequestIsNotRPC + * @tc.desc: The URI of HTTP request is not the method of RPC + * @tc.type: FUNC + */ +HWTEST_F(HttpServerTest, RequestIsNotRPC, TestSize.Level1) +{ + TS_LOGI("test21-5"); + HttpServer httpServer; + RpcServer rpcServer; + pthread_t pthreadId = 0; + int ret = 0; + + httpServer.RegisterRpcFunction(&rpcServer); + ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer); + if (ret != 0) { + TS_LOGE("Server pthread create fail"); + pthread_exit(nullptr); + } + + sleep(1); + std::string bufToSend = + "POST /query HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length:20\r\n\r\n\ + select * from meta\r\n"; + + ret = HttpClient(bufToSend.c_str()); + if (ret < 0) { + TS_LOGE("Client fail"); + } + httpServer.Exit(); + ret = pthread_join(pthreadId, nullptr); + if (ret != 0) { + TS_LOGE("Server pthread jion fail"); + } + char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 404 Not Found\r\nConnection: Keep-Alive\r\n\r\n"}; + EXPECT_STREQ(targetStr, g_clientRecvBuf); +} +/** + * @tc.name: RequestTimeout + * @tc.desc: Incomplete request content data + * @tc.type: FUNC + */ +HWTEST_F(HttpServerTest, RequestTimeout, TestSize.Level1) +{ + TS_LOGI("test21-6"); + HttpServer httpServer; + RpcServer rpcServer; + pthread_t pthreadId = 0; + int ret = 0; + + httpServer.RegisterRpcFunction(&rpcServer); + ret = pthread_create(&pthreadId, nullptr, HttpServerThread, &httpServer); + if (ret != 0) { + TS_LOGE("Server pthread create fail"); + pthread_exit(nullptr); + } + + sleep(1); + std::string buf = + "GET /sqlquery HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length:\ + 28\r\n\r\nselect * from measure\r\n"; + + ret = HttpClient(buf.c_str()); + if (ret < 0) { + TS_LOGE("Client fail"); + } + httpServer.Exit(); + ret = pthread_join(pthreadId, nullptr); + if (ret != 0) { + TS_LOGE("Server pthread jion fail"); + } + char targetStr[MAX_TESET_BUF_SIZE] = {"HTTP/1.1 408 Request Time-out\r\nConnection: Keep-Alive\r\n\r\n"}; + EXPECT_STREQ(targetStr, g_clientRecvBuf); +} +} // namespace TraceStreamer +} // namespace SysTuning \ No newline at end of file diff --git a/host/trace_streamer/test/unittest/irq_filter_test.cpp b/host/trace_streamer/test/unittest/irq_filter_test.cpp index 33ebaa9e4f9b24f46908f84eb761b0a35f9f3565..3054f126e38813e532cea06741a1cc9dc84beebc 100644 --- a/host/trace_streamer/test/unittest/irq_filter_test.cpp +++ b/host/trace_streamer/test/unittest/irq_filter_test.cpp @@ -51,12 +51,12 @@ public: */ HWTEST_F(IrqFilterTest, IrqHandlerEntryTest, TestSize.Level1) { - TS_LOGI("test10-1"); + TS_LOGI("test22-1"); int64_t ts1 = 100; uint32_t cpu1 = 1; DataIndex nameId1 = 1; streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); } /** @@ -66,16 +66,16 @@ HWTEST_F(IrqFilterTest, IrqHandlerEntryTest, TestSize.Level1) */ HWTEST_F(IrqFilterTest, IrqHandlerEntryTestNotMatch, TestSize.Level1) { - TS_LOGI("test10-2"); + TS_LOGI("test22-2"); int64_t ts1 = 120; uint32_t cpu1 = 1; DataIndex nameId1 = 1; streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); ts1 = 110; uint32_t irqRet = 1; streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, irqRet); // IrqHandlerEntry - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 2); // TRACE_EVENT_IRQ_HANDLER_ENTRY STAT_EVENT_DATA_LOST auto eventCount = traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_ENTRY, STAT_EVENT_DATA_LOST); @@ -89,12 +89,12 @@ HWTEST_F(IrqFilterTest, IrqHandlerEntryTestNotMatch, TestSize.Level1) */ HWTEST_F(IrqFilterTest, IrqHandlerExitTestEmpty, TestSize.Level1) { - TS_LOGI("test10-3"); + TS_LOGI("test22-3"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t ret = 1; // 1 for handled, else for unhandled streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); // IrqHandlerExit - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 0); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 0); // TRACE_EVENT_IRQ_HANDLER_EXIT STAT_EVENT_NOTMATCH auto eventCount = traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_NOTMATCH); @@ -108,17 +108,17 @@ HWTEST_F(IrqFilterTest, IrqHandlerExitTestEmpty, TestSize.Level1) */ HWTEST_F(IrqFilterTest, IrqHandlerEnterAndExitTest, TestSize.Level1) { - TS_LOGI("test10-4"); + TS_LOGI("test22-4"); int64_t ts1 = 100; uint32_t cpu1 = 1; DataIndex nameId1 = 1; streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); uint32_t irqRet = 1; // 1 for handled, else for unhandled streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, irqRet); // IrqHandlerExit - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().ArgSetIdsData()[0] == 0); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 1); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().values_[0] == static_cast(streamFilters_.irqFilter_->irqHandled_)); @@ -133,24 +133,24 @@ HWTEST_F(IrqFilterTest, IrqHandlerEnterAndExitTest, TestSize.Level1) */ HWTEST_F(IrqFilterTest, IrqHandlerDoubleEnterAndExitTest, TestSize.Level1) { - TS_LOGI("test10-4-2"); + TS_LOGI("test22-5"); int64_t ts1 = 100; uint32_t cpu1 = 1; DataIndex nameId1 = 1; streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); uint32_t ret = 1; // 1 for handled, else for unhandled cpu1 = 2; ts1 = 150; streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); // IrqHandlerExit - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); EXPECT_TRUE(traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_IRQ_HANDLER_EXIT, STAT_EVENT_NOTMATCH) == 1); cpu1 = 1; ts1 = 200; streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); // IrqHandlerExit - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().ArgSetIdsData()[0] == 0); } /** @@ -160,30 +160,30 @@ HWTEST_F(IrqFilterTest, IrqHandlerDoubleEnterAndExitTest, TestSize.Level1) */ HWTEST_F(IrqFilterTest, IrqHandlerTripleEnterAndExitTest, TestSize.Level1) { - TS_LOGI("test10-5"); + TS_LOGI("test22-6"); int64_t ts1 = 100; uint32_t cpu1 = 1; DataIndex nameId1 = 1; streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); // IrqHandlerEntry - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); uint32_t ret = 1; // 1 for handled, else for unhandled ts1 = 150; streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); // IrqHandlerExit - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); // check args - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().ArgSetIdsData()[0] == 0); ts1 = 200; cpu1 = 1; nameId1 = 1; streamFilters_.irqFilter_->IrqHandlerEntry(ts1, cpu1, nameId1); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 2); ret = 1; // 1 for handled, else for unhandled ts1 = 250; streamFilters_.irqFilter_->IrqHandlerExit(ts1, cpu1, ret); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 2); // check args - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[1] == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().ArgSetIdsData()[1] == 1); } /** @@ -193,12 +193,12 @@ HWTEST_F(IrqFilterTest, IrqHandlerTripleEnterAndExitTest, TestSize.Level1) */ HWTEST_F(IrqFilterTest, SoftIrqEntryTest, TestSize.Level1) { - TS_LOGI("test10-6"); + TS_LOGI("test22-7"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); } /** @@ -208,15 +208,15 @@ HWTEST_F(IrqFilterTest, SoftIrqEntryTest, TestSize.Level1) */ HWTEST_F(IrqFilterTest, SoftIrqEntryNotMatch, TestSize.Level1) { - TS_LOGI("test10-7"); + TS_LOGI("test22-8"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); // SoftIrqEntry - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); ts1 = 150; streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); // SoftIrqEntry - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 2); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 2); EXPECT_TRUE( traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_ENTRY, STAT_EVENT_DATA_LOST) == 1); } @@ -228,12 +228,12 @@ HWTEST_F(IrqFilterTest, SoftIrqEntryNotMatch, TestSize.Level1) */ HWTEST_F(IrqFilterTest, SoftIrqExitEmptyTest, TestSize.Level1) { - TS_LOGI("test10-8"); + TS_LOGI("test22-9"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 0); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 0); EXPECT_TRUE( traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); } @@ -245,19 +245,19 @@ HWTEST_F(IrqFilterTest, SoftIrqExitEmptyTest, TestSize.Level1) */ HWTEST_F(IrqFilterTest, SoftIrqTest, TestSize.Level1) { - TS_LOGI("test10-9"); + TS_LOGI("test22-10"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); ts1 = 150; uint32_t irqRet = 1; streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, irqRet); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().ArgSetIdsData()[0] == 0); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().ArgSetIdsData()[0] == 0); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().Size() == 1); - printf("%lld\n", traceDataCache_.GetConstArgSetData().values_[0]); + printf("%ld\n", traceDataCache_.GetConstArgSetData().values_[0]); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().values_[0] == static_cast(streamFilters_.irqFilter_->irqActionNameIds_[irqRet])); EXPECT_TRUE(traceDataCache_.GetConstArgSetData().names_[0] == streamFilters_.irqFilter_->irqRet_); @@ -271,16 +271,16 @@ HWTEST_F(IrqFilterTest, SoftIrqTest, TestSize.Level1) */ HWTEST_F(IrqFilterTest, SoftIrqTestWithIrqEntryAndExit, TestSize.Level1) { - TS_LOGI("test10-10"); + TS_LOGI("test22-11"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); ts1 = 150; cpu1 = 2; streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); EXPECT_TRUE( traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); } @@ -292,22 +292,22 @@ HWTEST_F(IrqFilterTest, SoftIrqTestWithIrqEntryAndExit, TestSize.Level1) */ HWTEST_F(IrqFilterTest, SoftIrqTestOneEntryTwoNotMatchExit, TestSize.Level1) { - TS_LOGI("test10-11"); + TS_LOGI("test22-12"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); ts1 = 150; cpu1 = 2; streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); EXPECT_TRUE( traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); ts1 = 200; cpu1 = 3; streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); EXPECT_TRUE( traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 2); } @@ -319,22 +319,22 @@ HWTEST_F(IrqFilterTest, SoftIrqTestOneEntryTwoNotMatchExit, TestSize.Level1) */ HWTEST_F(IrqFilterTest, SoftIrqTestWithSingleNotMatchExit, TestSize.Level1) { - TS_LOGI("test10-12"); + TS_LOGI("test22-13"); int64_t ts1 = 100; uint32_t cpu1 = 1; uint32_t vec = 1; streamFilters_.irqFilter_->SoftIrqEntry(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); ts1 = 150; cpu1 = 2; streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); EXPECT_TRUE( traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); ts1 = 200; cpu1 = 1; streamFilters_.irqFilter_->SoftIrqExit(ts1, cpu1, vec); - EXPECT_TRUE(traceDataCache_.GetConstInternalSlicesData().Size() == 1); + EXPECT_TRUE(traceDataCache_.GetConstIrqData().Size() == 1); EXPECT_TRUE( traceDataCache_.GetConstStatAndInfo().GetValue(TRACE_EVENT_SOFTIRQ_EXIT, STAT_EVENT_DATA_LOST) == 1); } diff --git a/host/trace_streamer/test/unittest/measure_filter_test.cpp b/host/trace_streamer/test/unittest/measure_filter_test.cpp old mode 100644 new mode 100755 index 6e20f9aeac0a862a6a9b81fb10064b606a80cf5e..0508e5a134f1a6933604751fd37e8e7ef4447b92 --- a/host/trace_streamer/test/unittest/measure_filter_test.cpp +++ b/host/trace_streamer/test/unittest/measure_filter_test.cpp @@ -55,7 +55,7 @@ public: */ HWTEST_F(MeasureFilterTest, ThreadMeasureFilter, TestSize.Level1) { - TS_LOGI("test8-1"); + TS_LOGI("test23-1"); auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); uint32_t filterId = stream_.streamFilters_->threadMeasureFilter_->GetOrCreateFilterId(INTERNAL_THREAD_ID_0, nameIndex0); @@ -83,7 +83,7 @@ HWTEST_F(MeasureFilterTest, ThreadMeasureFilter, TestSize.Level1) */ HWTEST_F(MeasureFilterTest, ThreadFilter, TestSize.Level1) { - TS_LOGI("test8-2"); + TS_LOGI("test23-2"); auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); uint32_t filterId = stream_.streamFilters_->threadFilter_->GetOrCreateFilterId(INTERNAL_THREAD_ID_0, nameIndex0); EXPECT_TRUE(filterId == 0); @@ -110,7 +110,7 @@ HWTEST_F(MeasureFilterTest, ThreadFilter, TestSize.Level1) */ HWTEST_F(MeasureFilterTest, CpuFilter, TestSize.Level1) { - TS_LOGI("test8-3"); + TS_LOGI("test23-3"); auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(CPU_TYPE_0); uint32_t filterId = stream_.streamFilters_->cpuMeasureFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); EXPECT_TRUE(filterId == 0); @@ -137,7 +137,7 @@ HWTEST_F(MeasureFilterTest, CpuFilter, TestSize.Level1) */ HWTEST_F(MeasureFilterTest, ProcessFilter, TestSize.Level1) { - TS_LOGI("test8-4"); + TS_LOGI("test23-4"); auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); uint32_t filterId = stream_.streamFilters_->processFilterFilter_->GetOrCreateFilterId(INTERNAL_PROCESS_ID_0, nameIndex_0); @@ -161,7 +161,7 @@ HWTEST_F(MeasureFilterTest, ProcessFilter, TestSize.Level1) */ HWTEST_F(MeasureFilterTest, ClockRateFilter, TestSize.Level1) { - TS_LOGI("test8-5"); + TS_LOGI("test23-5"); auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); uint32_t filterId = stream_.streamFilters_->clockRateFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); EXPECT_TRUE(filterId == 0); @@ -188,7 +188,7 @@ HWTEST_F(MeasureFilterTest, ClockRateFilter, TestSize.Level1) */ HWTEST_F(MeasureFilterTest, ClockEnableFilter, TestSize.Level1) { - TS_LOGI("test8-6"); + TS_LOGI("test23-6"); auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); uint32_t filterId = stream_.streamFilters_->clockEnableFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); EXPECT_TRUE(filterId == 0); @@ -215,7 +215,7 @@ HWTEST_F(MeasureFilterTest, ClockEnableFilter, TestSize.Level1) */ HWTEST_F(MeasureFilterTest, ClockDisableFilter, TestSize.Level1) { - TS_LOGI("test8-7"); + TS_LOGI("test23-7"); auto nameIndex_0 = stream_.traceDataCache_->GetDataIndex(TASK_NAME_0); uint32_t filterId = stream_.streamFilters_->clockDisableFilter_->GetOrCreateFilterId(CPU_ID_0, nameIndex_0); EXPECT_TRUE(filterId == 0); @@ -242,13 +242,13 @@ HWTEST_F(MeasureFilterTest, ClockDisableFilter, TestSize.Level1) */ HWTEST_F(MeasureFilterTest, MeasureFilterTest, TestSize.Level1) { - TS_LOGI("test8-8"); + TS_LOGI("test23-8"); uint64_t itid = 1; const std::string_view MEASURE_ITEM_NAME = "mem_rss"; auto nameIndex0 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME); auto threadMeasureFilter = stream_.streamFilters_->processMeasureFilter_.get(); threadMeasureFilter->AppendNewMeasureData(itid, nameIndex0, 168758682476000, 1200); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == 1); } /** @@ -259,7 +259,7 @@ HWTEST_F(MeasureFilterTest, MeasureFilterTest, TestSize.Level1) */ HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToSingleThread, TestSize.Level1) { - TS_LOGI("test8-9"); + TS_LOGI("test23-9"); uint64_t itid = 1; auto threadMeasureFilter = stream_.streamFilters_->processMeasureFilter_.get(); const std::string_view MEASURE_ITEM_NAME = "mem_rss"; @@ -268,7 +268,7 @@ HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToSingleThread, TestSize.Lev const std::string_view MEASURE_ITEM_NAME2 = "mem_vm"; auto nameIndex1 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME2); threadMeasureFilter->AppendNewMeasureData(itid, nameIndex1, 168758682477000, 9200); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == 2); } /** @@ -279,7 +279,7 @@ HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToSingleThread, TestSize.Lev */ HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToMultiThread, TestSize.Level1) { - TS_LOGI("test8-10"); + TS_LOGI("test23-10"); uint64_t itid = 1; uint64_t itid2 = 2; auto threadMeasureFilter = stream_.streamFilters_->processMeasureFilter_.get(); @@ -289,9 +289,9 @@ HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToMultiThread, TestSize.Leve const std::string_view MEASURE_ITEM_NAME2 = "mem_vm"; auto nameIndex1 = stream_.traceDataCache_->GetDataIndex(MEASURE_ITEM_NAME2); threadMeasureFilter->AppendNewMeasureData(itid2, nameIndex1, 168758682477000, 9200); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().Size() == 2); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[0] == 1200); - EXPECT_TRUE(stream_.traceDataCache_->GetConstMeasureData().ValuesData()[1] == 9200); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == 2); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().ValuesData()[0] == 1200); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().ValuesData()[1] == 9200); } /** @@ -301,7 +301,7 @@ HWTEST_F(MeasureFilterTest, MeasureFilterAddMultiMemToMultiThread, TestSize.Leve */ HWTEST_F(MeasureFilterTest, MeasureFilterAddPerfclLfMux, TestSize.Level1) { - TS_LOGI("test8-11"); + TS_LOGI("test23-11"); uint64_t cpuId = 1; int64_t state = 0; auto threadMeasureFilter = stream_.streamFilters_->clockDisableFilter_.get(); @@ -313,13 +313,13 @@ HWTEST_F(MeasureFilterTest, MeasureFilterAddPerfclLfMux, TestSize.Level1) } /** - * @tc.name: MeasureFilterAddPerfclLfMux + * @tc.name: MeasureFilterAddPerfclPll * @tc.desc: Add perfcl_pll status test * @tc.type: FUNC */ HWTEST_F(MeasureFilterTest, MeasureFilterAddPerfclPll, TestSize.Level1) { - TS_LOGI("test8-12"); + TS_LOGI("test23-12"); uint64_t cpuId = 1; int64_t state = 1747200000; auto threadMeasureFilter = stream_.streamFilters_->clockRateFilter_.get(); diff --git a/host/trace_streamer/test/unittest/native_hook_parser_test.cpp b/host/trace_streamer/test/unittest/native_hook_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c67334be1ffca2667be5b689c63bc52b5c551aff --- /dev/null +++ b/host/trace_streamer/test/unittest/native_hook_parser_test.cpp @@ -0,0 +1,1913 @@ +/* + * 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. + */ + +#include +#include +#include +#include + +#include "htrace_native_hook_parser.h" +#include "native_hook_result.pb.h" +#include "parser/bytrace_parser/bytrace_parser.h" +#include "parser/common_types.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; + +namespace SysTuning { +namespace TraceStreamer { +const uint64_t TV_SEC_01 = 1632675525; +const uint64_t TV_SEC_02 = 1632675526; +const uint64_t TV_SEC_03 = 1632675527; +const uint64_t TV_SEC_04 = 1632675528; +const uint64_t TV_NSEC_01 = 996560701; +const uint64_t TV_NSEC_02 = 999560702; +const uint64_t TV_NSEC_03 = 996560703; +const uint64_t TV_NSEC_04 = 999560704; +const uint64_t TIMESTAMP_01 = TV_NSEC_01 + TV_SEC_01 * SEC_TO_NS; +const uint64_t TIMESTAMP_02 = TV_NSEC_02 + TV_SEC_02 * SEC_TO_NS; +const uint64_t TIMESTAMP_03 = TV_NSEC_03 + TV_SEC_03 * SEC_TO_NS; +const uint64_t TIMESTAMP_04 = TV_NSEC_04 + TV_SEC_04 * SEC_TO_NS; +const int32_t PID = 2716; +const int32_t TID_01 = 1532; +const int32_t TID_02 = 1532; +const uint64_t MEM_ADDR_01 = 10453088; +const uint64_t MEM_ADDR_02 = 10453089; +const uint64_t MEM_ADDR_03 = 10453090; +const int64_t MEM_SIZE_01 = 4096; +const int64_t MEM_SIZE_02 = 2048; +const uint64_t CALL_STACK_IP_01 = 4154215627; +const uint64_t CALL_STACK_IP_02 = 4154215630; +const uint64_t CALL_STACK_SP_01 = 4146449696; +const uint64_t CALL_STACK_SP_02 = 4146449698; +const std::string SYMBOL_NAME_01 = "__aeabi_read_tp"; +const std::string SYMBOL_NAME_02 = "ThreadMmap"; +const std::string FILE_PATH_01 = "/system/lib/ld-musl-arm.so.1"; +const std::string FILE_PATH_02 = "/system/bin/nativetest_c"; +const uint64_t OFFSET_01 = 359372; +const uint64_t OFFSET_02 = 17865; +const uint64_t SYMBOL_OFFSET_01 = 255; +const uint64_t SYMBOL_OFFSET_02 = 33; +const std::string ALLOCEVENT = "AllocEvent"; +const std::string FREEEVENT = "FreeEvent"; +const std::string MMAPEVENT = "MmapEvent"; +const std::string MUNMAPEVENT = "MunmapEvent"; +const std::string MMAP_SUB_TYPE_01 = "mmapType1"; +const std::string MMAP_SUB_TYPE_02 = "mmapType2"; +class NativeHookParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() {} + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; +}; + +class NativeHookCache { +public: + NativeHookCache(const uint64_t callChainId, + const uint32_t ipid, + const uint32_t itid, + const std::string eventType, + const uint64_t subType, + const uint64_t startTimeStamp, + const uint64_t endTimeStamp, + const uint64_t duration, + const uint64_t address, + const int64_t memSize, + const int64_t allMemSize, + const uint64_t currentSizeDurations) + : callChainId_(callChainId), + ipid_(ipid), + itid_(itid), + eventType_(eventType), + subType_(subType), + startTimeStamp_(startTimeStamp), + endTimeStamp_(endTimeStamp), + duration_(duration), + address_(address), + memSize_(memSize), + allMemSize_(allMemSize), + currentSizeDurations_(currentSizeDurations) + { + } + + NativeHookCache(const NativeHook& nativeHook, uint64_t index) + { + if (nativeHook.Size() <= index) { + TS_LOGE("index out of deque bounds! nativeHook.Size() = %lu, index = %lu", nativeHook.Size(), index); + return; + } + callChainId_ = nativeHook.CallChainIds()[index]; + ipid_ = nativeHook.Ipids()[index]; + itid_ = nativeHook.Itids()[index]; + eventType_ = nativeHook.EventTypes()[index]; + subType_ = nativeHook.SubTypes()[index]; + startTimeStamp_ = nativeHook.TimeStamData()[index]; + endTimeStamp_ = nativeHook.EndTimeStamps()[index]; + duration_ = nativeHook.Durations()[index]; + address_ = nativeHook.Addrs()[index]; + memSize_ = nativeHook.MemSizes()[index]; + allMemSize_ = nativeHook.AllMemSizes()[index]; + currentSizeDurations_ = nativeHook.CurrentSizeDurs()[index]; + } + ~NativeHookCache() = default; + NativeHookCache(const NativeHookCache&) = delete; + NativeHookCache& operator=(const NativeHookCache&) = delete; + bool operator==(const NativeHookCache& nativeHookCache) const + { + if (nativeHookCache.GetCallChainId() != callChainId_) { + TS_LOGE("callChainId_ = %lu, nativeHookCache.GetCallChainId() = %lu", callChainId_, + nativeHookCache.GetCallChainId()); + return false; + } + if (nativeHookCache.GetPid() != ipid_) { + TS_LOGE("ipid_ = %u, nativeHookCache.GetPid() = %u", ipid_, nativeHookCache.GetPid()); + return false; + } + if (nativeHookCache.GetTid() != itid_) { + TS_LOGE("itid_ = %u, nativeHookCache.GetTid() = %u", nativeHookCache.GetTid(), itid_); + return false; + } + if (nativeHookCache.GetEventType() != eventType_) { + TS_LOGE("eventType_ = %s, nativeHookCache.GetEventType() = %s", eventType_.c_str(), + nativeHookCache.GetEventType().c_str()); + return false; + } + if (nativeHookCache.GetSubType() != subType_) { + TS_LOGE("subType_ = %lu, nativeHookCache.GetSubType() = %lu", subType_, nativeHookCache.GetSubType()); + return false; + } + if (nativeHookCache.GetStartTimeStamp() != startTimeStamp_) { + TS_LOGE("startTimeStamp_ = %lu, nativeHookCache.GetStartTimeStamp() = %lu", startTimeStamp_, + nativeHookCache.GetStartTimeStamp()); + return false; + } + if (nativeHookCache.GetEndTimeStamp() != endTimeStamp_) { + TS_LOGE(" endTimeStamp_ = %lu, nativeHookCache.GetEndTimeStamp() = %lu", endTimeStamp_, + nativeHookCache.GetEndTimeStamp()); + return false; + } + if (nativeHookCache.GetDuration() != duration_) { + TS_LOGE("duration_ = %lu, nativeHookCache.GetDuration() = %lu", duration_, nativeHookCache.GetDuration()); + return false; + } + if (nativeHookCache.GetEndTimeStamp() != endTimeStamp_) { + TS_LOGE("address_ = %lu, nativeHookCache.GetAddress() = %lu", address_, nativeHookCache.GetAddress()); + return false; + } + if (nativeHookCache.GetMemSize() != memSize_) { + TS_LOGE("memSize_ = %ld, nativeHookCache.GetMemSize() = %ld", memSize_, nativeHookCache.GetMemSize()); + return false; + } + if (nativeHookCache.GetAllMemSize() != allMemSize_) { + TS_LOGE("allMemSize_ = %lu, nativeHookCache.GetAllMemSize() = %lu", allMemSize_, + nativeHookCache.GetAllMemSize()); + return false; + } + if (nativeHookCache.GetCurrentSizeDuration() != currentSizeDurations_) { + TS_LOGE("currentSizeDurations_ = %lu, nativeHookCache.GetCurrentSizeDuration() = %lu", + currentSizeDurations_, nativeHookCache.GetCurrentSizeDuration()); + return false; + } + return true; + } + inline uint64_t GetCallChainId() const + { + return callChainId_; + } + inline uint32_t GetPid() const + { + return ipid_; + } + inline uint32_t GetTid() const + { + return itid_; + } + inline std::string GetEventType() const + { + return eventType_; + } + inline uint64_t GetSubType() const + { + return subType_; + } + inline uint64_t GetStartTimeStamp() const + { + return startTimeStamp_; + } + inline uint64_t GetEndTimeStamp() const + { + return endTimeStamp_; + } + inline uint64_t GetDuration() const + { + return duration_; + } + inline uint64_t GetAddress() const + { + return address_; + } + inline int64_t GetMemSize() const + { + return memSize_; + } + inline int64_t GetAllMemSize() const + { + return allMemSize_; + } + inline uint64_t GetCurrentSizeDuration() const + { + return currentSizeDurations_; + } + +private: + uint64_t callChainId_; + uint32_t ipid_; + uint32_t itid_; + std::string eventType_; + uint64_t subType_; + uint64_t startTimeStamp_; + uint64_t endTimeStamp_; + uint64_t duration_; + uint64_t address_; + int64_t memSize_; + int64_t allMemSize_; + uint64_t currentSizeDurations_; +}; + +class NativeHookFrameCache { +public: + NativeHookFrameCache(const uint64_t callChainId, + const uint64_t depth, + const uint64_t ip, + const uint64_t sp, + const uint64_t symbolName, + const uint64_t filePath, + const uint64_t offset, + const uint64_t symbolOffset) + : callChainId_(callChainId), + depth_(depth), + ip_(ip), + sp_(sp), + symbolName_(symbolName), + filePath_(filePath), + offset_(offset), + symbolOffset_(symbolOffset) + { + } + + NativeHookFrameCache(const NativeHookFrame& nativeHookFrame, const uint64_t index) + { + if (nativeHookFrame.Size() <= index) { + TS_LOGE("index out of deque bounds! nativeHookFrame.Size() = %lu, index = %lu", nativeHookFrame.Size(), + index); + return; + } + callChainId_ = nativeHookFrame.CallChainIds()[index]; + depth_ = nativeHookFrame.Depths()[index]; + ip_ = nativeHookFrame.Ips()[index]; + sp_ = nativeHookFrame.Sps()[index]; + symbolName_ = nativeHookFrame.SymbolNames()[index]; + filePath_ = nativeHookFrame.FilePaths()[index]; + offset_ = nativeHookFrame.Offsets()[index]; + symbolOffset_ = nativeHookFrame.SymbolOffsets()[index]; + } + + ~NativeHookFrameCache() = default; + NativeHookFrameCache(const NativeHookFrameCache&) = delete; + NativeHookFrameCache& operator=(const NativeHookFrameCache&) = delete; + bool operator==(const NativeHookFrameCache& frameCache) const + { + if (frameCache.GetCallChainId() != callChainId_) { + TS_LOGE("callChainId_ = %lu, frameCache.GetCallChainId() = %lu", callChainId_, frameCache.GetCallChainId()); + return false; + } + if (frameCache.GetDepth() != depth_) { + TS_LOGE("depth_ = %lu, frameCache.GetDepth() = %lu", depth_, frameCache.GetDepth()); + return false; + } + if (frameCache.GetIp() != ip_) { + TS_LOGE("ip_ = %lu, frameCache.GetIp() = %lu", ip_, frameCache.GetIp()); + return false; + } + if (frameCache.GetSp() != sp_) { + TS_LOGE("sp_ = %lu, frameCache.GetSp() = %lu", sp_, frameCache.GetSp()); + return false; + } + if (frameCache.GetSymbolName() != symbolName_) { + TS_LOGE("symbolName_ = %lu, frameCache.GetSymbolName() = %lu", symbolName_, frameCache.GetSymbolName()); + return false; + } + if (frameCache.GetFilePath() != filePath_) { + TS_LOGE("filePath_ = %lu, frameCache.GetFilePath() = %lu", filePath_, frameCache.GetFilePath()); + return false; + } + if (frameCache.GetOffset() != offset_) { + TS_LOGE("offset_ = %lu, frameCache.GetOffset() = %lu", offset_, frameCache.GetOffset()); + return false; + } + if (frameCache.GetSymbolOffset() != symbolOffset_) { + TS_LOGE("symbolOffset_ = %lu, frameCache.GetSymbolName() = %lu", symbolOffset_, frameCache.GetSymbolName()); + return false; + } + return true; + } + inline uint64_t GetCallChainId() const + { + return callChainId_; + } + inline uint64_t GetDepth() const + { + return depth_; + } + inline uint64_t GetIp() const + { + return ip_; + } + inline uint64_t GetSp() const + { + return sp_; + } + inline uint64_t GetSymbolName() const + { + return symbolName_; + } + inline uint64_t GetFilePath() const + { + return filePath_; + } + inline uint64_t GetOffset() const + { + return offset_; + } + inline uint64_t GetSymbolOffset() const + { + return symbolOffset_; + } + +private: + uint64_t callChainId_; + uint64_t depth_; + uint64_t ip_; + uint64_t sp_; + uint64_t symbolName_; + uint64_t filePath_; + uint64_t offset_; + uint64_t symbolOffset_; +}; + +/** + * @tc.name: ParseBatchNativeHookWithOutNativeHookData + * @tc.desc: Parse a BatchNativeHookData that does not contain any NativeHookData + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithOutNativeHookData, TestSize.Level1) +{ + TS_LOGI("test24-1"); + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + auto size = stream_.traceDataCache_->GetConstHilogData().Size(); + EXPECT_FALSE(size); +} + +/** + * @tc.name: ParseBatchNativeHookWithOneMalloc + * @tc.desc: Parse a BatchNativeHookData with only one Malloc + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithOneMalloc, TestSize.Level1) +{ + TS_LOGI("test24-2"); + // construct AllocEvent + AllocEvent* allocEvent = new AllocEvent(); + allocEvent->set_pid(PID); + allocEvent->set_tid(TID_01); + allocEvent->set_addr(MEM_ADDR_01); + allocEvent->set_size(MEM_SIZE_01); + // construct AllocEvent's Frame + auto frame = allocEvent->add_frame_info(); + frame->set_ip(CALL_STACK_IP_01); + frame->set_sp(CALL_STACK_SP_01); + frame->set_symbol_name(SYMBOL_NAME_01); + frame->set_file_path(FILE_PATH_01); + frame->set_offset(OFFSET_01); + frame->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto nativeHookData = batchNativeHookData->add_events(); + nativeHookData->set_tv_sec(TV_SEC_01); + nativeHookData->set_tv_nsec(TV_NSEC_01); + nativeHookData->set_allocated_alloc_event(allocEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + NativeHookCache expectNativeHookCache(1, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, TIMESTAMP_01, + 0, 0, MEM_ADDR_01, MEM_SIZE_01, MEM_SIZE_01, 0); + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + NativeHookCache resultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(expectNativeHookCache == resultNativeHookCache); + + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(1, size); + + // Verification parse NativeHook Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_01); + auto expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_01); + NativeHookFrameCache expectFrameCache(1, 0, 0, 0, expectSymbolData, expectFilePathData, OFFSET_01, + SYMBOL_OFFSET_01); + NativeHookFrameCache resultFrameCache(nativeHookFrame, 0); + EXPECT_TRUE(expectFrameCache == resultFrameCache); + + size = nativeHookFrame.Size(); + EXPECT_EQ(1, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseBatchNativeHookWithMultipleMalloc + * @tc.desc: Parse a NativeHook with multiple Malloc and Frame + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithMultipleMalloc, TestSize.Level1) +{ + TS_LOGI("test24-3"); + // constructs first AllocEvent with two Frame + AllocEvent* firstAllocEvent = new AllocEvent(); + firstAllocEvent->set_pid(PID); + firstAllocEvent->set_tid(TID_01); + firstAllocEvent->set_addr(MEM_ADDR_01); + firstAllocEvent->set_size(MEM_SIZE_01); + // construct first AllocEvent's first Frame + auto firstAllocFirstFrame = firstAllocEvent->add_frame_info(); + firstAllocFirstFrame->set_ip(CALL_STACK_IP_01); + firstAllocFirstFrame->set_sp(CALL_STACK_SP_01); + firstAllocFirstFrame->set_symbol_name(SYMBOL_NAME_01); + firstAllocFirstFrame->set_file_path(FILE_PATH_01); + firstAllocFirstFrame->set_offset(OFFSET_01); + firstAllocFirstFrame->set_symbol_offset(SYMBOL_OFFSET_01); + // construct first AllocEvent's second Frame + auto firstAllocSecondFrame = firstAllocEvent->add_frame_info(); + firstAllocSecondFrame->set_ip(CALL_STACK_IP_02); + firstAllocSecondFrame->set_sp(CALL_STACK_SP_02); + firstAllocSecondFrame->set_symbol_name(SYMBOL_NAME_02); + firstAllocSecondFrame->set_file_path(FILE_PATH_02); + firstAllocSecondFrame->set_offset(OFFSET_02); + firstAllocSecondFrame->set_symbol_offset(SYMBOL_OFFSET_02); + + // constructs second AllocEvent with two Frame + AllocEvent* secondAllocEvent = new AllocEvent(); + secondAllocEvent->set_pid(PID); + secondAllocEvent->set_tid(TID_02); + secondAllocEvent->set_addr(MEM_ADDR_02); + secondAllocEvent->set_size(MEM_SIZE_02); + // construct second AllocEvent's first Frame + auto secondAllocFirstFrame = secondAllocEvent->add_frame_info(); + secondAllocFirstFrame->set_ip(CALL_STACK_IP_01); + secondAllocFirstFrame->set_sp(CALL_STACK_SP_01); + secondAllocFirstFrame->set_symbol_name(SYMBOL_NAME_01); + secondAllocFirstFrame->set_file_path(FILE_PATH_01); + secondAllocFirstFrame->set_offset(OFFSET_01); + secondAllocFirstFrame->set_symbol_offset(SYMBOL_OFFSET_01); + // construct second AllocEvent's second Frame + auto secondAllocSecondFrame = secondAllocEvent->add_frame_info(); + secondAllocSecondFrame->set_ip(CALL_STACK_IP_02); + secondAllocSecondFrame->set_sp(CALL_STACK_SP_02); + secondAllocSecondFrame->set_symbol_name(SYMBOL_NAME_02); + secondAllocSecondFrame->set_file_path(FILE_PATH_02); + secondAllocSecondFrame->set_offset(OFFSET_02); + secondAllocSecondFrame->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add first NativeHookData + auto firstNativeHookData = batchNativeHookData->add_events(); + firstNativeHookData->set_tv_sec(TV_SEC_01); + firstNativeHookData->set_tv_nsec(TV_NSEC_01); + firstNativeHookData->set_allocated_alloc_event(firstAllocEvent); + // add second NativeHookData + auto secondNativeHookData = batchNativeHookData->add_events(); + secondNativeHookData->set_tv_sec(TV_SEC_02); + secondNativeHookData->set_tv_nsec(TV_NSEC_02); + secondNativeHookData->set_allocated_alloc_event(secondAllocEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + // Calculate partial expectations + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + EXPECT_TRUE(MEM_SIZE_01 == nativeHook.AllMemSizes()[0]); + EXPECT_TRUE(nativeHook.CurrentSizeDurs()[0] == TIMESTAMP_02 - TIMESTAMP_01); + + // Construct the nativehookcache object using the element with subscript 0 in nativehook and compare it with the + // expected value + NativeHookCache firstExpectNativeHookCache(1, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_01, 0, 0, MEM_ADDR_01, MEM_SIZE_01, MEM_SIZE_01, + TIMESTAMP_02 - TIMESTAMP_01); + NativeHookCache firstResultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(firstExpectNativeHookCache == firstResultNativeHookCache); + + // construct first Malloc event's first frame expect value. + // Note: the nativehookframe data is parsed in reverse order + auto firstExpectSymbol = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_02); + auto firstExpectFilePath = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_02); + auto secondExpectSymbol = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_01); + auto secondExpectFilePath = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_01); + NativeHookFrameCache firstMallocExpectFirstFrame(1, 0, 0, 0, firstExpectSymbol, firstExpectFilePath, OFFSET_02, + SYMBOL_OFFSET_02); + // Construct the NativeHookFrameCache object using the element with subscript 0 in NativeHookFrame and compare it + // with the expected value + NativeHookFrameCache firstMallocResultFirstFrame(nativeHookFrame, 0); + EXPECT_TRUE(firstMallocExpectFirstFrame == firstMallocResultFirstFrame); + + // construct first Malloc event's second frame expect value. + NativeHookFrameCache firstMallocExpectSecondFrame(1, 1, 0, 0, secondExpectSymbol, secondExpectFilePath, OFFSET_01, + SYMBOL_OFFSET_01); + NativeHookFrameCache firstMallocResultSecondFrame(nativeHookFrame, 1); + EXPECT_TRUE(firstMallocExpectSecondFrame == firstMallocResultSecondFrame); + + // Construct the nativehookcache object using the element with subscript 1 in nativehook and compare it with the + // expected value + expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); + NativeHookCache secondExpectNativeHookCache(1, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_02, 0, 0, MEM_ADDR_02, MEM_SIZE_02, MEM_SIZE_01 + MEM_SIZE_02, + 0); + NativeHookCache secondResultNativeHookCache(nativeHook, 1); + EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); + + // construct second Malloc event's first frame expect value. + // Note: the nativehookframe data is parsed in reverse order + NativeHookFrameCache secondMallocExpectFirstFrame(1, 0, 0, 0, firstExpectSymbol, firstExpectFilePath, OFFSET_02, + SYMBOL_OFFSET_02); + // Construct the NativeHookFrameCache object using the element with subscript 2 in NativeHookFrame and compare it + // Verify the compression algorithm here= + EXPECT_EQ(nativeHookFrame.CallChainIds()[1], 1); + EXPECT_EQ(nativeHookFrame.Depths()[1], 1); + EXPECT_EQ(nativeHookFrame.Ips()[1], 0); + EXPECT_EQ(nativeHookFrame.Sps()[1], 0); + EXPECT_EQ(nativeHookFrame.SymbolNames()[1], secondExpectSymbol); + EXPECT_EQ(nativeHookFrame.FilePaths()[1], secondExpectFilePath); + EXPECT_EQ(nativeHookFrame.Offsets()[1], OFFSET_01); + EXPECT_EQ(nativeHookFrame.SymbolOffsets()[1], SYMBOL_OFFSET_01); +} + +/** + * @tc.name: ParseBatchNativeHookWithOneFree + * @tc.desc: Parse a BatchNativeHookData with only one Free + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithOneFree, TestSize.Level1) +{ + TS_LOGI("test24-4"); + // construct FreeEvent + FreeEvent* freeEvent = new FreeEvent(); + freeEvent->set_pid(PID); + freeEvent->set_tid(TID_01); + freeEvent->set_addr(MEM_ADDR_01); + // construct FreeEvent's Frame + auto frame = freeEvent->add_frame_info(); + frame->set_ip(CALL_STACK_IP_01); + frame->set_sp(CALL_STACK_SP_01); + frame->set_symbol_name(SYMBOL_NAME_01); + frame->set_file_path(FILE_PATH_01); + frame->set_offset(OFFSET_01); + frame->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto nativeHookData = batchNativeHookData->add_events(); + nativeHookData->set_tv_sec(TV_SEC_01); + nativeHookData->set_tv_nsec(TV_NSEC_01); + nativeHookData->set_allocated_free_event(freeEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(0, size); + size = stream_.traceDataCache_->GetConstNativeHookFrameData().Size(); + EXPECT_EQ(0, size); + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseBatchNativeHookWithMultipleFree + * @tc.desc: Parse a NativeHook with multiple Free and Frame + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithMultipleFree, TestSize.Level1) +{ + TS_LOGI("test24-5"); + // constructs first FreeEvent with two Frame + FreeEvent* firstFreeEvent = new FreeEvent(); + firstFreeEvent->set_pid(PID); + firstFreeEvent->set_tid(TID_01); + firstFreeEvent->set_addr(MEM_ADDR_01); + // construct first FreeEvent's first Frame + auto firstFreeFirstFrame = firstFreeEvent->add_frame_info(); + firstFreeFirstFrame->set_ip(CALL_STACK_IP_01); + firstFreeFirstFrame->set_sp(CALL_STACK_SP_01); + firstFreeFirstFrame->set_symbol_name(SYMBOL_NAME_01); + firstFreeFirstFrame->set_file_path(FILE_PATH_01); + firstFreeFirstFrame->set_offset(OFFSET_01); + firstFreeFirstFrame->set_symbol_offset(SYMBOL_OFFSET_01); + // construct first FreeEvent's second Frame + auto firstFreeSecondFrame = firstFreeEvent->add_frame_info(); + firstFreeSecondFrame->set_ip(CALL_STACK_IP_02); + firstFreeSecondFrame->set_sp(CALL_STACK_SP_02); + firstFreeSecondFrame->set_symbol_name(SYMBOL_NAME_02); + firstFreeSecondFrame->set_file_path(FILE_PATH_02); + firstFreeSecondFrame->set_offset(OFFSET_02); + firstFreeSecondFrame->set_symbol_offset(SYMBOL_OFFSET_02); + + // constructs second FreeEvent with two Frame + FreeEvent* secondFreeEvent = new FreeEvent(); + secondFreeEvent->set_pid(PID); + secondFreeEvent->set_tid(TID_02); + secondFreeEvent->set_addr(MEM_ADDR_02); + // construct second FreeEvent's first Frame + auto secondFreeFirstFrame = secondFreeEvent->add_frame_info(); + secondFreeFirstFrame->set_ip(CALL_STACK_IP_01); + secondFreeFirstFrame->set_sp(CALL_STACK_SP_01); + secondFreeFirstFrame->set_symbol_name(SYMBOL_NAME_01); + secondFreeFirstFrame->set_file_path(FILE_PATH_01); + secondFreeFirstFrame->set_offset(OFFSET_01); + secondFreeFirstFrame->set_symbol_offset(SYMBOL_OFFSET_01); + // construct second FreeEvent's second Frame + auto secondFreeSecondFrame = secondFreeEvent->add_frame_info(); + secondFreeSecondFrame->set_ip(CALL_STACK_IP_02); + secondFreeSecondFrame->set_sp(CALL_STACK_SP_02); + secondFreeSecondFrame->set_symbol_name(SYMBOL_NAME_02); + secondFreeSecondFrame->set_file_path(FILE_PATH_02); + secondFreeSecondFrame->set_offset(OFFSET_02); + secondFreeSecondFrame->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add first NativeHookData + auto firstNativeHookData = batchNativeHookData->add_events(); + firstNativeHookData->set_tv_sec(TV_SEC_01); + firstNativeHookData->set_tv_nsec(TV_NSEC_01); + firstNativeHookData->set_allocated_free_event(firstFreeEvent); + // add second NativeHookData + auto secondNativeHookData = batchNativeHookData->add_events(); + secondNativeHookData->set_tv_sec(TV_SEC_02); + secondNativeHookData->set_tv_nsec(TV_NSEC_02); + secondNativeHookData->set_allocated_free_event(secondFreeEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + // Calculate partial expectations + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + EXPECT_TRUE(0 == nativeHook.Size()); + EXPECT_TRUE(0 == nativeHookFrame.Size()); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); +} + +/** + * @tc.name: ParseBatchNativeHookWithOnePairsMallocAndFree + * @tc.desc: Parse a BatchNativeHookData with a pair of matching Malloc and Free Event + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithOnePairsMallocAndFree, TestSize.Level1) +{ + TS_LOGI("test24-6"); + // construct AllocEvent + AllocEvent* allocEvent = new AllocEvent(); + allocEvent->set_pid(PID); + allocEvent->set_tid(TID_01); + allocEvent->set_addr(MEM_ADDR_01); + allocEvent->set_size(MEM_SIZE_01); + // construct AllocEvent's Frame + auto allocframe = allocEvent->add_frame_info(); + allocframe->set_ip(CALL_STACK_IP_01); + allocframe->set_sp(CALL_STACK_SP_01); + allocframe->set_symbol_name(SYMBOL_NAME_01); + allocframe->set_file_path(FILE_PATH_01); + allocframe->set_offset(OFFSET_01); + allocframe->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct FreeEvent + FreeEvent* freeEvent = new FreeEvent(); + freeEvent->set_pid(PID); + freeEvent->set_tid(TID_02); + freeEvent->set_addr(MEM_ADDR_01); + // construct FreeEvent's Frame + auto freeframe = freeEvent->add_frame_info(); + freeframe->set_ip(CALL_STACK_IP_02); + freeframe->set_sp(CALL_STACK_SP_02); + freeframe->set_symbol_name(SYMBOL_NAME_02); + freeframe->set_file_path(FILE_PATH_02); + freeframe->set_offset(OFFSET_02); + freeframe->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto nativeHookMallocData = batchNativeHookData->add_events(); + nativeHookMallocData->set_tv_sec(TV_SEC_01); + nativeHookMallocData->set_tv_nsec(TV_NSEC_01); + nativeHookMallocData->set_allocated_alloc_event(allocEvent); + auto nativeHookFreeData = batchNativeHookData->add_events(); + nativeHookFreeData->set_tv_sec(TV_SEC_02); + nativeHookFreeData->set_tv_nsec(TV_NSEC_02); + nativeHookFreeData->set_allocated_free_event(freeEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse Malloc event results + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + NativeHookCache firstExpectNativeHookCache(1, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_01, TIMESTAMP_02, TIMESTAMP_02 - TIMESTAMP_01, MEM_ADDR_01, + MEM_SIZE_01, MEM_SIZE_01, TIMESTAMP_02 - TIMESTAMP_01); + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + NativeHookCache firstResultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(firstExpectNativeHookCache == firstResultNativeHookCache); + + // Verification parse Malloc Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_01); + auto expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_01); + NativeHookFrameCache secondExpectFrameCache(1, 0, 0, 0, expectSymbolData, expectFilePathData, OFFSET_01, + SYMBOL_OFFSET_01); + NativeHookFrameCache secondResultFrameCache(nativeHookFrame, 0); + EXPECT_TRUE(secondExpectFrameCache == secondResultFrameCache); + + // Verification parse Free event results + expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); + NativeHookCache expectNativeHookCache(2, expect_ipid, expect_itid, FREEEVENT.c_str(), INVALID_UINT64, TIMESTAMP_02, + 0, 0, MEM_ADDR_01, MEM_SIZE_01, 0, 0); + NativeHookCache resultNativeHookCache(nativeHook, 1); + EXPECT_TRUE(expectNativeHookCache == resultNativeHookCache); + + // Verification parse Free Event Frame results + expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_02); + expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_02); + NativeHookFrameCache expectFrameCache(2, 0, 0, 0, expectSymbolData, expectFilePathData, OFFSET_02, + SYMBOL_OFFSET_02); + NativeHookFrameCache resultFrameCache(nativeHookFrame, 1); + EXPECT_TRUE(expectFrameCache == resultFrameCache); + + auto size = nativeHookFrame.Size(); + EXPECT_EQ(2, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseBatchNativeHookWithNotMatchMallocAndFree + * @tc.desc: Parse a BatchNativeHookData with Not Match Malloc and Free Event + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithNotMatchMallocAndFree, TestSize.Level1) +{ + TS_LOGI("test24-7"); + // construct AllocEvent + AllocEvent* allocEvent = new AllocEvent(); + allocEvent->set_pid(PID); + allocEvent->set_tid(TID_01); + allocEvent->set_addr(MEM_ADDR_01); + allocEvent->set_size(MEM_SIZE_01); + // construct AllocEvent's Frame + auto allocframe = allocEvent->add_frame_info(); + allocframe->set_ip(CALL_STACK_IP_01); + allocframe->set_sp(CALL_STACK_SP_01); + allocframe->set_symbol_name(SYMBOL_NAME_01); + allocframe->set_file_path(FILE_PATH_01); + allocframe->set_offset(OFFSET_01); + allocframe->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct FreeEvent + FreeEvent* freeEvent = new FreeEvent(); + freeEvent->set_pid(PID); + freeEvent->set_tid(TID_02); + freeEvent->set_addr(MEM_ADDR_02); + auto freeframe = freeEvent->add_frame_info(); + // construct FreeEvent's Frame + freeframe->set_ip(CALL_STACK_IP_02); + freeframe->set_sp(CALL_STACK_SP_02); + freeframe->set_symbol_name(SYMBOL_NAME_02); + freeframe->set_file_path(FILE_PATH_02); + freeframe->set_offset(OFFSET_02); + freeframe->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto nativeHookMallocData = batchNativeHookData->add_events(); + nativeHookMallocData->set_tv_sec(TV_SEC_01); + nativeHookMallocData->set_tv_nsec(TV_NSEC_01); + nativeHookMallocData->set_allocated_alloc_event(allocEvent); + auto nativeHookFreeData = batchNativeHookData->add_events(); + nativeHookFreeData->set_tv_sec(TV_SEC_02); + nativeHookFreeData->set_tv_nsec(TV_NSEC_02); + nativeHookFreeData->set_allocated_free_event(freeEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse Malloc event results + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + NativeHookCache firstExpectNativeHookCache(1, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_01, 0, 0, MEM_ADDR_01, MEM_SIZE_01, MEM_SIZE_01, 0); + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + NativeHookCache firstResultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(firstExpectNativeHookCache == firstResultNativeHookCache); + + // Verification parse Malloc Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_01); + auto expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_01); + NativeHookFrameCache firstExpectFrameCache(1, 0, 0, 0, expectSymbolData, expectFilePathData, OFFSET_01, + SYMBOL_OFFSET_01); + NativeHookFrameCache firstResultFrameCache(nativeHookFrame, 0); + EXPECT_TRUE(firstExpectFrameCache == firstResultFrameCache); + + auto size = nativeHookFrame.Size(); + EXPECT_EQ(1, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseTwoMallocAndFreeEventMatched + * @tc.desc: Parse a BatchNativeHookData with two Malloc and two Free Event, that Malloc and Free was matched. + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseTwoMallocAndFreeEventMatched, TestSize.Level1) +{ + TS_LOGI("test24-8"); + // construct first AllocEvent + AllocEvent* firstAllocEvent = new AllocEvent(); + firstAllocEvent->set_pid(PID); + firstAllocEvent->set_tid(TID_01); + firstAllocEvent->set_addr(MEM_ADDR_01); + firstAllocEvent->set_size(MEM_SIZE_01); + + // construct second AllocEvent + AllocEvent* secondAllocEvent = new AllocEvent(); + secondAllocEvent->set_pid(PID); + secondAllocEvent->set_tid(TID_02); + secondAllocEvent->set_addr(MEM_ADDR_02); + secondAllocEvent->set_size(MEM_SIZE_02); + + // construct first FreeEvent + FreeEvent* firstFreeEvent = new FreeEvent(); + firstFreeEvent->set_pid(PID); + firstFreeEvent->set_tid(TID_01); + firstFreeEvent->set_addr(MEM_ADDR_01); + + // construct second FreeEvent + FreeEvent* secondFreeEvent = new FreeEvent(); + secondFreeEvent->set_pid(PID); + secondFreeEvent->set_tid(TID_02); + secondFreeEvent->set_addr(MEM_ADDR_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto firstMallocData = batchNativeHookData->add_events(); + firstMallocData->set_tv_sec(TV_SEC_01); + firstMallocData->set_tv_nsec(TV_NSEC_01); + firstMallocData->set_allocated_alloc_event(firstAllocEvent); + auto firstFreeData = batchNativeHookData->add_events(); + firstFreeData->set_tv_sec(TV_SEC_02); + firstFreeData->set_tv_nsec(TV_NSEC_02); + firstFreeData->set_allocated_free_event(firstFreeEvent); + auto secondMallocData = batchNativeHookData->add_events(); + secondMallocData->set_tv_sec(TV_SEC_03); + secondMallocData->set_tv_nsec(TV_NSEC_03); + secondMallocData->set_allocated_alloc_event(secondAllocEvent); + auto secondFreeData = batchNativeHookData->add_events(); + secondFreeData->set_tv_sec(TV_SEC_04); + secondFreeData->set_tv_nsec(TV_NSEC_04); + secondFreeData->set_allocated_free_event(secondFreeEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse first Malloc event results + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + NativeHookCache firstExpectMallocCache(INVALID_UINT64, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_01, TIMESTAMP_02, TIMESTAMP_02 - TIMESTAMP_01, MEM_ADDR_01, + MEM_SIZE_01, MEM_SIZE_01, TIMESTAMP_02 - TIMESTAMP_01); + NativeHookCache firstResultMallocCache(nativeHook, 0); + EXPECT_TRUE(firstExpectMallocCache == firstResultMallocCache); + + // Verification parse first Free event results + NativeHookCache firstExpectFreeCache(INVALID_UINT64, expect_ipid, expect_itid, FREEEVENT.c_str(), INVALID_UINT64, TIMESTAMP_02, + 0, 0, MEM_ADDR_01, MEM_SIZE_01, 0, TIMESTAMP_03 - TIMESTAMP_02); + NativeHookCache firstResultFreeCache(nativeHook, 1); + EXPECT_TRUE(firstExpectFreeCache == firstResultFreeCache); + + expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); + NativeHookCache secondExpectMallocCache(INVALID_UINT64, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_03, TIMESTAMP_04, TIMESTAMP_04 - TIMESTAMP_03, MEM_ADDR_02, + MEM_SIZE_02, MEM_SIZE_02, TIMESTAMP_04 - TIMESTAMP_03); + NativeHookCache secondResultMallocCache(nativeHook, 2); + EXPECT_TRUE(secondExpectMallocCache == secondResultMallocCache); + + // Verification parse first Free event results + NativeHookCache secondExpectFreeCache(INVALID_UINT64, expect_ipid, expect_itid, FREEEVENT.c_str(), INVALID_UINT64, TIMESTAMP_04, + 0, 0, MEM_ADDR_02, MEM_SIZE_02, 0, 0); + NativeHookCache secondResultFreeCache(nativeHook, 3); + EXPECT_TRUE(secondExpectFreeCache == secondResultFreeCache); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); +} + +/** + * @tc.name: ParseTwoMallocAndFreeEventPartialMatched + * @tc.desc: Parse a BatchNativeHookData with two Malloc and two Free Event, that Malloc and Free was partial matched. + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseTwoMallocAndFreeEventPartialMatched, TestSize.Level1) +{ + TS_LOGI("test24-9"); + // construct first AllocEvent + AllocEvent* firstAllocEvent = new AllocEvent(); + firstAllocEvent->set_pid(PID); + firstAllocEvent->set_tid(TID_01); + firstAllocEvent->set_addr(MEM_ADDR_01); + firstAllocEvent->set_size(MEM_SIZE_01); + + // construct second AllocEvent + AllocEvent* secondAllocEvent = new AllocEvent(); + secondAllocEvent->set_pid(PID); + secondAllocEvent->set_tid(TID_02); + secondAllocEvent->set_addr(MEM_ADDR_02); + secondAllocEvent->set_size(MEM_SIZE_02); + + // construct first FreeEvent + FreeEvent* firstFreeEvent = new FreeEvent(); + firstFreeEvent->set_pid(PID); + firstFreeEvent->set_tid(TID_01); + firstFreeEvent->set_addr(MEM_ADDR_01); + + // construct second FreeEvent + FreeEvent* secondFreeEvent = new FreeEvent(); + secondFreeEvent->set_pid(PID); + secondFreeEvent->set_tid(TID_02); + secondFreeEvent->set_addr(MEM_ADDR_03); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto firstMallocData = batchNativeHookData->add_events(); + firstMallocData->set_tv_sec(TV_SEC_01); + firstMallocData->set_tv_nsec(TV_NSEC_01); + firstMallocData->set_allocated_alloc_event(firstAllocEvent); + auto firstFreeData = batchNativeHookData->add_events(); + firstFreeData->set_tv_sec(TV_SEC_02); + firstFreeData->set_tv_nsec(TV_NSEC_02); + firstFreeData->set_allocated_free_event(firstFreeEvent); + auto secondMallocData = batchNativeHookData->add_events(); + secondMallocData->set_tv_sec(TV_SEC_03); + secondMallocData->set_tv_nsec(TV_NSEC_03); + secondMallocData->set_allocated_alloc_event(secondAllocEvent); + auto secondFreeData = batchNativeHookData->add_events(); + secondFreeData->set_tv_sec(TV_SEC_04); + secondFreeData->set_tv_nsec(TV_NSEC_04); + secondFreeData->set_allocated_free_event(secondFreeEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse first Malloc event results + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + NativeHookCache firstExpectMallocCache(INVALID_UINT64, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_01, TIMESTAMP_02, TIMESTAMP_02 - TIMESTAMP_01, MEM_ADDR_01, + MEM_SIZE_01, MEM_SIZE_01, TIMESTAMP_02 - TIMESTAMP_01); + NativeHookCache firstResultMallocCache(nativeHook, 0); + EXPECT_TRUE(firstExpectMallocCache == firstResultMallocCache); + + // Verification parse first Free event results + NativeHookCache firstExpectFreeCache(INVALID_UINT64, expect_ipid, expect_itid, FREEEVENT.c_str(), INVALID_UINT64, TIMESTAMP_02, + 0, 0, MEM_ADDR_01, MEM_SIZE_01, 0, TIMESTAMP_03 - TIMESTAMP_02); + NativeHookCache firstResultFreeCache(nativeHook, 1); + EXPECT_TRUE(firstExpectFreeCache == firstResultFreeCache); + + // Verification parse second Malloc event results + expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); + NativeHookCache secondExpectMallocCache(INVALID_UINT64, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_03, 0, 0, MEM_ADDR_02, MEM_SIZE_02, MEM_SIZE_02, 0); + NativeHookCache secondResultMallocCache(nativeHook, 2); + EXPECT_TRUE(secondExpectMallocCache == secondResultMallocCache); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); +} + +/** + * @tc.name: ParseBatchNativeHookWithOneMmap + * @tc.desc: Parse a BatchNativeHookData with only one MMAP + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithOneMmap, TestSize.Level1) +{ + TS_LOGI("test24-10"); + // construct MmapEvent + MmapEvent* mmapEvent = new MmapEvent(); + mmapEvent->set_pid(PID); + mmapEvent->set_tid(TID_01); + mmapEvent->set_addr(MEM_ADDR_01); + mmapEvent->set_size(MEM_SIZE_01); + mmapEvent->set_type(MMAP_SUB_TYPE_01); + // construct MmapEvent's Frame + auto frame = mmapEvent->add_frame_info(); + frame->set_ip(CALL_STACK_IP_01); + frame->set_sp(CALL_STACK_SP_01); + frame->set_symbol_name(SYMBOL_NAME_01); + frame->set_file_path(FILE_PATH_01); + frame->set_offset(OFFSET_01); + frame->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto nativeHookData = batchNativeHookData->add_events(); + nativeHookData->set_tv_sec(TV_SEC_01); + nativeHookData->set_tv_nsec(TV_NSEC_01); + nativeHookData->set_allocated_mmap_event(mmapEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + auto mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_01); + NativeHookCache expectNativeHookCache(1, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, TIMESTAMP_01, 0, + 0, MEM_ADDR_01, MEM_SIZE_01, MEM_SIZE_01, 0); + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + NativeHookCache resultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(expectNativeHookCache == resultNativeHookCache); + + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(1, size); + + // Verification parse NativeHook Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_01); + auto expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_01); + NativeHookFrameCache expectFrameCache(1, 0, 0, 0, expectSymbolData, expectFilePathData, OFFSET_01, + SYMBOL_OFFSET_01); + NativeHookFrameCache resultFrameCache(nativeHookFrame, 0); + EXPECT_TRUE(expectFrameCache == resultFrameCache); + + size = nativeHookFrame.Size(); + EXPECT_EQ(1, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseBatchNativeHookWithOneMunmap + * @tc.desc: Parse a BatchNativeHookData with only one MMAP + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithOneMunmap, TestSize.Level1) +{ + TS_LOGI("test24-11"); + // construct MunmapEvent + MunmapEvent* munmapEvent = new MunmapEvent(); + munmapEvent->set_pid(PID); + munmapEvent->set_tid(TID_01); + munmapEvent->set_addr(MEM_ADDR_01); + munmapEvent->set_size(MEM_SIZE_01); + // construct MunmapEvent's Frame + auto frame = munmapEvent->add_frame_info(); + frame->set_ip(CALL_STACK_IP_01); + frame->set_sp(CALL_STACK_SP_01); + frame->set_symbol_name(SYMBOL_NAME_01); + frame->set_file_path(FILE_PATH_01); + frame->set_offset(OFFSET_01); + frame->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto nativeHookData = batchNativeHookData->add_events(); + nativeHookData->set_tv_sec(TV_SEC_01); + nativeHookData->set_tv_nsec(TV_NSEC_01); + nativeHookData->set_allocated_munmap_event(munmapEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(0, size); + + // Verification parse NativeHook Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + + size = nativeHookFrame.Size(); + EXPECT_EQ(0, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseBatchNativeHookWithMultipleMmap + * @tc.desc: Parse a BatchNativeHookData with multiple MMAP + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithMultipleMmap, TestSize.Level1) +{ + TS_LOGI("test24-12"); + // construct first MmapEvent + MmapEvent* firstMmapEvent = new MmapEvent(); + firstMmapEvent->set_pid(PID); + firstMmapEvent->set_tid(TID_01); + firstMmapEvent->set_addr(MEM_ADDR_01); + firstMmapEvent->set_size(MEM_SIZE_01); + firstMmapEvent->set_type(MMAP_SUB_TYPE_01); + // construct first MmapEvent's Frame + auto firstFrame = firstMmapEvent->add_frame_info(); + firstFrame->set_ip(CALL_STACK_IP_01); + firstFrame->set_sp(CALL_STACK_SP_01); + firstFrame->set_symbol_name(SYMBOL_NAME_01); + firstFrame->set_file_path(FILE_PATH_01); + firstFrame->set_offset(OFFSET_01); + firstFrame->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct second MmapEvent + MmapEvent* secondMmapEvent = new MmapEvent(); + secondMmapEvent->set_pid(PID); + secondMmapEvent->set_tid(TID_02); + secondMmapEvent->set_addr(MEM_ADDR_02); + secondMmapEvent->set_size(MEM_SIZE_02); + secondMmapEvent->set_type(MMAP_SUB_TYPE_02); + // construct second MmapEvent's Frame + auto secondFrame = secondMmapEvent->add_frame_info(); + secondFrame->set_ip(CALL_STACK_IP_02); + secondFrame->set_sp(CALL_STACK_SP_02); + secondFrame->set_symbol_name(SYMBOL_NAME_02); + secondFrame->set_file_path(FILE_PATH_02); + secondFrame->set_offset(OFFSET_02); + secondFrame->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto firstNativeHookData = batchNativeHookData->add_events(); + firstNativeHookData->set_tv_sec(TV_SEC_01); + firstNativeHookData->set_tv_nsec(TV_NSEC_01); + firstNativeHookData->set_allocated_mmap_event(firstMmapEvent); + auto secondNativeHookData = batchNativeHookData->add_events(); + secondNativeHookData->set_tv_sec(TV_SEC_02); + secondNativeHookData->set_tv_nsec(TV_NSEC_02); + secondNativeHookData->set_allocated_mmap_event(secondMmapEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + auto mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_01); + + NativeHookCache firstExpectNativeHookCache(1, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + TIMESTAMP_01, 0, 0, MEM_ADDR_01, MEM_SIZE_01, MEM_SIZE_01, + TIMESTAMP_02 - TIMESTAMP_01); + NativeHookCache firstResultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(firstExpectNativeHookCache == firstResultNativeHookCache); + + expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); + mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_02); + NativeHookCache secondExpectNativeHookCache(2, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + TIMESTAMP_02, 0, 0, MEM_ADDR_02, MEM_SIZE_02, MEM_SIZE_01 + MEM_SIZE_02, + 0); + NativeHookCache secondResultNativeHookCache(nativeHook, 1); + EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(2, size); + + // Verification parse NativeHook Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_01); + auto expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_01); + NativeHookFrameCache firstExpectFrameCache(1, 0, 0, 0, expectSymbolData, expectFilePathData, OFFSET_01, + SYMBOL_OFFSET_01); + NativeHookFrameCache firstResultFrameCache(nativeHookFrame, 0); + EXPECT_TRUE(firstExpectFrameCache == firstResultFrameCache); + + expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_02); + expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_02); + NativeHookFrameCache expectFrameCache(2, 0, 0, 0, expectSymbolData, expectFilePathData, OFFSET_02, + SYMBOL_OFFSET_02); + NativeHookFrameCache resultFrameCache(nativeHookFrame, 1); + EXPECT_TRUE(expectFrameCache == resultFrameCache); + + size = nativeHookFrame.Size(); + EXPECT_EQ(2, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); +} + +/** + * @tc.name: ParseBatchNativeHookWithMultipleMunmap + * @tc.desc: Parse a BatchNativeHookData with multiple munmap + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithMultipleMunmap, TestSize.Level1) +{ + TS_LOGI("test24-13"); + // construct first MunmapEvent + MunmapEvent* firstMunmapEvent = new MunmapEvent(); + firstMunmapEvent->set_pid(PID); + firstMunmapEvent->set_tid(TID_01); + firstMunmapEvent->set_addr(MEM_ADDR_01); + firstMunmapEvent->set_size(MEM_SIZE_01); + // construct MunmapEvent's Frame + auto firstFrame = firstMunmapEvent->add_frame_info(); + firstFrame->set_ip(CALL_STACK_IP_01); + firstFrame->set_sp(CALL_STACK_SP_01); + firstFrame->set_symbol_name(SYMBOL_NAME_01); + firstFrame->set_file_path(FILE_PATH_01); + firstFrame->set_offset(OFFSET_01); + firstFrame->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct second MunmapEvent + MunmapEvent* secondMunmapEvent = new MunmapEvent(); + secondMunmapEvent->set_pid(PID); + secondMunmapEvent->set_tid(TID_02); + secondMunmapEvent->set_addr(MEM_ADDR_02); + secondMunmapEvent->set_size(MEM_SIZE_02); + // construct MunmapEvent's Frame + auto secondFrame = secondMunmapEvent->add_frame_info(); + secondFrame->set_ip(CALL_STACK_IP_02); + secondFrame->set_sp(CALL_STACK_SP_02); + secondFrame->set_symbol_name(SYMBOL_NAME_02); + secondFrame->set_file_path(FILE_PATH_02); + secondFrame->set_offset(OFFSET_02); + secondFrame->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto firstNativeHookData = batchNativeHookData->add_events(); + firstNativeHookData->set_tv_sec(TV_SEC_01); + firstNativeHookData->set_tv_nsec(TV_NSEC_01); + firstNativeHookData->set_allocated_munmap_event(firstMunmapEvent); + auto secondNativeHookData = batchNativeHookData->add_events(); + secondNativeHookData->set_tv_sec(TV_SEC_02); + secondNativeHookData->set_tv_nsec(TV_NSEC_02); + secondNativeHookData->set_allocated_munmap_event(secondMunmapEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(0, size); + + // Verification parse NativeHook Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + + size = nativeHookFrame.Size(); + EXPECT_EQ(0, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); +} + +/** + * @tc.name: ParseOnePairsMmapAndMunmapEvent + * @tc.desc: Parse a BatchNativeHookData with one pairs Mmap and MunmapEvent + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseOnePairsMmapAndMunmapEvent, TestSize.Level1) +{ + TS_LOGI("test24-14"); + // construct MmapEvent + MmapEvent* mmapEvent = new MmapEvent(); + mmapEvent->set_pid(PID); + mmapEvent->set_tid(TID_01); + mmapEvent->set_addr(MEM_ADDR_01); + mmapEvent->set_size(MEM_SIZE_01); + mmapEvent->set_type(MMAP_SUB_TYPE_01); + // construct MmapEvent's Frame + auto firstFrame = mmapEvent->add_frame_info(); + firstFrame->set_ip(CALL_STACK_IP_01); + firstFrame->set_sp(CALL_STACK_SP_01); + firstFrame->set_symbol_name(SYMBOL_NAME_01); + firstFrame->set_file_path(FILE_PATH_01); + firstFrame->set_offset(OFFSET_01); + firstFrame->set_symbol_offset(SYMBOL_OFFSET_01); + auto secondFrame = mmapEvent->add_frame_info(); + secondFrame->set_ip(CALL_STACK_IP_02); + secondFrame->set_sp(CALL_STACK_SP_02); + secondFrame->set_symbol_name(SYMBOL_NAME_02); + secondFrame->set_file_path(FILE_PATH_02); + secondFrame->set_offset(OFFSET_02); + secondFrame->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct first MunmapEvent + MunmapEvent* munmapEvent = new MunmapEvent(); + munmapEvent->set_pid(PID); + munmapEvent->set_tid(TID_01); + munmapEvent->set_addr(MEM_ADDR_01); + munmapEvent->set_size(MEM_SIZE_01); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto nativeHookMmapData = batchNativeHookData->add_events(); + nativeHookMmapData->set_tv_sec(TV_SEC_01); + nativeHookMmapData->set_tv_nsec(TV_NSEC_01); + nativeHookMmapData->set_allocated_mmap_event(mmapEvent); + auto nativeHookMunmapData = batchNativeHookData->add_events(); + nativeHookMunmapData->set_tv_sec(TV_SEC_02); + nativeHookMunmapData->set_tv_nsec(TV_NSEC_02); + nativeHookMunmapData->set_allocated_munmap_event(munmapEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + auto mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_01); + NativeHookCache firstExpectNativeHookCache(1, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + TIMESTAMP_01, TIMESTAMP_02, TIMESTAMP_02 - TIMESTAMP_01, MEM_ADDR_01, + MEM_SIZE_01, MEM_SIZE_01, TIMESTAMP_02 - TIMESTAMP_01); + NativeHookCache firstResultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(firstExpectNativeHookCache == firstResultNativeHookCache); + + NativeHookCache secondExpectNativeHookCache(INVALID_UINT64, expect_ipid, expect_itid, MUNMAPEVENT.c_str(), + INVALID_UINT64, TIMESTAMP_02, 0, 0, MEM_ADDR_01, MEM_SIZE_01, 0, 0); + NativeHookCache secondResultNativeHookCache(nativeHook, 1); + EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); + + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(2, size); + + // Verification parse NativeHook Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_02); + auto expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_02); + NativeHookFrameCache firstExpectFrameCache(1, 0, 0, 0, expectSymbolData, expectFilePathData, OFFSET_02, + SYMBOL_OFFSET_02); + NativeHookFrameCache firstResultFrameCache(nativeHookFrame, 0); + EXPECT_TRUE(firstExpectFrameCache == firstResultFrameCache); + + expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_01); + expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_01); + NativeHookFrameCache secondExpectFrameCache(1, 1, 0, 0, expectSymbolData, expectFilePathData, OFFSET_01, + SYMBOL_OFFSET_01); + NativeHookFrameCache secondResultFrameCache(nativeHookFrame, 1); + EXPECT_TRUE(secondExpectFrameCache == secondResultFrameCache); + + size = nativeHookFrame.Size(); + EXPECT_EQ(2, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseNotMatchMmapAndMunmapEvent + * @tc.desc: Parse a BatchNativeHookData with not match Mmap and MunmapEvent + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseNotMatchMmapAndMunmapEvent, TestSize.Level1) +{ + TS_LOGI("test24-15"); + // construct MmapEvent + MmapEvent* mmapEvent = new MmapEvent(); + mmapEvent->set_pid(PID); + mmapEvent->set_tid(TID_01); + mmapEvent->set_addr(MEM_ADDR_01); + mmapEvent->set_size(MEM_SIZE_01); + mmapEvent->set_type(MMAP_SUB_TYPE_01); + // construct MmapEvent's Frame + auto firstFrame = mmapEvent->add_frame_info(); + firstFrame->set_ip(CALL_STACK_IP_01); + firstFrame->set_sp(CALL_STACK_SP_01); + firstFrame->set_symbol_name(SYMBOL_NAME_01); + firstFrame->set_file_path(FILE_PATH_01); + firstFrame->set_offset(OFFSET_01); + firstFrame->set_symbol_offset(SYMBOL_OFFSET_01); + auto secondFrame = mmapEvent->add_frame_info(); + secondFrame->set_ip(CALL_STACK_IP_02); + secondFrame->set_sp(CALL_STACK_SP_02); + secondFrame->set_symbol_name(SYMBOL_NAME_02); + secondFrame->set_file_path(FILE_PATH_02); + secondFrame->set_offset(OFFSET_02); + secondFrame->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct MunmapEvent + MunmapEvent* munmapEvent = new MunmapEvent(); + munmapEvent->set_pid(PID); + munmapEvent->set_tid(TID_01); + munmapEvent->set_addr(MEM_ADDR_02); + munmapEvent->set_size(MEM_SIZE_01); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto nativeHookMmapData = batchNativeHookData->add_events(); + nativeHookMmapData->set_tv_sec(TV_SEC_01); + nativeHookMmapData->set_tv_nsec(TV_NSEC_01); + nativeHookMmapData->set_allocated_mmap_event(mmapEvent); + auto nativeHookMunmapData = batchNativeHookData->add_events(); + nativeHookMunmapData->set_tv_sec(TV_SEC_02); + nativeHookMunmapData->set_tv_nsec(TV_NSEC_02); + nativeHookMunmapData->set_allocated_munmap_event(munmapEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + auto mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_01); + NativeHookCache firstExpectNativeHookCache(1, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + TIMESTAMP_01, 0, 0, MEM_ADDR_01, MEM_SIZE_01, MEM_SIZE_01, 0); + NativeHookCache firstResultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(firstExpectNativeHookCache == firstResultNativeHookCache); + + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(1, size); + + // Verification parse NativeHook Frame results + const NativeHookFrame& nativeHookFrame = stream_.traceDataCache_->GetConstNativeHookFrameData(); + auto expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_02); + auto expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_02); + NativeHookFrameCache firstExpectFrameCache(1, 0, 0, 0, expectSymbolData, expectFilePathData, OFFSET_02, + SYMBOL_OFFSET_02); + NativeHookFrameCache firstResultFrameCache(nativeHookFrame, 0); + EXPECT_TRUE(firstExpectFrameCache == firstResultFrameCache); + + expectSymbolData = stream_.traceDataCache_->dataDict_.GetStringIndex(SYMBOL_NAME_01); + expectFilePathData = stream_.traceDataCache_->dataDict_.GetStringIndex(FILE_PATH_01); + NativeHookFrameCache secondExpectFrameCache(1, 1, 0, 0, expectSymbolData, expectFilePathData, OFFSET_01, + SYMBOL_OFFSET_01); + NativeHookFrameCache secondResultFrameCache(nativeHookFrame, 1); + EXPECT_TRUE(secondExpectFrameCache == secondResultFrameCache); + + size = nativeHookFrame.Size(); + EXPECT_EQ(2, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} + +/** + * @tc.name: ParseTwoPairsMatchedMmapAndMunmapEvent + * @tc.desc: Parse a BatchNativeHookData with two pairs matched Mmap and MunmapEvent + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseTwoPairsMatchedMmapAndMunmapEvent, TestSize.Level1) +{ + TS_LOGI("test24-16"); + // construct first MmapEvent + MmapEvent* firstMmapEvent = new MmapEvent(); + firstMmapEvent->set_pid(PID); + firstMmapEvent->set_tid(TID_01); + firstMmapEvent->set_addr(MEM_ADDR_01); + firstMmapEvent->set_size(MEM_SIZE_01); + firstMmapEvent->set_type(MMAP_SUB_TYPE_01); + // construct second MmapEvent + MmapEvent* secondMmapEvent = new MmapEvent(); + secondMmapEvent->set_pid(PID); + secondMmapEvent->set_tid(TID_02); + secondMmapEvent->set_addr(MEM_ADDR_02); + secondMmapEvent->set_size(MEM_SIZE_02); + secondMmapEvent->set_type(MMAP_SUB_TYPE_02); + + // construct first MunmapEvent + MunmapEvent* firstMunmapEvent = new MunmapEvent(); + firstMunmapEvent->set_pid(PID); + firstMunmapEvent->set_tid(TID_01); + firstMunmapEvent->set_addr(MEM_ADDR_01); + firstMunmapEvent->set_size(MEM_SIZE_01); + // construct second MunmapEvent + MunmapEvent* secondMunmapEvent = new MunmapEvent(); + secondMunmapEvent->set_pid(PID); + secondMunmapEvent->set_tid(TID_02); + secondMunmapEvent->set_addr(MEM_ADDR_02); + secondMunmapEvent->set_size(MEM_SIZE_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto firstNativeHookMmapData = batchNativeHookData->add_events(); + firstNativeHookMmapData->set_tv_sec(TV_SEC_01); + firstNativeHookMmapData->set_tv_nsec(TV_NSEC_01); + firstNativeHookMmapData->set_allocated_mmap_event(firstMmapEvent); + auto firstNativeHookMunmapData = batchNativeHookData->add_events(); + firstNativeHookMunmapData->set_tv_sec(TV_SEC_02); + firstNativeHookMunmapData->set_tv_nsec(TV_NSEC_02); + firstNativeHookMunmapData->set_allocated_munmap_event(firstMunmapEvent); + auto secondNativeHookMmapData = batchNativeHookData->add_events(); + secondNativeHookMmapData->set_tv_sec(TV_SEC_03); + secondNativeHookMmapData->set_tv_nsec(TV_NSEC_03); + secondNativeHookMmapData->set_allocated_mmap_event(secondMmapEvent); + auto secondNativeHookMunmapData = batchNativeHookData->add_events(); + secondNativeHookMunmapData->set_tv_sec(TV_SEC_04); + secondNativeHookMunmapData->set_tv_nsec(TV_NSEC_04); + secondNativeHookMunmapData->set_allocated_munmap_event(secondMunmapEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + auto mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_01); + NativeHookCache firstExpectNativeHookCache(INVALID_UINT64, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + TIMESTAMP_01, TIMESTAMP_02, TIMESTAMP_02 - TIMESTAMP_01, MEM_ADDR_01, + MEM_SIZE_01, MEM_SIZE_01, TIMESTAMP_02 - TIMESTAMP_01); + NativeHookCache firstResultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(firstExpectNativeHookCache == firstResultNativeHookCache); + + NativeHookCache secondExpectNativeHookCache(INVALID_UINT64, expect_ipid, expect_itid, MUNMAPEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_02, 0, 0, MEM_ADDR_01, MEM_SIZE_01, 0, + TIMESTAMP_03 - TIMESTAMP_02); + NativeHookCache secondResultNativeHookCache(nativeHook, 1); + EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); + + expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); + mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_02); + NativeHookCache thirdExpectNativeHookCache(INVALID_UINT64, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + TIMESTAMP_03, TIMESTAMP_04, TIMESTAMP_04 - TIMESTAMP_03, MEM_ADDR_02, + MEM_SIZE_02, MEM_SIZE_02, TIMESTAMP_04 - TIMESTAMP_03); + NativeHookCache thirdResultNativeHookCache(nativeHook, 2); + EXPECT_TRUE(thirdExpectNativeHookCache == thirdResultNativeHookCache); + + NativeHookCache fourthExpectNativeHookCache(INVALID_UINT64, expect_ipid, expect_itid, MUNMAPEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_04, 0, 0, MEM_ADDR_02, MEM_SIZE_02, 0, 0); + NativeHookCache fourthResultNativeHookCache(nativeHook, 3); + EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); + + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(4, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); +} + +/** + * @tc.name: ParsePartialMatchedMmapAndMunmapEvent + * @tc.desc: Parse a BatchNativeHookData with partial matched Mmap and MunmapEvent + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParsePartialMatchedMmapAndMunmapEvent, TestSize.Level1) +{ + TS_LOGI("test24-17"); + // construct AllocEvent + MmapEvent* firstMmapEvent = new MmapEvent(); + firstMmapEvent->set_pid(PID); + firstMmapEvent->set_tid(TID_01); + firstMmapEvent->set_addr(MEM_ADDR_01); + firstMmapEvent->set_size(MEM_SIZE_01); + firstMmapEvent->set_type(MMAP_SUB_TYPE_01); + MmapEvent* secondMmapEvent = new MmapEvent(); + secondMmapEvent->set_pid(PID); + secondMmapEvent->set_tid(TID_02); + secondMmapEvent->set_addr(MEM_ADDR_02); + secondMmapEvent->set_size(MEM_SIZE_02); + secondMmapEvent->set_type(MMAP_SUB_TYPE_02); + + // construct first MunmapEvent + MunmapEvent* firstMunmapEvent = new MunmapEvent(); + firstMunmapEvent->set_pid(PID); + firstMunmapEvent->set_tid(TID_01); + firstMunmapEvent->set_addr(MEM_ADDR_01); + firstMunmapEvent->set_size(MEM_SIZE_01); + MunmapEvent* secondMunmapEvent = new MunmapEvent(); + secondMunmapEvent->set_pid(PID); + secondMunmapEvent->set_tid(TID_02); + secondMunmapEvent->set_addr(MEM_ADDR_03); + secondMunmapEvent->set_size(MEM_SIZE_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto firstNativeHookMmapData = batchNativeHookData->add_events(); + firstNativeHookMmapData->set_tv_sec(TV_SEC_01); + firstNativeHookMmapData->set_tv_nsec(TV_NSEC_01); + firstNativeHookMmapData->set_allocated_mmap_event(firstMmapEvent); + auto firstNativeHookMunmapData = batchNativeHookData->add_events(); + firstNativeHookMunmapData->set_tv_sec(TV_SEC_02); + firstNativeHookMunmapData->set_tv_nsec(TV_NSEC_02); + firstNativeHookMunmapData->set_allocated_munmap_event(firstMunmapEvent); + auto secondNativeHookMmapData = batchNativeHookData->add_events(); + secondNativeHookMmapData->set_tv_sec(TV_SEC_03); + secondNativeHookMmapData->set_tv_nsec(TV_NSEC_03); + secondNativeHookMmapData->set_allocated_mmap_event(secondMmapEvent); + auto secondNativeHookMunmapData = batchNativeHookData->add_events(); + secondNativeHookMunmapData->set_tv_sec(TV_SEC_04); + secondNativeHookMunmapData->set_tv_nsec(TV_NSEC_04); + secondNativeHookMunmapData->set_allocated_munmap_event(secondMunmapEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + auto mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_01); + NativeHookCache firstExpectNativeHookCache(INVALID_UINT64, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + TIMESTAMP_01, TIMESTAMP_02, TIMESTAMP_02 - TIMESTAMP_01, MEM_ADDR_01, + MEM_SIZE_01, MEM_SIZE_01, TIMESTAMP_02 - TIMESTAMP_01); + NativeHookCache firstResultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(firstExpectNativeHookCache == firstResultNativeHookCache); + + NativeHookCache secondExpectNativeHookCache(INVALID_UINT64, expect_ipid, expect_itid, MUNMAPEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_02, 0, 0, MEM_ADDR_01, MEM_SIZE_01, 0, + TIMESTAMP_03 - TIMESTAMP_02); + NativeHookCache secondResultNativeHookCache(nativeHook, 1); + EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); + + expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); + mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_02); + NativeHookCache thirdExpectNativeHookCache(INVALID_UINT64, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + TIMESTAMP_03, 0, 0, MEM_ADDR_02, MEM_SIZE_02, MEM_SIZE_02, 0); + NativeHookCache thirdResultNativeHookCache(nativeHook, 2); + EXPECT_TRUE(thirdExpectNativeHookCache == thirdResultNativeHookCache); + + NativeHookCache fourthExpectNativeHookCache(INVALID_UINT64, expect_ipid, expect_itid, MUNMAPEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_04, 0, 0, MEM_ADDR_03, MEM_SIZE_02, MEM_SIZE_02, 0); + NativeHookCache fourthResultNativeHookCache(nativeHook, 3); + EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); + + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(3, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(2 == eventCount); +} + +/** + * @tc.name: ParseBatchNativeHookWithAllTypesEvents + * @tc.desc: Parse a BatchNativeHookData with one pairs Mmap and MunmapEvent and one pairs Malloc and Free + * @tc.type: FUNC + */ +HWTEST_F(NativeHookParserTest, ParseBatchNativeHookWithAllTypesEvents, TestSize.Level1) +{ + TS_LOGI("test24-18"); + // construct MmapEvent + MmapEvent* mmapEvent = new MmapEvent(); + mmapEvent->set_pid(PID); + mmapEvent->set_tid(TID_01); + mmapEvent->set_addr(MEM_ADDR_01); + mmapEvent->set_size(MEM_SIZE_01); + mmapEvent->set_type(MMAP_SUB_TYPE_01); + // construct MmapEvent's Frame + auto mmapframe = mmapEvent->add_frame_info(); + mmapframe->set_ip(CALL_STACK_IP_01); + mmapframe->set_sp(CALL_STACK_SP_01); + mmapframe->set_symbol_name(SYMBOL_NAME_01); + mmapframe->set_file_path(FILE_PATH_01); + mmapframe->set_offset(OFFSET_01); + mmapframe->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct MunmapEvent + MunmapEvent* munmapEvent = new MunmapEvent(); + munmapEvent->set_pid(PID); + munmapEvent->set_tid(TID_01); + munmapEvent->set_addr(MEM_ADDR_01); + munmapEvent->set_size(MEM_SIZE_01); + // construct MunmapEvent's Frame + auto munmapframe = munmapEvent->add_frame_info(); + munmapframe->set_ip(CALL_STACK_IP_01); + munmapframe->set_sp(CALL_STACK_SP_01); + munmapframe->set_symbol_name(SYMBOL_NAME_01); + munmapframe->set_file_path(FILE_PATH_01); + munmapframe->set_offset(OFFSET_01); + munmapframe->set_symbol_offset(SYMBOL_OFFSET_01); + + // construct AllocEvent + AllocEvent* allocEvent = new AllocEvent(); + allocEvent->set_pid(PID); + allocEvent->set_tid(TID_02); + allocEvent->set_addr(MEM_ADDR_02); + allocEvent->set_size(MEM_SIZE_02); + // construct AllocEvent's Frame + auto allocframe = allocEvent->add_frame_info(); + allocframe->set_ip(CALL_STACK_IP_02); + allocframe->set_sp(CALL_STACK_SP_02); + allocframe->set_symbol_name(SYMBOL_NAME_02); + allocframe->set_file_path(FILE_PATH_02); + allocframe->set_offset(OFFSET_02); + allocframe->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct FreeEvent + FreeEvent* freeEvent = new FreeEvent(); + freeEvent->set_pid(PID); + freeEvent->set_tid(TID_02); + freeEvent->set_addr(MEM_ADDR_02); + // construct FreeEvent's Frame + auto freeframe = freeEvent->add_frame_info(); + freeframe->set_ip(CALL_STACK_IP_02); + freeframe->set_sp(CALL_STACK_SP_02); + freeframe->set_symbol_name(SYMBOL_NAME_02); + freeframe->set_file_path(FILE_PATH_02); + freeframe->set_offset(OFFSET_02); + freeframe->set_symbol_offset(SYMBOL_OFFSET_02); + + // construct BatchNativeHookData + BatchNativeHookData* batchNativeHookData = new BatchNativeHookData(); + + // add NativeHookData + auto nativeHookMmapData = batchNativeHookData->add_events(); + nativeHookMmapData->set_tv_sec(TV_SEC_01); + nativeHookMmapData->set_tv_nsec(TV_NSEC_01); + nativeHookMmapData->set_allocated_mmap_event(mmapEvent); + auto nativeHookMunmapData = batchNativeHookData->add_events(); + nativeHookMunmapData->set_tv_sec(TV_SEC_02); + nativeHookMunmapData->set_tv_nsec(TV_NSEC_02); + nativeHookMunmapData->set_allocated_munmap_event(munmapEvent); + auto nativeHookAllocData = batchNativeHookData->add_events(); + nativeHookAllocData->set_tv_sec(TV_SEC_03); + nativeHookAllocData->set_tv_nsec(TV_NSEC_03); + nativeHookAllocData->set_allocated_alloc_event(allocEvent); + auto nativeHookFreeData = batchNativeHookData->add_events(); + nativeHookFreeData->set_tv_sec(TV_SEC_04); + nativeHookFreeData->set_tv_nsec(TV_NSEC_04); + nativeHookFreeData->set_allocated_free_event(freeEvent); + + // start parse + HtraceNativeHookParser htraceNativeHookParser(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + htraceNativeHookParser.SortNativeHookData(*batchNativeHookData); + htraceNativeHookParser.FinishParseNativeHookData(); + + // Verification parse NativeHook results + const NativeHook& nativeHook = stream_.traceDataCache_->GetConstNativeHookData(); + auto expect_ipid = stream_.streamFilters_->processFilter_->GetInternalPid(PID); + auto expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_01); + auto mmapSubType = stream_.traceDataCache_->dataDict_.GetStringIndex(MMAP_SUB_TYPE_01); + NativeHookCache firstExpectNativeHookCache(1, expect_ipid, expect_itid, MMAPEVENT.c_str(), mmapSubType, + TIMESTAMP_01, TIMESTAMP_02, TIMESTAMP_02 - TIMESTAMP_01, MEM_ADDR_01, + MEM_SIZE_01, MEM_SIZE_01, TIMESTAMP_02 - TIMESTAMP_01); + NativeHookCache firstResultNativeHookCache(nativeHook, 0); + EXPECT_TRUE(firstExpectNativeHookCache == firstResultNativeHookCache); + + NativeHookCache secondExpectNativeHookCache(1, expect_ipid, expect_itid, MUNMAPEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_02, 0, 0, MEM_ADDR_01, MEM_SIZE_01, 0, 0); + NativeHookCache secondResultNativeHookCache(nativeHook, 1); + EXPECT_TRUE(secondExpectNativeHookCache == secondResultNativeHookCache); + + expect_itid = stream_.streamFilters_->processFilter_->GetInternalTid(TID_02); + NativeHookCache thirdExpectNativeHookCache(2, expect_ipid, expect_itid, ALLOCEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_03, TIMESTAMP_04, TIMESTAMP_04 - TIMESTAMP_03, MEM_ADDR_02, + MEM_SIZE_02, MEM_SIZE_02, TIMESTAMP_04 - TIMESTAMP_03); + NativeHookCache thirdResultNativeHookCache(nativeHook, 2); + EXPECT_TRUE(thirdExpectNativeHookCache == thirdResultNativeHookCache); + + NativeHookCache fourthExpectNativeHookCache(2, expect_ipid, expect_itid, FREEEVENT.c_str(), INVALID_UINT64, + TIMESTAMP_04, 0, 0, MEM_ADDR_02, MEM_SIZE_02, 0, 0); + NativeHookCache fourthResultNativeHookCache(nativeHook, 3); + EXPECT_TRUE(fourthExpectNativeHookCache == fourthResultNativeHookCache); + + auto size = stream_.traceDataCache_->GetConstNativeHookData().Size(); + EXPECT_EQ(4, size); + + auto eventCount = + stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MUNMAP, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_MALLOC, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_NATIVE_HOOK_FREE, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); +} +} // namespace TraceStreamer +} // namespace SysTuning \ No newline at end of file diff --git a/host/trace_streamer/test/unittest/paged_memory_parser_test.cpp b/host/trace_streamer/test/unittest/paged_memory_parser_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..9ebd7288b171e77d1f2f6618f7fdf4d7c0194cba --- /dev/null +++ b/host/trace_streamer/test/unittest/paged_memory_parser_test.cpp @@ -0,0 +1,289 @@ + +/* + * 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. + */ +#include +#include +#include "paged_memory_data_parser.h" +#include "cpu_filter.h" +#include "ebpf_data_parser.h" +#include "ebpf_stdtype.h" +#include "process_filter.h" +#include "trace_streamer_selector.h" +#include "ts_common.h" +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +using namespace SysTuning::EbpfStdtype; +namespace SysTuning ::TraceStreamer { +const std::string COMMAND_LINE = "hiebpf --events ptrace --duration 50"; +class EbpfPagedMemoryParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} + +public: + TraceStreamerSelector stream_ = {}; +}; +const uint64_t START_TIME = 1725645867369; +const uint64_t END_TIME = 1725645967369; +const uint64_t PAGEED_MEM_ADDR = 46549876; +const uint64_t IPS_01 = 548606407208; +const uint64_t IPS_02 = 548607407208; +const uint64_t EBPF_COMMAND_MAX_SIZE = 1000; +/** + * @tc.name: EbpfPagedMemoryParserCorrectWithoutCallback + * @tc.desc: Test parse PagedMem data without callback + * @tc.type: FUNC + */ +HWTEST_F(EbpfPagedMemoryParserTest, EbpfPagedMemoryParserCorrectWithoutCallback, TestSize.Level1) +{ + TS_LOGI("test31-1"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = COMMAND_LINE.length(); + memcpy_s(ebpfHeader.cmdline, EBPF_COMMAND_MAX_SIZE, COMMAND_LINE.c_str(), COMMAND_LINE.length()); + std::deque dequeBuffer; + dequeBuffer.insert(dequeBuffer.end(), &(reinterpret_cast(&ebpfHeader))[0], + &(reinterpret_cast(&ebpfHeader))[EbpfDataHeader::EBPF_DATA_HEADER_SIZE]); + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(PagedMemoryFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_VM; + PagedMemoryFixedHeader pagedMemoryFixedHeader; + pagedMemoryFixedHeader.pid = 32; + pagedMemoryFixedHeader.tid = 32; + memcpy_s(pagedMemoryFixedHeader.comm, MAX_PROCESS_NAME_SZIE, "process", MAX_PROCESS_NAME_SZIE); + pagedMemoryFixedHeader.startTime = START_TIME; + pagedMemoryFixedHeader.endTime = END_TIME; + pagedMemoryFixedHeader.addr = PAGEED_MEM_ADDR; + pagedMemoryFixedHeader.size = 1; + pagedMemoryFixedHeader.nips = 0; + pagedMemoryFixedHeader.type = 2; + dequeBuffer.insert(dequeBuffer.end(), &(reinterpret_cast(&ebpfTypeAndLength))[0], + &(reinterpret_cast(&ebpfTypeAndLength))[sizeof(EbpfTypeAndLength)]); + dequeBuffer.insert(dequeBuffer.end(), &(reinterpret_cast(&pagedMemoryFixedHeader))[0], + &(reinterpret_cast(&pagedMemoryFixedHeader))[sizeof(PagedMemoryFixedHeader)]); + + std::unique_ptr ebpfDataParser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(ebpfDataParser->reader_->GetPagedMemoryMap().size()); + ebpfDataParser->ParsePagedMemoryEvent(); + ebpfDataParser->Finish(); + EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstPagedMemorySampleData().CallChainIds()[0]; + EXPECT_EQ(callChainId, INVALID_UINT64); + auto type = stream_.traceDataCache_->GetConstPagedMemorySampleData().Types()[0]; + EXPECT_EQ(type, 2); + + auto startTs = stream_.traceDataCache_->GetConstPagedMemorySampleData().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME); + auto endTs = stream_.traceDataCache_->GetConstPagedMemorySampleData().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME); + auto dur = stream_.traceDataCache_->GetConstPagedMemorySampleData().Durs()[0]; + EXPECT_EQ(dur, END_TIME - START_TIME); + auto size = stream_.traceDataCache_->GetConstPagedMemorySampleData().Sizes()[0]; + EXPECT_EQ(size, 1); + auto ExpectAddr = ebpfDataParser->ConvertToHexTextIndex(pagedMemoryFixedHeader.addr); + auto addr = stream_.traceDataCache_->GetConstPagedMemorySampleData().Addr()[0]; + EXPECT_EQ(addr, ExpectAddr); +} + +/** + * @tc.name: EbpfPagedMemoryParserwrongWithoutCallback + * @tc.desc: Test parse pagedMem data without callback and startTs > endTs + * @tc.type: FUNC + */ +HWTEST_F(EbpfPagedMemoryParserTest, EbpfPagedMemoryParserwrongWithoutCallback, TestSize.Level1) +{ + TS_LOGI("test31-2"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = COMMAND_LINE.length(); + memcpy_s(ebpfHeader.cmdline, EBPF_COMMAND_MAX_SIZE, COMMAND_LINE.c_str(), COMMAND_LINE.length()); + std::deque dequeBuffer; + dequeBuffer.insert(dequeBuffer.end(), &(reinterpret_cast(&ebpfHeader))[0], + &(reinterpret_cast(&ebpfHeader))[EbpfDataHeader::EBPF_DATA_HEADER_SIZE]); + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(PagedMemoryFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_VM; + PagedMemoryFixedHeader pagedMemoryFixedHeader; + pagedMemoryFixedHeader.pid = 32; + pagedMemoryFixedHeader.tid = 32; + memcpy_s(pagedMemoryFixedHeader.comm, MAX_PROCESS_NAME_SZIE, "process", MAX_PROCESS_NAME_SZIE); + pagedMemoryFixedHeader.startTime = END_TIME; + pagedMemoryFixedHeader.endTime = START_TIME; + pagedMemoryFixedHeader.addr = PAGEED_MEM_ADDR; + pagedMemoryFixedHeader.size = 1; + pagedMemoryFixedHeader.nips = 0; + pagedMemoryFixedHeader.type = 2; + dequeBuffer.insert(dequeBuffer.end(), &(reinterpret_cast(&ebpfTypeAndLength))[0], + &(reinterpret_cast(&ebpfTypeAndLength))[sizeof(EbpfTypeAndLength)]); + dequeBuffer.insert(dequeBuffer.end(), &(reinterpret_cast(&pagedMemoryFixedHeader))[0], + &(reinterpret_cast(&pagedMemoryFixedHeader))[sizeof(PagedMemoryFixedHeader)]); + + std::unique_ptr ebpfDataParser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(ebpfDataParser->reader_->GetPagedMemoryMap().size()); + ebpfDataParser->ParsePagedMemoryEvent(); + ebpfDataParser->Finish(); + EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstPagedMemorySampleData().CallChainIds()[0]; + EXPECT_FALSE(callChainId == INVALID_UINT64); + auto type = stream_.traceDataCache_->GetConstPagedMemorySampleData().Types()[0]; + EXPECT_FALSE(type == 2); + + auto startTs = stream_.traceDataCache_->GetConstPagedMemorySampleData().StartTs()[0]; + EXPECT_FALSE(startTs == pagedMemoryFixedHeader.startTime); + auto endTs = stream_.traceDataCache_->GetConstPagedMemorySampleData().EndTs()[0]; + EXPECT_FALSE(endTs == pagedMemoryFixedHeader.endTime); + auto dur = stream_.traceDataCache_->GetConstPagedMemorySampleData().Durs()[0]; + EXPECT_FALSE(dur == endTs - startTs); + auto size = stream_.traceDataCache_->GetConstPagedMemorySampleData().Sizes()[0]; + EXPECT_FALSE(size == 1); + auto ExpectAddr = ebpfDataParser->ConvertToHexTextIndex(pagedMemoryFixedHeader.addr); + auto addr = stream_.traceDataCache_->GetConstPagedMemorySampleData().Addr()[0]; + EXPECT_FALSE(addr == ExpectAddr); +} + +/** + * @tc.name: EbpfPagedMemoryParserCorrectWithOneCallback + * @tc.desc: Test parse PagedMem data with one callback + * @tc.type: FUNC + */ +HWTEST_F(EbpfPagedMemoryParserTest, EbpfPagedMemoryParserCorrectWithOneCallback, TestSize.Level1) +{ + TS_LOGI("test31-3"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = COMMAND_LINE.length(); + memcpy_s(ebpfHeader.cmdline, EBPF_COMMAND_MAX_SIZE, COMMAND_LINE.c_str(), COMMAND_LINE.length()); + std::deque dequeBuffer; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(PagedMemoryFixedHeader); + ebpfTypeAndLength.type = ITEM_EVENT_VM; + PagedMemoryFixedHeader pagedMemoryFixedHeader; + pagedMemoryFixedHeader.pid = 32; + pagedMemoryFixedHeader.tid = 32; + memcpy_s(pagedMemoryFixedHeader.comm, MAX_PROCESS_NAME_SZIE, "process", MAX_PROCESS_NAME_SZIE); + pagedMemoryFixedHeader.startTime = START_TIME; + pagedMemoryFixedHeader.endTime = END_TIME; + pagedMemoryFixedHeader.addr = PAGEED_MEM_ADDR; + pagedMemoryFixedHeader.size = 1; + pagedMemoryFixedHeader.nips = 1; + pagedMemoryFixedHeader.type = 2; + const uint64_t ips[1] = {IPS_01}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&pagedMemoryFixedHeader), + reinterpret_cast(&pagedMemoryFixedHeader + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(ips), + reinterpret_cast(&ips + 1)); + std::unique_ptr ebpfDataParser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(ebpfDataParser->reader_->GetPagedMemoryMap().size()); + ebpfDataParser->ParsePagedMemoryEvent(); + ebpfDataParser->Finish(); + EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstPagedMemorySampleData().CallChainIds()[0]; + EXPECT_EQ(callChainId, 0); + auto type = stream_.traceDataCache_->GetConstPagedMemorySampleData().Types()[0]; + EXPECT_EQ(type, 2); + auto startTs = stream_.traceDataCache_->GetConstPagedMemorySampleData().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME); + auto endTs = stream_.traceDataCache_->GetConstPagedMemorySampleData().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME); + auto dur = stream_.traceDataCache_->GetConstPagedMemorySampleData().Durs()[0]; + EXPECT_EQ(dur, END_TIME - START_TIME); + auto size = stream_.traceDataCache_->GetConstPagedMemorySampleData().Sizes()[0]; + EXPECT_EQ(size, 1); + auto ExpectAddr = ebpfDataParser->ConvertToHexTextIndex(pagedMemoryFixedHeader.addr); + auto addr = stream_.traceDataCache_->GetConstPagedMemorySampleData().Addr()[0]; + EXPECT_EQ(addr, ExpectAddr); + auto ExpectIps0 = ebpfDataParser->ConvertToHexTextIndex(ips[0]); + auto ips0 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[0]; + EXPECT_EQ(ips0, ExpectIps0); +} + +/** + * @tc.name: EbpfPagedMemoryParserCorrectWithMultipleCallback + * @tc.desc: Test parse PagedMem data with Multiple callback + * @tc.type: FUNC + */ +HWTEST_F(EbpfPagedMemoryParserTest, EbpfPagedMemoryParserCorrectWithMultipleCallback, TestSize.Level1) +{ + TS_LOGI("test31-4"); + EbpfDataHeader ebpfHeader; + ebpfHeader.header.clock = EBPF_CLOCK_BOOTTIME; + ebpfHeader.header.cmdLineLen = COMMAND_LINE.length(); + memcpy_s(ebpfHeader.cmdline, EBPF_COMMAND_MAX_SIZE, COMMAND_LINE.c_str(), COMMAND_LINE.length()); + std::deque dequeBuffer; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfHeader), + reinterpret_cast(&ebpfHeader + 1)); + EbpfTypeAndLength ebpfTypeAndLength; + ebpfTypeAndLength.length = sizeof(PagedMemoryFixedHeader) + 2 * sizeof(uint64_t); + ebpfTypeAndLength.type = ITEM_EVENT_VM; + PagedMemoryFixedHeader pagedMemoryFixedHeader; + pagedMemoryFixedHeader.pid = 32; + pagedMemoryFixedHeader.tid = 32; + memcpy_s(pagedMemoryFixedHeader.comm, MAX_PROCESS_NAME_SZIE, "process", MAX_PROCESS_NAME_SZIE); + pagedMemoryFixedHeader.startTime = START_TIME; + pagedMemoryFixedHeader.endTime = END_TIME; + pagedMemoryFixedHeader.addr = PAGEED_MEM_ADDR; + pagedMemoryFixedHeader.size = 1; + pagedMemoryFixedHeader.nips = 2; + pagedMemoryFixedHeader.type = 2; + const uint64_t ips[2] = {IPS_01, IPS_02}; + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&ebpfTypeAndLength), + reinterpret_cast(&ebpfTypeAndLength + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(&pagedMemoryFixedHeader), + reinterpret_cast(&pagedMemoryFixedHeader + 1)); + dequeBuffer.insert(dequeBuffer.end(), reinterpret_cast(ips), + reinterpret_cast(&ips + 1)); + std::unique_ptr ebpfDataParser = + std::make_unique(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + EXPECT_TRUE(ebpfDataParser->Init(dequeBuffer, dequeBuffer.size())); + EXPECT_TRUE(ebpfDataParser->reader_->GetPagedMemoryMap().size()); + ebpfDataParser->ParsePagedMemoryEvent(); + ebpfDataParser->Finish(); + EXPECT_TRUE(ebpfDataParser->reader_->ebpfDataHeader_->header.clock == EBPF_CLOCK_BOOTTIME); + auto callChainId = stream_.traceDataCache_->GetConstPagedMemorySampleData().CallChainIds()[0]; + EXPECT_EQ(callChainId, 0); + auto type = stream_.traceDataCache_->GetConstPagedMemorySampleData().Types()[0]; + EXPECT_EQ(type, 2); + auto startTs = stream_.traceDataCache_->GetConstPagedMemorySampleData().StartTs()[0]; + EXPECT_EQ(startTs, START_TIME); + auto endTs = stream_.traceDataCache_->GetConstPagedMemorySampleData().EndTs()[0]; + EXPECT_EQ(endTs, END_TIME); + auto dur = stream_.traceDataCache_->GetConstPagedMemorySampleData().Durs()[0]; + EXPECT_EQ(dur, END_TIME - START_TIME); + auto size = stream_.traceDataCache_->GetConstPagedMemorySampleData().Sizes()[0]; + EXPECT_EQ(size, 1); + auto ExpectAddr = ebpfDataParser->ConvertToHexTextIndex(pagedMemoryFixedHeader.addr); + auto addr = stream_.traceDataCache_->GetConstPagedMemorySampleData().Addr()[0]; + EXPECT_EQ(addr, ExpectAddr); + auto ExpectIps0 = ebpfDataParser->ConvertToHexTextIndex(ips[0]); + auto ips0 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[1]; + EXPECT_EQ(ips0, ExpectIps0); + auto ExpectIps1 = ebpfDataParser->ConvertToHexTextIndex(ips[1]); + auto ips1 = stream_.traceDataCache_->GetConstEbpfCallStackData().Ips()[0]; + EXPECT_EQ(ips1, ExpectIps1); +} +} // namespace SysTuning::TraceStreamer diff --git a/host/trace_streamer/test/unittest/parser_test.cpp b/host/trace_streamer/test/unittest/parser_test.cpp old mode 100644 new mode 100755 index f6511fb83eb82c6528ca4c3e238377ab0be458a5..620aeec10cceacde95641b20cf5cdbadb1cf67e8 --- a/host/trace_streamer/test/unittest/parser_test.cpp +++ b/host/trace_streamer/test/unittest/parser_test.cpp @@ -42,10 +42,10 @@ protected: */ HWTEST_F(ParserTest, BytraceParserTest, TestSize.Level1) { - TS_LOGI("test9-1"); - const std::string tracePath = "/data/resource/ut_bytrace_input_full.txt"; - const std::string utGoldDb = "/data/resource/ut_bytrace_input_full_gold.db"; - const std::string dbPath = "/data/resource/out_db1.db"; + TS_LOGI("test25-1"); + const std::string tracePath = "data/resource/ut_bytrace_input_full.txt"; + const std::string utGoldDb = "data/resource/ut_bytrace_input_full_gold.db"; + const std::string dbPath = "data/resource/out_db1.db"; constexpr size_t readSize = 1024 * 1024; constexpr uint32_t lineLength = 256; @@ -56,7 +56,7 @@ HWTEST_F(ParserTest, BytraceParserTest, TestSize.Level1) ta->SetCleanMode(false); int fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); while (true) { - std::unique_ptr buf = std::make_unique(std::move(readSize)); + std::unique_ptr buf = std::make_unique(readSize); auto rsize = base::Read(fd, buf.get(), readSize); if (rsize == 0) { break; @@ -83,7 +83,7 @@ HWTEST_F(ParserTest, BytraceParserTest, TestSize.Level1) FILE* file2 = nullptr; char line1[lineLength]; char line2[lineLength]; - const std::string command1 = "md5sum /data/resource/ut_bytrace_input_full_gold.db"; + const std::string command1 = "md5sum data/resource/ut_bytrace_input_full_gold.db"; const std::string md5DbPath = "md5sum "+ dbPath; file1 = popen(command1.c_str(), "r"); file2 = popen(md5DbPath.c_str(), "r"); @@ -112,10 +112,10 @@ HWTEST_F(ParserTest, BytraceParserTest, TestSize.Level1) */ HWTEST_F(ParserTest, HtraceParserTest, TestSize.Level1) { - TS_LOGI("test9-2"); - const std::string tracePath = "/data/resource/htrace.bin"; - const std::string utGoldDb = "/data/resource/htrace_gold.db"; - const std::string dbPath = "/data/resource/out_db2.db"; + TS_LOGI("test25-2"); + const std::string tracePath = "data/resource/htrace.bin"; + const std::string utGoldDb = "data/resource/htrace_gold.db"; + const std::string dbPath = "data/resource/out_db2.db"; constexpr size_t readSize = 1024; constexpr uint32_t lineLength = 256; @@ -126,7 +126,7 @@ HWTEST_F(ParserTest, HtraceParserTest, TestSize.Level1) ta->SetCleanMode(false); int fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); while (true) { - std::unique_ptr buf = std::make_unique(std::move(readSize)); + std::unique_ptr buf = std::make_unique(readSize); auto rsize = base::Read(fd, buf.get(), readSize); if (rsize == 0) { @@ -154,7 +154,149 @@ HWTEST_F(ParserTest, HtraceParserTest, TestSize.Level1) FILE* file2 = nullptr; char line1[lineLength]; char line2[lineLength]; - const std::string command1 = "md5sum /data/resource/htrace_gold.db"; + const std::string command1 = "md5sum data/resource/htrace_gold.db"; + const std::string md5DbPath = "md5sum "+ dbPath; + file1 = popen(command1.c_str(), "r"); + file2 = popen(md5DbPath.c_str(), "r"); + if (file1 && file2) { + if (fgets(line1, lineLength, file1) != nullptr && fgets(line2, lineLength, file2) != nullptr) { + std::string str1(line1); + std::string str2(line2); + str1 = str1.substr(0, str1.find_first_of(' ')); + str2 = str2.substr(0, str2.find_first_of(' ')); + EXPECT_TRUE(str1.compare(str2) == 0); + } + } + } else { + EXPECT_TRUE(false); + } + + if (access(dbPath.c_str(), F_OK) == 0) { + remove(dbPath.c_str()); + } +} + +/** + * @tc.name: HtraceAndPerfParserTest + * @tc.desc: Test parsing htrace and perf binary file export database + * @tc.type: FUNC + */ +HWTEST_F(ParserTest, HtraceAndPerfParserTest, TestSize.Level1) +{ + TS_LOGI("test25-3"); + const std::string tracePath = "data/resource/htrace_perf.bin"; + const std::string utGoldDb = "data/resource/htrace_perf_gold.db"; + const std::string dbPath = "data/resource/out_db3.db"; + constexpr size_t readSize = 1024; + constexpr uint32_t lineLength = 256; + + if (access(tracePath.c_str(), F_OK) == 0) { + std::unique_ptr ta = + std::make_unique(); + ta->EnableMetaTable(false); + ta->SetCleanMode(false); + int fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); + while (true) { + std::unique_ptr buf = std::make_unique(readSize); + auto rsize = base::Read(fd, buf.get(), readSize); + + if (rsize == 0) { + break; + } + if (rsize < 0) { + TS_LOGD("Reading trace file over (errno: %d, %s)", errno, strerror(errno)); + break; + } + if (!ta->ParseTraceDataSegment(std::move(buf), rsize)) { + break; + }; + } + ta->WaitForParserEnd(); + close(fd); + ta->ExportDatabase(dbPath); + ta->Clear(); + EXPECT_TRUE(access(dbPath.c_str(), F_OK) == 0); + } else { + EXPECT_TRUE(false); + } + + if (access(utGoldDb.c_str(), F_OK) == 0) { + FILE* file1 = nullptr; + FILE* file2 = nullptr; + char line1[lineLength]; + char line2[lineLength]; + const std::string command1 = "md5sum data/resource/htrace_perf_gold.db"; + const std::string md5DbPath = "md5sum "+ dbPath; + file1 = popen(command1.c_str(), "r"); + file2 = popen(md5DbPath.c_str(), "r"); + if (file1 && file2) { + if (fgets(line1, lineLength, file1) != nullptr && fgets(line2, lineLength, file2) != nullptr) { + std::string str1(line1); + std::string str2(line2); + str1 = str1.substr(0, str1.find_first_of(' ')); + str2 = str2.substr(0, str2.find_first_of(' ')); + EXPECT_TRUE(str1.compare(str2) == 0); + } + } + } else { + EXPECT_TRUE(false); + } + + if (access(dbPath.c_str(), F_OK) == 0) { + remove(dbPath.c_str()); + } +} + +/** + * @tc.name: HtraceAndEbpfParserTest + * @tc.desc: Test parsing htrace and ebpf binary file export database + * @tc.type: FUNC + */ +HWTEST_F(ParserTest, HtraceAndEbpfParserTest, TestSize.Level1) +{ + TS_LOGI("test25-4"); + const std::string tracePath = "data/resource/htrace_ebpf.bin"; + const std::string utGoldDb = "data/resource/htrace_ebpf_gold.db"; + const std::string dbPath = "data/resource/out_db4.db"; + constexpr size_t readSize = 1024; + constexpr uint32_t lineLength = 256; + + if (access(tracePath.c_str(), F_OK) == 0) { + std::unique_ptr ta = + std::make_unique(); + ta->EnableMetaTable(false); + ta->SetCleanMode(false); + int fd(base::OpenFile(tracePath, O_RDONLY, G_FILE_PERMISSION)); + while (true) { + std::unique_ptr buf = std::make_unique(readSize); + auto rsize = base::Read(fd, buf.get(), readSize); + + if (rsize == 0) { + break; + } + if (rsize < 0) { + TS_LOGD("Reading trace file over (errno: %d, %s)", errno, strerror(errno)); + break; + } + if (!ta->ParseTraceDataSegment(std::move(buf), rsize)) { + break; + }; + } + ta->WaitForParserEnd(); + close(fd); + ta->ExportDatabase(dbPath); + ta->Clear(); + EXPECT_TRUE(access(dbPath.c_str(), F_OK) == 0); + } else { + EXPECT_TRUE(false); + } + + if (access(utGoldDb.c_str(), F_OK) == 0) { + FILE* file1 = nullptr; + FILE* file2 = nullptr; + char line1[lineLength]; + char line2[lineLength]; + const std::string command1 = "md5sum data/resource/htrace_ebpf_gold.db"; const std::string md5DbPath = "md5sum "+ dbPath; file1 = popen(command1.c_str(), "r"); file2 = popen(md5DbPath.c_str(), "r"); diff --git a/host/trace_streamer/test/unittest/process_filter_test.cpp b/host/trace_streamer/test/unittest/process_filter_test.cpp old mode 100644 new mode 100755 index db31d5eb6d3808d8cb6fc04ba17995904452ca3d..efe47b4d98039942cf839f9d3741430abe2f3bc6 --- a/host/trace_streamer/test/unittest/process_filter_test.cpp +++ b/host/trace_streamer/test/unittest/process_filter_test.cpp @@ -43,22 +43,21 @@ public: */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThread, TestSize.Level1) { - TS_LOGI("test10-1"); + TS_LOGI("test26-1"); uint64_t ts = 168758662877000; - uint32_t tid = 2716; - uint32_t iTid0 = streamFilters_.processFilter_->UpdateOrCreateThread(ts, tid); + uint32_t tid0 = 2716; + uint32_t iTid0 = streamFilters_.processFilter_->UpdateOrCreateThread(ts, tid0); EXPECT_TRUE(iTid0 == 1); - uint32_t tid2 = 2519; - uint32_t iTid1 = streamFilters_.processFilter_->UpdateOrCreateThread(0, 2519); + uint32_t tid1 = 2519; + uint32_t iTid1 = streamFilters_.processFilter_->UpdateOrCreateThread(0, tid1); EXPECT_TRUE(iTid1 == 2); Thread* thread = traceDataCache_.GetThreadData(iTid0); - EXPECT_TRUE(thread->tid_ == tid); + EXPECT_TRUE(thread->tid_ == tid0); thread = traceDataCache_.GetThreadData(iTid1); - EXPECT_TRUE(thread->tid_ == tid2); - EXPECT_TRUE(thread->internalPid_ == 0); + EXPECT_TRUE(thread->tid_ == tid1); } /** @@ -68,21 +67,21 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThread, TestSize.Level1) */ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithName, TestSize.Level1) { - TS_LOGI("test10-2"); - uint32_t pid = 8629; + TS_LOGI("test26-2"); + uint32_t pid0 = 8629; std::string_view processName = "RenderThread"; - uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); + uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid0, processName); EXPECT_TRUE(iPid0 == 1); - uint32_t pid2 = 8709; - uint32_t iPid1 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid2, processName); + uint32_t pid1 = 8709; + uint32_t iPid1 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid1, processName); EXPECT_TRUE(iPid1 == 2); Process* process = traceDataCache_.GetProcessData(iPid0); - EXPECT_TRUE(process->pid_ == pid); + EXPECT_TRUE(process->pid_ == pid0); process = traceDataCache_.GetProcessData(iPid1); - EXPECT_TRUE(process->pid_ == pid2); + EXPECT_TRUE(process->pid_ == pid1); } /** @@ -92,7 +91,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithName, TestSize.Level1) */ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameSingleIpid, TestSize.Level1) { - TS_LOGI("test10-3"); + TS_LOGI("test26-3"); uint32_t pid = 8629; std::string_view processName = "RenderThread"; uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); @@ -106,14 +105,14 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameSingleIpid, TestSize.Le */ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameMultiIpid, TestSize.Level1) { - TS_LOGI("test10-4"); - uint32_t pid = 8629; + TS_LOGI("test26-4"); + uint32_t pid0 = 8629; std::string_view processName = "RenderThread"; - uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); + uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid0, processName); EXPECT_TRUE(iPid0 == 1); - uint32_t pid2 = 8709; - uint32_t iPid1 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid2, processName); + uint32_t pid1 = 8709; + uint32_t iPid1 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid1, processName); EXPECT_TRUE(iPid1 == 2); } @@ -124,7 +123,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameMultiIpid, TestSize.Lev */ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameSinglePid, TestSize.Level1) { - TS_LOGI("test10-5"); + TS_LOGI("test26-5"); uint32_t pid = 8629; std::string_view processName = "RenderThread"; uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); @@ -141,14 +140,14 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameSinglePid, TestSize.Lev */ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameMultiPid, TestSize.Level1) { - TS_LOGI("test10-6"); - uint32_t pid = 8629; + TS_LOGI("test26-6"); + uint32_t pid0 = 8629; std::string_view processName = "RenderThread"; - uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid, processName); + uint32_t iPid0 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid0, processName); EXPECT_TRUE(iPid0 == 1); - uint32_t pid2 = 8709; - uint32_t iPid1 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid2, processName); + uint32_t pid1 = 8709; + uint32_t iPid1 = streamFilters_.processFilter_->UpdateOrCreateProcessWithName(pid1, processName); EXPECT_TRUE(iPid1 == 2); uint32_t pid3 = 87091; @@ -156,10 +155,10 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameMultiPid, TestSize.Leve EXPECT_TRUE(iPid2 == 3); Process* process = traceDataCache_.GetProcessData(iPid0); - EXPECT_TRUE(process->pid_ == pid); + EXPECT_TRUE(process->pid_ == pid0); process = traceDataCache_.GetProcessData(iPid1); - EXPECT_TRUE(process->pid_ == pid2); + EXPECT_TRUE(process->pid_ == pid1); process = traceDataCache_.GetProcessData(iPid2); EXPECT_TRUE(process->pid_ == pid3); @@ -172,7 +171,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateProcessWithNameMultiPid, TestSize.Leve */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithName, TestSize.Level1) { - TS_LOGI("test10-7"); + TS_LOGI("test26-7"); uint64_t ts = 168758662957020; uint32_t tid = 123; std::string_view threadName = "RenderThread"; @@ -190,7 +189,6 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithName, TestSize.Level1) thread = traceDataCache_.GetThreadData(iTid1); EXPECT_TRUE(thread->tid_ == tid2); - EXPECT_TRUE(thread->internalPid_ == 0); EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName2)); } @@ -201,7 +199,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithName, TestSize.Level1) */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameSingleItid, TestSize.Level1) { - TS_LOGI("test10-8"); + TS_LOGI("test26-8"); uint64_t ts = 168758662957020; uint32_t tid = 123; std::string_view threadName = "RenderThread"; @@ -216,7 +214,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameSingleItid, TestSize.Lev */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameGenarateTidAndItid, TestSize.Level1) { - TS_LOGI("test10-9"); + TS_LOGI("test26-9"); uint64_t ts = 168758662957020; uint32_t tid = 123; std::string_view threadName = "RenderThread2"; @@ -228,13 +226,13 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameGenarateTidAndItid, Test } /** - * @tc.name: UpdateOrCreateThreadWithNameMultiItid + * @tc.name: UpdateOrCreateThreadWithNameDoubleItid * @tc.desc: Test genarate double itid with UpdateOrCreateThreadWithName interface * @tc.type: FUNC */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameDoubleItid, TestSize.Level1) { - TS_LOGI("test10-10"); + TS_LOGI("test26-10"); uint64_t ts = 168758662957020; uint32_t tid = 123; std::string_view threadName = "RenderThread"; @@ -247,7 +245,6 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameDoubleItid, TestSize.Lev EXPECT_TRUE(iTid1 == 2); auto thread = traceDataCache_.GetThreadData(iTid1); EXPECT_TRUE(thread->tid_ == tid2); - EXPECT_TRUE(thread->internalPid_ == 0); EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName2)); } @@ -258,7 +255,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameDoubleItid, TestSize.Lev */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameTripleItid, TestSize.Level1) { - TS_LOGI("test10-11"); + TS_LOGI("test26-11"); uint64_t ts = 168758662957020; uint32_t tid = 123; std::string_view threadName = "RenderThread"; @@ -276,7 +273,6 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameTripleItid, TestSize.Lev EXPECT_TRUE(iTid2 == 3); auto thread = traceDataCache_.GetThreadData(iTid2); EXPECT_TRUE(thread->tid_ == tid3); - EXPECT_TRUE(thread->internalPid_ == 0); EXPECT_TRUE(thread->nameIndex_ == traceDataCache_.GetDataIndex(threadName3)); } @@ -287,7 +283,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithNameTripleItid, TestSize.Lev */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndName, TestSize.Level1) { - TS_LOGI("test10-12"); + TS_LOGI("test26-12"); uint32_t tid = 869; uint32_t pid = 123; std::string_view threadName = "RenderThread"; @@ -306,7 +302,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndName, TestSize.Level1) */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndNameAbnomal, TestSize.Level1) { - TS_LOGI("test10-13"); + TS_LOGI("test26-13"); uint32_t tid = 869; uint32_t pid = 123; std::string_view threadName = "RenderThread"; @@ -323,7 +319,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndNameAbnomal, TestSize. */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndNameSingleItid, TestSize.Level1) { - TS_LOGI("test10-14"); + TS_LOGI("test26-14"); uint32_t tid = 869; uint32_t pid = 123; std::string_view threadName = "RenderThread"; @@ -339,13 +335,13 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndNameSingleItid, TestSi */ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndNameAbnomalPid, TestSize.Level1) { - TS_LOGI("test10-15"); + TS_LOGI("test26-15"); uint32_t tid = 869; - uint32_t pid = 123; + uint32_t pid0 = 123; std::string_view threadName = "RenderThread"; - streamFilters_.processFilter_->UpdateOrCreateThreadWithPidAndName(tid, pid, threadName); - uint32_t pid2 = 124; - auto itid = streamFilters_.processFilter_->GetInternalPid(pid2); + streamFilters_.processFilter_->UpdateOrCreateThreadWithPidAndName(tid, pid0, threadName); + uint32_t pid1 = 124; + auto itid = streamFilters_.processFilter_->GetInternalPid(pid1); EXPECT_TRUE(itid == INVALID_ID); } @@ -356,7 +352,7 @@ HWTEST_F(ProcessFilterTest, UpdateOrCreateThreadWithPidAndNameAbnomalPid, TestSi */ HWTEST_F(ProcessFilterTest, UpdateThreadWithName, TestSize.Level1) { - TS_LOGI("test10-16"); + TS_LOGI("test26-16"); uint32_t tid = 869; uint64_t timestamp = 168758662957020; std::string_view threadName = "RenderThread"; @@ -375,7 +371,7 @@ HWTEST_F(ProcessFilterTest, UpdateThreadWithName, TestSize.Level1) */ HWTEST_F(ProcessFilterTest, UpdateProcessWithName, TestSize.Level1) { - TS_LOGI("test10-17"); + TS_LOGI("test26-17"); uint32_t pid = 869; uint64_t timestamp = 168758662957020; std::string_view processName = "RenderProcess"; diff --git a/host/trace_streamer/test/unittest/rpc_server_test.cpp b/host/trace_streamer/test/unittest/rpc_server_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ea0ad55ee9b943635aecf4945110e8ba82ba1279 --- /dev/null +++ b/host/trace_streamer/test/unittest/rpc_server_test.cpp @@ -0,0 +1,87 @@ +/* + * 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. + */ + +#include +#include + +#include "rpc/rpc_server.h" + +using namespace testing::ext; +namespace SysTuning { +namespace TraceStreamer { +class RpcServerTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} +public: + TraceStreamerSelector stream_ = {}; +}; +std::string g_result; +void res(const std::string result, int finish) +{ + TS_LOGI("%s", result.c_str()); + g_result = result; +} + +/** + * @tc.name: CorrectTraceData + * @tc.desc: Upload correct trace file data + * @tc.type: FUNC + */ +HWTEST_F(RpcServerTest, CorrectTraceData, TestSize.Level1) +{ + TS_LOGI("test27-1"); + std::string PARSERDATA("sugov:0-178 ( 178) [001] .... 28462.257501: cpu_frequency: state=816000 cpu_id=0 \n"); + std::string SQLQUERY("select * from measure;"); + + RpcServer rpcServer; + auto ret = rpcServer.ParseData((const uint8_t*)PARSERDATA.c_str(), PARSERDATA.length(), res); + EXPECT_TRUE(res); + EXPECT_TRUE(ret); + ret = rpcServer.ParseDataOver((const uint8_t*)PARSERDATA.c_str(), PARSERDATA.length(), res); + EXPECT_TRUE(res); + EXPECT_TRUE(ret); + ret = rpcServer.SqlQuery((const uint8_t*)SQLQUERY.c_str(), SQLQUERY.length(), res); + EXPECT_TRUE(res); + EXPECT_TRUE(ret); +} + +/** + * @tc.name: WrongTraceData + * @tc.desc: Upload wrong tracking file data + * @tc.type: FUNC + */ +HWTEST_F(RpcServerTest, WrongTraceData, TestSize.Level1) +{ + TS_LOGI("test27-2"); + std::string PARSERDATA("sugov:0-178 ( 178) [001] .... 28462.277458: cpu_frequency: state=600000 cpu_id=2 \n"); + std::string SQLQUERY("select * from measure_e;"); + + RpcServer rpcServer; + auto ret = rpcServer.ParseData((const uint8_t*)PARSERDATA.c_str(), PARSERDATA.length(), res); + EXPECT_TRUE(res); + EXPECT_TRUE(ret); + ret = rpcServer.ParseDataOver((const uint8_t*)PARSERDATA.c_str(), PARSERDATA.length(), res); + EXPECT_TRUE(res); + EXPECT_TRUE(ret); + ret = rpcServer.SqlQuery((const uint8_t*)SQLQUERY.c_str(), SQLQUERY.length(), res); + EXPECT_TRUE(g_result == "dberror\r\n"); + EXPECT_FALSE(ret); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/slice_filter_test.cpp b/host/trace_streamer/test/unittest/slice_filter_test.cpp old mode 100644 new mode 100755 index 6846cba534403a421d6b0d6e40c8119f8c671add..de37e3e365d8b1f112c1181f4305e9a48465180a --- a/host/trace_streamer/test/unittest/slice_filter_test.cpp +++ b/host/trace_streamer/test/unittest/slice_filter_test.cpp @@ -46,7 +46,7 @@ public: */ HWTEST_F(SliceFilterTest, SliceTestOnceCall, TestSize.Level1) { - TS_LOGI("test1"); + TS_LOGI("test28-1"); uint64_t ts = 168758662957000; uint64_t ts2 = 168758663011000; @@ -54,7 +54,7 @@ HWTEST_F(SliceFilterTest, SliceTestOnceCall, TestSize.Level1) uint32_t threadGroupId1 = 2519; DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("call_function_one"); - stream_.streamFilters_->sliceFilter_->BeginSlice(ts, pid1, threadGroupId1, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts, pid1, threadGroupId1, cat, splitStrIndex); stream_.streamFilters_->sliceFilter_->EndSlice(ts2, pid1, threadGroupId1); auto slices = stream_.traceDataCache_->GetInternalSlicesData(); EXPECT_TRUE(slices->Size() == 1); @@ -68,16 +68,16 @@ HWTEST_F(SliceFilterTest, SliceTestOnceCall, TestSize.Level1) */ HWTEST_F(SliceFilterTest, SliceTestNestedTwoMethod, TestSize.Level1) { - TS_LOGI("test2"); + TS_LOGI("test28-2"); uint64_t ts1 = 168758670506000; uint32_t pid1 = 1298; uint32_t threadGroupId1 = 1298; DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("call_function_one"); - stream_.streamFilters_->sliceFilter_->BeginSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts1, pid1, threadGroupId1, cat, splitStrIndex); splitStrIndex = stream_.traceDataCache_->GetDataIndex("call_function_two"); uint64_t ts2 = 168758670523000; - stream_.streamFilters_->sliceFilter_->BeginSlice(ts2, pid1, threadGroupId1, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts2, pid1, threadGroupId1, cat, splitStrIndex); uint64_t ts3 = 168758670720000; stream_.streamFilters_->sliceFilter_->EndSlice(ts3, pid1, threadGroupId1); uint64_t ts4 = 168758670732000; @@ -96,21 +96,21 @@ HWTEST_F(SliceFilterTest, SliceTestNestedTwoMethod, TestSize.Level1) */ HWTEST_F(SliceFilterTest, SliceTestNestedTwoMethodStackAndOneMethodStack, TestSize.Level1) { - TS_LOGI("test3"); + TS_LOGI("test28-3"); uint64_t ts1 = 168758663018000; uint32_t pid1 = 2532; uint32_t threadGroupId1 = 2519; DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_one"); - stream_.streamFilters_->sliceFilter_->BeginSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_one"); uint64_t ts2 = 168758663028000; uint32_t pid2 = 2533; uint32_t threadGroupId2 = 2529; - stream_.streamFilters_->sliceFilter_->BeginSlice(ts2, pid2, threadGroupId2, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts2, pid2, threadGroupId2, cat, splitStrIndex); splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_two"); uint64_t ts3 = 168758679303000; - stream_.streamFilters_->sliceFilter_->BeginSlice(ts3, pid1, threadGroupId1, cat, splitStrIndex); // slice 2 + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts3, pid1, threadGroupId1, cat, splitStrIndex); // slice 2 // end thread_one_call_function_two uint64_t ts4 = 168758682466000; stream_.streamFilters_->sliceFilter_->EndSlice(ts4, pid1, threadGroupId1); @@ -137,7 +137,7 @@ HWTEST_F(SliceFilterTest, SliceTestNestedTwoMethodStackAndOneMethodStack, TestSi */ HWTEST_F(SliceFilterTest, SliceTestWithoutBeginSlice, TestSize.Level1) { - TS_LOGI("test3"); + TS_LOGI("test28-4"); uint64_t ts1 = 168758663018000; uint32_t pid1 = 2532; uint32_t threadGroupId1 = 2519; @@ -153,30 +153,30 @@ HWTEST_F(SliceFilterTest, SliceTestWithoutBeginSlice, TestSize.Level1) */ HWTEST_F(SliceFilterTest, SliceTestWithMultiNestedCall, TestSize.Level1) { - TS_LOGI("test3"); + TS_LOGI("test28-5"); uint64_t ts1 = 168758663018000; uint32_t pid1 = 2532; uint32_t threadGroupId1 = 2519; DataIndex cat = stream_.traceDataCache_->GetDataIndex("Catalog"); DataIndex splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_one"); - stream_.streamFilters_->sliceFilter_->BeginSlice(ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts1, pid1, threadGroupId1, cat, splitStrIndex); // slice 0 splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_one"); uint64_t ts2 = 168758663028000; uint32_t pid2 = 2533; uint32_t threadGroupId2 = 2529; - stream_.streamFilters_->sliceFilter_->BeginSlice(ts2, pid2, threadGroupId2, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts2, pid2, threadGroupId2, cat, splitStrIndex); splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_two"); uint64_t ts3 = 168758679303000; - stream_.streamFilters_->sliceFilter_->BeginSlice(ts3, pid1, threadGroupId1, cat, splitStrIndex); // slice 2 + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts3, pid1, threadGroupId1, cat, splitStrIndex); // slice 2 splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_two"); uint64_t ts4 = 168758679312000; - stream_.streamFilters_->sliceFilter_->BeginSlice(ts4, pid2, threadGroupId2, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts4, pid2, threadGroupId2, cat, splitStrIndex); splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_one_call_function_three"); uint64_t ts5 = 168758679313000; - stream_.streamFilters_->sliceFilter_->BeginSlice(ts5, pid1, threadGroupId1, cat, splitStrIndex); // slice 4 + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts5, pid1, threadGroupId1, cat, splitStrIndex); // slice 4 splitStrIndex = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_three"); uint64_t ts6 = 168758679323000; - stream_.streamFilters_->sliceFilter_->BeginSlice(ts6, pid2, threadGroupId2, cat, splitStrIndex); + stream_.streamFilters_->sliceFilter_->BeginSlice("comm", ts6, pid2, threadGroupId2, cat, splitStrIndex); // end thread_one_call_function_three uint64_t ts7 = 168758682456000; stream_.streamFilters_->sliceFilter_->EndSlice(ts7, pid1, threadGroupId1); @@ -216,7 +216,7 @@ HWTEST_F(SliceFilterTest, SliceTestWithMultiNestedCall, TestSize.Level1) */ HWTEST_F(SliceFilterTest, AsyncTest, TestSize.Level1) { - TS_LOGI("test3"); + TS_LOGI("test28-6"); uint64_t ts1 = 168758663018000; uint32_t pid1 = 2532; uint32_t threadGroupId1 = 2519; @@ -239,7 +239,7 @@ HWTEST_F(SliceFilterTest, AsyncTest, TestSize.Level1) */ HWTEST_F(SliceFilterTest, FinishAsyncSliceWithoutStart, TestSize.Level1) { - TS_LOGI("test3"); + TS_LOGI("test28-7"); uint64_t ts = 100; uint32_t pid = 2532; uint32_t threadGroupId = 2519; @@ -257,7 +257,7 @@ HWTEST_F(SliceFilterTest, FinishAsyncSliceWithoutStart, TestSize.Level1) */ HWTEST_F(SliceFilterTest, AsyncTestTwiceCallStack, TestSize.Level1) { - TS_LOGI("test3"); + TS_LOGI("test28-8"); uint64_t ts1 = 168758663018000; uint32_t pid1 = 2532; uint32_t threadGroupId1 = 2519; @@ -289,7 +289,7 @@ HWTEST_F(SliceFilterTest, AsyncTestTwiceCallStack, TestSize.Level1) */ HWTEST_F(SliceFilterTest, BeginAsyncSliceThreeTimes, TestSize.Level1) { - TS_LOGI("test3"); + TS_LOGI("test28-9"); uint64_t ts1 = 168758663018000; uint32_t pid1 = 2532; uint32_t threadGroupId1 = 2519; @@ -324,13 +324,13 @@ HWTEST_F(SliceFilterTest, BeginAsyncSliceThreeTimes, TestSize.Level1) } /** - * @tc.name: BeginAsyncSliceThreeTimes + * @tc.name: BeginSliceMultiTimes * @tc.desc: Test asynchronous call muti times * @tc.type: FUNC */ HWTEST_F(SliceFilterTest, BeginSliceMultiTimes, TestSize.Level1) { - TS_LOGI("test3"); + TS_LOGI("test28-10"); uint64_t ts1 = 168758663018000; uint32_t pid1 = 2532; uint32_t threadGroupId1 = 2519; @@ -360,7 +360,7 @@ HWTEST_F(SliceFilterTest, BeginSliceMultiTimes, TestSize.Level1) DataIndex splitStrIndex6 = stream_.traceDataCache_->GetDataIndex("thread_two_call_function_three"); uint64_t ts6 = 168758679323000; - stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts6, pid2, threadGroupId2, cat2, splitStrIndex6); // slice 5 + stream_.streamFilters_->sliceFilter_->StartAsyncSlice(ts6, pid2, threadGroupId2, cat3, splitStrIndex6); // slice 5 // end thread_one_call_function_three uint64_t ts7 = 168758682456000; @@ -369,7 +369,7 @@ HWTEST_F(SliceFilterTest, BeginSliceMultiTimes, TestSize.Level1) // end thread_one_call_function_two uint64_t ts8 = 168758682466000; - stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts8, pid1, threadGroupId2, cat, + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts8, pid2, threadGroupId2, cat, splitStrIndex2); // end slice 1 // end thread_one_call_function_one @@ -384,12 +384,12 @@ HWTEST_F(SliceFilterTest, BeginSliceMultiTimes, TestSize.Level1) // end thread_two_call_function_two slice 3 uint64_t ts11 = 168758679344000; - stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts11, pid2, threadGroupId1, cat3, + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts11, pid1, threadGroupId1, cat3, splitStrIndex5); // end slice 4 // end thread_two_call_function_one slice 1 uint64_t ts12 = 168758689323000; - stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts12, pid2, threadGroupId2, cat2, + stream_.streamFilters_->sliceFilter_->FinishAsyncSlice(ts12, pid2, threadGroupId2, cat3, splitStrIndex6); // end slice 5 auto slices = stream_.traceDataCache_->GetInternalSlicesData(); @@ -401,10 +401,10 @@ HWTEST_F(SliceFilterTest, BeginSliceMultiTimes, TestSize.Level1) EXPECT_TRUE(slices->Depths()[1] == 0); EXPECT_TRUE(slices->DursData()[2] == ts9 - ts3); // slice 2 - EXPECT_TRUE(slices->Depths()[2] == 1); + EXPECT_TRUE(slices->Depths()[2] == 0); EXPECT_TRUE(slices->DursData()[3] == ts10 - ts4); // slice 3 - EXPECT_TRUE(slices->Depths()[3] == 1); + EXPECT_TRUE(slices->Depths()[3] == 0); EXPECT_TRUE(slices->DursData()[4] == ts11 - ts5); // slice 4 diff --git a/host/trace_streamer/test/unittest/smaps_parser_test.cpp b/host/trace_streamer/test/unittest/smaps_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..71c3feea48a266cafa950f3f36505aa747b870a6 --- /dev/null +++ b/host/trace_streamer/test/unittest/smaps_parser_test.cpp @@ -0,0 +1,287 @@ +/* + * 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. + */ + +#include +#include + +#include "htrace_mem_parser.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class SmapsParserTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + + void TearDown() + { + if (access(dbPath_.c_str(), F_OK) == 0) { + remove(dbPath_.c_str()); + } + } + +public: + SysTuning::TraceStreamer::TraceStreamerSelector stream_ = {}; + const std::string dbPath_ = "data/resource/out.db"; +}; +/** + * @tc.name: ParseSmapsParse + * @tc.desc: Parse SmapsData object and export database + * @tc.type: FUNC + */ +HWTEST_F(SmapsParserTest, ParseSmapsParse, TestSize.Level1) +{ + TS_LOGI("test29-1"); + HtraceMemParser SmapsEvent(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + ProcessMemoryInfo* memInfo = tracePacket.add_processesinfo(); + SmapsInfo* smapsInfo = memInfo->add_smapinfo(); + EXPECT_TRUE(smapsInfo != nullptr); + int size = memInfo->smapinfo_size(); + EXPECT_TRUE(size == 1); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_BOOTTIME; + + SmapsEvent.ParseProcessInfo(tracePacket, timeStamp); + SmapsEvent.Finish(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(),F_OK) == 0); + memInfo->clear_smapinfo(); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SMAPS, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == MEM_MAX * 1); + EXPECT_EQ(stream_.traceDataCache_->GetConstProcessData().size(), 1); +} +/** + * @tc.name: ParseSmapsParseTestMeasureDataSize + * @tc.desc: Parse SmapsData object and count StatInfo + * @tc.type: FUNC + */ +HWTEST_F(SmapsParserTest, ParseSmapsParseTestMeasureDataSize, TestSize.Level1) +{ + TS_LOGI("test29-2"); + HtraceMemParser SmapsEvent(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + ProcessMemoryInfo* memInfo = tracePacket.add_processesinfo(); + SmapsInfo* SmapsInfo = memInfo->add_smapinfo(); + EXPECT_TRUE(SmapsInfo != nullptr); + int size = memInfo->smapinfo_size(); + EXPECT_TRUE(size == 1); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_BOOTTIME; + std::string startAddr = "5589523000"; + std::string endAddr = "5589543000"; + std::string permission = "r--p"; + std::string path = "/system/bin/hiprofilerd"; + uint64_t vartualSize = 128; + uint64_t rss = 112; + uint64_t pss = 112; + uint64_t reside = 87.5; + SmapsInfo->set_start_addr(startAddr); + SmapsInfo->set_end_addr(endAddr); + SmapsInfo->set_permission(permission); + SmapsInfo->set_path(path); + SmapsInfo->set_size(vartualSize); + SmapsInfo->set_rss(rss); + SmapsInfo->set_pss(pss); + SmapsInfo->set_reside(reside); + + SmapsEvent.ParseProcessInfo(tracePacket, timeStamp); + SmapsEvent.Finish(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(),F_OK) == 0); + memInfo->clear_smapinfo(); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SMAPS, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + EXPECT_TRUE(stream_.traceDataCache_->GetConstProcessMeasureData().Size() == MEM_MAX * 1); + EXPECT_EQ(stream_.traceDataCache_->GetConstProcessData().size(), 1); + + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().StartAddrs()[0] == "0x5589523000"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().EndAddrs()[0] == "0x5589543000"); + uint64_t protection = stream_.traceDataCache_->GetDataIndex(permission); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().ProtectionIds()[0] == protection); + uint64_t pat = stream_.traceDataCache_->GetDataIndex(path); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().PathIds()[0] == pat); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Sizes()[0] == vartualSize); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Rss()[0] == rss); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Pss()[0] == pss); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Resides()[0] == reside); + EXPECT_EQ(stream_.traceDataCache_->GetConstProcessData().size(), 1); +} +/** + * @tc.name: ParseSmapsParseTestMutiMeasureData + * @tc.desc: Parse muti SmapsData object and count StatInfo + * @tc.type: FUNC + */ +HWTEST_F(SmapsParserTest, ParseSmapsParseTestMutiMeasureData, TestSize.Level1) +{ + TS_LOGI("test29-3"); + HtraceMemParser SmapsEvent(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + ProcessMemoryInfo* memInfo = tracePacket.add_processesinfo(); + SmapsInfo* smapsInfo0 = memInfo->add_smapinfo(); + EXPECT_TRUE(smapsInfo0 != nullptr); + int size = memInfo->smapinfo_size(); + EXPECT_TRUE(size == 1); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock0 = TS_CLOCK_BOOTTIME; + std::string startAddr0 = "5589523000"; + std::string endAddr0 = "5589543000"; + std::string permission0 = "r--p"; + std::string path0 = "/system/bin/hiprofilerd"; + uint64_t vartualSize0 = 128; + uint64_t rss0 = 112; + uint64_t pss0 = 112; + uint64_t reside0 = 87.5; + smapsInfo0->set_start_addr(startAddr0); + smapsInfo0->set_end_addr(endAddr0); + smapsInfo0->set_permission(permission0); + smapsInfo0->set_path(path0); + smapsInfo0->set_size(vartualSize0); + smapsInfo0->set_rss(rss0); + smapsInfo0->set_pss(pss0); + smapsInfo0->set_reside(reside0); + + SmapsInfo* smapsInfo1 = memInfo->add_smapinfo(); + EXPECT_TRUE(smapsInfo1 != nullptr); + size = memInfo->smapinfo_size(); + EXPECT_TRUE(size == 2); + timeStamp = 1616439852302; + BuiltinClocks clock1 = TS_CLOCK_BOOTTIME; + std::string startAddr1 = "5589543000"; + std::string endAddr1 = "5589589000"; + std::string permission1 = "r-xp"; + std::string path1 = "/system/bin/hiprofilerd"; + uint64_t vartualSize1 = 280; + uint64_t rss1 = 280; + uint64_t pss1 = 280; + uint64_t reside1 = 100; + smapsInfo1->set_start_addr(startAddr1); + smapsInfo1->set_end_addr(endAddr1); + smapsInfo1->set_permission(permission1); + smapsInfo1->set_path(path1); + smapsInfo1->set_size(vartualSize1); + smapsInfo1->set_rss(rss1); + smapsInfo1->set_pss(pss1); + smapsInfo1->set_reside(reside1); + + SmapsEvent.ParseProcessInfo(tracePacket, timeStamp); + SmapsEvent.Finish(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(),F_OK) == 0); + memInfo->clear_smapinfo(); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SMAPS, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().StartAddrs()[0] == "0x5589523000"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().EndAddrs()[0] == "0x5589543000"); + uint64_t protection = stream_.traceDataCache_->GetDataIndex(permission0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().ProtectionIds()[0] == protection); + uint64_t pathId = stream_.traceDataCache_->GetDataIndex(path0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().PathIds()[0] == pathId); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Sizes()[0] == vartualSize0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Rss()[0] == rss0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Pss()[0] == pss0); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Resides()[0] == reside0); + + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().StartAddrs()[1] == "0x5589543000"); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().EndAddrs()[1] == "0x5589589000"); + protection = stream_.traceDataCache_->GetDataIndex(permission1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().ProtectionIds()[1] == protection); + pathId = stream_.traceDataCache_->GetDataIndex(path1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().PathIds()[1] == pathId); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Sizes()[1] == vartualSize1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Rss()[1] == rss1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Pss()[1] == pss1); + EXPECT_TRUE(stream_.traceDataCache_->GetConstSmapsData().Resides()[1] == reside1); +} +/** + * @tc.name: ParseMutiEmptySmapsDataAndCountStatInfo + * @tc.desc: Parse muti Empty SmapsData object and count StatInfo + * @tc.type: FUNC + */ +HWTEST_F(SmapsParserTest, ParseMutiEmptySmapsDataAndCountStatInfo, TestSize.Level1) +{ + TS_LOGI("test29-4"); + HtraceMemParser SmapsEvent(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + ProcessMemoryInfo* memInfo = tracePacket.add_processesinfo(); + SmapsInfo* smapsInfo0 = memInfo->add_smapinfo(); + EXPECT_TRUE(smapsInfo0 != nullptr); + int size = memInfo->smapinfo_size(); + EXPECT_TRUE(size == 1); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_BOOTTIME; + + SmapsInfo* smapsInfo1 = memInfo->add_smapinfo(); + EXPECT_TRUE(smapsInfo1 != nullptr); + size = memInfo->smapinfo_size(); + EXPECT_TRUE(size == 2); + + SmapsEvent.ParseProcessInfo(tracePacket, timeStamp); + SmapsEvent.Finish(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(),F_OK) == 0); + memInfo->clear_smapinfo(); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SMAPS, STAT_EVENT_RECEIVED); + EXPECT_TRUE(1 == eventCount); + EXPECT_EQ(stream_.traceDataCache_->GetConstProcessData().size(), 1); +} +/** + * @tc.name: ParseEmptySmapsData + * @tc.desc: Parse Empty SmapsData + * @tc.type: FUNC + */ +HWTEST_F(SmapsParserTest, ParseEmptySmapsData, TestSize.Level1) +{ + TS_LOGI("test29-5"); + HtraceMemParser SmapsEvent(stream_.traceDataCache_.get(), stream_.streamFilters_.get()); + + MemoryData tracePacket; + int size = tracePacket.processesinfo_size(); + EXPECT_TRUE(size == 0); + uint64_t timeStamp = 1616439852302; + BuiltinClocks clock = TS_CLOCK_BOOTTIME; + + SmapsEvent.ParseProcessInfo(tracePacket, timeStamp); + SmapsEvent.Finish(); + stream_.traceDataCache_->ExportDatabase(dbPath_); + + EXPECT_TRUE(access(dbPath_.c_str(),F_OK) == 0); + tracePacket.clear_processesinfo(); + + auto eventCount = stream_.traceDataCache_->GetConstStatAndInfo().GetValue(TRACE_SMAPS, STAT_EVENT_RECEIVED); + // EXPECT_TRUE(0 == eventCount); + EXPECT_EQ(0, eventCount); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/span_join_test.cpp b/host/trace_streamer/test/unittest/span_join_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af1dcaa59d1263f2f7190674bb126b27b40fdda1 --- /dev/null +++ b/host/trace_streamer/test/unittest/span_join_test.cpp @@ -0,0 +1,245 @@ +/* + * 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. + */ + +#include +#include + +#include "span_join.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +namespace SysTuning { +namespace TraceStreamer { +class SpanJoinTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} + +public: + void Prepare(const std::string& sql) + { + int size = static_cast(sql.size()); + sqlite3_prepare_v2(stream_.traceDataCache_->db_, sql.c_str(), size, &stmt_, nullptr); + } + + void Step(const std::string& sql) + { + Prepare(sql); + sqlite3_step(stmt_); + } + + void Next(const std::vector column) + { + sqlite3_step(stmt_); + for (size_t i = 0; i < column.size(); ++i) { + sqlite3_column_int64(stmt_, static_cast(i)); + } + } + sqlite3_stmt* stmt_; + TraceStreamerSelector stream_ = {}; +}; +/** + * @tc.name: SpanjoinTwoTable + * @tc.desc: SpanjoinTwoTable with ts,dur,and partitioned cpu + * @tc.type: FUNC + */ +HWTEST_F(SpanJoinTest, SpanjoinTwoTable, TestSize.Level1) +{ + TS_LOGI("test30-1"); + Step("CREATE TABLE FirstTable(ts UNSIGNED INT PRIMARY KEY, dur UNSIGNED INT, cpu UNSIGNED INT);"); + Step("CREATE TABLE SecondTable(ts UNSIGNED INT PRIMARY KEY, dur UNSIGNED INT, cpu UNSIGNED INT);"); + Step( + "CREATE VIRTUAL TABLE SpanjoinTable using span_join(FirstTable partitioned cpu, SecondTable partitioned cpu);"); + Step("INSERT INTO FirstTable VALUES(100, 10, 5);"); + Step("INSERT INTO FirstTable VALUES(110, 50, 5);"); + Step("INSERT INTO FirstTable VALUES(120, 100, 2);"); + Step("INSERT INTO FirstTable VALUES(160, 10, 5);"); + Step("INSERT INTO SecondTable VALUES(100, 5, 5);"); + Step("INSERT INTO SecondTable VALUES(105, 100, 5);"); + Step("INSERT INTO SecondTable VALUES(110, 50, 2);"); + Step("INSERT INTO SecondTable VALUES(160, 100, 2);"); + Prepare("SELECT * FROM SpanjoinTable"); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_ROW); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 120); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 40); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 2); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_ROW); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 160); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 60); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 2); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_ROW); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 100); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 5); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 5); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_ROW); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 105); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 5); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 5); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_ROW); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 110); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 50); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 5); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_ROW); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 160); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 10); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 5); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_DONE); +} +/** + * @tc.name: SpanjoinTwoTableWithoutPartitioned + * @tc.desc: SpanjoinTwoTable with ts,dur,and without partitioned cpu + * @tc.type: FUNC + */ +HWTEST_F(SpanJoinTest, SpanjoinTwoTableWithoutPartitioned, TestSize.Level2) +{ + TS_LOGI("test30-2"); + Step("CREATE TABLE FirstTable(ts UNSIGNED INT PRIMARY KEY, dur UNSIGNED INT);"); + Step("CREATE TABLE SecondTable(ts UNSIGNED INT PRIMARY KEY, dur UNSIGNED INT);"); + Step( + "CREATE VIRTUAL TABLE SpanjoinTable using span_join(FirstTable partitioned cpu, SecondTable partitioned cpu);"); + Step("INSERT INTO FirstTable VALUES(100, 10);"); + Step("INSERT INTO FirstTable VALUES(110, 50);"); + Step("INSERT INTO FirstTable VALUES(120, 100);"); + Step("INSERT INTO FirstTable VALUES(160, 10);"); + Step("INSERT INTO SecondTable VALUES(100, 5);"); + Step("INSERT INTO SecondTable VALUES(105, 100);"); + Step("INSERT INTO SecondTable VALUES(110, 50);"); + Step("INSERT INTO SecondTable VALUES(160, 100);"); + Prepare("SELECT * FROM SpanjoinTable"); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_DONE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_DONE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_DONE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_DONE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_DONE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_DONE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_DONE); +} +/** + * @tc.name: SpanjoinTwoTableWithoutTs + * @tc.desc: SpanjoinTwoTableWithoutTs with dur, partitioned cpu and without ts + * @tc.type: FUNC + */ +HWTEST_F(SpanJoinTest, SpanjoinTwoTableWithoutTs, TestSize.Level3) +{ + TS_LOGI("test30-3"); + Step("CREATE TABLE FirstTable(dur UNSIGNED INT, cpu UNSIGNED INT);"); + Step("CREATE TABLE SecondTable(dur UNSIGNED INT, cpu UNSIGNED INT);"); + Step( + "CREATE VIRTUAL TABLE SpanjoinTable using span_join(FirstTable partitioned cpu, SecondTable partitioned cpu);"); + Step("INSERT INTO FirstTable VALUES(10, 5);"); + Step("INSERT INTO FirstTable VALUES(50, 5);"); + Step("INSERT INTO FirstTable VALUES(100, 2);"); + Step("INSERT INTO FirstTable VALUES(10, 5);"); + Step("INSERT INTO SecondTable VALUES(5, 5);"); + Step("INSERT INTO SecondTable VALUES(100, 5);"); + Step("INSERT INTO SecondTable VALUES(50, 2);"); + Step("INSERT INTO SecondTable VALUES(100, 2);"); + Prepare("SELECT * FROM SpanjoinTable"); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); +} +/** + * @tc.name: SpanjoinTwoTableWithoutDur + * @tc.desc: SpanjoinTwoTableWithoutTs with ts, partitioned cpu and without dur + * @tc.type: FUNC + */ +HWTEST_F(SpanJoinTest, SpanjoinTwoTableWithoutDur, TestSize.Level4) +{ + TS_LOGI("test30-4"); + Step("CREATE TABLE FirstTable(ts UNSIGNED INT PRIMARY KEY, cpu UNSIGNED INT);"); + Step("CREATE TABLE SecondTable(ts UNSIGNED INT PRIMARY KEY, cpu UNSIGNED INT);"); + Step( + "CREATE VIRTUAL TABLE SpanjoinTable using span_join(FirstTable partitioned cpu, SecondTable partitioned cpu);"); + Step("INSERT INTO FirstTable VALUES(100, 5);"); + Step("INSERT INTO FirstTable VALUES(110, 5);"); + Step("INSERT INTO FirstTable VALUES(120, 2);"); + Step("INSERT INTO FirstTable VALUES(160, 5);"); + Step("INSERT INTO SecondTable VALUES(100, 5);"); + Step("INSERT INTO SecondTable VALUES(105, 5);"); + Step("INSERT INTO SecondTable VALUES(110, 2);"); + Step("INSERT INTO SecondTable VALUES(160, 2);"); + Prepare("SELECT * FROM SpanjoinTable"); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); + EXPECT_EQ(sqlite3_column_int64(stmt_, 0), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 1), 0); + EXPECT_EQ(sqlite3_column_int64(stmt_, 2), 0); + EXPECT_EQ(sqlite3_step(stmt_), SQLITE_MISUSE); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/table_test.cpp b/host/trace_streamer/test/unittest/table_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e4ade1a5ff0f56f06e5db0ec29c858ea18cfda2 --- /dev/null +++ b/host/trace_streamer/test/unittest/table_test.cpp @@ -0,0 +1,1490 @@ +/* + * 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. + */ + +#include +#include + +#include "htrace_mem_parser.h" +#include "rpc_server.h" +#include "trace_data_cache.h" +#include "trace_streamer_selector.h" + +using namespace testing::ext; +using namespace SysTuning::TraceStreamer; +namespace SysTuning { +namespace TraceStreamer { +class TableTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} + +public: + TraceStreamerSelector stream_ = {}; +}; + +/** + * @tc.name: AppnameTableTest + * @tc.desc: Appname Table Test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, AppnameTableTest, TestSize.Level1) +{ + TS_LOGI("test31-1"); + std::string sqlSelect = "select * from app_name"; + uint8_t flags = 0; + DataIndex eventSource = stream_.traceDataCache_->GetDataIndex("eventSource"); + DataIndex appName = stream_.traceDataCache_->GetDataIndex("app1"); + stream_.traceDataCache_->GetAppNamesData()->AppendAppName(flags, eventSource, appName); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: ArgsTableTest + * @tc.desc: Args Table Test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ArgsTableTest, TestSize.Level1) +{ + TS_LOGI("test31-2"); + std::string sqlSelect = "select * from args"; + std::string sqlSelect1 = "select * from args where id = 1"; + std::string sqlSelect2 = "select * from args where key > 1"; + std::string sqlSelect3 = "select * from args where id < 1"; + std::string sqlSelect4 = "select * from args where id >= 1"; + std::string sqlSelect5 = "select * from args where id <= 1"; + DataIndex nameId0 = stream_.traceDataCache_->GetDataIndex("args0"); + DataIndex nameId1 = stream_.traceDataCache_->GetDataIndex("args1"); + BaseDataType dataType0 = BASE_DATA_TYPE_INT; + BaseDataType dataType1 = BASE_DATA_TYPE_STRING; + int64_t value0 = 123; + int64_t value1 = 456; + size_t argSet0 = 321; + size_t argSet1 = 654; + stream_.traceDataCache_->InitDB(); + stream_.traceDataCache_->GetArgSetData()->AppendNewArg(nameId0, dataType0, value0, argSet0); + stream_.traceDataCache_->GetArgSetData()->AppendNewArg(nameId1, dataType1, value1, argSet1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 2); +} +/** + * @tc.name: CallstackTableTest + * @tc.desc: Callstack Table Test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, CallstackTableTest, TestSize.Level1) +{ + TS_LOGI("test31-3"); + std::string sqlSelect = "select * from callstack"; + std::string sqlSelect1 = "select * from callstack where id = 1"; + std::string sqlSelect2 = "select * from callstack where ts > 1"; + std::string sqlSelect3 = "select * from callstack where callid < 1"; + std::string sqlSelect4 = "select * from callstack where cookie >= 1"; + std::string sqlSelect5 = "select * from callstack where cookie <= 1"; + uint64_t startT = 1; + uint64_t durationNs = 1; + InternalTid internalTid = 1; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("callstack"); + uint16_t nameIdentify = 1; + DataIndex name = stream_.traceDataCache_->GetDataIndex("name"); + uint8_t depth = 1; + uint64_t cookid = stream_.traceDataCache_->GetDataIndex("cook"); + const std::optional& parentId = 1; + + uint64_t startT1 = 1; + uint64_t durationNs1 = 1; + InternalTid internalTid1 = 1; + DataIndex cat1 = stream_.traceDataCache_->GetDataIndex("callstack1"); + uint16_t nameIdentify1 = 1; + DataIndex name1 = stream_.traceDataCache_->GetDataIndex("name1"); + uint8_t depth1 = 1; + uint64_t cookid1 = stream_.traceDataCache_->GetDataIndex("cook1"); + const std::optional& parentId1 = 1; + + stream_.traceDataCache_->InitDB(); + stream_.traceDataCache_->GetInternalSlicesData()->AppendInternalAsyncSlice( + startT, durationNs, internalTid, cat, nameIdentify, name, depth, cookid, parentId); + stream_.traceDataCache_->GetInternalSlicesData()->AppendInternalAsyncSlice( + startT1, durationNs1, internalTid1, cat1, nameIdentify1, name1, depth1, cookid1, parentId1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: ClkEventFilterTableTest + * @tc.desc: ClkEvent filter table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ClkEventFilterTableTest, TestSize.Level1) +{ + TS_LOGI("test31-4"); + std::string sqlSelect = "select * from clk_event_filter"; + std::string sqlSelect1 = "select * from clk_event_filter where id = 1"; + std::string sqlSelect2 = "select * from clk_event_filter where name < 0"; + std::string sqlSelect3 = "select * from clk_event_filter where id > 0"; + std::string sqlSelect4 = "select * from clk_event_filter where id >= 0"; + std::string sqlSelect5 = "select * from clk_event_filter where id <= 0"; + uint64_t id = 1; + uint64_t rate = 1; + DataIndex name = stream_.traceDataCache_->GetDataIndex("name"); + uint64_t cpu = 1; + + uint64_t id1 = 1; + uint64_t rate1 = 0; + DataIndex name1 = stream_.traceDataCache_->GetDataIndex("name1"); + uint64_t cpu1 = 1; + stream_.traceDataCache_->GetClkEventFilterData()->AppendNewFilter(id, rate, name, cpu); + stream_.traceDataCache_->GetClkEventFilterData()->AppendNewFilter(id1, rate1, name1, cpu1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 2); +} +/** + * @tc.name: ClockEventFilterTableTest + * @tc.desc: ClockEvent filter table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ClockEventFilterTableTest, TestSize.Level1) +{ + TS_LOGI("test31-5"); + std::string sqlSelect = "select * from clock_event_filter"; + std::string sqlSelect1 = "select * from clock_event_filter where id = 1"; + std::string sqlSelect2 = "select * from clock_event_filter where type > 1"; + std::string sqlSelect3 = "select * from clock_event_filter where name < 1"; + std::string sqlSelect4 = "select * from clock_event_filter where cpu >= 1"; + std::string sqlSelect5 = "select * from clock_event_filter where id <= 1"; + uint64_t id = 1; + uint64_t type = 1; + DataIndex name = stream_.traceDataCache_->GetDataIndex("name"); + uint64_t cpu = 1; + + uint64_t id1 = 1; + uint64_t type1 = 0; + DataIndex name1 = stream_.traceDataCache_->GetDataIndex("name1"); + uint64_t cpu1 = 1; + stream_.traceDataCache_->GetClockEventFilterData()->AppendNewFilter(id, type, name, cpu); + stream_.traceDataCache_->GetClockEventFilterData()->AppendNewFilter(id1, type1, name1, cpu1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 2); +} +/** + * @tc.name: CpuMeasureFilterTableTest + * @tc.desc: Cpu measure filter table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, CpuMeasureFilterTableTest, TestSize.Level1) +{ + TS_LOGI("test31-6"); + std::string sqlSelect = "select * from cpu_measure_filter"; + std::string sqlSelect1 = "select * from cpu_measure_filter where id = 1"; + std::string sqlSelect2 = "select * from cpu_measure_filter where id > 1"; + std::string sqlSelect3 = "select * from cpu_measure_filter where type < 1"; + std::string sqlSelect4 = "select * from cpu_measure_filter where name >= 1"; + std::string sqlSelect5 = "select * from cpu_measure_filter where cpu <= 1"; + uint64_t filterId = 2; + DataIndex name = stream_.traceDataCache_->GetDataIndex("name"); + uint32_t cpu = 1; + + uint64_t filterId1 = 1; + DataIndex name1 = stream_.traceDataCache_->GetDataIndex("name1"); + uint32_t cpu1 = 2; + + stream_.traceDataCache_->GetCpuMeasuresData()->AppendNewFilter(filterId, name, cpu); + stream_.traceDataCache_->GetCpuMeasuresData()->AppendNewFilter(filterId1, name1, cpu1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: CpuUsageFilterTableTest + * @tc.desc: Cpu usage filter table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, CpuUsageFilterTableTest, TestSize.Level1) +{ + TS_LOGI("test31-7"); + std::string sqlSelect = "select * from cpu_usage"; + uint64_t newTimeStamp = 1663869124160; + uint64_t dur = 560; + double totalLoad = 2; + double userLoad = 2; + double systemLoad = 2; + int64_t thread = 2; + + uint64_t newTimeStamp1 = 1663869224160; + uint64_t dur1 = 550; + double totalLoad1 = 1; + double userLoad1 = 1; + double systemLoad1 = 1; + int64_t thread1 = 1; + + stream_.traceDataCache_->GetCpuUsageInfoData()->AppendNewData(newTimeStamp, dur, totalLoad, userLoad, userLoad, + thread); + stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + stream_.traceDataCache_->GetCpuUsageInfoData()->AppendNewData(newTimeStamp1, dur1, totalLoad1, userLoad1, userLoad1, + thread1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); +} +/** + * @tc.name: DataDictTableTest + * @tc.desc: Data dict table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, DataDictTableTest, TestSize.Level1) +{ + TS_LOGI("test31-8"); + std::string sqlSelect = "select * from data_dict"; + std::string sqlSelect1 = "select * from data_dict where id = 1"; + std::string sqlSelect2 = "select * from data_dict where id > 1"; + std::string sqlSelect3 = "select * from data_dict where id < 1"; + std::string sqlSelect4 = "select * from data_dict where id >= 1"; + std::string sqlSelect5 = "select * from data_dict where data <= 1"; + stream_.traceDataCache_->GetDataFromDict(1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 52); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 50); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 51); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: DataTypeTableTest + * @tc.desc: Data type table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, DataTypeTableTest, TestSize.Level1) +{ + TS_LOGI("test31-9"); + std::string sqlSelect = "select * from data_type"; + std::string sqlSelect1 = "select * from data_type where id = 1"; + std::string sqlSelect2 = "select * from data_type where id > 1"; + std::string sqlSelect3 = "select * from data_type where id < 1"; + std::string sqlSelect4 = "select * from data_type where typeId >= 1"; + std::string sqlSelect5 = "select * from data_type where id <= 1"; + BaseDataType dataType = BASE_DATA_TYPE_INT; + DataIndex dataDescIndex = stream_.traceDataCache_->GetDataIndex("dataDescIndex"); + BaseDataType dataType1 = BASE_DATA_TYPE_STRING; + DataIndex dataDescIndex1 = stream_.traceDataCache_->GetDataIndex("dataDescIndex1"); + + stream_.traceDataCache_->GetDataTypeData()->AppendNewDataType(dataType, dataDescIndex); + stream_.traceDataCache_->GetDataTypeData()->AppendNewDataType(dataType1, dataDescIndex1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 6); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 4); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 4); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 2); +} +/** + * @tc.name: DiskIoTableTest + * @tc.desc: Disk io table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, DiskIoTableTest, TestSize.Level1) +{ + TS_LOGI("test31-10"); + std::string sqlSelect = "select * from diskio"; + uint64_t ts = 1663869124160; + uint64_t dur = 540; + uint64_t rd = 5; + uint64_t wr = 5; + uint64_t rdPerSec = 6; + uint64_t wrPerSec = 6; + double rdCountPerSec = 2; + double wrCountPerSec = 2; + uint64_t rdCount = 2; + uint64_t wrCount = 2; + + stream_.traceDataCache_->GetDiskIOData()->AppendNewData(ts, dur, rd, wr, rdPerSec, wrPerSec, rdCountPerSec, + wrCountPerSec, rdCount, wrCount); + stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); +} +/** + * @tc.name: EbpfCallstackTableTest + * @tc.desc: Ebpf callstack table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, EbpfCallstackTableTest, TestSize.Level1) +{ + TS_LOGI("test31-11"); + std::string sqlSelect = "select * from ebpf_callstack"; + std::string sqlSelect1 = "select * from ebpf_callstack where id = 1"; + std::string sqlSelect2 = "select * from ebpf_callstack where id > 1"; + std::string sqlSelect3 = "select * from ebpf_callstack where id < 1"; + std::string sqlSelect4 = "select * from ebpf_callstack where id >= 1"; + std::string sqlSelect5 = "select * from ebpf_callstack where id <= 1"; + std::string sqlSelect6 = "select * from hidump"; + uint64_t callChainId = 1; + uint32_t depth = 1; + uint64_t ip = 1; + uint64_t symbolId = 1; + uint64_t filePathId = 1; + + uint64_t callChainId1 = 2; + uint32_t depth1 = 2; + uint64_t ip1 = 2; + uint64_t symbolId1 = 2; + uint64_t filePathId1 = 2; + + uint64_t timestamp = 1663869124160; + uint32_t fps = 1; + + uint64_t timestamp1 = 1663869224160; + uint32_t fps1 = 2; + + stream_.traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(timestamp, fps); + stream_.traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(timestamp1, fps1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect6.c_str(), false); + EXPECT_EQ(row, 2); + + stream_.traceDataCache_->GetEbpfCallStack()->AppendNewData(callChainId, depth, ip, symbolId, filePathId); + stream_.traceDataCache_->GetEbpfCallStack()->AppendNewData(callChainId1, depth1, ip1, symbolId1, filePathId1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 2); +} +/** + * @tc.name: FileSystemSampleTableTest + * @tc.desc: File system sample table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, FileSystemSampleTableTest, TestSize.Level1) +{ + TS_LOGI("test31-12"); + std::string sqlSelect = "select * from file_system_sample"; + std::string sqlSelect1 = "select * from file_system_sample where id = 1"; + std::string sqlSelect2 = "select * from file_system_sample where type > 1"; + std::string sqlSelect3 = "select * from hidump"; + std::string sqlSelect4 = "select * from hidump where id = 1"; + std::string sqlSelect5 = "select * from hidump where ts < 1663869124160"; + // std::string sqlSelect6 = "select * from hidump"; + uint64_t callChainId = 1; + uint16_t type = 1; + uint32_t ipid = 1; + uint32_t itid = 1; + uint64_t startTs = 1663869124160; + uint64_t endTs = 1663869124260; + uint64_t dur = 100; + DataIndex returnValue = stream_.traceDataCache_->GetDataIndex("returnValue"); + DataIndex errorCode = stream_.traceDataCache_->GetDataIndex("errorCode"); + size_t size = 1; + int32_t fd = 0; + DataIndex fileId = stream_.traceDataCache_->GetDataIndex("fileId"); + DataIndex firstArgument = stream_.traceDataCache_->GetDataIndex("firstArgument"); + DataIndex secondArgument = stream_.traceDataCache_->GetDataIndex("secondArgument"); + DataIndex thirdArgument = stream_.traceDataCache_->GetDataIndex("thirdArgument"); + DataIndex fourthArgument = stream_.traceDataCache_->GetDataIndex("fourthArgument"); + + uint64_t callChainId1 = 2; + uint16_t type1 = 2; + uint32_t ipid1 = 2; + uint32_t itid1 = 2; + uint64_t startTs1 = 1663869124161; + uint64_t endTs1 = 1663869124261; + uint64_t dur1 = 200; + DataIndex returnValue1 = stream_.traceDataCache_->GetDataIndex("returnValue1"); + DataIndex errorCode1 = stream_.traceDataCache_->GetDataIndex("errorCode1"); + size_t size1 = 2; + int32_t fd1 = 1; + DataIndex fileId1 = stream_.traceDataCache_->GetDataIndex("fileId1"); + DataIndex firstArgument1 = stream_.traceDataCache_->GetDataIndex("firstArgument1"); + DataIndex secondArgument1 = stream_.traceDataCache_->GetDataIndex("secondArgument1"); + DataIndex thirdArgument1 = stream_.traceDataCache_->GetDataIndex("thirdArgument1"); + DataIndex fourthArgument1 = stream_.traceDataCache_->GetDataIndex("fourthArgument1"); + + uint64_t timestamp = 1663869124160; + uint32_t fps = 1; + + uint64_t timestamp1 = 1663869224160; + uint32_t fps1 = 2; + + stream_.traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(timestamp, fps); + stream_.traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(timestamp1, fps1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 0); + + stream_.traceDataCache_->GetFileSystemSample()->AppendNewData( + callChainId, type, ipid, itid, startTs, endTs, dur, returnValue, errorCode, size, fd, fileId, firstArgument, + secondArgument, thirdArgument, fourthArgument); + stream_.traceDataCache_->GetFileSystemSample()->AppendNewData( + callChainId1, type1, ipid1, itid1, startTs1, endTs1, dur1, returnValue1, errorCode1, size1, fd1, fileId1, + firstArgument1, secondArgument1, thirdArgument1, fourthArgument1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: HidumpTableTest + * @tc.desc: Hidump table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, HidumpTableTest, TestSize.Level1) +{ + TS_LOGI("test31-13"); + std::string sqlSelect = "select * from hidump"; + uint64_t timestamp = 1663869124160; + uint32_t fps = 1; + + stream_.traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(timestamp, fps); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: HisysEventMeasureTableTest + * @tc.desc: Hisys event measure table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, HisysEventMeasureTableTest, TestSize.Level1) +{ + TS_LOGI("test31-14"); + std::string sqlSelect = "select * from hisys_event_measure"; + uint64_t serial = 1; + uint64_t ts = 1663869124160; + uint32_t nameId = stream_.traceDataCache_->GetDataIndex("event"); + uint32_t keyId = stream_.traceDataCache_->GetDataIndex("data"); + int32_t type = 1; + double numericValue = 0; + DataIndex stringValue = stream_.traceDataCache_->GetDataIndex("stringValue"); + + stream_.traceDataCache_->GetSyseventMeasureData()->AppendData(ts, nameId, keyId, type, numericValue, stringValue, serial); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: InstantTableTest + * @tc.desc: Instant table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, InstantTableTest, TestSize.Level1) +{ + TS_LOGI("test31-15"); + std::string sqlSelect = "select * from instant"; + std::string sqlSelect2 = "select * from instant where name = \"name\""; + std::string sqlSelect3 = "select * from instant where ts < 1663869124160"; + std::string sqlSelect4 = "select * from instant where ref > 1"; + std::string sqlSelect5 = "select * from instant where wakeup_from >= 1"; + uint64_t timestamp = 1663869124160; + DataIndex nameIndex = stream_.traceDataCache_->GetDataIndex("name"); + int64_t internalTid = 1; + int64_t wakeupFromInternalPid = 1; + + DataIndex nameIndex1 = stream_.traceDataCache_->GetDataIndex("name1"); + int64_t internalTid1 = 2; + int64_t wakeupFromInternalPid1 = 2; + + std::string sqlSelect1 = "select * from measure"; + uint32_t type = 1; + int64_t value = 1; + uint32_t filterId = 1; + + uint32_t type1 = 2; + uint64_t timestamp1 = 1663869124160; + int64_t value1 = 2; + uint32_t filterId1 = 2; + + stream_.traceDataCache_->GetMeasureData()->AppendMeasureData(type, timestamp, value, filterId); + stream_.traceDataCache_->GetMeasureData()->AppendMeasureData(type1, timestamp1, value1, filterId1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 2); + + stream_.traceDataCache_->GetInstantsData()->AppendInstantEventData(timestamp, nameIndex, internalTid, + wakeupFromInternalPid); + stream_.traceDataCache_->GetInstantsData()->AppendInstantEventData(timestamp1, nameIndex1, internalTid1, + wakeupFromInternalPid1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: IoLatencySampleTableTest + * @tc.desc: Io latency sample table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, IoLatencySampleTableTest, TestSize.Level1) +{ + TS_LOGI("test31-16"); + std::string sqlSelect = "select * from bio_latency_sample"; + std::string sqlSelect1 = "select * from hidump"; + std::string sqlSelect2 = "select * from bio_latency_sample where id = 1"; + uint64_t callChainId = 1; + uint64_t type = 1; + uint64_t ipid = 1; + uint64_t itid = 1; + uint64_t startTs = 1663869124160; + uint64_t endTs = 1663869224160; + uint64_t latencyDur = 200; + uint32_t tier = 1; + uint64_t size = 1; + uint64_t blockNumber = 1; + uint64_t filePathId = stream_.traceDataCache_->GetDataIndex("filePathId"); + uint64_t durPer4k = 1; + + uint64_t callChainId1 = 2; + uint64_t type1 = 2; + uint64_t ipid1 = 2; + uint64_t itid1 = 2; + uint64_t startTs1 = 1663869224160; + uint64_t endTs1 = 1663869424160; + uint64_t latencyDur1 = 200; + uint32_t tier1 = 2; + uint64_t size1 = 2; + uint64_t blockNumber1 = 2; + uint64_t filePathId1 = stream_.traceDataCache_->GetDataIndex("filePathId1"); + uint64_t durPer4k1 = 2; + + uint64_t timestamp = 1663869124160; + uint32_t fps = 1; + + uint64_t timestamp1 = 1663869224160; + uint32_t fps1 = 2; + + stream_.traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(timestamp, fps); + stream_.traceDataCache_->GetHidumpData()->AppendNewHidumpInfo(timestamp1, fps1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 2); + + stream_.traceDataCache_->GetBioLatencySampleData()->AppendNewData( + callChainId, type, ipid, itid, startTs, endTs, latencyDur, tier, size, blockNumber, filePathId, durPer4k); + stream_.traceDataCache_->GetBioLatencySampleData()->AppendNewData(callChainId1, type1, ipid1, itid1, startTs1, + endTs1, latencyDur1, tier1, size1, blockNumber1, + filePathId1, durPer4k1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: IrqTableTest + * @tc.desc: Irq table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, IrqTableTest, TestSize.Level1) +{ + TS_LOGI("test31-17"); + std::string sqlSelect = "select * from irq"; + std::string sqlSelect1 = "select * from irq where id < 2"; + uint64_t startT = 1663869124160; + uint64_t durationNs = 200; + InternalTid internalTid = 1; + DataIndex cat = stream_.traceDataCache_->GetDataIndex("cat"); + uint16_t nameIdentify = 1; + DataIndex name = stream_.traceDataCache_->GetDataIndex("name"); + uint8_t depth = 1; + const std::optional& parentId = 1; + + uint64_t startT1 = 1663869224160; + uint64_t durationNs1 = 200; + InternalTid internalTid1 = 2; + DataIndex cat1 = stream_.traceDataCache_->GetDataIndex("cat1"); + uint16_t nameIdentify1 = 2; + DataIndex name1 = stream_.traceDataCache_->GetDataIndex("name1"); + uint8_t depth1 = 2; + const std::optional& parentId1 = 2; + + stream_.traceDataCache_->GetIrqData()->AppendInternalSlice(startT, durationNs, internalTid, cat, nameIdentify, name, + depth, parentId); + stream_.traceDataCache_->GetIrqData()->AppendInternalSlice(startT1, durationNs1, internalTid1, cat1, nameIdentify1, + name1, depth1, parentId1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 2); +} +/** + * @tc.name: LiveProcessTableTest + * @tc.desc: Live Process table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, LiveProcessTableTest, TestSize.Level1) +{ + TS_LOGI("test31-18"); + std::string sqlSelect = "select * from live_process"; + uint64_t newTimeStamp = 1663869124160; + uint64_t dur = 200; + int32_t processID = 1; + std::string processName = "processName"; + int32_t parentProcessID = 1; + int32_t uid = 1; + std::string userName = "userName"; + double cpuUsage = 1; + int32_t pssInfo = 1; + uint64_t cpuTime = 1663888624160; + int32_t threads = 1; + int64_t diskWrites = 1; + int64_t diskReads = 1; + + stream_.traceDataCache_->GetLiveProcessData()->AppendNewData(newTimeStamp, dur, processID, processName, + parentProcessID, uid, userName, cpuUsage, pssInfo, + cpuTime, threads, diskWrites, diskReads); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: LogTableTest + * @tc.desc: Log table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, LogTableTest, TestSize.Level1) +{ + TS_LOGI("test31-19"); + std::string sqlSelect = "select * from log"; + uint64_t seq = 1; + uint64_t timestamp = 1663869124160; + uint32_t pid = 1; + uint32_t tid = 1; + DataIndex level = stream_.traceDataCache_->GetDataIndex("leve"); + DataIndex tag = stream_.traceDataCache_->GetDataIndex("tag"); + DataIndex context = stream_.traceDataCache_->GetDataIndex("context"); + uint64_t originTs = 1; + + stream_.traceDataCache_->GetHilogData()->AppendNewLogInfo(seq, timestamp, pid, tid, level, tag, context, originTs); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: MeasureTableTest + * @tc.desc: Measure table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, MeasureTableTest, TestSize.Level1) +{ + TS_LOGI("test31-20"); + std::string sqlSelect = "select * from measure"; + std::string sqlSelect1 = "select * from measure where ts = 1663869124160"; + uint32_t type = 1; + uint64_t timestamp = 1663869124160; + int64_t value = 1; + uint32_t filterId = 1; + + uint32_t type1 = 2; + uint64_t timestamp1 = 1663869224160; + int64_t value1 = 2; + uint32_t filterId1 = 2; + + stream_.traceDataCache_->GetMeasureData()->AppendMeasureData(type, timestamp, value, filterId); + stream_.traceDataCache_->GetMeasureData()->AppendMeasureData(type1, timestamp1, value1, filterId1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: MeasureFilterTableTest + * @tc.desc: Measure Filter table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, MeasureFilterTableTest, TestSize.Level1) +{ + TS_LOGI("test31-21"); + std::string sqlSelect = "select * from measure_filter"; + uint64_t filterId = stream_.traceDataCache_->GetDataIndex("filter");; + uint32_t nameIndex = stream_.traceDataCache_->GetDataIndex("name"); + uint64_t internalTid = 1; + + stream_.traceDataCache_->GetThreadMeasureFilterData()->AppendNewFilter(filterId, nameIndex, internalTid); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: MetaTableTest + * @tc.desc: Meta table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, MetaTableTest, TestSize.Level1) +{ + TS_LOGI("test31-22"); + std::string sqlSelect = "select * from meta"; + + stream_.traceDataCache_->GetMetaData(); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 9); +} +/** + * @tc.name: NativeHookTableTest + * @tc.desc: Native hook table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, NativeHookTableTest, TestSize.Level1) +{ + TS_LOGI("test31-23"); + std::string sqlSelect = "select * from native_hook"; + std::string sqlSelect1 = "select * from native_hook where id = 1"; + std::string sqlSelect2 = "select * from native_hook where ipid > 1"; + std::string sqlSelect3 = "select * from native_hook where itid >= 1"; + std::string sqlSelect4 = "select * from native_hook where callchain_id < 1"; + uint64_t callChainId = 1; + uint32_t ipid = 1; + uint32_t itid = 1; + std::string eventType = "eventType"; + DataIndex subType = stream_.traceDataCache_->GetDataIndex("subType"); + uint64_t timestamp = 1663869124160; + uint64_t endTimestamp = 1663869124360; + uint64_t duration = 200; + uint64_t addr = 1; + int64_t memSize = 1; + int64_t curMemSize = 1; + + uint64_t callChainId1 = 2; + uint32_t ipid1 = 2; + uint32_t itid1 = 2; + std::string eventType1 = "eventType1"; + DataIndex subType1 = stream_.traceDataCache_->GetDataIndex("subType1"); + uint64_t timestamp1 = 1663869224160; + uint64_t endTimestamp1 = 1663869224360; + uint64_t duration1 = 200; + uint64_t addr1 = 2; + int64_t memSize1 = 2; + int64_t curMemSize1 = 2; + + stream_.traceDataCache_->GetNativeHookData()->AppendNewNativeHookData( + callChainId, ipid, itid, eventType, subType, timestamp, endTimestamp, duration, addr, memSize, curMemSize); + stream_.traceDataCache_->GetNativeHookData()->AppendNewNativeHookData( + callChainId1, ipid1, itid1, eventType1, subType1, timestamp1, endTimestamp1, duration1, addr1, memSize1, curMemSize1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: NativeHookFrameTableTest + * @tc.desc: Native hook Frame table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, NativeHookFrameTableTest, TestSize.Level1) +{ + TS_LOGI("test31-24"); + std::string sqlSelect = "select * from native_hook_frame"; + std::string sqlSelect1 = "select * from native_hook_frame where id = 1"; + std::string sqlSelect2 = "select * from native_hook_frame where callchain_id > 1"; + std::string sqlSelect3 = "select * from native_hook_frame where symbol_id >= 1"; + std::string sqlSelect4 = "select * from native_hook_frame where file_id < 2"; + uint64_t callChainId = 1; + uint64_t depth = 1; + uint64_t ip = 1; + uint64_t sp = 1; + DataIndex symbolName = stream_.traceDataCache_->GetDataIndex("symbolName"); + DataIndex filePath = stream_.traceDataCache_->GetDataIndex("filePath"); + uint64_t offset = 1; + uint64_t symbolOffset = 1; + + uint64_t callChainId1 = 2; + uint64_t depth1 = 2; + uint64_t ip1 = 2; + uint64_t sp1 = 2; + DataIndex symbolName1 = stream_.traceDataCache_->GetDataIndex("symbolName1"); + DataIndex filePath1 = stream_.traceDataCache_->GetDataIndex("filePath1"); + uint64_t offset1 = 2; + uint64_t symbolOffset1 = 2; + + stream_.traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame(callChainId, depth, ip, sp, symbolName, + filePath, offset, symbolOffset); + stream_.traceDataCache_->GetNativeHookFrameData()->AppendNewNativeHookFrame( + callChainId1, depth1, ip1, sp1, symbolName1, filePath1, offset1, symbolOffset1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: NetworkTableTest + * @tc.desc: Network table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, NetworkTableTest, TestSize.Level1) +{ + TS_LOGI("test31-25"); + std::string sqlSelect = "select * from network"; + uint64_t newTimeStamp = 1663869124160; + uint64_t tx = 1; + uint64_t rx = 1; + uint64_t dur = 200; + double rxSpeed = 1; + double txSpeed = 1; + uint64_t packetIn = 1; + double packetInSec = 1; + uint64_t packetOut = 1; + double packetOutSec = 1; + const std::string& netType = "nettype"; + + stream_.traceDataCache_->GetNetworkData()->AppendNewNetData(newTimeStamp, tx, rx, dur, rxSpeed, txSpeed, packetIn, + packetInSec, packetOut, packetOutSec, netType); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: PerfCallchainTableTest + * @tc.desc: Perf callchain table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, PerfCallchainTableTest, TestSize.Level1) +{ + TS_LOGI("test31-26"); + std::string sqlSelect = "select * from perf_callchain"; + std::string sqlSelect1 = "select * from perf_callchain where id = 1"; + std::string sqlSelect2 = "select * from perf_callchain where callchain_id > 1"; + std::string sqlSelect3 = "select * from perf_callchain where file_id < 1"; + std::string sqlSelect4 = "select * from perf_callchain where symbol_id >= 1"; + uint64_t sampleId = stream_.traceDataCache_->GetDataIndex("sample"); + uint64_t callChainId = stream_.traceDataCache_->GetDataIndex("callChain"); + uint64_t vaddrInFile = 1; + uint64_t fileId = stream_.traceDataCache_->GetDataIndex("file"); + uint64_t symbolId = stream_.traceDataCache_->GetDataIndex("symbolId"); + + uint64_t sampleId1 = stream_.traceDataCache_->GetDataIndex("sample1"); + uint64_t callChainId1 = stream_.traceDataCache_->GetDataIndex("callChain1"); + uint64_t vaddrInFile1 = 2; + uint64_t fileId1 = stream_.traceDataCache_->GetDataIndex("file1"); + uint64_t symbolId1 = stream_.traceDataCache_->GetDataIndex("symbolId1"); + + stream_.traceDataCache_->GetPerfCallChainData()->AppendNewPerfCallChain(sampleId, callChainId, vaddrInFile, fileId, + symbolId); + + stream_.traceDataCache_->GetPerfCallChainData()->AppendNewPerfCallChain(sampleId1, callChainId1, vaddrInFile1, fileId1, + symbolId1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: PerfFilesTableTest + * @tc.desc: Perf files table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, PerfFilesTableTest, TestSize.Level1) +{ + TS_LOGI("test31-27"); + std::string sqlSelect = "select * from perf_files"; + std::string sqlSelect1 = "select * from perf_files where id = 1"; + std::string sqlSelect2 = "select * from perf_files where file_id < 1"; + uint64_t fileIds = stream_.traceDataCache_->GetDataIndex("file"); + uint32_t serial = 1; + DataIndex symbols = stream_.traceDataCache_->GetDataIndex("symbol"); + DataIndex filePath = stream_.traceDataCache_->GetDataIndex("filePath"); + + uint64_t fileIds1 = stream_.traceDataCache_->GetDataIndex("file1"); + uint32_t serial1 = 1; + DataIndex symbols1 = stream_.traceDataCache_->GetDataIndex("symbol1"); + DataIndex filePath1 = stream_.traceDataCache_->GetDataIndex("filePath1"); + + stream_.traceDataCache_->GetPerfFilesData()->AppendNewPerfFiles(fileIds, serial, symbols, filePath); + stream_.traceDataCache_->GetPerfFilesData()->AppendNewPerfFiles(fileIds1, serial1, symbols1, filePath1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: PerfReportTableTest + * @tc.desc: Perf report table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, PerfReportTableTest, TestSize.Level1) +{ + TS_LOGI("test31-28"); + std::string sqlSelect = "select * from perf_report"; + DataIndex type = stream_.traceDataCache_->GetDataIndex("type"); + DataIndex value = stream_.traceDataCache_->GetDataIndex("value"); + + stream_.traceDataCache_->GetPerfReportData()->AppendNewPerfReport(type, value); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: PerfSampleTableTest + * @tc.desc: Perf sample table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, PerfSampleTableTest, TestSize.Level1) +{ + TS_LOGI("test31-29"); + std::string sqlSelect = "select * from perf_sample"; + std::string sqlSelect1 = "select * from perf_sample where id = 1"; + std::string sqlSelect2 = "select * from perf_sample where callchain_id > 1"; + std::string sqlSelect3 = "select * from perf_sample where thread_id < 1"; + std::string sqlSelect4 = "select * from perf_sample where event_type_id >= 1"; + std::string sqlSelect5 = "select * from perf_sample where cpu_id <= 1"; + uint64_t sampleId = stream_.traceDataCache_->GetDataIndex("type"); + uint64_t timestamp = 1663869124160; + uint64_t tid = 1; + uint64_t eventCount = 2; + uint64_t eventTypeId = 1; + uint64_t timestampTrace = 1; + uint64_t cpuId = 1; + uint64_t threadState = stream_.traceDataCache_->GetDataIndex("threadState"); + + uint64_t sampleId1 = stream_.traceDataCache_->GetDataIndex("type1"); + uint64_t timestamp1 = 1663869124160; + uint64_t tid1 = 2; + uint64_t eventCount1 = 3; + uint64_t eventTypeId1 = 2; + uint64_t timestampTrace1 = 2; + uint64_t cpuId1 = 2; + uint64_t threadState1 = stream_.traceDataCache_->GetDataIndex("threadState1"); + + stream_.traceDataCache_->GetPerfSampleData()->AppendNewPerfSample(sampleId, timestamp, tid, eventCount, eventTypeId, + timestampTrace, cpuId, threadState); + stream_.traceDataCache_->GetPerfSampleData()->AppendNewPerfSample( + sampleId1, timestamp1, tid1, eventCount1, eventTypeId1, timestampTrace1, cpuId1, threadState1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: PerfThreadTableTest + * @tc.desc: Perf Thread table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, PerfThreadTableTest, TestSize.Level1) +{ + TS_LOGI("test31-30"); + std::string sqlSelect = "select * from perf_thread"; + std::string sqlSelect1 = "select * from perf_thread where id = 1"; + std::string sqlSelect2 = "select * from perf_thread where thread_id > 1"; + std::string sqlSelect3 = "select * from perf_thread where process_id < 1"; + uint64_t pid = 1; + uint64_t tid = 1; + DataIndex threadName = stream_.traceDataCache_->GetDataIndex("threadState"); + + uint64_t pid1 = 2; + uint64_t tid1 = 2; + DataIndex threadName1 = stream_.traceDataCache_->GetDataIndex("threadState1"); + + stream_.traceDataCache_->GetPerfThreadData()->AppendNewPerfThread(pid, tid, threadName); + stream_.traceDataCache_->GetPerfThreadData()->AppendNewPerfThread(pid1, tid1, threadName1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: ProcessTableTest + * @tc.desc: Process table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ProcessTableTest, TestSize.Level1) +{ + TS_LOGI("test31-31"); + std::string sqlSelect = "select * from process"; + std::string sqlSelect1 = "select * from process where id = 1"; + + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: ProcessFilterTableTest + * @tc.desc: Process filter table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ProcessFilterTableTest, TestSize.Level1) +{ + TS_LOGI("test31-32"); + std::string sqlSelect = "select * from process_filter"; + uint64_t id = 1; + DataIndex name = stream_.traceDataCache_->GetDataIndex("name"); + uint32_t internalPid = 1; + + stream_.traceDataCache_->GetProcessFilterData()->AppendNewFilter(id, name, internalPid); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: ProcessMeasureTableTest + * @tc.desc: Process Measure table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ProcessMeasureTableTest, TestSize.Level1) +{ + TS_LOGI("test31-33"); + std::string sqlSelect = "select * from process_measure"; + uint32_t type = 1; + uint64_t timestamp = 1663869124160; + int64_t value = 1; + uint32_t filterId = 1; + + stream_.traceDataCache_->GetProcessMeasureData()->AppendMeasureData(type, timestamp, value, filterId); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: ProcessMeasureFilterTableTest + * @tc.desc: Process Measure filter table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ProcessMeasureFilterTableTest, TestSize.Level1) +{ + TS_LOGI("test31-34"); + std::string sqlSelect = "select * from process_measure_filter"; + std::string sqlSelect1 = "select * from process_measure_filter where id = 1"; + std::string sqlSelect2 = "select * from process_measure_filter where ipid < 1"; + std::string sqlSelect3 = "select * from process_measure_filter where name = \"name\""; + uint64_t id = 1; + DataIndex name = stream_.traceDataCache_->GetDataIndex("name"); + uint32_t internalPid = 1; + + uint64_t id1 = 1; + DataIndex name1 = stream_.traceDataCache_->GetDataIndex("name1"); + uint32_t internalPid1 = 1; + + stream_.traceDataCache_->GetProcessMeasureFilterData()->AppendNewFilter(id, name, internalPid); + stream_.traceDataCache_->GetProcessMeasureFilterData()->AppendNewFilter(id1, name1, internalPid1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 2); +} +/** + * @tc.name: RawTableTest + * @tc.desc: Raw table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, RawTableTest, TestSize.Level1) +{ + TS_LOGI("test31-35"); + std::string sqlSelect = "select * from raw"; + std::string sqlSelect1 = "select * from raw where id = 1"; + std::string sqlSelect2 = "select * from raw where name = \"sched_waking\""; + std::string sqlSelect3 = "select * from raw where ts = 1663869124160"; + std::string sqlSelect4 = "select * from raw where itid < 2"; + uint32_t id = 1; + uint64_t timestamp = 1663869124160; + uint32_t name = stream_.traceDataCache_->GetDataIndex("cpu_idle"); + uint32_t cpu = 1; + uint32_t internalTid = 1; + + uint32_t id1 = 2; + uint64_t timestamp1 = 1663869224160; + uint32_t name1 = stream_.traceDataCache_->GetDataIndex("sched_waking"); + uint32_t cpu1 = 2; + uint32_t internalTid1 = 2; + + stream_.traceDataCache_->GetRawData()->AppendRawData(id, timestamp, name, cpu, internalTid); + stream_.traceDataCache_->GetRawData()->AppendRawData(id1, timestamp1, name1, cpu1, internalTid1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: SchedSliceTest + * @tc.desc: Sched slice table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, SchedSliceTest, TestSize.Level1) +{ + TS_LOGI("test31-36"); + std::string sqlSelect = "select * from sched_slice"; + std::string sqlSelect1 = "select * from sched_slice where id = 1"; + std::string sqlSelect2 = "select * from sched_slice where ts > 1"; + std::string sqlSelect3 = "select * from sched_slice where cpu < 1"; + std::string sqlSelect4 = "select * from sched_slice where itid >= 1"; + std::string sqlSelect5 = "select * from sched_slice where ipid <= 1"; + std::string sqlSelect6 = "select * from sched_slice where dur >= 200"; + uint64_t ts = 1663869124160; + uint64_t dur = 200; + uint64_t cpu = 1; + uint64_t internalTid = 1; + uint64_t endState = 1; + uint64_t priority = 1; + + uint64_t ts1 = 1663869224160; + uint64_t dur1 = 200; + uint64_t cpu1 = 2; + uint64_t internalTid1 = 2; + uint64_t endState1 = 2; + uint64_t priority1 = 2; + + stream_.traceDataCache_->GetSchedSliceData()->AppendSchedSlice(ts, dur, cpu, internalTid, endState, priority); + stream_.traceDataCache_->GetSchedSliceData()->AppendSchedSlice(ts1, dur1, cpu1, internalTid1, endState1, priority1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect6.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: SmapsTest + * @tc.desc: Smaps table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, SmapsTest, TestSize.Level1) +{ + TS_LOGI("test31-37"); + std::string sqlSelect = "select * from smaps"; + uint64_t timeStamp = 1663869124160; + std::string startAddr = "startAddr"; + std::string endAddr = "endAddr"; + uint64_t dirty = 1; + uint64_t swapper = 1; + uint64_t rss = 1; + uint64_t pss = 1; + uint64_t size = 2; + double reside = 1; + DataIndex protectionId = stream_.traceDataCache_->GetDataIndex("protection"); + DataIndex pathId = stream_.traceDataCache_->GetDataIndex("path"); + + stream_.traceDataCache_->GetSmapsData()->AppendNewData(timeStamp, startAddr, endAddr, dirty, swapper, rss, pss, + size, reside, protectionId, pathId); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: StatTableTest + * @tc.desc: Stat table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, StatTableTest, TestSize.Level1) +{ + TS_LOGI("test31-38"); + std::string sqlSelect = "select * from stat"; + stream_.traceDataCache_->GetStatAndInfo(); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 395); +} +/** + * @tc.name: SymbolsTableTest + * @tc.desc: Symbols table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, SymbolsTableTest, TestSize.Level1) +{ + TS_LOGI("test31-39"); + std::string sqlSelect = "select * from symbols"; + std::string sqlSelect1 = "select * from symbols where id = 1"; + std::string sqlSelect2 = "select * from symbols where id < 1"; + const DataIndex& name = stream_.traceDataCache_->GetDataIndex("name"); + const uint64_t& addr = 1; + + const DataIndex& name1 = stream_.traceDataCache_->GetDataIndex("name1"); + const uint64_t& addr1 = 2; + + stream_.traceDataCache_->GetSymbolsData()->InsertSymbol(name, addr); + stream_.traceDataCache_->GetSymbolsData()->InsertSymbol(name1, addr1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: SyscallTableTest + * @tc.desc: Syscall table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, SyscallTableTest, TestSize.Level1) +{ + TS_LOGI("test31-40"); + std::string sqlSelect = "select * from syscall"; + int64_t sysCallNum = 1; + DataIndex type = stream_.traceDataCache_->GetDataIndex("type"); + uint64_t ipid = 1; + uint64_t timestamp = 1663869124160; + int64_t ret = 1; + + stream_.traceDataCache_->GetSysCallData()->AppendSysCallData(sysCallNum, type, ipid, timestamp, ret); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: SysEventFilterTableTest + * @tc.desc: SysEventFilter table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, SysEventFilterTableTest, TestSize.Level1) +{ + TS_LOGI("test31-41"); + std::string sqlSelect = "select * from sys_event_filter"; + std::string sqlSelect1 = "select * from sys_event_filter where id = 1"; + std::string sqlSelect2 = "select * from sys_event_filter where id > 1"; + std::string sqlSelect3 = "select * from sys_event_filter where id < 1"; + std::string sqlSelect4 = "select * from sys_event_filter where id >= 1"; + std::string sqlSelect5 = "select * from sys_event_filter where id <= 1"; + uint64_t filterId = 1; + DataIndex type = stream_.traceDataCache_->GetDataIndex("type"); + DataIndex nameId = stream_.traceDataCache_->GetDataIndex("name"); + + uint64_t filterId1 = 2; + DataIndex type1 = stream_.traceDataCache_->GetDataIndex("type1"); + DataIndex nameId1 = stream_.traceDataCache_->GetDataIndex("name1"); + + stream_.traceDataCache_->GetSysMeasureFilterData()->AppendNewFilter(filterId, type, nameId); + stream_.traceDataCache_->GetSysMeasureFilterData()->AppendNewFilter(filterId1, type1, nameId1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 2); +} +/** + * @tc.name: SysMemMeasureTableTest + * @tc.desc: SysMemMeasure table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, SysMemMeasureTableTest, TestSize.Level1) +{ + TS_LOGI("test31-42"); + std::string sqlSelect = "select * from sys_mem_measure"; + uint32_t type = 1; + uint64_t timestamp = 1663869124160; + int64_t value = 1; + uint32_t filterId = stream_.traceDataCache_->GetDataIndex("filter"); + + stream_.traceDataCache_->GetSysMemMeasureData()->AppendMeasureData(type, timestamp, value, filterId); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: ThreadTableTest + * @tc.desc: Thread table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ThreadTableTest, TestSize.Level1) +{ + TS_LOGI("test31-43"); + std::string sqlSelect = "select * from thread"; + + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: ThreadFilterTableTest + * @tc.desc: ThreadFilter table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ThreadFilterTableTest, TestSize.Level1) +{ + TS_LOGI("test31-44"); + std::string sqlSelect = "select * from thread_filter"; + uint64_t filterId = stream_.traceDataCache_->GetDataIndex("ilter"); + uint32_t nameIndex = stream_.traceDataCache_->GetDataIndex("name"); + uint64_t internalTid = 1; + + stream_.traceDataCache_->GetThreadFilterData()->AppendNewFilter(filterId, nameIndex, internalTid); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +/** + * @tc.name: ThreadStateTableTest + * @tc.desc: ThreadState table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, ThreadStateTableTest, TestSize.Level1) +{ + TS_LOGI("test31-45"); + std::string sqlSelect = "select * from thread_state"; + std::string sqlSelect1 = "select * from thread_state where id = 1"; + std::string sqlSelect2 = "select * from thread_state where tid > 1"; + std::string sqlSelect3 = "select * from thread_state where pid < 1"; + std::string sqlSelect4 = "select * from thread_state where itid >= 1"; + std::string sqlSelect5 = "select * from thread_state where cpu <= 1"; + std::string sqlSelect6 = "select * from thread_state where ts = 1663869124160"; + std::string sqlSelect7 = "select * from thread_state where dur = 1"; + std::string sqlSelect8 = "select * from thread_state where state = \"idState\""; + InternalTime ts = 1663869124160; + InternalTime dur = 200; + InternalCpu cpu = 1; + InternalTid itid = 1; + TableRowId idState = 1; + + InternalTime ts1 = 1663869224160; + InternalTime dur1 = 200; + InternalCpu cpu1 = 2; + InternalTid itid1 = 2; + TableRowId idState1 = 2; + + stream_.traceDataCache_->GetThreadStateData()->AppendThreadState(ts, dur, cpu, itid, idState); + stream_.traceDataCache_->GetThreadStateData()->AppendThreadState(ts1, dur1, cpu1, itid1, idState1); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect1.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect2.c_str(), false); + EXPECT_EQ(row, 2); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect3.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect4.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect5.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect6.c_str(), false); + EXPECT_EQ(row, 1); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect7.c_str(), false); + EXPECT_EQ(row, 0); + row = stream_.traceDataCache_->SearchDatabase(sqlSelect8.c_str(), false); + EXPECT_EQ(row, 0); +} +/** + * @tc.name: TraceRangeTableTest + * @tc.desc: TraceRange table test + * @tc.type: FUNC + */ +HWTEST_F(TableTest, TraceRangeTableTest, TestSize.Level1) +{ + TS_LOGI("test31-46"); + std::string sqlSelect = "select * from trace_range"; + + stream_.traceDataCache_->UpdateTraceRange(); + auto row = stream_.traceDataCache_->SearchDatabase(sqlSelect.c_str(), false); + EXPECT_EQ(row, 1); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/host/trace_streamer/test/unittest/wasm_func_test.cpp b/host/trace_streamer/test/unittest/wasm_func_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03a3c1a920e661d3c05b700e156656e9140f1d26 --- /dev/null +++ b/host/trace_streamer/test/unittest/wasm_func_test.cpp @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#include +#include + +#include "rpc/rpc_server.h" +#include "wasm_func.h" + +using namespace testing::ext; +namespace SysTuning { +namespace TraceStreamer { +class WasmFuncTest : public ::testing::Test { +public: + void SetUp() + { + stream_.InitFilter(); + } + void TearDown() {} +public: + TraceStreamerSelector stream_ = {}; +}; +constexpr int MAX_TESET_BUF_SIZE = 1024; + +/** + * @tc.name: CorrectTraceData + * @tc.desc: Upload correct trace file data + * @tc.type: FUNC + */ +HWTEST_F(WasmFuncTest, CorrectTraceData, TestSize.Level1) +{ + TS_LOGI("test32-1"); + std::string parseData("sugov:0-178 ( 178) [001] .... 28462.257501: cpu_frequency: state=816000 cpu_id=0 \n"); + std::string sqlQuery("select * from measure;"); + + char out[MAX_TESET_BUF_SIZE] = {0}; + + int ret = TraceStreamerParseData((const uint8_t*)parseData.c_str(), parseData.length()); + EXPECT_EQ(0, ret); + ret = TraceStreamerParseDataOver(); + EXPECT_EQ(0, ret); + ret = TraceStreamerSqlQuery((const uint8_t*)sqlQuery.c_str(), sqlQuery.length(), (uint8_t*)out, MAX_TESET_BUF_SIZE); + TS_LOGI("sql value:%s", out); + EXPECT_NE(-1, ret); + ret = TraceStreamerReset(); + EXPECT_EQ(0, ret); +} + +/** + * @tc.name: WrongTraceData + * @tc.desc: Upload wrong tracking file data + * @tc.type: FUNC + */ +HWTEST_F(WasmFuncTest, WrongTraceData, TestSize.Level1) +{ + TS_LOGI("test32-2"); + std::string parseData("sugov:0-178 ( 178) [001] .... 28462.277458: cpu_frequency: state=600000 cpu_id=2 \n"); + std::string sqlQuery("select * from measure_a;"); + + char out[MAX_TESET_BUF_SIZE] = {0}; + + int ret = TraceStreamerParseData((const uint8_t*)parseData.c_str(), parseData.length()); + EXPECT_EQ(0, ret); + ret = TraceStreamerParseDataOver(); + EXPECT_EQ(0, ret); + ret = TraceStreamerSqlQuery((const uint8_t*)sqlQuery.c_str(), sqlQuery.length(), (uint8_t*)out, MAX_TESET_BUF_SIZE); + TS_LOGI("sql value:%s", out); + EXPECT_EQ(-1, ret); + ret = TraceStreamerReset(); + EXPECT_EQ(0, ret); +} +} // namespace TraceStreamer +} // namespace SysTuning \ No newline at end of file