Skip to content
This repository was archived by the owner on Sep 17, 2024. It is now read-only.

Commit 12c2eec

Browse files
authored
fix(isnan): set rate to 0 if its nan (#207)
* fix(profiling): dont serialize if measurement is empty * profiling(isnan): check if number isnan * profiling(isnan): check if number isnan * profiling(isnan): check if number isnan * fix: check if napi sets value
1 parent 4b05e62 commit 12c2eec

File tree

2 files changed

+46
-22
lines changed

2 files changed

+46
-22
lines changed

bindings/cpu_profiler.cc

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,16 @@ void MeasurementsTicker::cpu_callback() {
138138
uv_cpu_info_t* cpu = &cpu_stats;
139139
int count;
140140
int err = uv_cpu_info(&cpu, &count);
141+
141142
if (err) {
142143
return;
143144
}
144145

145-
uint64_t ts = uv_hrtime();
146146
if(count < 1) {
147-
for(auto cb : cpu_listeners) {
148-
cb.second(ts, 0.0);
149-
}
150147
return;
151148
}
152149

150+
uint64_t ts = uv_hrtime();
153151
uint64_t total = 0;
154152
uint64_t idle_total = 0;
155153

@@ -169,16 +167,22 @@ void MeasurementsTicker::cpu_callback() {
169167
double total_avg = total / count;
170168
double rate = 1.0 - idle_avg / total_avg;
171169

172-
if(rate < 0.0) {
170+
if(rate < 0.0 || isnan(rate)) {
173171
rate = 0.0;
174172
}
175173

176-
for(auto cb : cpu_listeners) {
177-
cb.second(ts, rate);
178-
}
174+
auto it = cpu_listeners.begin();
175+
while (it != cpu_listeners.end()) {
176+
if (it->second(ts, rate)) {
177+
it = cpu_listeners.erase(it);
178+
}
179+
else {
180+
++it;
181+
}
182+
};
179183

180184
uv_free_cpu_info(cpu, count);
181-
}
185+
};
182186

183187
void MeasurementsTicker::ticker(uv_timer_t* handle) {
184188
MeasurementsTicker* self = static_cast<MeasurementsTicker*>(handle->data);
@@ -664,8 +668,19 @@ static napi_value TranslateMeasurementsDouble(const napi_env& env, const char* u
664668
napi_value entry;
665669
napi_create_object(env, &entry);
666670

671+
double v = values[i];
672+
if(isnan(v)){
673+
v = 0.0;
674+
}
675+
667676
napi_value value;
668-
napi_create_double(env, RoundDoubleToPrecision(values[i], 4), &value);
677+
if(napi_create_double(env, RoundDoubleToPrecision(v, 4), &value) != napi_ok){
678+
if(napi_create_double(env, 0.0, &value) != napi_ok){
679+
// If we failed twice, throw an error
680+
napi_throw_error(env, "NAPI_ERROR", "Failed to create double value.");
681+
break;
682+
}
683+
}
669684

670685
napi_value ts;
671686
napi_create_int64(env, timestamps[i], &ts);
@@ -933,19 +948,23 @@ static napi_value StopProfiling(napi_env env, napi_callback_info info) {
933948
napi_value measurements;
934949
napi_create_object(env, &measurements);
935950

936-
static const char* memory_unit = "byte";
937-
napi_value heap_usage_measurements = TranslateMeasurements(env, memory_unit, profile->second->heap_usage_write_index(), profile->second->heap_usage_values(), profile->second->heap_usage_timestamps());
951+
if(profile->second->heap_usage_write_index() > 0){
952+
static const char* memory_unit = "byte";
953+
napi_value heap_usage_measurements = TranslateMeasurements(env, memory_unit, profile->second->heap_usage_write_index(), profile->second->heap_usage_values(), profile->second->heap_usage_timestamps());
938954

939-
if (heap_usage_measurements != nullptr) {
940-
napi_set_named_property(env, measurements, "memory_footprint", heap_usage_measurements);
941-
}
955+
if (heap_usage_measurements != nullptr) {
956+
napi_set_named_property(env, measurements, "memory_footprint", heap_usage_measurements);
957+
};
958+
};
942959

943-
static const char* cpu_unit = "percent";
944-
napi_value cpu_usage_measurements = TranslateMeasurementsDouble(env, cpu_unit, profile->second->cpu_usage_write_index(), profile->second->cpu_usage_values(), profile->second->cpu_usage_timestamps());
960+
if(profile->second->cpu_usage_write_index() > 0){
961+
static const char* cpu_unit = "percent";
962+
napi_value cpu_usage_measurements = TranslateMeasurementsDouble(env, cpu_unit, profile->second->cpu_usage_write_index(), profile->second->cpu_usage_values(), profile->second->cpu_usage_timestamps());
945963

946-
if (cpu_usage_measurements != nullptr) {
947-
napi_set_named_property(env, measurements, "cpu_usage", cpu_usage_measurements);
948-
}
964+
if (cpu_usage_measurements != nullptr) {
965+
napi_set_named_property(env, measurements, "cpu_usage", cpu_usage_measurements);
966+
};
967+
};
949968

950969
napi_set_named_property(env, js_profile, "measurements", measurements);
951970

src/cpu_profiler.test.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ const assertValidSamplesAndStacks = (stacks: ThreadCpuProfile['stacks'], samples
4444
}
4545
};
4646

47+
const isValidMeasurementValue = (v: any) => {
48+
if (isNaN(v)) return false;
49+
return typeof v === 'number' && v > 0;
50+
};
51+
4752
const assertValidMeasurements = (measurement: RawThreadCpuProfile['measurements']['memory_footprint'] | undefined) => {
4853
if (!measurement) {
4954
throw new Error('Measurement is undefined');
@@ -243,7 +248,7 @@ describe('Profiler bindings', () => {
243248
expect(heap_usage.values.length).toBeGreaterThan(6);
244249
expect(heap_usage.values.length).toBeLessThanOrEqual(11);
245250
expect(heap_usage.unit).toBe('byte');
246-
expect(heap_usage.values.every((v) => v.value > 0)).toBe(true);
251+
expect(heap_usage.values.every((v) => isValidMeasurementValue(v.value))).toBe(true);
247252
assertValidMeasurements(profile.measurements['memory_footprint']);
248253
});
249254

@@ -258,7 +263,7 @@ describe('Profiler bindings', () => {
258263
}
259264
expect(cpu_usage.values.length).toBeGreaterThan(6);
260265
expect(cpu_usage.values.length).toBeLessThanOrEqual(11);
261-
expect(cpu_usage.values.every((v) => v.value > 0)).toBe(true);
266+
expect(cpu_usage.values.every((v) => isValidMeasurementValue(v.value))).toBe(true);
262267
expect(cpu_usage.unit).toBe('percent');
263268
assertValidMeasurements(profile.measurements['cpu_usage']);
264269
});

0 commit comments

Comments
 (0)