Skip to content

Commit c8a2238

Browse files
committed
[DNS] tp: speed up JSON tokenization/parsing by 4.5x
Switch away from jsoncpp which has atrocious perf for parsing in favour of writing our own parser. Moreover, remove some uses of a poor quality json value fetch function in favour of our own. test Fix fix fix
1 parent 02240e4 commit c8a2238

File tree

20 files changed

+2295
-800
lines changed

20 files changed

+2295
-800
lines changed

BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2211,6 +2211,7 @@ perfetto_filegroup(
22112211
perfetto_filegroup(
22122212
name = "src_trace_processor_importers_json_minimal",
22132213
srcs = [
2214+
"src/trace_processor/importers/json/json_parser.h",
22142215
"src/trace_processor/importers/json/json_utils.cc",
22152216
"src/trace_processor/importers/json/json_utils.h",
22162217
],

CHANGELOG

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ Unreleased:
44
SQL Standard library:
55
*
66
Trace Processor:
7-
*
7+
* Improved performance of parsing JSON by 7x. JSON traces should now load
8+
much faster in the Perfetto UI and the trace processor.
89
UI:
9-
*
10+
* Improved JSON loading performance. See `Trace Processor` section above.
1011
SDK:
1112
*
1213

src/trace_processor/importers/common/BUILD.gn

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,10 @@ source_set("common") {
107107

108108
source_set("trace_parser_hdr") {
109109
sources = [ "trace_parser.h" ]
110-
deps = [ "../../../../gn:default_deps" ]
110+
deps = [
111+
":parser_types",
112+
"../../../../gn:default_deps",
113+
]
111114
}
112115

113116
source_set("parser_types") {

src/trace_processor/importers/common/parser_types.h

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,16 @@
2020
#include <array>
2121
#include <cstdint>
2222
#include <functional>
23+
#include <limits>
24+
#include <memory>
2325
#include <optional>
24-
#include <string>
2526
#include <utility>
2627
#include <variant>
28+
#include <vector>
2729

2830
#include "perfetto/trace_processor/ref_counted.h"
2931
#include "perfetto/trace_processor/trace_blob_view.h"
32+
#include "src/trace_processor/containers/interval_tree.h"
3033
#include "src/trace_processor/containers/string_pool.h"
3134
#include "src/trace_processor/importers/proto/packet_sequence_state_generation.h"
3235

@@ -57,16 +60,72 @@ struct alignas(8) InlineSchedWaking {
5760
static_assert(sizeof(InlineSchedWaking) == 16);
5861

5962
struct alignas(8) JsonEvent {
60-
struct Begin {};
61-
struct End {};
62-
struct Scoped {
63-
int64_t dur;
63+
int64_t dur = std::numeric_limits<int64_t>::max();
64+
65+
uint32_t pid = 0;
66+
uint32_t tid = 0;
67+
68+
StringPool::Id name = StringPool::Id::Null();
69+
StringPool::Id cat = StringPool::Id::Null();
70+
71+
union IdStrOrUint64 {
72+
StringPool::Id id_str;
73+
uint64_t id_uint64;
6474
};
65-
struct Other {};
66-
using Type = std::variant<Begin, End, Scoped, Other>;
75+
IdStrOrUint64 id;
76+
IdStrOrUint64 bind_id;
77+
78+
int64_t tts = std::numeric_limits<int64_t>::max();
79+
int64_t tdur = std::numeric_limits<int64_t>::max();
80+
int64_t async_cookie = std::numeric_limits<int64_t>::max();
81+
82+
std::unique_ptr<char[]> args;
83+
84+
char phase = '\0';
85+
86+
uint64_t flow_in : 1;
87+
uint64_t flow_out : 1;
6788

68-
std::string value;
69-
Type type;
89+
uint64_t pid_is_string_id : 1;
90+
uint64_t tid_is_string_id : 1;
91+
92+
uint64_t bind_enclosing_slice : 1;
93+
94+
enum class IdType : uint64_t {
95+
kNone = 0,
96+
kString = 1,
97+
kUint64 = 2,
98+
};
99+
IdType id_type : 2;
100+
IdType bind_id_type : 2;
101+
102+
enum class Scope : uint64_t {
103+
kNone = 0,
104+
kGlobal = 1,
105+
kProcess = 2,
106+
kThread = 3,
107+
};
108+
Scope scope : 2;
109+
110+
enum class AsyncCookieType : uint64_t {
111+
kId,
112+
kId2Local,
113+
kId2Global,
114+
};
115+
AsyncCookieType async_cookie_type : 2;
116+
117+
uint64_t args_size : 43;
118+
119+
JsonEvent()
120+
: flow_in(false),
121+
flow_out(false),
122+
pid_is_string_id(false),
123+
tid_is_string_id(false),
124+
bind_enclosing_slice(false),
125+
id_type(IdType::kNone),
126+
bind_id_type(IdType::kNone),
127+
scope(Scope::kNone),
128+
args_size(0) {}
70129
};
71130
static_assert(sizeof(JsonEvent) % 8 == 0);
72131

src/trace_processor/importers/common/trace_parser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <cstdint>
2121
#include <string>
22+
#include "src/trace_processor/importers/common/parser_types.h"
2223

2324
namespace perfetto::trace_processor {
2425
namespace perf_importer {
@@ -63,7 +64,7 @@ class ProtoTraceParser {
6364
class JsonTraceParser {
6465
public:
6566
virtual ~JsonTraceParser();
66-
virtual void ParseJsonPacket(int64_t, std::string) = 0;
67+
virtual void ParseJsonPacket(int64_t, JsonEvent) = 0;
6768
virtual void ParseSystraceLine(int64_t, SystraceLine) = 0;
6869
virtual void ParseLegacyV8ProfileEvent(int64_t, LegacyV8CpuProfileEvent) = 0;
6970
};

src/trace_processor/importers/json/BUILD.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@ import("../../../../gn/test.gni")
1717

1818
source_set("minimal") {
1919
sources = [
20+
"json_parser.h",
2021
"json_utils.cc",
2122
"json_utils.h",
2223
]
2324
deps = [
2425
"../../../../gn:default_deps",
26+
"../../containers",
2527
"../../storage",
28+
"../../types",
2629
"../common",
2730
]
2831
if (enable_perfetto_trace_processor_json) {
@@ -41,6 +44,7 @@ if (enable_perfetto_trace_processor_json) {
4144
deps = [
4245
":minimal",
4346
"../../../../gn:default_deps",
47+
"../../containers",
4448
"../../sorter",
4549
"../../storage",
4650
"../../tables",

0 commit comments

Comments
 (0)