forked from igaw/jitterdebugger
-
Notifications
You must be signed in to change notification settings - Fork 0
/
jd_samples_hdf5.c
159 lines (129 loc) · 3.75 KB
/
jd_samples_hdf5.c
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// SPDX-License-Identifier: MIT
#define _GNU_SOURCE
#include <errno.h>
#include <string.h>
#include <hdf5.h>
#include <H5PTpublic.h>
#include "jitterdebugger.h"
#define min(x,y) \
({ \
typeof(x) __x = (x); \
typeof(x) __y = (y); \
__x < __y ? __x : __y; \
})
#define BLOCK_SIZE 10000
struct cpu_data {
hid_t set;
uint64_t count;
struct latency_sample *data;
};
static int output_hdf5(struct jd_samples_info *info, FILE *input)
{
struct cpu_data *cpudata;
struct latency_sample *data, *s, *d;
hid_t file, type;
herr_t err;
uint64_t nrs, bs;
size_t nr;
off_t sz;
unsigned int i, cnt;
char *sid;
char *ofile;
if (asprintf(&ofile, "%s/samples.hdf5", info->dir) < 0)
err_handler(errno, "asprintf()");
if (fseeko(input, 0L, SEEK_END) < 0)
err_handler(errno, "fseek()");
sz = ftello(input);
if (fseeko(input, 0L, SEEK_SET) < 0)
err_handler(errno, "fseek()");
nrs = sz / sizeof(struct latency_sample);
bs = min(nrs, BLOCK_SIZE);
data = malloc(sizeof(struct latency_sample) * bs);
if (!data)
err_handler(ENOMEM, "malloc()");
file = H5Fcreate(ofile, H5F_ACC_TRUNC,
H5P_DEFAULT, H5P_DEFAULT);
if (file == H5I_INVALID_HID)
err_handler(EIO, "failed to open file %s\n", ofile);
type = H5Tcreate(H5T_COMPOUND, sizeof(struct latency_sample));
if (type == H5I_INVALID_HID)
err_handler(EIO, "failed to create compound HDF5 type");
err = H5Tinsert(type, "CPUID", 0, H5T_NATIVE_UINT32);
if (err < 0)
err_handler(EIO,
"failed to add type info to HDF5 compound type");
err = H5Tinsert(type, "Seconds", 4, H5T_NATIVE_UINT64);
if (err < 0)
err_handler(EIO,
"failed to add type info to HDF5 compound type");
err = H5Tinsert(type, "Nanoseconds", 12, H5T_NATIVE_UINT64);
if (err < 0)
err_handler(EIO,
"failed to add type info to HDF5 compound type");
err = H5Tinsert(type, "Value", 20, H5T_NATIVE_UINT64);
if (err < 0)
err_handler(EIO,
"failed to add type info to HDF5 compound type");
cpudata = malloc(info->cpus_online * sizeof(struct cpu_data));
if (!cpudata)
err_handler(errno, "failed to allocated memory for cpu sets\n");
for (i = 0; i < info->cpus_online; i++) {
cpudata[i].count = 0;
cpudata[i].data = malloc(BLOCK_SIZE * sizeof(struct latency_sample));
if (asprintf(&sid, "cpu%d\n", i) < 0)
err_handler(errno, "failed to create label\n");
cpudata[i].set = H5PTcreate(file, sid, type, (hsize_t)bs, H5P_DEFAULT);
free(sid);
if (cpudata[i].set == H5I_INVALID_HID)
err_handler(EIO, "failed to create HDF5 packet table");
}
for (;;) {
nr = fread(data, sizeof(struct latency_sample), bs, input);
if (nr != bs) {
if (feof(input))
break;
if (ferror(input))
err_handler(errno, "fread()");
}
for (i = 0; i < nr; i++) {
s = &data[i];
if (s->cpuid >= info->cpus_online) {
fprintf(stderr, "invalid sample found (cpuid %d)\n",
s->cpuid);
continue;
}
cnt = cpudata[s->cpuid].count;
d = &(cpudata[s->cpuid].data[cnt]);
memcpy(d, s, sizeof(struct latency_sample));
cpudata[s->cpuid].count++;
}
for (i = 0; i < info->cpus_online; i++) {
H5PTappend(cpudata[i].set, cpudata[i].count, cpudata[i].data);
cpudata[i].count = 0;
}
}
free(data);
for (i = 0; i < info->cpus_online; i++) {
H5PTclose(cpudata[i].set);
free(cpudata[i].data);
}
free(cpudata);
H5Tclose(type);
H5Fclose(file);
free(ofile);
return 0;
}
static struct jd_samples_ops hdf5_ops = {
.name = "Hierarchical Data Format",
.format = "hdf5",
.output = output_hdf5,
};
static int hdf5_plugin_init(void)
{
return jd_samples_register(&hdf5_ops);
}
static void hdf5_plugin_cleanup(void)
{
jd_samples_unregister(&hdf5_ops);
}
JD_PLUGIN_DEFINE(hdf5_plugin_init, hdf5_plugin_cleanup);