* 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 { PerfCmdLine, PerfFile, PerfSample, PerfStack, PerfThread } from '../../bean/PerfProfile';
import { query } from '../SqlLite';
import { HiSysEventStruct } from '../ui-worker/ProcedureWorkerHiSysEvent';
import { TaskTabStruct } from '../../component/trace/sheet/task/TabPaneTaskFrames';
import { GpuCountBean, SearchGpuFuncBean } from '../../bean/GpufreqBean';
export const queryPerfFiles = (): Promise<Array<PerfFile>> =>
query('queryPerfFiles', `select file_id as fileId,symbol,path from perf_files`, {});
export const queryPerfCallChainName = ():
Promise<Array<unknown>> => query('queryPerfCallChainName', `select callchain_id,depth,name from perf_callchain`, {});
export const queryPerfProcess = (): Promise<Array<PerfThread>> =>
query(
'queryPerfThread',
`select process_id as pid,thread_name as processName from perf_thread where process_id = thread_id`,
{}
);
export const queryPerfThread = (): Promise<Array<PerfThread>> =>
query(
'queryPerfThread',
`select a.thread_id as tid,
a.thread_name as threadName,
a.process_id as pid,
b.thread_name as processName
from perf_thread a
left join (select distinct process_id, thread_name from perf_thread where process_id = thread_id) b
on a.process_id = b.process_id
order by pid;`,
{}
);
export const queryPerfSampleListByTimeRange = (
leftNs: number,
rightNs: number,
cpus: Array<number>,
processes: Array<number>,
threads: Array<number>,
eventTypeId?: number
): Promise<Array<PerfSample>> => {
let sql = `
select A.callchain_id as sampleId,
A.thread_id as tid,
C.thread_name as threadName,
A.thread_state as state,
C.process_id as pid,
(timestamp_trace - R.start_ts) as time,
cpu_id as core
from perf_sample A,trace_range R
left join perf_thread C on A.thread_id = C.thread_id
where time >= $leftNs and time <= $rightNs and A.thread_id != 0
`;
if (eventTypeId !== undefined) {
sql = `${sql} and event_type_id = ${eventTypeId}`;
}
if (cpus.length !== 0 || processes.length !== 0 || threads.length !== 0) {
let arg1 = cpus.length > 0 ? `or core in (${cpus.join(',')}) ` : '';
let arg2 = processes.length > 0 ? `or pid in (${processes.join(',')}) ` : '';
let arg3 = threads.length > 0 ? `or tid in (${threads.join(',')})` : '';
let arg = `${arg1}${arg2}${arg3}`.substring(3);
sql = `${sql} and (${arg})`;
}
return query('queryPerfSampleListByTimeRange', sql, {
$leftNs: leftNs,
$rightNs: rightNs,
});
};
export const queryPerfSampleChildListByTree = (
leftNs: number,
rightNs: number,
pid?: number,
tid?: number,
): Promise<Array<PerfSample>> => {
let sql = `
select A.callchain_id as sampleId,
A.thread_id as tid,
C.thread_name as threadName,
A.thread_state as state,
C.process_id as pid,
(timestamp_trace - R.start_ts) as time,
cpu_id as core
from perf_sample A,trace_range R
left join perf_thread C on A.thread_id = C.thread_id
where time >= $leftNs and time <= $rightNs and A.thread_id != 0
`;
if (pid) {
sql = `${sql} and C.process_id = ${pid}`;
}
if (pid && tid !== undefined) {
sql = `${sql} and A.thread_id = ${tid}`;
}
return query('queryPerfSampleChildListByTree', sql, {
$leftNs: leftNs,
$rightNs: rightNs,
});
};
export const queryPerfSampleIdsByTimeRange = (
leftNs: number,
rightNs: number,
cpus: Array<number>,
processes: Array<number>,
threads: Array<number>
): Promise<Array<PerfSample>> => {
let sql = `
select A.callchain_id as sampleId
from perf_sample A,trace_range R
left join perf_thread C on A.thread_id = C.thread_id
where (timestamp_trace - R.start_ts) >= $leftNs and (timestamp_trace - R.start_ts) <= $rightNs and A.thread_id != 0
`;
if (cpus.length !== 0 || processes.length !== 0 || threads.length !== 0) {
let arg1 = cpus.length > 0 ? `or A.cpu_id in (${cpus.join(',')}) ` : '';
let arg2 = processes.length > 0 ? `or C.process_id in (${processes.join(',')}) ` : '';
let arg3 = threads.length > 0 ? `or A.thread_id in (${threads.join(',')})` : '';
let arg = `${arg1}${arg2}${arg3}`.substring(3);
sql = `${sql} and (${arg})`;
}
return query('queryPerfSampleIdsByTimeRange', sql, {
$leftNs: leftNs,
$rightNs: rightNs,
});
};
export const queryPerfSampleCallChain = (sampleId: number): Promise<Array<PerfStack>> =>
query(
'queryPerfSampleCallChain',
`
select
callchain_id as callChainId,
callchain_id as sampleId,
file_id as fileId,
symbol_id as symbolId,
vaddr_in_file as vaddrInFile,
source_file_id as sourceId,
line_number as lineNumber,
name as symbol
from perf_callchain where callchain_id = $sampleId;
`,
{ $sampleId: sampleId }
);
export const queryPerfCmdline = (): Promise<Array<PerfCmdLine>> =>
query(
'queryPerfCmdline',
`
select report_value from perf_report where report_type = 'cmdline'
`,
{}
);
export const queryPerfEventType = (): Promise<Array<{ id: number; report: string }>> =>
query(
'queryPerfEventType',
`
select id,report_value as report from perf_report where id in (
select distinct event_type_id from perf_sample);
`,
{}
);
* HiPerf
*/
export const queryHiPerfEventList = ():
Promise<Array<unknown>> =>
query('queryHiPerfEventList', `select id,report_value from perf_report where report_type='config_name'`, {});
export const queryHiPerfEventListData = (
eventTypeId: number
):
Promise<Array<unknown>> =>
query(
'queryHiPerfEventListData',
`
select s.callchain_id,
(s.timestamp_trace-t.start_ts) startNS
from perf_sample s,trace_range t
where
event_type_id=${eventTypeId}
and s.thread_id != 0
and s.callchain_id != -1;
`,
{ $eventTypeId: eventTypeId }
);
export const queryHiPerfEventData = (
eventTypeId: number,
cpu: number
):
Promise<Array<unknown>> =>
query(
'queryHiPerfEventList',
`
select s.callchain_id,
(s.timestamp_trace-t.start_ts) startNS
from perf_sample s,trace_range t
where
event_type_id=${eventTypeId}
and cpu_id=${cpu}
and s.thread_id != 0
and s.callchain_id != -1;
`,
{ $eventTypeId: eventTypeId, $cpu: cpu }
);
export const queryHiPerfCpuData = (
cpu: number
):
Promise<Array<unknown>> =>
query(
'queryHiPerfCpuData',
`
select s.callchain_id,
(s.timestamp_trace-t.start_ts) startNS, event_count, event_type_id
from perf_sample s,trace_range t
where
cpu_id=${cpu}
and s.thread_id != 0;`,
{ $cpu: cpu }
);
export const queryHiPerfCpuMergeData = ():
Promise<Array<unknown>> =>
query(
'queryHiPerfCpuData',
`select s.callchain_id,(s.timestamp_trace-t.start_ts) startNS, event_count, event_type_id from perf_sample s,trace_range t
where s.thread_id != 0;`,
{}
);
export const queryHiPerfCpuMergeData2 = ():
Promise<Array<unknown>> =>
query(
'queryHiPerfCpuData2',
`select distinct cpu_id from perf_sample where thread_id != 0 order by cpu_id desc;`,
{}
);
export const queryHiPerfProcessData = (
pid: number
):
Promise<Array<unknown>> =>
query(
'queryHiPerfProcessData',
`
SELECT sp.callchain_id,
th.thread_name,
th.thread_id tid,
th.process_id pid,
sp.timestamp_trace - tr.start_ts startNS,
event_count,
event_type_id
from perf_sample sp,
trace_range tr
left join perf_thread th on th.thread_id = sp.thread_id
where pid = ${pid} and sp.thread_id != 0 `,
{ $pid: pid }
);
export const queryHiPerfThreadData = (
tid: number
):
Promise<Array<unknown>> =>
query(
'queryHiPerfThreadData',
`
SELECT sp.callchain_id,
th.thread_name,
th.thread_id tid,
th.process_id pid,
sp.timestamp_trace - tr.start_ts startNS,
event_count,
event_type_id
from perf_sample sp,
trace_range tr
left join perf_thread th on th.thread_id = sp.thread_id
where tid = ${tid} and sp.thread_id != 0 ;`,
{ $tid: tid }
);
export const getGpufreqDataCut = (
tIds: string,
funcName: string,
leftNS: number,
rightNS: number,
single: boolean,
loop: boolean
): Promise<Array<SearchGpuFuncBean>> => {
let queryCondition: string = '';
if (single) {
queryCondition += `select s.funName,s.startTime,s.dur,s.startTime+s.dur as endTime,s.tid,s.threadName,s.pid from state s
where endTime between ${leftNS} and ${rightNS}`;
}
if (loop) {
queryCondition += `select s.funName,s.startTime,s.loopEndTime-s.startTime as dur,s.loopEndTime as endTime,s.tid,s.threadName,s.pid from state s
where endTime between ${leftNS} and ${rightNS} `;
}
return query(
'getGpufreqDataCut',
`
with state as
(select
*
from
(select
c.name as funName,
c.ts - r.start_ts as startTime,
c.dur,
lead(c.ts - r.start_ts, 1, null) over( order by c.ts - r.start_ts) loopEndTime,
t.tid,
t.name as threadName,
p.pid
from
callstack c
left join
thread t on c.callid = t.id
left join
process p on t.ipid = p.id
left join
trace_range r
where
c.name like '${funcName}%'
and
tid = '${tIds}'
and
startTime between ${leftNS} and ${rightNS}))
${queryCondition}
`,
{ $search: funcName }
);
};
export const getGpufreqData = (leftNS: number, rightNS: number, earliest: boolean): Promise<Array<GpuCountBean>> => {
let queryCondition: string = '';
if (!earliest) {
queryCondition += ` where not ((s.ts - r.start_ts + ifnull(s.dur,0) < ${leftNS}) or (s.ts - r.start_ts > ${rightNS}))`;
}
return query(
'getGpufreqData',
`
with state as
(select
name,
filter_id,
ts,
endts,
endts-ts as dur,
value as val
from
(select
measure.filter_id,
clock_event_filter.name,
measure.ts,
lead(ts, 1, null) over( order by measure.ts) endts,
measure.value
from
clock_event_filter,
trace_range
left join
measure
where
clock_event_filter.name = 'gpufreq'
and
clock_event_filter.type = 'clock_set_rate'
and
clock_event_filter.id = measure.filter_id
order by measure.ts)
where
endts is not null
)
select
s.name as thread,
s.val/1000000 as freq,
s.val*s.dur as value,
s.val,
s.ts-r.start_ts as startNS,
s.dur,
s.endts- r.start_ts as endTime
from
state s,
trace_range r
${queryCondition}
order by ts
`,
{ $leftNS: leftNS, $rightNS: rightNS }
);
};
export const queryHiSysEventTabData = (leftNs: number, rightNs: number): Promise<Array<HiSysEventStruct>> =>
query(
'queryHiSysEventTabData',
`SELECT S.id,
D2.data AS domain,
D.data AS eventName,
type AS eventType,
time_zone AS tz,
pid,
tid,
uid,
info,
level,
seq,
contents,
S.ts - TR.start_ts AS startTs,
1 AS dur,
CASE
WHEN level = 'MINOR' THEN
0
WHEN level = 'CRITICAL' THEN
1
END AS depth
FROM hisys_all_event AS S ,trace_range AS TR
LEFT JOIN data_dict AS D on S.event_name_id = D.id
LEFT JOIN data_dict AS D2 on S.domain_id = D2.id
WHERE S.id is not null
and startTs >= ${Math.floor(leftNs)}
and startTs <= ${Math.floor(rightNs)}
ORDER BY S.ts`
);
export const queryHiSysEventData = (): Promise<Array<HiSysEventStruct>> =>
query(
'queryHiSysEventData',
`SELECT l.ts - tr.start_ts as startNs FROM hisys_all_event AS l, trace_range tr WHERE startNs > 0 LIMIT 1`
);
export const queryHiPerfProcessCount = (
leftNs: number,
rightNs: number,
cpus: Array<number>,
threads: Array<number>,
processes: Array<number>
):
Promise<Array<unknown>> => {
let str = '';
if (processes.length > 0) {
str = ` and C.process_id in (${processes.join(',')})`;
}
if (threads.length > 0) {
str = ` and A.thread_id in (${threads.join(',')}) `;
}
if (processes.length > 0 && threads.length > 0) {
str = ` and (C.process_id in (${processes.join(',')}) or A.thread_id in (${threads.join(',')}))`;
}
if (cpus.length > 0) {
str = ` and A.cpu_id in (${cpus.join(',')})`;
}
if (cpus.length > 0 && processes.length > 0) {
str = ` and (C.process_id in (${processes.join(',')}) or A.cpu_id in (${cpus.join(',')}))`;
}
return query(
'queryHiPerfProcessCount',
`
select C.process_id as pid,
(A.timestamp_trace - R.start_ts) as time,
C.thread_name as threadName,
A.thread_id as tid,
A.id,
A.callchain_id
from perf_sample A,trace_range R
left join perf_thread C on A.thread_id = C.thread_id and A.thread_id != 0
where time >= $leftNs and time <= $rightNs and A.callchain_id > 0
${str}
`,
{ $leftNs: leftNs, $rightNs: rightNs }
);
};
export const queryTransferList = (): Promise<Array<{ id: number; cmdStr: string }>> =>
query('queryTransferList', `select id, report_value as cmdStr from perf_report where report_type = 'config_name'`);
export const queryConcurrencyTask = (
itid: number,
selectStartTime: number,
selectEndTime: number
): Promise<TaskTabStruct[]> =>
query<TaskTabStruct>(
'queryConcurrencyTask',
`SELECT thread.tid,
thread.ipid,
callstack.name AS funName,
callstack.ts AS startTs,
(case when callstack.dur = -1 then (SELECT end_ts FROM trace_range) else callstack.dur end) as dur,
callstack.id,
task_pool.priority,
task_pool.allocation_task_row AS allocationTaskRow,
task_pool.execute_task_row AS executeTaskRow,
task_pool.return_task_row AS returnTaskRow,
task_pool.task_id AS executeId
FROM thread
LEFT JOIN callstack ON thread.id = callstack.callid
LEFT JOIN task_pool ON callstack.id = task_pool.execute_task_row
WHERE ipid in (SELECT thread.ipid
FROM thread
WHERE thread.itid = $itid)
AND thread.name LIKE '%TaskWork%'
AND callstack.name LIKE 'H:Task Perform:%'
AND -- 左包含
(($selectStartTime <= callstack.ts AND $selectEndTime > callstack.ts)
OR -- 右包含
($selectStartTime < callstack.ts + callstack.dur AND $selectEndTime >= callstack.ts + callstack.dur)
OR -- 包含
($selectStartTime >= callstack.ts AND $selectEndTime <= callstack.ts +
(case when callstack.dur = -1 then (SELECT end_ts FROM trace_range) else callstack.dur end))
OR -- 被包含
($selectStartTime <= callstack.ts AND $selectEndTime >= callstack.ts + callstack.dur))
ORDER BY callstack.ts;`,
{ $itid: itid, $selectStartTime: selectStartTime, $selectEndTime: selectEndTime }
);