blob: ec5f2dc1b7be58ae4eb93b7f1a7ec4d37343a33b [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file contains information for gathering Blobfs metrics.
#include "metrics.h"
#include <lib/async/cpp/task.h>
#include <lib/fzl/time.h>
#include <lib/zx/time.h>
#include <fs/trace.h>
namespace blobfs {
namespace {
// Time between each Cobalt flush.
constexpr zx::duration kCobaltFlushTimer = zx::min(5);
size_t TicksToMs(const zx::ticks& ticks) { return fzl::TicksToNs(ticks) / zx::msec(1); }
} // namespace
BlobfsMetrics::~BlobfsMetrics() { Dump(); }
cobalt_client::CollectorOptions BlobfsMetrics::GetBlobfsOptions() {
cobalt_client::CollectorOptions options = cobalt_client::CollectorOptions::GeneralAvailability();
// Filesystems project name as defined in cobalt-analytics projects.yaml.
options.project_name = "local_storage";
return options;
}
void BlobfsMetrics::Dump() const {
if (!Collecting()) {
return;
}
constexpr uint64_t mb = 1 << 20;
FS_TRACE_INFO("Allocation Info:\n");
FS_TRACE_INFO(" Allocated %zu blobs (%zu MB) in %zu ms\n", blobs_created_,
blobs_created_total_size_ / mb, TicksToMs(total_allocation_time_ticks_));
FS_TRACE_INFO("Writeback Info:\n");
FS_TRACE_INFO(" (Client) Wrote %zu MB of data and %zu MB of merkle trees\n",
data_bytes_written_ / mb, merkle_bytes_written_ / mb);
FS_TRACE_INFO(" (Client) Enqueued writeback in %zu ms, made merkle tree in %zu ms\n",
TicksToMs(total_write_enqueue_time_ticks_),
TicksToMs(total_merkle_generation_time_ticks_));
FS_TRACE_INFO(" (Writeback Thread) Wrote %zu MB of data in %zu ms\n",
total_writeback_bytes_written_ / mb, TicksToMs(total_writeback_time_ticks_));
FS_TRACE_INFO("Lookup Info:\n");
FS_TRACE_INFO(" Opened %zu blobs (%zu MB)\n", blobs_opened_, blobs_opened_total_size_ / mb);
FS_TRACE_INFO(" Verified %zu blobs (%zu MB data, %zu MB merkle)\n", blobs_verified_,
blobs_verified_total_size_data_ / mb, blobs_verified_total_size_merkle_ / mb);
FS_TRACE_INFO(" Spent %zu ms reading %zu MB from disk, %zu ms verifying\n",
TicksToMs(total_read_from_disk_time_ticks_), bytes_read_from_disk_ / mb,
TicksToMs(total_verification_time_ticks_));
}
void BlobfsMetrics::ScheduleMetricFlush() {
async::PostDelayedTask(
flush_loop_.dispatcher(),
[this]() {
mutable_collector()->Flush();
ScheduleMetricFlush();
},
kCobaltFlushTimer);
}
void BlobfsMetrics::Collect() {
cobalt_metrics_.EnableMetrics(true);
// TODO(gevalentino): Once we have async llcpp bindings, instead pass a dispatcher for
// handling collector IPCs.
flush_loop_.StartThread("blobfs-metric-flusher");
ScheduleMetricFlush();
}
void BlobfsMetrics::UpdateAllocation(uint64_t size_data, const fs::Duration& duration) {
if (Collecting()) {
blobs_created_++;
blobs_created_total_size_ += size_data;
total_allocation_time_ticks_ += duration;
}
}
void BlobfsMetrics::UpdateLookup(uint64_t size) {
if (Collecting()) {
blobs_opened_++;
blobs_opened_total_size_ += size;
}
}
void BlobfsMetrics::UpdateClientWrite(uint64_t data_size, uint64_t merkle_size,
const fs::Duration& enqueue_duration,
const fs::Duration& generate_duration) {
if (Collecting()) {
data_bytes_written_ += data_size;
merkle_bytes_written_ += merkle_size;
total_write_enqueue_time_ticks_ += enqueue_duration;
total_merkle_generation_time_ticks_ += generate_duration;
}
}
void BlobfsMetrics::UpdateWriteback(uint64_t size, const fs::Duration& duration) {
if (Collecting()) {
total_writeback_time_ticks_ += duration;
total_writeback_bytes_written_ += size;
}
}
void BlobfsMetrics::UpdateMerkleDiskRead(uint64_t size, const fs::Duration& duration) {
if (Collecting()) {
total_read_from_disk_time_ticks_ += duration;
bytes_read_from_disk_ += size;
}
}
void BlobfsMetrics::UpdateMerkleDecompress(uint64_t size_compressed, uint64_t size_uncompressed,
const fs::Duration& read_duration,
const fs::Duration& decompress_duration) {
if (Collecting()) {
bytes_compressed_read_from_disk_ += size_compressed;
bytes_decompressed_from_disk_ += size_uncompressed;
total_read_compressed_time_ticks_ += read_duration;
total_decompress_time_ticks_ += decompress_duration;
}
}
void BlobfsMetrics::UpdateMerkleVerify(uint64_t size_data, uint64_t size_merkle,
const fs::Duration& duration) {
if (Collecting()) {
blobs_verified_++;
blobs_verified_total_size_data_ += size_data;
blobs_verified_total_size_merkle_ += size_merkle;
total_verification_time_ticks_ += duration;
}
}
} // namespace blobfs