diff --git a/ide/src/trace/bean/BoxSelection.ts b/ide/src/trace/bean/BoxSelection.ts index 22ecff1997f517409ee04e0b83a9861ec38066d1..a77c8bae5b376ce05f291d0cb804be807762d84c 100644 --- a/ide/src/trace/bean/BoxSelection.ts +++ b/ide/src/trace/bean/BoxSelection.ts @@ -103,6 +103,8 @@ export class SelectionParam { irqCallIds: Array = []; softIrqCallIds: Array = []; funTids: Array = []; + threadSysCallIds: Array = []; + processSysCallIds: Array = []; funAsync: Array<{ name: string; pid: number, tid: number | undefined }> = []; funCatAsync: Array<{ pid: number; threadName: string }> = []; nativeMemory: Array = []; @@ -195,6 +197,16 @@ export class SelectionParam { } } + // @ts-ignore + pushSysCallIds(it: TraceRow): void { + if (it.rowType === TraceRow.ROW_TYPE_THREAD_SYS_CALL) { + const arr = it.rowId?.split('-'); + if (arr && arr.length === 3) { + this.threadSysCallIds.push(parseInt(arr[1])); + } + } + } + // @ts-ignore pushCpuStateFilterIds(it: TraceRow): void { if (it.rowType === TraceRow.ROW_TYPE_CPU_STATE_ALL) { @@ -259,6 +271,14 @@ export class SelectionParam { if (it.rowType === TraceRow.ROW_TYPE_PROCESS || it.rowType === TraceRow.ROW_TYPE_IMPORT) { sp.pushPidToSelection(this, it.rowId!, it.summaryProtoPid); sp.pushPidToSelection(this, it.rowId!); + if (it.getRowSettingCheckStateByKey('SysCall Event')) { + let pid = parseInt(it.rowId!); + if (!isNaN(pid!)) { + if (!this.processSysCallIds.includes(pid!)) { + this.processSysCallIds.push(pid!); + } + } + } if (it.getAttribute('hasStartup') === 'true') { this.startup = true; } @@ -1349,6 +1369,7 @@ export class SelectionParam { this.pushStaticInit(it, sp); this.pushAppStartUp(it, sp); this.pushThread(it, sp); + this.pushSysCallIds(it); this.pushVirtualMemory(it, sp); this.pushFps(it, sp); this.pushCpuAbility(it, sp); @@ -1389,6 +1410,16 @@ export class BoxJumpParam { currentId: string | undefined | null; } +export class SysCallBoxJumpParam { + traceId: string | undefined | null; + leftNs: number = 0; + rightNs: number = 0; + processId: number[] | undefined; + threadId: number[] | undefined; + sysCallId: number | undefined; + isJumpPage: boolean | undefined; +} + export class SliceBoxJumpParam { traceId: string | undefined | null; leftNs: number = 0; diff --git a/ide/src/trace/component/SpSystemTrace.event.ts b/ide/src/trace/component/SpSystemTrace.event.ts index 165126d615a35e2c5b1c3906c4cde10c37673cfa..da0632941ac24396ceca06f69b997ea12617e41c 100644 --- a/ide/src/trace/component/SpSystemTrace.event.ts +++ b/ide/src/trace/component/SpSystemTrace.event.ts @@ -63,6 +63,7 @@ import { XpowerGpuFreqStruct, XpowerGpuFreqStructOnClick } from '../database/ui- import { XpowerThreadCountStruct, XpowerThreadCountStructOnClick } from '../database/ui-worker/ProcedureWorkerXpowerThreadCount'; import { XpowerGpuFreqCountStruct, XpowerGpuFreqCountStructOnClick } from '../database/ui-worker/ProcedureWorkerXpowerGpuFreqCount'; import { SnapShotOnClick, SnapShotStruct } from '../database/ui-worker/ProcedureWorkerSnaps'; +import { ThreadSysCallStruct, ThreadSysCallStructOnClick } from '../database/ui-worker/ProcedureWorkerThreadSysCall'; function timeoutJudge(sp: SpSystemTrace): number { let timeoutJudge = window.setTimeout((): void => { @@ -421,6 +422,7 @@ function allStructOnClick(clickRowType: string, sp: SpSystemTrace, row?: TraceRo .then(() => sampleStructOnClick(clickRowType, sp, row as TraceRow, entry as SampleStruct)) .then(() => gpuCounterStructOnClick(clickRowType, sp, entry as GpuCounterStruct)) .then(() => PerfToolsStructOnClick(clickRowType, sp, entry as PerfToolStruct)) + .then(() => ThreadSysCallStructOnClick(clickRowType, sp, entry as ThreadSysCallStruct)) .then(() => SnapShotOnClick(clickRowType, sp, entry as SnapShotStruct)) .then(() => { if (!JankStruct.hoverJankStruct && JankStruct.delJankLineFlag) { @@ -578,7 +580,8 @@ function spSystemTraceDocumentOnMouseMoveMouseUp( sp.hoverStructNull(); } const transformYMatch = sp.canvasPanel?.style.transform.match(/\((\d+)[^\)]+\)/); - const transformY = transformYMatch![1]; + if (transformYMatch && transformYMatch![1]) { + const transformY = transformYMatch![1]; let favoriteHeight = sp.favoriteChartListEL!.getBoundingClientRect().height; // @ts-ignore let memTr = rows.filter((item: unknown) => item.rowType === TraceRow.ROW_TYPE_MEM); @@ -611,6 +614,7 @@ function spSystemTraceDocumentOnMouseMoveMouseUp( tr.findHoverStruct?.(); tr.focusHandler?.(ev); }); + } requestAnimationFrame(() => sp.refreshCanvas(true, 'sp move up')); } diff --git a/ide/src/trace/component/SpSystemTrace.ts b/ide/src/trace/component/SpSystemTrace.ts index c771f929b9aa4fa9d68a6e5737b19b4ee28a9a09..32bcd13688b70ad7745652180fb1416d4a1ff4a2 100644 --- a/ide/src/trace/component/SpSystemTrace.ts +++ b/ide/src/trace/component/SpSystemTrace.ts @@ -144,6 +144,7 @@ import { XpowerThreadInfoStruct } from '../database/ui-worker/ProcedureWorkerXpo import { XpowerGpuFreqStruct } from '../database/ui-worker/ProcedureWorkerXpowerGpuFreq'; import { LitProgressBar } from '../../base-ui/progress-bar/LitProgressBar'; import { SnapShotStruct } from '../database/ui-worker/ProcedureWorkerSnaps'; +import { ThreadSysCallStruct } from '../database/ui-worker/ProcedureWorkerThreadSysCall'; function dpr(): number { return window.devicePixelRatio || 1; @@ -1370,6 +1371,7 @@ export class SpSystemTrace extends BaseElement { CpuStruct.hoverCpuStruct = undefined; CpuFreqStruct.hoverCpuFreqStruct = undefined; ThreadStruct.hoverThreadStruct = undefined; + ThreadSysCallStruct.hoverStruct = undefined; FuncStruct.hoverFuncStruct = undefined; ProcessMemStruct.hoverProcessMemStruct = undefined; HiPerfCpuStruct.hoverStruct = undefined; @@ -1412,6 +1414,7 @@ export class SpSystemTrace extends BaseElement { CpuFreqStruct.selectCpuFreqStruct = undefined; ThreadStruct.selectThreadStruct = undefined; ThreadStruct.isClickPrio = false; + ThreadSysCallStruct.selectStruct = undefined; FuncStruct.selectFuncStruct = undefined; SpHiPerf.selectCpuStruct = undefined; CpuStateStruct.selectStateStruct = undefined; diff --git a/ide/src/trace/component/chart/SpProcessChart.ts b/ide/src/trace/component/chart/SpProcessChart.ts index 58265a037ddea48b3b87c97fe269de713d5e7031..ab9af407318177780046a4e5f6689e41e8436567 100644 --- a/ide/src/trace/component/chart/SpProcessChart.ts +++ b/ide/src/trace/component/chart/SpProcessChart.ts @@ -29,6 +29,7 @@ import { SoRender, SoStruct } from '../../database/ui-worker/ProcedureWorkerSoIn import { FlagsConfig } from '../SpFlags'; import { processDataSender } from '../../database/data-trafic/process/ProcessDataSender'; import { threadDataSender } from '../../database/data-trafic/process/ThreadDataSender'; +import { threadSysCallDataSender } from '../../database/data-trafic/process/ThreadSysCallDataSender'; import { funcDataSender } from '../../database/data-trafic/process/FuncDataSender'; import { processMemDataSender } from '../../database/data-trafic/process/ProcessMemDataSender'; import { processStartupDataSender } from '../../database/data-trafic/process/ProcessStartupDataSender'; @@ -43,6 +44,7 @@ import { queryAllSoInitNames, queryAllSrcSlices, queryEventCountMap, queryCallst import { queryProcessByTable, queryProcessContentCount, + querySysCallThreadIds, queryProcessMem, queryProcessSoMaxDepth, queryProcessThreadsByTable, @@ -53,13 +55,13 @@ import { } from '../../database/sql/ProcessThread.sql'; import { queryAllJankProcess } from '../../database/sql/Janks.sql'; import { BaseStruct } from '../../bean/BaseStruct'; -import { promises } from 'dns'; import { HangStruct } from '../../database/ui-worker/ProcedureWorkerHang'; import { hangDataSender } from '../../database/data-trafic/HangDataSender'; import { SpHangChart } from './SpHangChart'; import { queryHangData } from '../../database/sql/Hang.sql'; import { EmptyRender } from '../../database/ui-worker/cpu/ProcedureWorkerCPU'; import { renders } from '../../database/ui-worker/ProcedureWorker'; +import { ThreadSysCallStruct } from '../../database/ui-worker/ProcedureWorkerThreadSysCall'; const FOLD_HEIGHT = 24; export class SpProcessChart { @@ -482,6 +484,12 @@ export class SpProcessChart { }); info('convert tid and maxDepth array to map'); let pidCountArray = await queryProcessContentCount(traceId); + info('fetch syscall event tid'); + let sysCallTidArray = await querySysCallThreadIds(traceId); + Utils.getInstance().sysCallEventTidsMap.clear(); + sysCallTidArray.forEach((it) => { + Utils.getInstance().sysCallEventTidsMap.set(it.tid, it); + }); info('fetch per process pid,switch_count,thread_count,slice_count,mem_count'); pidCountArray.forEach((it) => { //@ts-ignore @@ -612,6 +620,7 @@ export class SpProcessChart { processRow.rowType = TraceRow.ROW_TYPE_PROCESS; processRow.rowParentId = ''; processRow.style.height = '40px'; + this.processRowSettingConfig(processRow); processRow.folder = true; if ( //@ts-ignore @@ -644,6 +653,20 @@ export class SpProcessChart { return processRow; } + processRowSettingConfig(row: TraceRow): void { + row.rowSettingCheckBoxList = ['SysCall Event']; + row.addRowSettingCheckBox(false); + row.rowSetting = 'enable'; + row.rowSettingPopoverDirection = 'bottomLeft'; + row.onRowSettingCheckBoxChangeHandler = (value): void => { + row.childrenList.forEach((childRow) => { + if (childRow.rowType === TraceRow.ROW_TYPE_THREAD_SYS_CALL) { + childRow.rowDiscard = !row.getRowSettingCheckStateByKey('SysCall Event'); + } + }) + }; + } + addProcessRowListener(processRow: TraceRow, actualRow: TraceRow | null): void { let offsetYTimeOut: unknown = undefined; processRow.addEventListener('expansion-change', (e: unknown) => { @@ -991,6 +1014,58 @@ export class SpProcessChart { return null; } + addThreadSysCallRow( + data: { + pid: number | null; + processName: string | null; + }, + processRow: TraceRow, + threadRow: TraceRow, + thread: unknown + ): TraceRow | null { + //@ts-ignore + const ids = Utils.getInstance().sysCallEventTidsMap.get(thread.tid); + if (ids) { + const threadSysCallRow = TraceRow.skeleton(); + threadSysCallRow.rowType = TraceRow.ROW_TYPE_THREAD_SYS_CALL; + threadSysCallRow.rowId = `${data.pid}-${ids.itid}-syscall`; + threadSysCallRow.rowParentId = `${data.pid}`; + threadSysCallRow.rowHidden = !processRow.expansion; + threadSysCallRow.style.width = '100%'; + threadSysCallRow.name = `syscall event ${ids.tid}`; + threadSysCallRow.addTemplateTypes('SysCallEvent'); + threadSysCallRow.setAttribute('children', ''); + threadSysCallRow.supplierFrame = async (): Promise => { + let promiseData = threadSysCallDataSender(ids.itid!, ids.tid!, data.pid!, threadSysCallRow); + if (promiseData === null) { + return new Promise>((resolve) => resolve([])); + } else { + return promiseData.then(); + } + }; + threadSysCallRow.favoriteChangeHandler = this.trace.favoriteChangeHandler; + threadSysCallRow.selectChangeHandler = this.trace.selectChangeHandler; + threadSysCallRow.findHoverStruct = (): void => { + ThreadSysCallStruct.hoverStruct = threadSysCallRow.getHoverStruct(); + }; + threadSysCallRow.onThreadHandler = rowThreadHandler( + 'threadSysCall', + 'context', + { + type: threadSysCallRow.rowId, + translateY: threadSysCallRow.translateY, + }, + threadSysCallRow, + this.trace + ); + threadSysCallRow.rowDiscard = true; + processRow.addChildTraceRowAfter(threadSysCallRow, threadRow); + return threadSysCallRow; + } + return null; + } + + jankSenderCallback( res: JankStruct[], type: string, @@ -1336,6 +1411,7 @@ export class SpProcessChart { // @ts-ignore this.insertRowToDoc(it, j, thread, pRow, tRow, list, tRowArr, actualRow, expectedRow, hangRow, startupRow, soRow); this.addFuncStackRow(it, thread, j, list, tRowArr, tRow, pRow); + this.addThreadSysCallRow(it, pRow, tRow, thread); // @ts-ignore if ((thread.switchCount || 0) === 0) { tRow.rowDiscard = true; diff --git a/ide/src/trace/component/trace/base/SysCallUtils.ts b/ide/src/trace/component/trace/base/SysCallUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..3b8609a10481af357255c43e73112320b1676df1 --- /dev/null +++ b/ide/src/trace/component/trace/base/SysCallUtils.ts @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const SysCallMap = new Map([ + [0, "sys_io_setup"], + [1, "sys_io_destroy"], + [2, "sys_io_submit"], + [3, "sys_io_cancel"], + [4, "sys_io_getevents"], + [5, "sys_setxattr"], + [6, "sys_lsetxattr"], + [7, "sys_fsetxattr"], + [8, "sys_getxattr"], + [9, "sys_lgetxattr"], + [10, "sys_fgetxattr"], + [11, "sys_listxattr"], + [12, "sys_llistxattr"], + [13, "sys_flistxattr"], + [14, "sys_removexattr"], + [15, "sys_lremovexattr"], + [16, "sys_fremovexattr"], + [17, "sys_getcwd"], + [18, "sys_lookup_dcookie"], + [19, "sys_eventfd2"], + [20, "sys_epoll_create1"], + [21, "sys_epoll_ctl"], + [22, "sys_epoll_pwait"], + [23, "sys_dup"], + [24, "sys_dup3"], + [25, "sys_fcntl"], + [26, "sys_inotify_init1"], + [27, "sys_inotify_add_watch"], + [28, "sys_inotify_rm_watch"], + [29, "sys_ioctl"], + [30, "sys_ioprio_set"], + [31, "sys_ioprio_get"], + [32, "sys_flock"], + [33, "sys_mknodat"], + [34, "sys_mkdirat"], + [35, "sys_unlinkat"], + [36, "sys_symlinkat"], + [37, "sys_linkat"], + [38, "sys_renameat"], + [39, "sys_umount2"], + [40, "sys_mount"], + [41, "sys_pivot_root"], + [42, "sys_nfsservctl"], + [43, "sys_statfs"], + [44, "sys_fstatfs"], + [45, "sys_truncate"], + [46, "sys_ftruncate"], + [47, "sys_fallocate"], + [48, "sys_faccessat"], + [49, "sys_chdir"], + [50, "sys_fchdir"], + [51, "sys_chroot"], + [52, "sys_fchmod"], + [53, "sys_fchmodat"], + [54, "sys_fchownat"], + [55, "sys_fchown"], + [56, "sys_openat"], + [57, "sys_close"], + [58, "sys_vhangup"], + [59, "sys_pipe2"], + [60, "sys_quotactl"], + [61, "sys_getdents64"], + [62, "sys_lseek"], + [63, "sys_read"], + [64, "sys_write"], + [65, "sys_readlinkat"], + [66, "sys_fstatat"], + [67, "sys_fstat"], + [68, "sys_sync"], + [69, "sys_fsync"], + [70, "sys_fdatasync"], + [71, "sys_sync_file_range"], + [72, "sys_timerfd_create"], + [73, "sys_timerfd_settime"], + [74, "sys_timerfd_gettime"], + [75, "sys_utimensat"], + [76, "sys_acct"], + [77, "sys_capget"], + [78, "sys_capset"], + [79, "sys_personality"], + [93, "sys_exit"], + [94, "sys_exit_group"], + [95, "sys_waitid"], + [96, "sys_set_tid_address"], + [97, "sys_unshare"], + [98, "sys_futex"], + [99, "sys_set_robust_list"], + [100, "sys_get_robust_list"], + [101, "sys_nanosleep"], + [102, "sys_getitimer"], + [103, "sys_setitimer"], + [104, "sys_kexec_load"], + [105, "sys_init_module"], + [106, "sys_delete_module"], + [107, "sys_timer_create"], + [108, "sys_timer_settime"], + [109, "sys_timer_gettime"], + [110, "sys_timer_getoverrun"], + [111, "sys_timer_delete"], + [112, "sys_clock_settime"], + [113, "sys_clock_gettime"], + [114, "sys_clock_getres"], + [115, "sys_clock_nanosleep"], + [116, "sys_syslog"], + [117, "sys_ptrace"], + [118, "sys_sched_setparam"], + [119, "sys_sched_setscheduler"], + [120, "sys_sched_getscheduler"], + [121, "sys_sched_getparam"], + [122, "sys_sched_setaffinity"], + [123, "sys_sched_getaffinity"], + [124, "sys_sched_yield"], + [125, "sys_sched_get_priority_max"], + [126, "sys_sched_get_priority_min"], + [127, "sys_sched_rr_get_interval"], + [128, "sys_restart_syscall"], + [129, "sys_kill"], + [130, "sys_tkill"], + [131, "sys_tgkill"], + [132, "sys_sigaltstack"], + [133, "sys_rt_sigsuspend"], + [134, "sys_rt_sigaction"], + [135, "sys_rt_sigprocmask"], + [136, "sys_rt_sigpending"], + [137, "sys_rt_sigtimedwait"], + [138, "sys_rt_sigqueueinfo"], + [139, "sys_rt_sigreturn"], + [140, "sys_setpriority"], + [141, "sys_getpriority"], + [142, "sys_reboot"], + [143, "sys_setregid"], + [144, "sys_setgid"], + [145, "sys_setreuid"], + [146, "sys_setuid"], + [147, "sys_setresuid"], + [148, "sys_getresuid"], + [149, "sys_setresgid"], + [150, "sys_getresgid"], + [151, "sys_setfsuid"], + [152, "sys_setfsgid"], + [153, "sys_times"], + [154, "sys_setpgid"], + [155, "sys_getpgid"], + [156, "sys_getsid"], + [157, "sys_setsid"], + [158, "sys_getgroups"], + [159, "sys_setgroups"], + [160, "sys_uname"], + [161, "sys_sethostname"], + [162, "sys_setdomainname"], + [163, "sys_getrlimit"], + [164, "sys_setrlimit"], + [165, "sys_getrusage"], + [166, "sys_umask"], + [167, "sys_prctl"], + [168, "sys_getcpu"], + [169, "sys_gettimeofday"], + [170, "sys_settimeofday"], + [171, "sys_adjtimex"], + [172, "sys_getpid"], + [173, "sys_getppid"], + [174, "sys_getuid"], + [175, "sys_geteuid"], + [176, "sys_getgid"], + [177, "sys_getegid"], + [178, "sys_gettid"], + [179, "sys_sysinfo"], + [180, "sys_mq_open"], + [181, "sys_mq_unlink"], + [182, "sys_mq_timedsend"], + [183, "sys_mq_timedreceive"], + [184, "sys_mq_notify"], + [185, "sys_mq_getsetattr"], + [186, "sys_msgget"], + [187, "sys_msgctl"], + [188, "sys_msgrcv"], + [189, "sys_msgsnd"], + [190, "sys_semget"], + [191, "sys_semctl"], + [192, "sys_semop"], + [193, "sys_semtimedop"], + [194, "sys_shmget"], + [195, "sys_shmctl"], + [196, "sys_shmat"], + [197, "sys_shmdt"], + [198, "sys_socket"], + [199, "sys_socketpair"], + [200, "sys_bind"], + [201, "sys_listen"], + [202, "sys_accept"], + [203, "sys_connect"], + [204, "sys_getsockname"], + [205, "sys_getpeername"], + [206, "sys_sendto"], + [207, "sys_recvfrom"], + [208, "sys_setsockopt"], + [209, "sys_getsockopt"], + [210, "sys_shutdown"], + [211, "sys_sendmsg"], + [212, "sys_recvmsg"], + [213, "sys_readahead"], + [214, "sys_brk"], + [215, "sys_munmap"], + [216, "sys_mremap"], + [217, "sys_add_key"], + [218, "sys_request_key"], + [219, "sys_keyctl"], + [220, "sys_clone"], + [221, "sys_execve"], + [222, "sys_mmap"], + [223, "sys_fadvise64"], + [224, "sys_swapon"], + [225, "sys_swapoff"], + [226, "sys_mprotect"], + [227, "sys_msync"], + [228, "sys_mlock"], + [229, "sys_munlock"], + [230, "sys_mlockall"], + [231, "sys_munlockall"], + [232, "sys_mincore"], + [233, "sys_madvise"], + [234, "sys_remap_file_pages"], + [235, "sys_mbind"], + [236, "sys_get_mempolicy"], + [237, "sys_set_mempolicy"], + [238, "sys_migrate_pages"], + [239, "sys_move_pages"], + [240, "sys_rt_tgsigqueueinfo"], + [241, "sys_perf_event_open"], + [242, "sys_accept4"], + [243, "sys_recvmmsg"], + [260, "sys_wait4"], + [261, "sys_prlimit64"], + [262, "sys_fanotify_init"], + [263, "sys_fanotify_mark"], + [264, "sys_name_to_handle_at"], + [265, "sys_open_by_handle_at"], + [266, "sys_clock_adjtime"], + [267, "sys_syncfs"], + [268, "sys_setns"], + [269, "sys_sendmmsg"], + [270, "sys_process_vm_readv"], + [271, "sys_process_vm_writev"], + [272, "sys_kcmp"], + [273, "sys_finit_module"], + [274, "sys_sched_setattr"], + [275, "sys_sched_getattr"], + [276, "sys_renameat2"], + [277, "sys_seccomp"], + [278, "sys_getrandom"], + [279, "sys_memfd_create"], + [280, "sys_bpf"], + [281, "sys_execveat"], + [282, "sys_userfaultfd"], + [283, "sys_membarrier"], + [284, "sys_mlock2"], + [285, "sys_copy_file_range"], + [286, "sys_preadv2"], + [287, "sys_pwritev2"], + [288, "sys_pkey_mprotect"], + [289, "sys_pkey_alloc"], + [290, "sys_pkey_free"], + [291, "sys_statx"], + [292, "sys_io_pgetevents"], + [293, "sys_rseq"], + [294, "sys_kexec_file_load"], + [424, "sys_pidfd_send_signal"], + [425, "sys_io_uring_setup"], + [426, "sys_io_uring_enter"], + [427, "sys_io_uring_register"], + [428, "sys_open_tree"], + [429, "sys_move_mount"], + [430, "sys_fsopen"], + [431, "sys_fsconfig"], + [432, "sys_fsmount"], + [433, "sys_fspick"], + [434, "sys_pidfd_open"], + [435, "sys_clone3"] +]); \ No newline at end of file diff --git a/ide/src/trace/component/trace/base/TraceRow.ts b/ide/src/trace/component/trace/base/TraceRow.ts index 7bda9c89dd3648f3c8ef1ef178b154f1c7cd029f..ea5fec73213c83cec14e0f34861d32da263a1609 100644 --- a/ide/src/trace/component/trace/base/TraceRow.ts +++ b/ide/src/trace/component/trace/base/TraceRow.ts @@ -79,6 +79,7 @@ export class TraceRow extends HTMLElement { static ROW_TYPE_APP_STARTUP = 'app-startup'; static ROW_TYPE_STATIC_INIT = 'static-init'; static ROW_TYPE_THREAD = 'thread'; + static ROW_TYPE_THREAD_SYS_CALL = 'thread-sys-call'; static ROW_TYPE_THREAD_NAME = 'sameThread_process'; static ROW_TYPE_MEM = 'mem'; static ROW_TYPE_VIRTUAL_MEMORY_GROUP = 'virtual-memory-group'; @@ -354,12 +355,21 @@ export class TraceRow extends HTMLElement { } set rowDiscard(value: boolean) { + let height = 0; if (value) { this.setAttribute('row-discard', ''); this.style.display = 'none'; + height = 0; } else { this.removeAttribute('row-discard'); this.style.display = 'block'; + height = this.clientHeight; + } + if (this.collect) { + window.publish(window.SmartEvent.UI.RowHeightChange, { + expand: this.funcExpand, + value: height, + }); } } @@ -656,7 +666,7 @@ export class TraceRow extends HTMLElement { } // @ts-ignore - addChildTraceRowAfter(child: TraceRow, targetRow: TraceRow): void { + addChildTraceRowAfter(child: TraceRow, targetRow: TraceRow, hidden: boolean = false): void { // @ts-ignore TraceRowConfig.allTraceRowList.push(child); child.parentRowEl = this; @@ -665,11 +675,11 @@ export class TraceRow extends HTMLElement { child.setAttribute('scene', ''); if (index !== -1) { this.childrenList.splice(index + 1, 0, child); - child.rowHidden = false; + child.rowHidden = hidden; this.fragment.insertBefore(child, this.fragment.childNodes.item(index + 1)); } else { this.childrenList.push(child); - child.rowHidden = false; + child.rowHidden = hidden; this.fragment.append(child); } } @@ -1022,21 +1032,23 @@ export class TraceRow extends HTMLElement { this.describeEl?.appendChild(this.rowCheckFilePop); } - addRowSettingCheckBox(): void { + addRowSettingCheckBox(appendAll: boolean = true): void { let nameEl = this.shadowRoot && (this.shadowRoot.querySelector('.name') as HTMLLabelElement); nameEl && (nameEl.style.maxWidth = '160px'); let collectEl = (this.shadowRoot && this.shadowRoot.querySelector('.collect') as LitIcon); collectEl && (collectEl.style.marginRight = '20px'); this.rowSettingCheckBoxPop = document.createElement('lit-popover') as LitPopover; let checkboxHtml = ''; - checkboxHtml += `
+ if (appendAll) { + checkboxHtml += `
`; + } this._rowSettingCheckBoxList && this._rowSettingCheckBoxList.forEach((item) => { checkboxHtml += `
- +
`; }); - this._rowSettingCheckedBoxList = new Array(this._rowSettingCheckBoxList?.length).fill(true); + this._rowSettingCheckedBoxList = new Array(this._rowSettingCheckBoxList?.length).fill(appendAll); this.rowSettingCheckBoxPop.innerHTML = `
${checkboxHtml}
@@ -1048,21 +1060,25 @@ export class TraceRow extends HTMLElement { item.onchange = (e: unknown): void => { // @ts-ignore this._rowSettingCheckedBoxList[this._rowSettingCheckBoxList?.indexOf(item.value)] = item.checked; - const allChecked = this._rowSettingCheckedBoxList!.every(item => item); - allCheckBox.checked = allChecked; + if (appendAll) { + const allChecked = this._rowSettingCheckedBoxList!.every(item => item); + allCheckBox.checked = allChecked; + } this.onRowSettingCheckBoxChangeHandler?.(this._rowSettingCheckedBoxList!); }; }); - allCheckBox.onchange = (e: unknown): void => { - checkBoxItems.forEach(item => { - // @ts-ignore - item.checked = allCheckBox.checked; - }); - this._rowSettingCheckedBoxList!.forEach((_, index) => { - this._rowSettingCheckedBoxList![index] = allCheckBox.checked; - }); - this.onRowSettingCheckBoxChangeHandler?.(this._rowSettingCheckedBoxList!); - }; + if (appendAll) { + allCheckBox.onchange = (e: unknown): void => { + checkBoxItems.forEach(item => { + // @ts-ignore + item.checked = allCheckBox.checked; + }); + this._rowSettingCheckedBoxList!.forEach((_, index) => { + this._rowSettingCheckedBoxList![index] = allCheckBox.checked; + }); + this.onRowSettingCheckBoxChangeHandler?.(this._rowSettingCheckedBoxList!); + }; + } this.rowSettingCheckBoxPop.id = 'rowSetting'; this.rowSettingCheckBoxPop.className = 'popover setting'; this.rowSettingCheckBoxPop.setAttribute('placement', 'bottomLeft'); @@ -1122,6 +1138,14 @@ export class TraceRow extends HTMLElement { return []; } + getRowSettingCheckStateByKey(key: string): boolean { + const index = this._rowSettingCheckBoxList?.indexOf(key); + if (index != undefined) { + return this._rowSettingCheckedBoxList?.[index] === true; + } + return false; + } + //@ts-ignore expandFunc(rootRow: TraceRow, sp: SpSystemTrace): void { if (this._enableCollapseChart && !this.funcExpand) { @@ -1388,6 +1412,10 @@ export class TraceRow extends HTMLElement { if (this.tipEL) { this.tipEL.style.display = 'none'; } + if (this.rowSettingCheckBoxPop) { + //@ts-ignore + this.rowSettingCheckBoxPop.visible = false; + } } loadingPin1: number = 0; @@ -1395,7 +1423,7 @@ export class TraceRow extends HTMLElement { static currentActiveRows: Array = []; drawFrame(): void { - if (!this.hasAttribute('row-hidden')) { + if (!this.hasAttribute('row-hidden') && !this.hasAttribute('row-discard')) { if (!this.loadingFrame || window.isLastFrame || !this.isComplete) { if (this.needRefresh || window.isLastFrame) { this.loadingFrame = true; diff --git a/ide/src/trace/component/trace/base/TraceSheet.ts b/ide/src/trace/component/trace/base/TraceSheet.ts index aa0ff8ee7319e88754e6ad153b56cc870548ee06..386717a37024d20a5c6968bc0d5ccfa3687b2c9a 100644 --- a/ide/src/trace/component/trace/base/TraceSheet.ts +++ b/ide/src/trace/component/trace/base/TraceSheet.ts @@ -16,7 +16,12 @@ import { BaseElement, element } from '../../../../base-ui/BaseElement'; import { type LitTabs } from '../../../../base-ui/tabs/lit-tabs'; import { LitTabpane } from '../../../../base-ui/tabs/lit-tabpane'; -import { BoxJumpParam, SelectionParam, SliceBoxJumpParam } from '../../../bean/BoxSelection'; +import { + BoxJumpParam, + SelectionParam, + SysCallBoxJumpParam, + SliceBoxJumpParam +} from '../../../bean/BoxSelection'; import { type TabPaneCurrentSelection } from '../sheet/TabPaneCurrentSelection'; import { type TabPaneFlag } from '../timer-shaft/TabPaneFlag'; import { type Flag } from '../timer-shaft/Flag'; @@ -28,6 +33,7 @@ import { type CpuStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerC import { CpuFreqStruct } from '../../../database/ui-worker/ProcedureWorkerFreq'; import { CpuFreqLimitsStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits'; import { type ThreadStruct } from '../../../database/ui-worker/ProcedureWorkerThread'; +import { type ThreadSysCallStruct } from '../../../database/ui-worker/ProcedureWorkerThreadSysCall'; import { type FuncStruct } from '../../../database/ui-worker/ProcedureWorkerFunc'; import { ProcessMemStruct } from '../../../database/ui-worker/ProcedureWorkerMem'; import { CpuStateStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuState'; @@ -110,6 +116,7 @@ import { PerfFunctionAsmParam } from '../../../bean/PerfAnalysis'; import { info, error } from '../../../../log/Log'; import { XpowerThreadCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerThreadCount'; import { XpowerGpuFreqCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerGpuFreqCount'; +import { TabPaneSysCallChild } from '../sheet/process/TabPaneSysCallChild'; @element('trace-sheet') @@ -303,6 +310,10 @@ export class TraceSheet extends BaseElement { this.getComponentByID('box-slices')?.addEventListener('td-click', (evt: unknown) => { this.tdSliceClickHandler(evt); }); + // @ts-ignore + this.getComponentByID('box-thread-syscall')?.addEventListener('td-click', (evt: unknown) => { + this.tdSysCallClickHandler(evt); + }); } private perfAnalysisListener(evt: MouseEvent): void { @@ -942,6 +953,9 @@ export class TraceSheet extends BaseElement { scrollPrio, callback ); + + displaySysCallData = (data: ThreadSysCallStruct) => + this.displayTab('current-selection').setSysCallData(data); displayMemData = (data: ProcessMemStruct): void => this.displayTab('current-selection').setMemData(data); displayHangData = (data: HangStruct, sp: SpSystemTrace, scrollCallback: Function): Promise => @@ -1457,6 +1471,43 @@ export class TraceSheet extends BaseElement { (pane.children.item(0) as TabPaneBoxChild).data = param; } + tdSysCallClickHandler(e: unknown): void { + // @ts-ignore + this.currentPaneID = e.target.parentElement.id; + //隐藏除了当前Tab页的其他Tab页 + this.shadowRoot!.querySelectorAll('lit-tabpane').forEach((it): boolean => + it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false) + ); //todo:看能不能优化 + let pane = this.getPaneByID('box-thread-syscall-child'); //通过Id找到需要展示的Tab页 + pane.closeable = true; //关闭的ican显示 + pane.hidden = false; + this.litTabs!.activeByKey(pane.key); //显示key值对应的Tab页 + // @ts-ignore + pane.tab = e.detail.name; //设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串 + let param = new SysCallBoxJumpParam(); + param.traceId = this.selection!.traceId; + param.leftNs = this.selection!.leftNs; + param.rightNs = this.selection!.rightNs; + // @ts-ignore + const level = e.detail.level; + if (level === 'Process') { + // @ts-ignore + param.processId = [e.detail.id]; + } else if (level === 'Thread'){ + // @ts-ignore + param.processId = [e.detail.parentId]; + // @ts-ignore + param.threadId = [e.detail.id]; + } else { + // @ts-ignore + param.threadId = [e.detail.parentId]; + // @ts-ignore + param.sysCallId = e.detail.id; + } + param.isJumpPage = true; // @ts-ignore + (pane.children.item(0) as TabPaneSysCallChild).data = param; + } + //Slice Tab点击Occurrences列下的td进行跳转 tdSliceClickHandler(e: unknown): void { // @ts-ignore diff --git a/ide/src/trace/component/trace/base/TraceSheetConfig.ts b/ide/src/trace/component/trace/base/TraceSheetConfig.ts index f5de86153d7f696dfb84db3e8839022138880bc7..d49ff7a63c5cbe9efa32f7709b60432508e80fa3 100644 --- a/ide/src/trace/component/trace/base/TraceSheetConfig.ts +++ b/ide/src/trace/component/trace/base/TraceSheetConfig.ts @@ -91,6 +91,7 @@ import { TabPaneIOTierStatisticsAnalysis } from '../sheet/file-system/TabPaneIOT import { TabPaneVirtualMemoryStatisticsAnalysis } from '../sheet/file-system/TabPaneVirtualMemoryStatisticsAnalysis'; import { TabPaneCurrent } from '../sheet/TabPaneCurrent'; import { TabPaneStartup } from '../sheet/process/TabPaneStartup'; +import { TabPaneSysCall } from '../sheet/process/TabPaneSysCall'; import { TabPaneStaticInit } from '../sheet/process/TabPaneStaticInit'; import { TabPaneTaskFrames } from '../sheet/task/TabPaneTaskFrames'; import { TabPaneFrameDynamic } from '../sheet/frame/TabPaneFrameDynamic'; @@ -151,6 +152,7 @@ import { TabPanePerfAsync } from '../sheet/hiperf/TabPerfAsyncList'; import { TabPaneUserPlugin } from '../sheet/userPlugin/TabPaneUserPlugin'; import { TabPaneDmaFence } from '../sheet/dma-fence/TabPaneDmaFenceSelect'; import { TabPaneSliceChild } from '../sheet/process/TabPaneSliceChild'; +import { TabPaneSysCallChild } from '../sheet/process/TabPaneSysCallChild'; import { TabPerfFuncAsm } from '../sheet/hiperf/TabPerfFuncAsm'; export let tabConfig: { @@ -216,6 +218,15 @@ export let tabConfig: { type: TabPaneStartup, require: (param: SelectionParam) => param.processIds.length > 0 && param.startup, }, + 'box-thread-syscall': { + title: 'SysCall Event', + type: TabPaneSysCall, + require: (param: SelectionParam) => param.processSysCallIds.length > 0 || param.threadSysCallIds.length > 0, + }, + 'box-thread-syscall-child': { + title: '', + type: TabPaneSysCallChild, + }, 'box-process-static-init': { title: 'Static Initialization', type: TabPaneStaticInit, diff --git a/ide/src/trace/component/trace/base/Utils.ts b/ide/src/trace/component/trace/base/Utils.ts index dc406525096e883e12f46efa1154d43bc01a0e36..e47afafd0d3648c9cd48b06a9aec5d082fc4b77c 100644 --- a/ide/src/trace/component/trace/base/Utils.ts +++ b/ide/src/trace/component/trace/base/Utils.ts @@ -55,6 +55,7 @@ export class Utils { totalNS: number = 1; private trace1ThreadMap: Map = new Map(); private trace1ProcessMap: Map = new Map(); + sysCallEventTidsMap: Map = new Map(); private trace1SchedSliceMap: Map< string, { @@ -223,6 +224,7 @@ export class Utils { this.trace2ThreadMap.clear(); this.trace1SchedSliceMap.clear(); this.trace2SchedSliceMap.clear(); + this.sysCallEventTidsMap.clear(); Utils.distributedTrace = []; } diff --git a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts index 0f82b5616e9e8ada9b8a561641335aa3bd5997da..0cfe639213d9866fdbb67cd37c68251d71ff4cc6 100644 --- a/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts +++ b/ide/src/trace/component/trace/sheet/TabPaneCurrentSelection.ts @@ -51,6 +51,7 @@ import { queryDistributedRelationAllData, queryRWakeUpFrom, queryRunnableTimeByRunning, + querySysCallEventDetail, queryThreadStateArgs, queryThreadWakeUp, queryThreadWakeUpFrom, @@ -70,6 +71,7 @@ import { XpowerAppDetailStruct } from '../../../database/ui-worker/ProcedureWork import { XpowerWifiStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerWifi'; import { XpowerThreadCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerThreadCount'; import { XpowerGpuFreqCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerGpuFreqCount'; +import { ThreadSysCallStruct } from '../../../database/ui-worker/ProcedureWorkerThreadSysCall'; const INPUT_WORD = 'This is the interval from when the task became eligible to run \n(e.g.because of notifying a wait queue it was a suspended on) to\n when it started running.'; @@ -1217,6 +1219,35 @@ export class TabPaneCurrentSelection extends BaseElement { }); } + async setSysCallData(data: ThreadSysCallStruct) { + this.setTableHeight('350px'); + this.initCanvas(); + let leftTitle: HTMLElement | null | undefined = this?.shadowRoot?.querySelector('#leftTitle'); + this.setTitleAndButtonStyle(); + if (leftTitle) { + leftTitle.innerText = 'SysCall Event'; + } + let list: unknown[] = []; + list.push({ name: 'Name', value: `${data.name} [${data.id}]` }); + list.push({ + name: 'StartTime(Relative)', + value: getTimeString(data.startTs || 0), + }); + list.push({ + name: 'StartTime(Absolute)', + value: ((data.startTs || 0) + Utils.getInstance().getRecordStartNS()) / 1000000000 + 's', + }); + list.push({ name: 'Duration', value: getTimeString(data.dur || 0) }); + const eventValue = await querySysCallEventDetail(data.itid!, data.startTs! + Utils.getInstance().getRecordStartNS(), data.dur!); + if (eventValue[0]) { + list.push({ name: 'Process', value: `${eventValue[0].pName} [${data.pid}]` }); + list.push({ name: 'Thread', value: `${eventValue[0].tName} [${data.tid}]` }); + list.push({ name: 'args', value: eventValue[0].args }); + list.push({ name: 'ret', value: eventValue[0].ret }); + } + this.currentSelectionTbl!.dataSource = list; + } + async setThreadData( data: ThreadStruct, scrollCallback: ((d: unknown) => void) | undefined, diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSysCall.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSysCall.ts new file mode 100644 index 0000000000000000000000000000000000000000..45304351a00f0c8b278193f78461856d7c56a0d0 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSysCall.ts @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseElement, element } from '../../../../../base-ui/BaseElement'; +import { LitTable } from '../../../../../base-ui/table/lit-table'; +import { SelectionParam } from '../../../../bean/BoxSelection'; +import { log } from '../../../../../log/Log'; +import { getProbablyTime } from '../../../../database/logic-worker/ProcedureLogicWorkerCommon'; +import { resizeObserver } from '../SheetUtils'; +import { querySysCallEventWithBoxSelect } from '../../../../database/sql/ProcessThread.sql'; +import { Utils } from '../../base/Utils'; +import { SysCallMap } from '../../base/SysCallUtils'; + +interface SysCallItem { + nameId: number; + name: string; + pName: string; + tName: string; + tid: number; + pid: number; + totalCount: number; + sumDur: number; + durStr?: string; +} + +interface SysCallTreeItem { + name: string; + id: number; + parentId?: number; + totalCount: number; + sumDur: number; + durStr: string; + level: string; + children: SysCallTreeItem[] +} + +@element('tabpane-syscall') +export class TabPaneSysCall extends BaseElement { + private sysCallTbl: LitTable | null | undefined; + private range: HTMLLabelElement | null | undefined; + private sysCallSource: Array = []; + private currentSelectionParam: SelectionParam | undefined; + + set data(sysCallParam: SelectionParam | unknown) { + if (this.currentSelectionParam === sysCallParam) { + return; + } // @ts-ignore + this.currentSelectionParam = sysCallParam; + //@ts-ignore + this.sysCallTbl?.shadowRoot?.querySelector('.table')?.style?.height = `${this.parentElement!.clientHeight - 45}px`; // @ts-ignore + this.range!.textContent = `Selected range: ${((sysCallParam.rightNs - sysCallParam.leftNs) / 1000000.0).toFixed( + 5 + )} ms`; + this.sysCallTbl!.loading = true; + let ipidArr: number[] = []; + Array.from(Utils.getInstance().sysCallEventTidsMap.values()).forEach(it => { + //@ts-ignore + if (sysCallParam?.processSysCallIds?.includes(it.pid)) { + ipidArr.push(it.ipid); + } + }) + //@ts-ignore + querySysCallEventWithBoxSelect(ipidArr, sysCallParam.threadSysCallIds, sysCallParam.leftNs, sysCallParam.rightNs).then( + (retult) => { + this.flatternToTree(retult as SysCallItem[]); + } + ); + } + + private flatternToTree(result: SysCallItem[]): void { + this.sysCallTbl!.loading = false; + if (result !== null && result.length > 0) { + log(`getTabsysCalls result size : ${result.length}`); + let map: Map = new Map(); + result.forEach((item) => { + item.name = SysCallMap.get(item.nameId) || ''; + item.durStr = getProbablyTime(item.sumDur); + this.processSysCallItem(item, map); + }); + let sysCalls: SysCallTreeItem[] = Array.from(map.values()); + this.sysCallSource = sysCalls; + this.sysCallTbl!.recycleDataSource = this.sysCallSource; + } else { + this.sysCallSource = []; + this.sysCallTbl!.recycleDataSource = []; + } + } + + private processSysCallItem(item: SysCallItem, map: Map): void { + const treeItem: SysCallTreeItem = { + id: item.nameId, + name: item.name, + level: 'SysCall', + parentId: item.tid, + totalCount: item.totalCount, + sumDur: item.sumDur, + durStr: item.durStr!, + children:[] + }; + let ps = map.get(item.pid!); + if (ps) { + ps.sumDur += item.sumDur || 0; + ps.durStr = getProbablyTime(ps.sumDur); + ps.totalCount += item.totalCount || 0; + let ts = ps.children?.find(it => it.id === item.tid); + if (ts) { + ts.sumDur += item.sumDur || 0; + ts.durStr = getProbablyTime(ts.sumDur); + ts.totalCount += item.totalCount || 0; + ts.children.push(treeItem); + } else { + ps.children.push({ + id: item.tid, + name: item.tName, + parentId: item.pid, + level: 'Thread', + totalCount: item.totalCount, + sumDur: item.sumDur, + durStr: item.durStr!, + children: [treeItem] + }) + } + } else { + map.set(item.pid!, { + id: item.pid, + level: 'Process', + name: `${item.pName} [${item.pid}]`, + totalCount: item.totalCount, + sumDur: item.sumDur, + durStr: item.durStr!, + children: [{ + id: item.tid, + level: 'Thread', + parentId: item.pid, + name: `${item.tName} [${item.tid}]`, + durStr: item.durStr!, + totalCount: item.totalCount, + sumDur: item.sumDur, + children: [treeItem] + }] + }); + } + } + + initElements(): void { + this.sysCallTbl = this.shadowRoot?.querySelector('#tb-syscall'); + this.range = this.shadowRoot?.querySelector('#syscall-time-range'); + this.sysCallTbl!.addEventListener('column-click', (evt: unknown) => { + // @ts-ignore + this.sortByColumn(evt.detail); + }); + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.sysCallTbl!); + } + + initHtml(): string { + return ` + +
+
+ +
+
+ + + + + + + + +
+ `; + } + + sortByColumn(sortDetail: unknown): void { + let compare = (itemA: SysCallTreeItem, itemB: SysCallTreeItem): number => { + // @ts-ignore + if (sortDetail.key === 'durStr') { + // @ts-ignore + if (sortDetail.sort === 0) { + return itemA.sumDur - itemB.sumDur; // @ts-ignore + } else if (sortDetail.sort === 1) { + return itemA.sumDur - itemB.sumDur; + } else { + return itemB.sumDur - itemA.sumDur; + } + } else { + // @ts-ignore + if (sortDetail.sort === 0) { + return itemA.totalCount - itemB.totalCount; // @ts-ignore + } else if (sortDetail.sort === 1) { + return itemA.totalCount - itemB.totalCount; + } else { + return itemB.totalCount - itemA.totalCount; + } + } + }; + this.sysCallSource.forEach((syscall) => { + syscall.children?.sort(compare); + }); + const deepSort = (arr: SysCallTreeItem[]) => { + arr.sort(compare); + arr.forEach(item => { + if (item.children) { + deepSort(item.children); + } + }) + }; + deepSort(this.sysCallSource); + this.sysCallTbl!.recycleDataSource = this.sysCallSource; + } +} diff --git a/ide/src/trace/component/trace/sheet/process/TabPaneSysCallChild.ts b/ide/src/trace/component/trace/sheet/process/TabPaneSysCallChild.ts new file mode 100644 index 0000000000000000000000000000000000000000..5b9317457edb19db54ab5b824dba38f8c756d0e0 --- /dev/null +++ b/ide/src/trace/component/trace/sheet/process/TabPaneSysCallChild.ts @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseElement, element } from '../../../../../base-ui/BaseElement'; +import { LitTable } from '../../../../../base-ui/table/lit-table'; +import { SysCallBoxJumpParam, SelectionData } from '../../../../bean/BoxSelection'; +import { Utils } from '../../base/Utils'; +import { resizeObserver } from '../SheetUtils'; +import { querySysCallEventWithRange } from '../../../../database/sql/ProcessThread.sql'; +import { SysCallMap } from '../../base/SysCallUtils'; + +interface SysCallChildItem { + pName: string; + tName: string; + pid: number; + tid: number; + nameId: number; + name: string; + startTs: string; + startTime: number; + absoluteTs: number; + dur: number; + args: string; + ret: number +} + +@element('tabpane-syscall-child') +export class TabPaneSysCallChild extends BaseElement { + private boxChildTbl: LitTable | null | undefined; + private boxChildRange: HTMLLabelElement | null | undefined; + private boxChildSource: Array = []; + private boxChildParam: SysCallBoxJumpParam | null | undefined; + + set data(boxChildValue: SysCallBoxJumpParam) { + //切换Tab页 保持childTab数据不变 除非重新点击跳转 + if (boxChildValue === this.boxChildParam || !boxChildValue.isJumpPage) { + return; + } // @ts-ignore + this.boxChildParam = boxChildValue; + //显示框选范围对应的时间 + this.boxChildRange!.textContent = `Selected range: ${parseFloat( + ((boxChildValue.rightNs - boxChildValue.leftNs) / 1000000.0).toFixed(5) + )} ms`; + this.boxChildTbl!.recycleDataSource = []; + this.getDataByDB(boxChildValue); + } + + initElements(): void { + this.boxChildTbl = this.shadowRoot?.querySelector('#tb-syscall-child'); + this.boxChildRange = this.shadowRoot?.querySelector('#time-range'); + this.boxChildTbl!.addEventListener('column-click', (evt): void => { + // @ts-ignore + this.sortByColumn(evt.detail); + }); + //监听row的点击事件,在对应起始时间上画标记棋子 + this.boxChildTbl!.addEventListener('row-click', (evt): void => { + //@ts-ignore + let param = evt.detail.data; + param.isSelected = true; + this.boxChildTbl!.clearAllSelection(param); + this.boxChildTbl!.setCurrentSelection(param); + document.dispatchEvent( + new CustomEvent('triangle-flag', { + detail: { time: [param.startTime], type: 'triangle' }, + }) + ); + }); + } + + connectedCallback(): void { + super.connectedCallback(); + resizeObserver(this.parentElement!, this.boxChildTbl!); + } + + getDataByDB(val: SysCallBoxJumpParam): void { + this.boxChildTbl!.loading = true; + let ipidArr: number[] = []; + let itidArr: number[] = []; + Array.from(Utils.getInstance().sysCallEventTidsMap.values()).forEach(it => { + if (val?.processId?.includes(it.pid)) { + ipidArr.push(it.ipid); + } + if (val?.threadId?.includes(it.tid)) { + itidArr.push(it.itid); + } + }); + querySysCallEventWithRange(ipidArr, itidArr, val.leftNs, val.rightNs, val.sysCallId).then(result => { + this.boxChildTbl!.loading = false; + const arr: Array = []; + result.forEach(it => { + arr.push({ + pName: it.pName, + tName: it.tName, + pid: it.pid, + tid: it.tid, + name: SysCallMap.get(it.nameId) || 'unknown event', + nameId: it.nameId, + startTime: it.startTs, + startTs: Utils.getProbablyTime(it.startTs), + // @ts-ignore + absoluteTs: ((window as unknown).recordStartNS + it.startTs) / 1000000000, + dur: it.dur / 1000000, + args: it.args, + ret: it.ret + }); + }); + this.boxChildSource = arr; + if (this.boxChildTbl) { + // @ts-ignore + this.boxChildTbl.recycleDataSource = arr; + } + }); + } + + initHtml(): string { + return ` + + +
+ + + + + + + + + + + + + + + + + + +
+ `; + } + + sortByColumn(detail: unknown): void { + // @ts-ignore + function compare(property, sort, type) { + return function (boxChildLeftData: SelectionData, boxChildRightData: SelectionData): number { + if (type === 'number') { + return sort === 2 + // @ts-ignore + ? parseFloat(boxChildRightData[property]) - parseFloat(boxChildLeftData[property]) + // @ts-ignore + : parseFloat(boxChildLeftData[property]) - parseFloat(boxChildRightData[property]); + } else { + // @ts-ignore + if (boxChildRightData[property] > boxChildLeftData[property]) { + return sort === 2 ? 1 : -1; + } else { + // @ts-ignore + if (boxChildRightData[property] === boxChildLeftData[property]) { + return 0; + } else { + return sort === 2 ? -1 : 1; + } + } + } + }; + } + + // @ts-ignore + this.boxChildSource.sort(compare(detail.key, detail.sort, 'string')); + this.boxChildTbl!.recycleDataSource = this.boxChildSource; + } +} diff --git a/ide/src/trace/database/data-trafic/process/ThreadSysCallDataReceiver.ts b/ide/src/trace/database/data-trafic/process/ThreadSysCallDataReceiver.ts new file mode 100644 index 0000000000000000000000000000000000000000..61af08b98bc6f9e81e315a17a3524ecf86c20a81 --- /dev/null +++ b/ide/src/trace/database/data-trafic/process/ThreadSysCallDataReceiver.ts @@ -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. + +import { Args } from '../CommonArgs'; +import { TraficEnum } from '../utils/QueryEnum'; + +export const chartThreadSysCallDataSql = (args: Args):unknown => { + return `SELECT syscall_number as id, itid, ts - ${args.recordStartNS} as startTs, dur + from syscall + where itid = ${args.itid} + and startTs + dur >= ${Math.floor(args.startNS)} + and startTs <= ${Math.floor(args.endNS)} + `; +}; + +export function threadSysCallDataReceiver(data: unknown, proc: Function): void { + //@ts-ignore + let sql = chartThreadSysCallDataSql(data.params); + let res = proc(sql); //@ts-ignore + arrayBufferHandler(data, res, data.params.trafic !== TraficEnum.SharedArrayBuffer, false); +} + +function arrayBufferHandler(data: unknown, res: unknown[], transfer: boolean, isEmpty: boolean): void { + //@ts-ignore + let startTs = new Float64Array(res.length); //@ts-ignore + let dur = new Float64Array(res.length); //@ts-ignore + let id = new Int32Array(res.length); //@ts-ignore + let itid = new Int32Array(res.length); //@ts-ignore + res.forEach((it, i) => { + //@ts-ignore + data.params.trafic === TraficEnum.ProtoBuffer && (it = it.processThreadSysCallData); //@ts-ignore + startTs[i] = it.startTs; //@ts-ignore + dur[i] = it.dur; //@ts-ignore + id[i] = it.id; //@ts-ignore + itid[i] = it.itid; //@ts-ignore + }); + (self as unknown as Worker).postMessage( + { + //@ts-ignore + id: data.id, //@ts-ignorew + action: data.action, + results: transfer + ? { + id: id.buffer, + itid: itid.buffer, + startTs: startTs.buffer, + dur: dur.buffer, + } + : {}, + len: res.length, + transfer: transfer, + isEmpty: isEmpty, + }, + transfer + ? [startTs.buffer, dur.buffer, id.buffer, itid.buffer] + : [] + ); +} diff --git a/ide/src/trace/database/data-trafic/process/ThreadSysCallDataSender.ts b/ide/src/trace/database/data-trafic/process/ThreadSysCallDataSender.ts new file mode 100644 index 0000000000000000000000000000000000000000..2e296f123e1e37b875038ec648f2666a9f462e47 --- /dev/null +++ b/ide/src/trace/database/data-trafic/process/ThreadSysCallDataSender.ts @@ -0,0 +1,82 @@ +// Copyright (c) 2021 Huawei Device Co., Ltd. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { CHART_OFFSET_LEFT, MAX_COUNT, QueryEnum, TraficEnum } from '../utils/QueryEnum'; +import { getThreadPool } from '../../SqlLite'; +import { TraceRow } from '../../../component/trace/base/TraceRow'; +import { SysCallMap } from '../../../component/trace/base/SysCallUtils'; +import { Utils } from '../../../component/trace/base/Utils'; +import { ThreadSysCallStruct } from '../../ui-worker/ProcedureWorkerThreadSysCall'; + +export function threadSysCallDataSender( + itid: number, + tid: number, + pid: number, + row: TraceRow, + traceId?: string +): Promise { + let trafic: number = TraficEnum.Memory; + let width = row.clientWidth || row.parentRowEl!.clientWidth - CHART_OFFSET_LEFT; + if (trafic === TraficEnum.SharedArrayBuffer && !row.sharedArrayBuffers) { + row.sharedArrayBuffers = { + startTs: new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * MAX_COUNT), + dur: new SharedArrayBuffer(Float64Array.BYTES_PER_ELEMENT * MAX_COUNT), + id: new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * MAX_COUNT), + itid: new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * MAX_COUNT), + ipid: new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * MAX_COUNT), + }; + } + return new Promise((resolve): void => { + getThreadPool(traceId).submitProto( + QueryEnum.ThreadDataSysCall, + { + itid: itid, + startNS: TraceRow.range?.startNS || 0, + endNS: TraceRow.range?.endNS || 0, + recordStartNS: Utils.getInstance().getRecordStartNS(traceId), + recordEndNS: Utils.getInstance().getRecordEndNS(traceId), + width: width, + trafic: trafic, + sharedArrayBuffers: row.sharedArrayBuffers, + }, + (res: unknown, len: number, transfer: boolean, isEmpty: boolean): void => { + if (isEmpty) { + resolve(true); + } else { + resolve(arrayBufferHandler(transfer ? res : row.sharedArrayBuffers, len, tid, pid)); + } + } + ); + }); +} + +function arrayBufferHandler(buffers: unknown, len: number, tid: number, pid: number): ThreadSysCallStruct[] { + let outArr: ThreadSysCallStruct[] = []; //@ts-ignore + let startTs = new Float64Array(buffers.startTs); //@ts-ignore + let dur = new Float64Array(buffers.dur); //@ts-ignore + let id = new Int32Array(buffers.id); //@ts-ignore + let itid = new Int32Array(buffers.itid); //@ts-ignore + for (let i = 0; i < len; i++) { + //@ts-ignore + outArr.push({ + startTs: startTs[i], + dur: dur[i], + id: id[i], + itid: itid[i], + name: SysCallMap.get(id[i]), + tid: tid, + pid: pid, + } as ThreadSysCallStruct); + } + return outArr; +} diff --git a/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts b/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts index 5531a9f3d4c4a83cb72837956223289356a7ee2c..f551dee718bbe1c46e18b2ab62f364357ad496c8 100644 --- a/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts +++ b/ide/src/trace/database/data-trafic/utils/ExecProtoForWorker.ts @@ -87,6 +87,7 @@ import { hangDataReceiver } from '../HangDataReceiver'; import { xpowerStatisticDataReceiver } from '../xpower/XpowerStatisticDataReceiver'; import { xpowerDataGpuFreqCountReceiver, xpowerDataGpuFreqReceiver } from '../xpower/XpowerGpuFrequencyRecevier'; import { xpowerDataThreadCountReceiver, xpowerDataThreadInfoReceiver } from '../xpower/XpowerThreadReceiver'; +import { threadSysCallDataReceiver } from '../process/ThreadSysCallDataReceiver'; // @ts-ignore const traficHandlers: Map = new Map([]); // @ts-ignore @@ -100,6 +101,7 @@ traficHandlers.set(QueryEnum.CpuStateData, cpuStateReceiver); traficHandlers.set(QueryEnum.CpuFreqLimitData, cpuFreqLimitReceiver); traficHandlers.set(QueryEnum.ProcessData, processDataReceiver); traficHandlers.set(QueryEnum.ThreadData, threadDataReceiver); +traficHandlers.set(QueryEnum.ThreadDataSysCall, threadSysCallDataReceiver); traficHandlers.set(QueryEnum.FuncData, funcDataReceiver); traficHandlers.set(QueryEnum.HiperfCallChart, hiPerfCallChartDataHandler); traficHandlers.set(QueryEnum.HiperfCallStack, hiPerfCallStackCacheHandler); diff --git a/ide/src/trace/database/data-trafic/utils/QueryEnum.ts b/ide/src/trace/database/data-trafic/utils/QueryEnum.ts index f50d855c826233e00e3d61d82a8e716ad4df8ee9..e5cd437539e63894c498d967baff3e1bc2c8f10d 100644 --- a/ide/src/trace/database/data-trafic/utils/QueryEnum.ts +++ b/ide/src/trace/database/data-trafic/utils/QueryEnum.ts @@ -98,8 +98,8 @@ export enum QueryEnum { XpowerGpuFreqData = 308, XpowerStatisticData = 309, XpowerWifiData = 310, - XpowerAppDetailData = 311 - + XpowerAppDetailData = 311, + ThreadDataSysCall = 312, } export const MAX_COUNT = 2000; export enum TraficEnum { diff --git a/ide/src/trace/database/sql/ProcessThread.sql.ts b/ide/src/trace/database/sql/ProcessThread.sql.ts index 18daf4b6324d693e1a9b2070a31c6fbb0a3b6402..5c74017784364464c34752959fc63c197c058f77 100644 --- a/ide/src/trace/database/sql/ProcessThread.sql.ts +++ b/ide/src/trace/database/sql/ProcessThread.sql.ts @@ -604,6 +604,108 @@ WHERE )` ); +export const querySysCallThreadIds = (traceId?: string): Promise> => + query( + 'querySysCallThreadIds', + `SELECT tid, pid, itid, thread.ipid +FROM + thread left join process on thread.ipid = process.ipid +WHERE + itid IN (SELECT DISTINCT( itid ) FROM syscall ) + `, + {}, + { traceId: traceId} + ); + +export const querySysCallEventDetail = +(itid: number, startTs: number, dur: number, traceId?: string): Promise> => + query( + 'querySysCallEventDetail', + `SELECT tid, thread.name as tName, pid, process.name as pName, args, ret +FROM + (select * from syscall where itid= ${itid} and ts = ${startTs} and dur = ${dur}) A + left join thread on A.itid = thread.itid + left join process on thread.ipid = process.ipid + `, + {}, + { traceId: traceId} + ); + +export const querySysCallEventWithBoxSelect = +(ipidArr: Array, itidArr: Array, leftNs: number, rightNs: number): Promise> => + query( + 'querySysCallEventWithBoxSelect', + `select ifnull(process.name, 'Process') as pName, + ifnull(thread.name, 'Thread') as tName, + process.pid, + thread.tid, + A.nameId, + A.sumDur, + A.totalCount +from ( +select itid, syscall_number as nameId, sum(dur) as sumDur, count(1) as totalCount +from syscall +where + ${itidArr.length > 0 ? 'itid in (' + itidArr.join(',') + ')' : '1 = 1'} + and not ((ts - ${window.recordStartNS} + ifnull(dur,0) < ${leftNs}) or (ts - ${window.recordStartNS} > ${rightNs})) +group by itid, syscall_number +) as A +left join thread on A.itid = thread.itid +left join process on thread.ipid = process.ipid +where + ${ipidArr.length > 0 ? 'thread.ipid in (' + ipidArr.join(',') + ')' : '1 = 1'} + `, + {} + ); + + export const querySysCallEventWithRange = +(ipidArr: Array, itidArr: Array, leftNs: number, rightNs: number, sysCallId?: number): Promise> => + query( + 'querySysCallEventWithRange', + `select ifnull(process.name, 'Process') as pName, + ifnull(thread.name, 'Thread') as tName, + process.pid, + thread.tid, + A.nameId, + A.startTs, + A.dur, + A.args, + A.ret +from ( + select itid, syscall_number as nameId, (ts - ${window.recordStartNS}) as startTs, dur, args, ret + from syscall + where + ${itidArr.length > 0 ? 'itid in (' + itidArr.join(',') + ')' : '1 = 1'} + and ${sysCallId !== undefined ? 'syscall_number = ' + sysCallId : '1 = 1' } + and not ((ts - ${window.recordStartNS} + ifnull(dur,0) < ${leftNs}) or (ts - ${window.recordStartNS} > ${rightNs})) + ) as A + left join thread on A.itid = thread.itid + left join process on thread.ipid = process.ipid +where + ${ipidArr.length > 0 ? 'thread.ipid in (' + ipidArr.join(',') + ')' : '1 = 1'} + `, + {} + ); + export const queryProcessContentCount = (traceId?: string): Promise> => query( `queryProcessContentCount`, diff --git a/ide/src/trace/database/ui-worker/ProcedureWorker.ts b/ide/src/trace/database/ui-worker/ProcedureWorker.ts index cba4720f12009088d68766b9640d1f743e943a39..b4391b7e202dac7e0d417f8a0956bcf49258f976 100644 --- a/ide/src/trace/database/ui-worker/ProcedureWorker.ts +++ b/ide/src/trace/database/ui-worker/ProcedureWorker.ts @@ -78,6 +78,7 @@ import { XpowerWifiRender } from './ProcedureWorkerXpowerWifi'; import { XpowerGpuFreqCountRender } from './ProcedureWorkerXpowerGpuFreqCount'; import { XpowerGpuFreqRender } from './ProcedureWorkerXpowerGpuFreq'; import { SnapShotRender } from './ProcedureWorkerSnaps'; +import { ThreadSysCallRender } from './ProcedureWorkerThreadSysCall'; let dataList: unknown = {}; let dataList2: unknown = {}; @@ -106,6 +107,7 @@ export let renders = { 'heap-snapshot': new HeapSnapshotRender(), mem: new MemRender(), thread: new ThreadRender(), + threadSysCall: new ThreadSysCallRender(), func: new FuncRender(), native: new NativeMemoryRender(), 'HiPerf-Group': new EmptyRender(), diff --git a/ide/src/trace/database/ui-worker/ProcedureWorkerThreadSysCall.ts b/ide/src/trace/database/ui-worker/ProcedureWorkerThreadSysCall.ts new file mode 100644 index 0000000000000000000000000000000000000000..aac9df64b4c0e4f7f136a78c65274f757a8168e4 --- /dev/null +++ b/ide/src/trace/database/ui-worker/ProcedureWorkerThreadSysCall.ts @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + dataFilterHandler, + BaseStruct, + isFrameContainPoint, + Render, + RequestMessage, + drawString, + drawLoadingFrame, +} from './ProcedureWorkerCommon'; +import { TraceRow } from '../../component/trace/base/TraceRow'; +import { ColorUtils } from '../../component/trace/base/ColorUtils'; +import { SpSystemTrace } from '../../component/SpSystemTrace'; + +export class ThreadSysCallRender extends Render { + renderMainThread( + threadReq: { + context: CanvasRenderingContext2D; + useCache: boolean; + type: string; + translateY: number; + }, + row: TraceRow + ): void { + let threadList = row.dataList; + let threadFilter = row.dataListCache; + dataFilterHandler(threadList, threadFilter, { + startKey: 'startTs', + durKey: 'dur', + startNS: TraceRow.range?.startNS ?? 0, + endNS: TraceRow.range?.endNS ?? 0, + totalNS: TraceRow.range?.totalNS ?? 0, + frame: row.frame, + paddingTop: 3, + useCache: threadReq.useCache || !(TraceRow.range?.refresh ?? false), + }); + drawLoadingFrame(threadReq.context, threadFilter, row); + threadReq.context.beginPath(); + let find: boolean = false; + for (let re of threadFilter) { + re.translateY = threadReq.translateY; + ThreadSysCallStruct.drawThread(threadReq.context, re); + if (row.isHover && re.frame && isFrameContainPoint(re.frame!, row.hoverX, row.hoverY)) { + ThreadSysCallStruct.hoverStruct = re; + find = true; + } + } + threadReq.context.closePath(); + } + + render(threadReq: RequestMessage, threadList: Array, threadFilter: Array): void {} +} + +export function ThreadSysCallStructOnClick( + clickRowType: string, + sp: SpSystemTrace, + entry?: ThreadSysCallStruct +): Promise { + return new Promise((resolve, reject) => { + if (clickRowType === TraceRow.ROW_TYPE_THREAD_SYS_CALL && (ThreadSysCallStruct.hoverStruct || entry)) { + ThreadSysCallStruct.selectStruct = entry || ThreadSysCallStruct.hoverStruct; + sp.timerShaftEL?.drawTriangle(ThreadSysCallStruct.selectStruct!.startTs || 0, 'inverted'); + sp.traceSheetEL?.displaySysCallData(ThreadSysCallStruct.selectStruct!); + sp.timerShaftEL?.modifyFlagList(undefined); + reject(new Error()); + } else { + resolve(null); + } + }); +} +export class ThreadSysCallStruct extends BaseStruct { + static hoverStruct: ThreadSysCallStruct | undefined; + static selectStruct: ThreadSysCallStruct | undefined; + name: string | undefined; + tid: number | undefined; + id: number | undefined; + pid: number | undefined; + itid: number | undefined; + startTs: number | undefined; + dur: number | undefined; + args: string | undefined; + ret: number | undefined; + + static drawThread(threadContext: CanvasRenderingContext2D, data: ThreadSysCallStruct): void { + if (data.frame) { + threadContext.globalAlpha = 1; + threadContext.fillStyle = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.name || '', 0, ColorUtils.FUNC_COLOR.length)]; + let textColor = ColorUtils.FUNC_COLOR[ColorUtils.hashFunc(data.name || '', 0, ColorUtils.FUNC_COLOR.length)]; + if (ThreadSysCallStruct.hoverStruct && data.name === ThreadSysCallStruct.hoverStruct.name) { + threadContext.globalAlpha = 0.7; + } + threadContext.fillRect(data.frame.x, data.frame.y, data.frame.width, data.frame.height); + threadContext.fillStyle = ColorUtils.funcTextColor(textColor); + threadContext.textBaseline = 'middle'; + threadContext.font = '8px sans-serif'; + data.frame.width > 7 && drawString(threadContext, data.name!, 2, data.frame, data); + if ( + ThreadSysCallStruct.selectStruct && + ThreadSysCallStruct.equals(ThreadSysCallStruct.selectStruct, data) + ) { + threadContext.strokeStyle = '#232c5d'; + threadContext.lineWidth = 2; + threadContext.strokeRect( + data.frame.x, + data.frame.y, + data.frame.width - 2, + data.frame.height + ); + } + } + } + + static equals(d1: ThreadSysCallStruct, d2: ThreadSysCallStruct): boolean { + return ( + d1 && + d2 && + d1.tid === d2.tid && + d1.name === d2.name && + d1.startTs === d2.startTs && + d1.dur === d2.dur + ); + } +} diff --git a/trace_streamer/doc/des_tables.md b/trace_streamer/doc/des_tables.md index 74580f0fd933916ffa778f0e0112ce66e101e137..494ef6ca99007294674ef3f2c69c6c4782c582c9 100755 --- a/trace_streamer/doc/des_tables.md +++ b/trace_streamer/doc/des_tables.md @@ -1479,19 +1479,21 @@ source_arg_set_id: 同一个source_arg_set_id代表一组数据,一般取得 #### 表结构 | Columns Name | SQL TYPE | |---- |---- | -|syscall_num |INT | -|type |TEXT | -|ipid |INT | +|syscall_number|INT | |ts |INT | +|dur |INT | +|itid |INT | +|args |TEXT | |ret |INT | #### 表描述 记录用户空间函数与内核空间函数相互调用记录。 #### 相关字段描述 -- syscall_num:系统调用的序号 -- type:固定取值:enter或者exit -- ipid:线程所属的进程ID -- ts:时间戳 -- ret:返回值,在type为exit时有效 +- syscall_number:系统调用的序号 +- ts:时间戳 +- dur:持续时间,记录系统调用的执行时间 +- itid: 记录发起调用的线程 +- args: 参数,记录系统调用的参数信息 +- ret:返回值,记录系统调用的返回结果 ### sys_event_filter表 #### 表结构 diff --git a/trace_streamer/src/filter/BUILD.gn b/trace_streamer/src/filter/BUILD.gn index cbe1e74f18f99d352780a73bed960d413b1eb5fe..509be0c35b6227f03d4be60ad63e76c2ac36246c 100644 --- a/trace_streamer/src/filter/BUILD.gn +++ b/trace_streamer/src/filter/BUILD.gn @@ -91,6 +91,7 @@ ohos_source_set("filter") { "process_filter.cpp", "slice_filter.cpp", "stat_filter.cpp", + "syscall_filter.cpp", "system_event_measure_filter.cpp", "task_pool_filter.cpp", ] diff --git a/trace_streamer/src/filter/syscall_filter.cpp b/trace_streamer/src/filter/syscall_filter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ded33ec256a35e40b1ab10c0ec2452ebf77fe0b --- /dev/null +++ b/trace_streamer/src/filter/syscall_filter.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "syscall_filter.h" + +#include "process_filter.h" + +namespace SysTuning { +namespace TraceStreamer { +SyscallFilter::SyscallFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter) + : FilterBase(dataCache, filter) +{ +} +SyscallFilter::~SyscallFilter() {} + +void SyscallFilter::UpdataSyscallEnterExitMap(const SyscallInfoRow &syscallInfoRow) +{ + TS_LOGI("SysEnterEvent: SysEnter ID %u", syscallInfoRow.number); + auto key = std::make_pair(syscallInfoRow.itid, syscallInfoRow.number); + syscallEnterExitMap_[key] = syscallInfoRow; +} + +void SyscallFilter::AppendSysCallInfo(uint32_t pid, uint32_t syscallNr, uint64_t ts, int64_t ret) +{ + TS_LOGI("SysExitEvent: SysEnter ID %u", syscallNr); + auto key = std::make_pair(pid, syscallNr); + auto syscallEnterExitItor = syscallEnterExitMap_.find(key); + if (syscallEnterExitItor != syscallEnterExitMap_.end() && syscallEnterExitItor->second.ts <= ts) { + uint64_t dur = ts - syscallEnterExitItor->second.ts; + syscallEnterExitItor->second.dur = dur; + syscallEnterExitItor->second.ret = ret; + syscallEnterExitItor->second.itid = streamFilters_->processFilter_->UpdateOrCreateThread(ts, pid); + traceDataCache_->GetSysCallData()->AppendSysCallData(syscallEnterExitItor->second); + syscallEnterExitMap_.erase(key); + } else { + TS_LOGW("SysExitEvent: No matching sysExit event found for syscallID = %u.", syscallNr); + } +} + +void SyscallFilter::Clear() +{ + syscallEnterExitMap_.clear(); +} +} // namespace TraceStreamer +} // namespace SysTuning diff --git a/trace_streamer/src/filter/syscall_filter.h b/trace_streamer/src/filter/syscall_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..93206ecfc4bdb50b7fbdbff14f7429460ce41956 --- /dev/null +++ b/trace_streamer/src/filter/syscall_filter.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SYSCALL_FILTER_H +#define SYSCALL_FILTER_H + +#include +#include + +#include "clock_filter_ex.h" +#include "common_types.h" +#include "filter_base.h" +#include "trace_streamer_filters.h" + +namespace SysTuning { +namespace TraceStreamer { +using namespace SysTuning::base; +class SyscallFilter : private FilterBase { +public: + SyscallFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter); + ~SyscallFilter() override; + void UpdataSyscallEnterExitMap(const SyscallInfoRow &syscallInfoRow); + void AppendSysCallInfo(uint32_t pid, uint32_t syscallNr, uint64_t ts, int64_t ret); + void Clear(); + +private: + std::map, SyscallInfoRow> syscallEnterExitMap_; +}; +} // namespace TraceStreamer +} // namespace SysTuning +#endif // SYSCALL_FILTER_H diff --git a/trace_streamer/src/parser/pbreader_parser/htrace_parser/htrace_event_parser.cpp b/trace_streamer/src/parser/pbreader_parser/htrace_parser/htrace_event_parser.cpp index 108f4c450e277aae7f800e3e1162c203407cb2d4..9f8efdfec22b453d003a96e5e754f46aa0d03ec7 100644 --- a/trace_streamer/src/parser/pbreader_parser/htrace_parser/htrace_event_parser.cpp +++ b/trace_streamer/src/parser/pbreader_parser/htrace_parser/htrace_event_parser.cpp @@ -39,6 +39,7 @@ #include "signal.pbreader.h" #include "slice_filter.h" #include "stat_filter.h" +#include "syscall_filter.h" #include "system_event_measure_filter.h" #include "task.pbreader.h" #include "thread_state_flag.h" @@ -994,16 +995,18 @@ bool HtraceEventParser::SysEnterEvent(const EventInfo &event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); ProtoReader::SysEnterFormat_Reader msg(event.detail); - auto ipid = streamFilters_->processFilter_->UpdateOrCreateThread(event.timeStamp, event.tgid); - traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), sysEnterName_, ipid, event.timeStamp, 0); + SyscallInfoRow syscallInfoRow; + syscallInfoRow.ts = event.timeStamp; + syscallInfoRow.itid = event.pid; + syscallInfoRow.number = msg.id(); + streamFilters_->syscallFilter_->UpdataSyscallEnterExitMap(syscallInfoRow); return true; } bool HtraceEventParser::SysExitEvent(const EventInfo &event) const { streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_EXIT, STAT_EVENT_RECEIVED); ProtoReader::SysExitFormat_Reader msg(event.detail); - auto ipid = streamFilters_->processFilter_->UpdateOrCreateThread(event.timeStamp, event.tgid); - traceDataCache_->GetSysCallData()->AppendSysCallData(msg.id(), sysExitName_, ipid, event.timeStamp, msg.ret()); + streamFilters_->syscallFilter_->AppendSysCallInfo(event.pid, msg.id(), event.timeStamp, msg.ret()); return true; } diff --git a/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.cpp b/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.cpp index e22021ff85893060a59b71d2cb1f70ad26a5612f..71978acc5c2269503bcd5d4e435eeff7d9c71e34 100644 --- a/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.cpp +++ b/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.cpp @@ -24,6 +24,7 @@ #include "process_filter.h" #include "slice_filter.h" #include "stat_filter.h" +#include "syscall_filter.h" #include "string_to_numerical.h" #include "thread_state_flag.h" #include "ts_common.h" @@ -71,6 +72,10 @@ BytraceEventParser::BytraceEventParser(TraceDataCache *dataCache, const TraceStr bind(&BytraceEventParser::IpiEntryEvent, this, std::placeholders::_1, std::placeholders::_2)}, {config_.eventNameMap_.at(TRACE_EVENT_IPI_EXIT), bind(&BytraceEventParser::IpiExitEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SYS_ENTRY), + bind(&BytraceEventParser::SysEnterEvent, this, std::placeholders::_1, std::placeholders::_2)}, + {config_.eventNameMap_.at(TRACE_EVENT_SYS_EXIT), + bind(&BytraceEventParser::SysExitEvent, this, std::placeholders::_1, std::placeholders::_2)}, }; InterruptEventInitialization(); ClockEventInitialization(); @@ -188,6 +193,72 @@ void BytraceEventParser::StackEventsInitialization() bind(&BytraceEventParser::WorkqueueExecuteEndEvent, this, std::placeholders::_1, std::placeholders::_2)); } +bool BytraceEventParser::SysEnterEvent(const ArgsMap &args, const BytraceLine &line) +{ + Unused(args); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_ENTRY, STAT_EVENT_RECEIVED); + std::string sysEnterStr = base::Strip(line.argsStr); + if (sysEnterStr.empty()) { + TS_LOGD("SysEnterEvent: Empty args string for sysEnterStr, skipping."); + return true; + } + + auto firstSpacePos = sysEnterStr.find(" "); + if (firstSpacePos == std::string::npos) { + TS_LOGD("SysEnterEvent: No space found in sysEnterStr: '%s', skipping.", sysEnterStr.c_str()); + return true; + } + + // eg:NR 240 (f73bfb0c, 80, 2, f73bfab8, 5f5d907, 0) + DataIndex argsDataIndex = INVALID_UINT64; + auto secondSpacePos = sysEnterStr.find(" ", firstSpacePos + 1); + if (secondSpacePos != std::string::npos) { + std::string argsStr = sysEnterStr.substr(secondSpacePos + 1); + argsDataIndex = traceDataCache_->GetDataIndex(argsStr); + } else { + secondSpacePos = sysEnterStr.length(); + } + + uint32_t syscallNumber = std::atoi(sysEnterStr.substr(firstSpacePos, secondSpacePos).c_str()); + SyscallInfoRow syscallInfoRow; + syscallInfoRow.ts = line.ts; + syscallInfoRow.itid = line.pid; + syscallInfoRow.args = argsDataIndex; + syscallInfoRow.number = syscallNumber; + streamFilters_->syscallFilter_->UpdataSyscallEnterExitMap(syscallInfoRow); + return true; +} + +bool BytraceEventParser::SysExitEvent(const ArgsMap &args, const BytraceLine &line) +{ + Unused(args); + streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_SYS_EXIT, STAT_EVENT_RECEIVED); + std::string sysExitStr = base::Strip(line.argsStr); + if (sysExitStr.empty()) { + TS_LOGD("SysExitEvent: Empty args string for sysExitStr, skipping."); + return true; + } + + auto firstSpacePos = sysExitStr.find(" "); + if (firstSpacePos == std::string::npos) { + TS_LOGD("SysExitEvent: No space found in sysExitStr: '%s', skipping.", sysExitStr.c_str()); + return true; + } + + // eg:NR 85 = -22 + int64_t ret = INVALID_INT64; + auto secondSpacePos = sysExitStr.find("= "); + if (secondSpacePos != std::string::npos) { + ret = std::atoi(sysExitStr.substr(secondSpacePos + 2).c_str()); + } else { + secondSpacePos = sysExitStr.length(); + } + + uint32_t sysExitId = std::atoi(sysExitStr.substr(firstSpacePos, secondSpacePos).c_str()); + streamFilters_->syscallFilter_->AppendSysCallInfo(line.pid, sysExitId, line.ts, ret); + return true; +} + bool BytraceEventParser::SchedSwitchEvent(const ArgsMap &args, const BytraceLine &line) const { if (args.empty() || args.size() < MIN_SCHED_SWITCH_ARGS_COUNT) { diff --git a/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.h b/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.h index cfef3a2d794388862f9e203fb7ef6e83b51da1f1..d434e48859638ad6eab69376cd58219c04b1584f 100644 --- a/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.h +++ b/trace_streamer/src/parser/ptreader_parser/bytrace_parser/bytrace_event_parser.h @@ -78,6 +78,8 @@ private: bool BinderTransaction(const ArgsMap &args, const BytraceLine &line) const; bool BinderTransactionReceived(const ArgsMap &args, const BytraceLine &line) const; bool BinderTransactionAllocBufEvent(const ArgsMap &args, const BytraceLine &line) const; + bool SysEnterEvent(const ArgsMap &args, const BytraceLine &line); + bool SysExitEvent(const ArgsMap &args, const BytraceLine &line); void GetDataSegArgs(const BytraceLine &bufLine, ArgsMap &args) const; void InterruptEventInitialization(); void ClockEventInitialization(); diff --git a/trace_streamer/src/table/ftrace/system_call_table.cpp b/trace_streamer/src/table/ftrace/system_call_table.cpp index 6ec56d27c8b8632c93194c138c1c88199b948279..76dbea5ef9a709e96ea87f74d9e7d99b4c5bddbd 100644 --- a/trace_streamer/src/table/ftrace/system_call_table.cpp +++ b/trace_streamer/src/table/ftrace/system_call_table.cpp @@ -17,15 +17,16 @@ namespace SysTuning { namespace TraceStreamer { -enum class Index : int32_t { SYSCALL_NUM = 0, TYPE, IPID, TS, RET }; +enum class Index : int32_t { SYSCALL_NUMBER, TS, DUR, ITID, ARGS, RET }; SystemCallTable::SystemCallTable(const TraceDataCache *dataCache) : TableBase(dataCache) { - tableColumn_.push_back(TableBase::ColumnInfo("syscall_num", "INTEGER")); - tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT")); - tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("syscall_number", "INTEGER")); tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER")); + tableColumn_.push_back(TableBase::ColumnInfo("args", "TEXT")); tableColumn_.push_back(TableBase::ColumnInfo("ret", "INTEGER")); - tablePriKey_.push_back("syscall_num"); + tablePriKey_.push_back("ts"); } SystemCallTable::~SystemCallTable() {} @@ -46,19 +47,21 @@ SystemCallTable::Cursor::~Cursor() {} int32_t SystemCallTable::Cursor::Column(int32_t column) const { switch (static_cast(column)) { - case Index::SYSCALL_NUM: - sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().SysCallsData()[CurrentRow()]); - break; - case Index::TYPE: - sqlite3_result_text(context_, dataCache_->GetDataFromDict(sysCallObj_.TypesData()[CurrentRow()]).c_str(), - STR_DEFAULT_LEN, nullptr); - break; - case Index::IPID: - sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().IpidsData()[CurrentRow()]); + case Index::SYSCALL_NUMBER: + sqlite3_result_int(context_, dataCache_->GetConstSysCallData().SysCallNumbersData()[CurrentRow()]); break; case Index::TS: sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().TimeStampData()[CurrentRow()]); break; + case Index::DUR: + sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().DursData()[CurrentRow()]); + break; + case Index::ITID: + sqlite3_result_int(context_, dataCache_->GetConstSysCallData().ItidsData()[CurrentRow()]); + break; + case Index::ARGS: + SetTypeColumnText(dataCache_->GetConstSysCallData().ArgsData()[CurrentRow()], INVALID_UINT64); + break; case Index::RET: sqlite3_result_int64(context_, dataCache_->GetConstSysCallData().RetsData()[CurrentRow()]); break; diff --git a/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.cpp b/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.cpp index 4b66c99534f084c686d47777147c2fb6b0aa08c1..3094cee043b745db481eabe91f0f52a1ab94b77d 100644 --- a/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.cpp +++ b/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.cpp @@ -13,16 +13,16 @@ * limitations under the License. */ #include "syscall_stdtype.h" - namespace SysTuning { namespace TraceStdtype { -size_t SysCall::AppendSysCallData(int64_t sysCallNum, DataIndex type, uint32_t ipid, uint64_t timeStamp, int64_t ret) +size_t SysCall::AppendSysCallData(const SyscallInfoRow& syscallInfoRow) { - sysCallNums_.emplace_back(sysCallNum); - types_.emplace_back(type); - ipids_.emplace_back(ipid); - timeStamps_.emplace_back(timeStamp); - rets_.emplace_back(ret); + sysCallNumbers_.emplace_back(syscallInfoRow.number); + timeStamps_.emplace_back(syscallInfoRow.ts); + durs_.emplace_back(syscallInfoRow.dur); + itids_.emplace_back(syscallInfoRow.itid); + args_.emplace_back(syscallInfoRow.args); + rets_.emplace_back(syscallInfoRow.ret); return Size() - 1; } } // namespace TraceStdtype diff --git a/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.h b/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.h index 0fa2844fb02faee8511d6be7fc9d85d9aa35cea3..e0834b94175940bd31ff2a1463bd648c1ced429f 100644 --- a/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.h +++ b/trace_streamer/src/trace_data/trace_stdtype/ftrace/syscall_stdtype.h @@ -19,43 +19,57 @@ namespace SysTuning { namespace TraceStdtype { +struct SyscallInfoRow { + uint64_t ts = INVALID_UINT64; + uint64_t dur = INVALID_UINT64; + InternalTid itid = INVALID_UINT32; + uint32_t number = INVALID_UINT32; + DataIndex args = INVALID_UINT64; + int64_t ret = INVALID_INT64; +}; class SysCall : public CacheBase, public BatchCacheBase { public: - size_t AppendSysCallData(int64_t sysCallNum, DataIndex type, uint32_t ipid, uint64_t timeStamp, int64_t ret); - const std::deque &SysCallsData() const + size_t AppendSysCallData(const SyscallInfoRow& syscallNrInfoRow); + const std::deque &SysCallNumbersData() const + { + return sysCallNumbers_; + } + const std::deque &DursData() const { - return sysCallNums_; + return durs_; } - const std::deque &TypesData() const + const std::deque &ItidsData() const { - return types_; + return itids_; } - const std::deque &IpidsData() const + const std::deque &ArgsData() const { - return ipids_; + return args_; } - const std::deque &RetsData() const + const std::deque &RetsData() const { return rets_; } void Clear() override { CacheBase::Clear(); - sysCallNums_.clear(); - types_.clear(); - ipids_.clear(); + sysCallNumbers_.clear(); + durs_.clear(); + itids_.clear(); + args_.clear(); rets_.clear(); } void ClearExportedData() override { - EraseElements(timeStamps_, sysCallNums_, types_, ipids_, rets_); + EraseElements(sysCallNumbers_, timeStamps_, durs_, itids_, args_, rets_); } private: - std::deque sysCallNums_ = {}; - std::deque types_ = {}; - std::deque ipids_ = {}; - std::deque rets_ = {}; + std::deque durs_ = {}; + std::deque sysCallNumbers_ = {}; + std::deque itids_ = {}; + std::deque args_ = {}; + std::deque rets_ = {}; }; } // namespace TraceStdtype } // namespace SysTuning diff --git a/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp b/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp index 31707d3238af296a27dee11b4c89d806412fce68..590125c3d553246951b777a23dea43cf956bb056 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_filters.cpp @@ -31,6 +31,7 @@ #include "process_filter.h" #include "slice_filter.h" #include "stat_filter.h" +#include "syscall_filter.h" #include "system_event_measure_filter.h" #include "task_pool_filter.h" @@ -45,6 +46,7 @@ void TraceStreamerFilters::FilterClear() cpuFilter_->Clear(); irqFilter_->Clear(); frameFilter_->Clear(); + syscallFilter_->Clear(); } } // namespace TraceStreamer } // namespace SysTuning diff --git a/trace_streamer/src/trace_streamer/trace_streamer_filters.h b/trace_streamer/src/trace_streamer/trace_streamer_filters.h index 4e223e904e3d8c6bfded1cb37b62bfe4d702fdf3..b82a22189ddfe966dbd5e70c7e1d05b3ef32f5c3 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_filters.h +++ b/trace_streamer/src/trace_streamer/trace_streamer_filters.h @@ -30,6 +30,7 @@ class StatFilter; class BinderFilter; class ArgsFilter; class IrqFilter; +class SyscallFilter; class SystemEventMeasureFilter; #ifdef ENABLE_HISYSEVENT class HiSysEventMeasureFilter; @@ -56,6 +57,7 @@ public: std::unique_ptr binderFilter_; std::unique_ptr argsFilter_; std::unique_ptr irqFilter_; + std::unique_ptr syscallFilter_; std::unique_ptr sysEventMemMeasureFilter_; std::unique_ptr sysEventVMemMeasureFilter_; std::unique_ptr sysEventSourceFilter_; diff --git a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp index 2d07bb03431c6cd88833434cad316eb7d843b277..4bb54b5fee06a6ce5fe367430397acaf11b1500f 100644 --- a/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp +++ b/trace_streamer/src/trace_streamer/trace_streamer_selector.cpp @@ -21,6 +21,7 @@ #include #include #include "animation_filter.h" +#include "syscall_filter.h" #include "app_start_filter.h" #include "args_filter.h" #include "binder_filter.h" @@ -157,6 +158,7 @@ void TraceStreamerSelector::InitFilter() streamFilters_->argsFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->irqFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->frameFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); + streamFilters_->syscallFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get()); streamFilters_->sysEventMemMeasureFilter_ = std::make_unique(traceDataCache_.get(), streamFilters_.get(), E_SYS_MEMORY_FILTER); streamFilters_->sysEventVMemMeasureFilter_ = std::make_unique( diff --git a/trace_streamer/src/version.cpp b/trace_streamer/src/version.cpp index 7a8226dd8c43818192660f6e726af26a3d8992f7..7b3d690bb01c55f71e3e3c437062920e86f3b3a8 100644 --- a/trace_streamer/src/version.cpp +++ b/trace_streamer/src/version.cpp @@ -17,7 +17,7 @@ namespace SysTuning { namespace TraceStreamer { size_t g_loadSize = 0; size_t g_fileSize = 0; -const std::string TRACE_STREAMER_VERSION = "4.3.2"; // version -const std::string TRACE_STREAMER_PUBLISH_VERSION = "2025/4/24"; // publish datetime +const std::string TRACE_STREAMER_VERSION = "4.3.4"; // version +const std::string TRACE_STREAMER_PUBLISH_VERSION = "2025/5/9"; // publish datetime } // namespace TraceStreamer } // namespace SysTuning