Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
MegEngine 天元
MegEngine
提交
84fc5c92
MegEngine
项目概览
MegEngine 天元
/
MegEngine
大约 1 年 前同步成功
通知
399
Star
4705
Fork
582
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
MegEngine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
84fc5c92
编写于
5月 15, 2021
作者:
M
Megvii Engine Team
提交者:
huangxinda
7月 19, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor(profiler): remove dump logic for old profiler
GitOrigin-RevId: f9a3b6d7b9b9178dd9ce53bb391d0a0077d8af3b
上级
5b5a8261
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
145 addition
and
390 deletion
+145
-390
imperative/src/impl/interpreter/interpreter_impl.cpp
imperative/src/impl/interpreter/interpreter_impl.cpp
+0
-1
imperative/src/impl/interpreter/profiler.cpp
imperative/src/impl/interpreter/profiler.cpp
+0
-250
imperative/src/impl/interpreter/profiler.h
imperative/src/impl/interpreter/profiler.h
+0
-2
imperative/src/impl/profiler/chrome_timeline.cpp
imperative/src/impl/profiler/chrome_timeline.cpp
+145
-0
imperative/src/include/megbrain/imperative/profiler.h
imperative/src/include/megbrain/imperative/profiler.h
+0
-137
未找到文件。
imperative/src/impl/interpreter/interpreter_impl.cpp
浏览文件 @
84fc5c92
...
...
@@ -847,7 +847,6 @@ void ChannelImpl::process_one_task(IdentifiedCommand& icmd) {
return
"unknown"
;
}
};
InterpreterProfiler
::
dump_data
(
cmd
.
basename
,
cmd
.
format
,
records
,
profiler
->
get_option
(),
host_map
);
}
else
if
constexpr
(
std
::
is_same_v
<
T
,
PushScope
>
)
{
state
.
scopes
.
push_back
(
cmd
.
scope_name
);
do_finish_command
();
...
...
imperative/src/impl/interpreter/profiler.cpp
浏览文件 @
84fc5c92
...
...
@@ -26,255 +26,5 @@
namespace
mgb
::
imperative
::
interpreter
::
intl
{
namespace
{
struct
InterpreterProfilerDumpChromeTimelineContext
{
// either host_thread(std::thread::id) or device_thread(CompNode)
using
Thread
=
std
::
variant
<
std
::
thread
::
id
,
CompNode
>
;
// input params
std
::
string
base_name
;
std
::
string
format
;
InterpreterProfiler
::
Data
profile_data
;
InterpreterProfiler
::
Option
option
;
std
::
function
<
std
::
string
(
std
::
thread
::
id
)
>
host_map
;
// internal states
decltype
(
getpid
())
pid
;
CompNode
::
UnorderedMap
<
std
::
map
<
double
,
CompNode
::
Event
*>>
device_sync_map
;
SmallVector
<
Thread
>
thread_list
;
double
time_start
;
// options
bool
show_operator_name
;
// results
ChromeTraceEventList
event_list
;
InterpreterProfilerDumpChromeTimelineContext
(
std
::
string
base_name
,
std
::
string
format
,
InterpreterProfiler
::
Data
profile_data
,
InterpreterProfiler
::
Option
option
,
std
::
function
<
std
::
string
(
std
::
thread
::
id
)
>
host_map
)
:
base_name
{
base_name
},
format
{
format
},
profile_data
{
profile_data
},
option
{
option
},
host_map
{
host_map
}
{
pid
=
getpid
();
time_start
=
option
.
align_time
?
time_start
:
0
;
show_operator_name
=
option
.
show_operator_name
;
}
// get device time from event
double
get_device_time
(
CompNode
::
Event
*
device_event
,
double
host_time
)
{
device_event
->
host_wait
();
auto
&
sync_map
=
device_sync_map
[
device_event
->
comp_node
()];
// find sync point
auto
iter
=
sync_map
.
begin
();
auto
sync_current
=
[
&
]
{
iter
=
sync_map
.
insert
(
iter
,
{
host_time
,
device_event
});
return
host_time
;
};
if
(
iter
==
sync_map
.
end
())
{
// not found, insert sync
return
sync_current
();
}
auto
&
[
base_time
,
base
]
=
*
iter
;
// calculate elapsed time
double
delta_time
=
base
->
elapsed_time_until
(
*
device_event
)
*
1e3
;
return
base_time
+
delta_time
;
};
template
<
typename
T
>
size_t
get_tid
(
T
t
)
{
for
(
size_t
i
=
0
;
i
<
thread_list
.
size
();
i
++
)
{
if
(
thread_list
[
i
]
==
Thread
{
t
})
{
return
i
;
}
}
thread_list
.
push_back
(
t
);
return
thread_list
.
size
()
-
1
;
};
ChromeTraceEvent
&
new_event
(
std
::
string
name
,
char
ph
,
uint64_t
tid
,
double
ts
)
{
return
event_list
.
new_event
().
name
(
name
).
ph
(
ph
).
tid
(
tid
).
ts
(
ts
).
pid
(
pid
);
};
// convert Command to json object. Has to be an callable object
static
auto
constexpr
cmd_to_args
=
[](
const
auto
&
cmd
)
{
auto
args
=
json
::
Object
::
make
();
cmd
.
get_props
([
&
](
const
char
*
key
,
auto
&&
value
){
(
*
args
)[
key
]
=
json
::
String
::
make
(
to_string
(
value
));
});
(
*
args
)[
"__type__"
]
=
json
::
String
::
make
(
typeid
(
cmd
).
name
());
return
args
;
};
void
process
()
{
// enumerate and process each record
for
(
auto
&
record
:
profile_data
.
records
)
{
std
::
visit
([
this
](
const
auto
&
record
){
using
TEvent
=
std
::
decay_t
<
decltype
(
record
.
data
)
>
;
Session
<
TEvent
>
(
*
this
,
record
).
process
();
},
record
);
}
for
(
size_t
tid
=
0
;
tid
<
thread_list
.
size
();
++
tid
)
{
auto
tname
=
std
::
visit
([
&
](
auto
host_or_device
)
->
std
::
string
{
using
T
=
std
::
decay_t
<
decltype
(
host_or_device
)
>
;
if
constexpr
(
std
::
is_same_v
<
T
,
std
::
thread
::
id
>
)
{
// take name from host_map
return
host_map
(
host_or_device
);
}
else
{
// use CompNode::to_string
return
host_or_device
.
to_string
();
}
},
thread_list
[
tid
]);
// assign thread name
new_event
(
"thread_name"
,
'M'
,
tid
,
0
)
.
arg
(
"name"
,
tname
);
}
// wraite output to file
std
::
string
out_buf
;
event_list
.
to_json
()
->
writeto
(
out_buf
,
4
);
std
::
ofstream
output_stream
;
output_stream
.
open
(
base_name
+
"."
+
format
);
output_stream
<<
out_buf
;
output_stream
.
flush
();
output_stream
.
close
();
}
template
<
typename
TEvent
>
struct
Session
{
InterpreterProfilerDumpChromeTimelineContext
&
ctx
;
const
ProfilerBase
::
EventRecord
<
TEvent
>&
record
;
const
TEvent
&
data
;
Session
(
InterpreterProfilerDumpChromeTimelineContext
&
ctx
,
const
ProfilerBase
::
EventRecord
<
TEvent
>&
record
)
:
ctx
{
ctx
},
record
{
record
},
data
{
record
.
data
}
{}
uint64_t
get_host_tid
()
{
return
ctx
.
get_tid
(
record
.
host
().
tid
);
};
double
get_host_ts
()
{
return
(
ctx
.
time_start
+
record
.
host
().
time
)
*
1e3
;
};
uint64_t
get_device_tid
()
{
return
ctx
.
get_tid
(
record
.
device
().
event
->
comp_node
());
};
double
get_device_ts
()
{
return
(
ctx
.
time_start
+
ctx
.
get_device_time
(
record
.
device
().
event
.
get
(),
record
.
device
().
after
))
*
1e3
;
};
ChromeTraceEvent
&
new_host_event
(
std
::
string
name
,
char
ph
)
{
return
ctx
.
new_event
(
std
::
move
(
name
),
ph
,
get_host_tid
(),
get_host_ts
());
};
ChromeTraceEvent
&
new_device_event
(
std
::
string
name
,
char
ph
)
{
return
ctx
.
new_event
(
std
::
move
(
name
),
ph
,
get_device_tid
(),
get_device_ts
());
};
void
process
()
{
// dispatch event by type
if
constexpr
(
std
::
is_same_v
<
TEvent
,
CommandEnqueueEvent
>
)
{
auto
args
=
std
::
visit
(
cmd_to_args
,
data
.
icmd
.
second
);
new_host_event
(
"CommandEnqueue"
,
'X'
).
dur
(
0
).
args
(
args
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
CommandExecuteEvent
>
)
{
auto
args
=
std
::
visit
(
cmd_to_args
,
data
.
icmd
.
second
);
new_host_event
(
"CommandExecute"
,
'B'
).
args
(
args
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
CommandFinishEvent
>
)
{
new_host_event
(
"CommandExecute"
,
'E'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
HostOpExecuteEvent
>
)
{
auto
args
=
json
::
Object
::
make
();
auto
props
=
OpDef
::
props
(
*
data
.
op
);
auto
name
=
data
.
op
->
trait
()
->
name
;
for
(
auto
&&
[
prop_name
,
prop_val
]
:
props
)
{
(
*
args
)[
std
::
string
(
"op."
)
+
prop_name
]
=
json
::
String
::
make
(
prop_val
);
}
(
*
args
)[
"name"
]
=
json
::
String
::
make
(
name
);
(
*
args
)[
"id"
]
=
json
::
Number
::
make
(
data
.
id
);
(
*
args
)[
"inputs"
]
=
json
::
String
::
make
(
to_string
(
data
.
inputs
));
(
*
args
)[
"outputs"
]
=
json
::
String
::
make
(
to_string
(
data
.
outputs
));
new_host_event
(
ctx
.
show_operator_name
?
name
:
"OpExecute"
,
'B'
).
args
(
args
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
DeviceOpExecuteEvent
>
)
{
auto
args
=
json
::
Object
::
make
();
auto
props
=
OpDef
::
props
(
*
data
.
op
);
auto
name
=
data
.
op
->
trait
()
->
name
;
for
(
auto
&&
[
prop_name
,
prop_val
]
:
props
)
{
(
*
args
)[
std
::
string
(
"op."
)
+
prop_name
]
=
json
::
String
::
make
(
prop_val
);
}
(
*
args
)[
"name"
]
=
json
::
String
::
make
(
name
);
(
*
args
)[
"id"
]
=
json
::
Number
::
make
(
data
.
id
);
(
*
args
)[
"inputs"
]
=
json
::
String
::
make
(
to_string
(
data
.
inputs
));
(
*
args
)[
"outputs"
]
=
json
::
String
::
make
(
to_string
(
data
.
outputs
));
new_device_event
(
ctx
.
show_operator_name
?
name
:
"OpExecute"
,
'B'
).
args
(
args
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
HostOpFinishEvent
>
)
{
auto
name
=
data
.
op
->
trait
()
->
name
;
new_host_event
(
ctx
.
show_operator_name
?
name
:
"OpExecute"
,
'E'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
DeviceOpFinishEvent
>
)
{
auto
name
=
data
.
op
->
trait
()
->
name
;
new_device_event
(
ctx
.
show_operator_name
?
name
:
"OpExecute"
,
'E'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
TensorDeclareEvent
>
)
{
json
::
Number
::
make
(
data
.
tensor_id
);
new_host_event
(
"TensorLifetime"
,
'N'
).
id
(
data
.
tensor_id
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
TensorProduceEvent
>
)
{
auto
snapshot
=
json
::
Object
::
make
();
(
*
snapshot
)[
"shape"
]
=
json
::
String
::
make
(
to_string
((
TensorShape
)
data
.
layout
));
(
*
snapshot
)[
"dtype"
]
=
json
::
String
::
make
(
to_string
(
data
.
layout
.
dtype
));
(
*
snapshot
)[
"device"
]
=
json
::
String
::
make
(
to_string
(
data
.
device
));
json
::
Number
::
make
(
data
.
tensor_id
);
new_host_event
(
"TensorLifetime"
,
'O'
).
id
(
data
.
tensor_id
).
arg
(
"snapshot"
,
snapshot
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
TensorEraseEvent
>
)
{
json
::
Number
::
make
(
data
.
tensor_id
);
new_host_event
(
"TensorLifetime"
,
'D'
).
id
(
data
.
tensor_id
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
TensorGetPropEvent
>
)
{
auto
args
=
json
::
Object
::
make
();
(
*
args
)[
"id"
]
=
json
::
Number
::
make
(
data
.
tensor_id
);
(
*
args
)[
"prop"
]
=
json
::
String
::
make
(
to_string
(
data
.
prop
));
(
*
args
)[
"prop_desc"
]
=
json
::
String
::
make
(
data
.
prop_desc
);
new_host_event
(
"TensorGetProp"
,
'X'
).
dur
(
0
).
args
(
args
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
TensorNotifyPropEvent
>
)
{
// TODO
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
TensorWaitPropEvent
>
)
{
auto
args
=
json
::
Object
::
make
();
(
*
args
)[
"id"
]
=
json
::
Number
::
make
(
data
.
tensor_id
);
(
*
args
)[
"prop"
]
=
json
::
String
::
make
(
to_string
(
data
.
prop
));
(
*
args
)[
"prop_desc"
]
=
json
::
String
::
make
(
data
.
prop_desc
);
new_host_event
(
"TensorWaitProp"
,
'B'
).
args
(
args
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
TensorWaitPropFinishEvent
>
)
{
auto
args
=
json
::
Object
::
make
();
(
*
args
)[
"id"
]
=
json
::
Number
::
make
(
data
.
tensor_id
);
(
*
args
)[
"prop"
]
=
json
::
String
::
make
(
to_string
(
data
.
prop
));
(
*
args
)[
"prop_desc"
]
=
json
::
String
::
make
(
data
.
prop_desc
);
new_host_event
(
"TensorWaitProp"
,
'E'
).
args
(
args
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
SyncStartEvent
>
)
{
new_host_event
(
"SyncEvent"
,
'B'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
SyncFinishEvent
>
)
{
new_host_event
(
"SyncEvent"
,
'E'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
ChannelBeginScope
>
)
{
new_host_event
(
data
.
name
,
'B'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
ChannelEndScope
>
)
{
new_host_event
(
data
.
name
,
'E'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
WorkerBeginScope
>
)
{
new_host_event
(
data
.
name
,
'B'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
WorkerEndScope
>
)
{
new_host_event
(
data
.
name
,
'E'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
DeviceBeginScope
>
)
{
new_device_event
(
data
.
name
,
'B'
);
}
else
if
constexpr
(
std
::
is_same_v
<
TEvent
,
DeviceEndScope
>
)
{
new_device_event
(
data
.
name
,
'E'
);
}
else
{
static_assert
(
!
std
::
is_same_v
<
TEvent
,
TEvent
>
);
}
}
};
};
}
void
InterpreterProfiler
::
dump_data
(
std
::
string
basename
,
std
::
string
format
,
InterpreterProfiler
::
Data
profile_data
,
const
InterpreterProfiler
::
Option
&
option
,
std
::
function
<
std
::
string
(
std
::
thread
::
id
)
>
host_map
)
{
InterpreterProfilerDumpChromeTimelineContext
{
basename
,
format
,
profile_data
,
option
,
host_map
}.
process
();
}
}
imperative/src/impl/interpreter/profiler.h
浏览文件 @
84fc5c92
...
...
@@ -61,8 +61,6 @@ public:
m_option
=
option
;
}
static
void
dump_data
(
std
::
string
basename
,
std
::
string
format
,
InterpreterProfiler
::
Data
profile_data
,
const
Option
&
option
,
std
::
function
<
std
::
string
(
std
::
thread
::
id
)
>
host_map
);
static
Mask
topic_to_mask
(
Topic
topic
)
{
Mask
result
;
if
(
topic
&
Command
)
{
...
...
imperative/src/impl/profiler/chrome_timeline.cpp
0 → 100644
浏览文件 @
84fc5c92
#include <string>
#include <memory>
#include "megbrain/utils/json.h"
namespace
mgb
{
namespace
imperative
{
class
ChromeTraceEvent
{
public:
ChromeTraceEvent
&
name
(
std
::
string
name
)
{
m_name
=
std
::
move
(
name
);
return
*
this
;
}
ChromeTraceEvent
&
tid
(
uint64_t
tid
)
{
m_tid
=
std
::
move
(
tid
);
return
*
this
;
}
ChromeTraceEvent
&
cat
(
std
::
string
cat
)
{
m_cat
=
std
::
move
(
cat
);
return
*
this
;
}
ChromeTraceEvent
&
pid
(
uint64_t
pid
)
{
m_pid
=
pid
;
return
*
this
;
}
ChromeTraceEvent
&
id
(
uint64_t
id
)
{
m_id
=
id
;
return
*
this
;
}
ChromeTraceEvent
&
idx
(
uint64_t
idx
)
{
m_idx
=
idx
;
return
*
this
;
}
ChromeTraceEvent
&
ts
(
double
ts
)
{
m_ts
=
ts
;
return
*
this
;
}
ChromeTraceEvent
&
dur
(
double
dur
)
{
m_dur
=
dur
;
return
*
this
;
}
ChromeTraceEvent
&
ph
(
char
ph
)
{
m_ph
=
ph
;
return
*
this
;
}
ChromeTraceEvent
&
bp
(
char
bp
)
{
m_bp
=
bp
;
return
*
this
;
}
ChromeTraceEvent
&
args
(
std
::
shared_ptr
<
json
::
Object
>
args
)
{
m_args
=
std
::
move
(
args
);
return
*
this
;
}
ChromeTraceEvent
&
arg
(
std
::
string
key
,
std
::
string
value
)
{
if
(
!
m_args
)
{
m_args
=
json
::
Object
::
make
();
}
(
*
m_args
)[
key
]
=
json
::
String
::
make
(
value
);
return
*
this
;
}
ChromeTraceEvent
&
arg
(
std
::
string
key
,
double
value
)
{
if
(
!
m_args
)
{
m_args
=
json
::
Object
::
make
();
}
(
*
m_args
)[
key
]
=
json
::
Number
::
make
(
value
);
return
*
this
;
}
ChromeTraceEvent
&
arg
(
std
::
string
key
,
std
::
shared_ptr
<
json
::
Value
>
value
)
{
if
(
!
m_args
)
{
m_args
=
json
::
Object
::
make
();
}
(
*
m_args
)[
key
]
=
value
;
return
*
this
;
}
std
::
shared_ptr
<
json
::
Object
>
to_json
()
const
{
auto
result
=
json
::
Object
::
make
();
auto
prop_str
=
[
&
](
auto
key
,
auto
value
)
{
if
(
value
.
empty
())
{
return
;
}
(
*
result
)[
key
]
=
json
::
String
::
make
(
value
);
};
auto
prop_num
=
[
&
](
auto
key
,
auto
value
)
{
if
(
!
value
)
{
return
;
}
(
*
result
)[
key
]
=
json
::
Number
::
make
(
value
.
value
());
};
auto
prop_char
=
[
&
](
auto
key
,
auto
value
)
{
if
(
!
value
)
{
return
;
}
(
*
result
)[
key
]
=
json
::
String
::
make
(
std
::
string
{}
+
value
.
value
());
};
prop_str
(
"name"
,
m_name
);
prop_num
(
"tid"
,
m_tid
);
prop_str
(
"cat"
,
m_cat
);
prop_num
(
"pid"
,
m_pid
);
prop_num
(
"id"
,
m_id
);
prop_num
(
"idx"
,
m_idx
);
prop_num
(
"ts"
,
m_ts
);
prop_num
(
"dur"
,
m_dur
);
prop_char
(
"ph"
,
m_ph
);
prop_char
(
"bp"
,
m_bp
);
if
(
m_args
)
{
(
*
result
)[
"args"
]
=
m_args
;
}
return
result
;
}
private:
std
::
string
m_name
;
std
::
string
m_cat
;
std
::
optional
<
uint64_t
>
m_tid
;
std
::
optional
<
uint64_t
>
m_pid
;
std
::
optional
<
uint64_t
>
m_id
;
std
::
optional
<
uint64_t
>
m_idx
;
std
::
optional
<
double
>
m_ts
;
std
::
optional
<
double
>
m_dur
;
std
::
optional
<
char
>
m_ph
;
std
::
optional
<
char
>
m_bp
;
std
::
shared_ptr
<
json
::
Object
>
m_args
;
};
class
ChromeTraceEventList
{
public:
ChromeTraceEvent
&
new_event
()
{
m_content
.
emplace_back
();
return
m_content
.
back
();
}
std
::
shared_ptr
<
json
::
Array
>
to_json
()
const
{
auto
result
=
json
::
Array
::
make
();
for
(
auto
&&
event
:
m_content
)
{
result
->
add
(
event
.
to_json
());
}
return
result
;
}
private:
std
::
vector
<
ChromeTraceEvent
>
m_content
;
};
}
// namespace imperative
}
// namespace mgb
imperative/src/include/megbrain/imperative/profiler.h
浏览文件 @
84fc5c92
...
...
@@ -190,142 +190,5 @@ protected:
std
::
atomic
<
Status
>
m_status
=
NotStarted
;
};
class
ChromeTraceEvent
{
public:
ChromeTraceEvent
&
name
(
std
::
string
name
)
{
m_name
=
std
::
move
(
name
);
return
*
this
;
}
ChromeTraceEvent
&
tid
(
uint64_t
tid
)
{
m_tid
=
std
::
move
(
tid
);
return
*
this
;
}
ChromeTraceEvent
&
cat
(
std
::
string
cat
)
{
m_cat
=
std
::
move
(
cat
);
return
*
this
;
}
ChromeTraceEvent
&
pid
(
uint64_t
pid
)
{
m_pid
=
pid
;
return
*
this
;
}
ChromeTraceEvent
&
id
(
uint64_t
id
)
{
m_id
=
id
;
return
*
this
;
}
ChromeTraceEvent
&
idx
(
uint64_t
idx
)
{
m_idx
=
idx
;
return
*
this
;
}
ChromeTraceEvent
&
ts
(
double
ts
)
{
m_ts
=
ts
;
return
*
this
;
}
ChromeTraceEvent
&
dur
(
double
dur
)
{
m_dur
=
dur
;
return
*
this
;
}
ChromeTraceEvent
&
ph
(
char
ph
)
{
m_ph
=
ph
;
return
*
this
;
}
ChromeTraceEvent
&
bp
(
char
bp
)
{
m_bp
=
bp
;
return
*
this
;
}
ChromeTraceEvent
&
args
(
std
::
shared_ptr
<
json
::
Object
>
args
)
{
m_args
=
std
::
move
(
args
);
return
*
this
;
}
ChromeTraceEvent
&
arg
(
std
::
string
key
,
std
::
string
value
)
{
if
(
!
m_args
)
{
m_args
=
json
::
Object
::
make
();
}
(
*
m_args
)[
key
]
=
json
::
String
::
make
(
value
);
return
*
this
;
}
ChromeTraceEvent
&
arg
(
std
::
string
key
,
double
value
)
{
if
(
!
m_args
)
{
m_args
=
json
::
Object
::
make
();
}
(
*
m_args
)[
key
]
=
json
::
Number
::
make
(
value
);
return
*
this
;
}
ChromeTraceEvent
&
arg
(
std
::
string
key
,
std
::
shared_ptr
<
json
::
Value
>
value
)
{
if
(
!
m_args
)
{
m_args
=
json
::
Object
::
make
();
}
(
*
m_args
)[
key
]
=
value
;
return
*
this
;
}
std
::
shared_ptr
<
json
::
Object
>
to_json
()
const
{
auto
result
=
json
::
Object
::
make
();
auto
prop_str
=
[
&
](
auto
key
,
auto
value
)
{
if
(
value
.
empty
())
{
return
;
}
(
*
result
)[
key
]
=
json
::
String
::
make
(
value
);
};
auto
prop_num
=
[
&
](
auto
key
,
auto
value
)
{
if
(
!
value
)
{
return
;
}
(
*
result
)[
key
]
=
json
::
Number
::
make
(
value
.
value
());
};
auto
prop_char
=
[
&
](
auto
key
,
auto
value
)
{
if
(
!
value
)
{
return
;
}
(
*
result
)[
key
]
=
json
::
String
::
make
(
std
::
string
{}
+
value
.
value
());
};
prop_str
(
"name"
,
m_name
);
prop_num
(
"tid"
,
m_tid
);
prop_str
(
"cat"
,
m_cat
);
prop_num
(
"pid"
,
m_pid
);
prop_num
(
"id"
,
m_id
);
prop_num
(
"idx"
,
m_idx
);
prop_num
(
"ts"
,
m_ts
);
prop_num
(
"dur"
,
m_dur
);
prop_char
(
"ph"
,
m_ph
);
prop_char
(
"bp"
,
m_bp
);
if
(
m_args
)
{
(
*
result
)[
"args"
]
=
m_args
;
}
return
result
;
}
private:
std
::
string
m_name
;
std
::
string
m_cat
;
std
::
optional
<
uint64_t
>
m_tid
;
std
::
optional
<
uint64_t
>
m_pid
;
std
::
optional
<
uint64_t
>
m_id
;
std
::
optional
<
uint64_t
>
m_idx
;
std
::
optional
<
double
>
m_ts
;
std
::
optional
<
double
>
m_dur
;
std
::
optional
<
char
>
m_ph
;
std
::
optional
<
char
>
m_bp
;
std
::
shared_ptr
<
json
::
Object
>
m_args
;
};
class
ChromeTraceEventList
{
public:
ChromeTraceEvent
&
new_event
()
{
m_content
.
emplace_back
();
return
m_content
.
back
();
}
std
::
shared_ptr
<
json
::
Array
>
to_json
()
const
{
auto
result
=
json
::
Array
::
make
();
for
(
auto
&&
event
:
m_content
)
{
result
->
add
(
event
.
to_json
());
}
return
result
;
}
private:
std
::
vector
<
ChromeTraceEvent
>
m_content
;
};
}
// namespace imperative
}
// namespace mgb
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录