forked from 741g/vperfetto
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vperfetto_merge.cpp
115 lines (97 loc) · 4.05 KB
/
vperfetto_merge.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "vperfetto.h"
#include <filesystem>
#include <fstream>
#include <sstream>
#include <string.h>
#include <stdlib.h>
static bool sValidFilename(const char* fn) {
if (!fn) {
fprintf(stderr, "ERROR: Invalid filename (is null)\n");
return false;
}
if (!strcmp("", fn)) {
fprintf(stderr, "ERROR: Invalid filename (is empty string)\n");
return false;
}
if (!std::filesystem::exists(fn)) {
fprintf(stderr, "ERROR: Filename [%s] does not refer to a filesystem object. As absolute: [%s]\n", fn, std::filesystem::absolute(fn).c_str());
return false;
}
if (!std::filesystem::is_regular_file(fn)) {
fprintf(stderr, "ERROR: Filename [%s] does not refer to a regular file. As absolute: [%s]\n", fn, std::filesystem::absolute(fn).c_str());
return false;
}
if (std::filesystem::is_empty(fn)) {
fprintf(stderr, "ERROR: Filename [%s] refers to an empty file. As absolute: [%s]\n", fn, std::filesystem::absolute(fn).c_str());
return false;
}
return true;
}
int main(int argc, char** argv) {
vperfetto::TraceCombineConfig config;
if (argc < 4) {
fprintf(stderr, "%s: error: invalid usage of vperfetto_merge. Usage: vperfetto_merge <guestTraceFile> <hostTraceFile> <combinedTraceFile>"
" [<guestClockBootTimeNsWhenHostTracingStarted>]"
" [--guest-tsc-offset <guest tsc-offset, ie: host file /sys/kernel/debug/kvm/4678-27/vcpu0/tsc-offset>]"
" [--merge-guest-into-host]\n", __func__);
return 1;
}
const char* guestFile = argv[1];
const char* hostFile = argv[2];
const char* combinedFile = argv[3];
fprintf(stderr, "vperfetto_merge start. Configuration:\n", __func__);
fprintf(stderr, "guest trace file: %s\n", guestFile);
fprintf(stderr, "host trace file: %s\n", hostFile);
fprintf(stderr, "combined trace file: %s\n", combinedFile);
if (!sValidFilename(guestFile)) return 1;
if (!sValidFilename(hostFile)) return 1;
config.guestFile = guestFile;
config.hostFile = hostFile;
config.combinedFile = combinedFile;
config.useGuestAbsoluteTime = false;
config.useGuestTimeDiff = false;
config.guestTscOffset = 0;
config.mergeGuestIntoHost = false;
config.addTraces = false;
for (int i = 4; i < argc; ++i) {
auto arg = std::string(argv[i]);
if (arg == "--guest-tsc-offset") {
if (++i >= argc) {
fprintf(stderr, "ERROR: missing value after --guest-tsc-offset\n");
return 1;
}
// User specified guest boottime
int64_t guestTscOffset;
std::istringstream ss(argv[i]);
if (!(ss >> guestTscOffset)) {
fprintf(stderr, "ERROR: Failed to parse guest-tsc-offset. Provided: [%s]\n", argv[i]);
return 1;
} else {
fprintf(stderr, "using specified guest-tsc-offset: %lld\n", (long long)guestTscOffset);
config.guestTscOffset = guestTscOffset;
}
} else if (arg == "--merge-guest-into-host") {
config.mergeGuestIntoHost = true;
} else if (arg == "--add-traces") {
config.addTraces = true;
} else {
// User specified guest boottime
uint64_t guestClockBootTimeNs;
std::istringstream ss(arg);
if (!(ss >> guestClockBootTimeNs)) {
fprintf(stderr, "ERROR: Failed to parse guest clock boot time ns. Provided: [%s]\n", arg.c_str());
return 1;
} else {
fprintf(stderr, "using specified guest time diff: %llu\n", (unsigned long long)guestClockBootTimeNs);
config.guestClockBootTimeNs = guestClockBootTimeNs;
config.useGuestAbsoluteTime = true;
}
}
}
if (!config.useGuestAbsoluteTime && !config.useGuestTimeDiff) {
// Derived guest boottime
fprintf(stderr, "Will derive guest clock boot time and time diff.\n");
}
vperfetto::combineTraces(&config);
return 0;
}