types[name] = type;
}
-void Metrics::add_histogram(const string &name, const vector<pair<string, string>> &labels, atomic<int64_t> *location, size_t num_elements)
+void Metrics::add_histogram(const string &name, const vector<pair<string, string>> &labels, atomic<int64_t> *first_bucket_location, atomic<double> *sum_location, size_t num_elements)
{
Histogram histogram;
histogram.name = name;
histogram.labels = labels;
- histogram.location_int64 = location;
+ histogram.first_bucket_location = first_bucket_location;
+ histogram.sum_location = sum_location;
histogram.num_elements = num_elements;
lock_guard<mutex> lock(mu);
for (const Histogram &histogram : histograms) {
ss << "# TYPE nageru_" << histogram.name << " histogram\n";
- int64_t sum = 0, count = 0;
+ int64_t count = 0;
for (size_t i = 0; i < histogram.num_elements; ++i) {
char buf[16];
snprintf(buf, sizeof(buf), "%lu", i);
vector<pair<string, string>> labels = histogram.labels;
labels.emplace_back("le", buf);
- int64_t val = histogram.location_int64[i].load();
- sum += i * val;
+ int64_t val = histogram.first_bucket_location[i].load();
count += val;
ss << serialize_name(histogram.name + "_bucket", labels) << " " << count << "\n";
}
- ss << serialize_name(histogram.name + "_sum", histogram.labels) << " " << sum << "\n";
+ ss << serialize_name(histogram.name + "_sum", histogram.labels) << " " << histogram.sum_location->load() << "\n";
ss << serialize_name(histogram.name + "_count", histogram.labels) << " " << count << "\n";
}
void add(const std::string &name, const std::vector<std::pair<std::string, std::string>> &labels, std::atomic<double> *location, Type type = TYPE_COUNTER);
// Only integer histogram, ie. keys are 0..(N-1).
- void add_histogram(const std::string &name, const std::vector<std::pair<std::string, std::string>> &labels, std::atomic<int64_t> *location, size_t num_elements);
+ void add_histogram(const std::string &name, const std::vector<std::pair<std::string, std::string>> &labels, std::atomic<int64_t> *first_bucket_location, std::atomic<double> *sum_location, size_t num_elements);
std::string serialize() const;
struct Histogram {
std::string name;
std::vector<std::pair<std::string, std::string>> labels;
- std::atomic<int64_t> *location_int64; // First bucket.
+ std::atomic<int64_t> *first_bucket_location;
+ std::atomic<double> *sum_location;
size_t num_elements;
};
global_metrics.add("x264_output_frames", {{ "type", "i" }}, &metric_x264_output_frames_i);
global_metrics.add("x264_output_frames", {{ "type", "p" }}, &metric_x264_output_frames_p);
global_metrics.add("x264_output_frames", {{ "type", "b" }}, &metric_x264_output_frames_b);
+ global_metrics.add_histogram("x264_crf", {}, metric_x264_crf, &metric_x264_crf_sum, crf_buckets);
}
X264Encoder::~X264Encoder()
++metric_x264_output_frames_p;
}
+ if (pic.prop.f_crf_avg <= 0.0) {
+ ++metric_x264_crf[0];
+ } else if (pic.prop.f_crf_avg <= crf_buckets - 1) {
+ ++metric_x264_crf[int(floor(pic.prop.f_crf_avg))];
+ } else {
+ // Just clamp; this isn't ideal, but at least the total count will be right.
+ ++metric_x264_crf[crf_buckets - 1];
+ }
+ metric_x264_crf_sum = metric_x264_crf_sum + pic.prop.f_crf_avg;
+
if (frames_being_encoded.count(pic.i_pts)) {
ReceivedTimestamps received_ts = frames_being_encoded[pic.i_pts];
frames_being_encoded.erase(pic.i_pts);
std::atomic<int64_t> metric_x264_output_frames_i{0};
std::atomic<int64_t> metric_x264_output_frames_p{0};
std::atomic<int64_t> metric_x264_output_frames_b{0};
+
+ static constexpr size_t crf_buckets = 50;
+ std::atomic<int64_t> metric_x264_crf[crf_buckets]{{0}};
+ std::atomic<double> metric_x264_crf_sum{0.0};
};
#endif // !defined(_X264ENCODE_H)
metric_x264_speedcontrol_buffer_available_seconds = buffer_fill * 1e-6;
metric_x264_speedcontrol_buffer_size_seconds = buffer_size * 1e-6;
- global_metrics.add_histogram("x264_speedcontrol_preset_used_frames", {}, metric_x264_speedcontrol_preset_used_frames, SC_PRESETS);
+ global_metrics.add_histogram("x264_speedcontrol_preset_used_frames", {}, metric_x264_speedcontrol_preset_used_frames, &metric_x264_speedcontrol_preset_used_frames_sum, SC_PRESETS);
global_metrics.add("x264_speedcontrol_buffer_available_seconds", &metric_x264_speedcontrol_buffer_available_seconds, Metrics::TYPE_GAUGE);
global_metrics.add("x264_speedcontrol_buffer_size_seconds", &metric_x264_speedcontrol_buffer_size_seconds, Metrics::TYPE_GAUGE);
global_metrics.add("x264_speedcontrol_idle_frames", &metric_x264_speedcontrol_idle_frames);
preset = new_preset;
++metric_x264_speedcontrol_preset_used_frames[new_preset];
+ // Non-atomic add, but that's fine, since there are no concurrent writers.
+ metric_x264_speedcontrol_preset_used_frames_sum = metric_x264_speedcontrol_preset_used_frames_sum + new_preset;
}
// Metrics.
std::atomic<int64_t> metric_x264_speedcontrol_preset_used_frames[SC_PRESETS]{{0}};
+ std::atomic<double> metric_x264_speedcontrol_preset_used_frames_sum{0.0};
std::atomic<double> metric_x264_speedcontrol_buffer_available_seconds{0.0};
std::atomic<double> metric_x264_speedcontrol_buffer_size_seconds{0.0};
std::atomic<int64_t> metric_x264_speedcontrol_idle_frames{0};