blob: 0aadf316aaf37b902352974b954f9bf791c3ad24 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "gpu/command_buffer/service/gpu_persistent_cache.h"
#include <string_view>
#include "base/containers/span.h"
#include "base/dcheck_is_on.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "base/types/expected_macros.h"
#include "components/persistent_cache/entry.h"
#include "components/persistent_cache/persistent_cache.h"
namespace gpu {
namespace {
constexpr size_t kMaxLoadStoreForTrackingCacheAvailable = 100;
class ScopedHistogramTimer {
public:
explicit ScopedHistogramTimer(const std::string& name) : name_(name) {}
~ScopedHistogramTimer() {
if (enabled_) {
base::UmaHistogramCustomMicrosecondsTimes(name_, timer_.Elapsed(),
base::Microseconds(1),
base::Seconds(30), 100);
}
}
void SetEnabled(bool enabled) { enabled_ = enabled; }
private:
const std::string name_;
base::ElapsedTimer timer_;
bool enabled_ = true;
};
} // namespace
GpuPersistentCache::GpuPersistentCache(std::string_view cache_prefix)
: cache_prefix_(cache_prefix) {}
GpuPersistentCache::~GpuPersistentCache() = default;
void GpuPersistentCache::InitializeCache(
persistent_cache::BackendParams backend_params) {
CHECK(!initialized_.IsSet());
persistent_cache_ =
persistent_cache::PersistentCache::Open(std::move(backend_params));
if (persistent_cache_) {
initialized_.Set();
}
}
size_t GpuPersistentCache::LoadData(const void* key,
size_t key_size,
void* value,
size_t value_size) {
std::string_view key_str(static_cast<const char*>(key), key_size);
std::unique_ptr<persistent_cache::Entry> entry = LoadEntry(key_str);
if (!entry) {
return 0;
}
if (value_size > 0) {
return entry->CopyContentTo(
UNSAFE_TODO(base::span(static_cast<uint8_t*>(value), value_size)));
}
return entry->GetContentSize();
}
std::unique_ptr<persistent_cache::Entry> GpuPersistentCache::LoadEntry(
std::string_view key) {
ScopedHistogramTimer timer(GetHistogramName("Load"));
const bool initialized = initialized_.IsSet();
TRACE_EVENT1("gpu", "GpuPersistentCache::LoadEntry", "persistent_cache_",
initialized);
// Track cache available for the 1st kMaxLoadStoreForTrackingCacheAvailable
// loads.
if (load_count_.fetch_add(1, std::memory_order_relaxed) <
kMaxLoadStoreForTrackingCacheAvailable) {
base::UmaHistogramBoolean(GetHistogramName("Load.CacheAvailable"),
initialized);
}
if (!initialized) {
timer.SetEnabled(false);
return nullptr;
}
ASSIGN_OR_RETURN(auto entry, persistent_cache_->Find(key),
[](persistent_cache::TransactionError error)
-> std::unique_ptr<persistent_cache::Entry> {
// TODO(crbug.com/377475540): Handle or at least address
// permanent errors.
return nullptr;
});
return entry;
}
void GpuPersistentCache::StoreData(const void* key,
size_t key_size,
const void* value,
size_t value_size) {
ScopedHistogramTimer timer(GetHistogramName("Store"));
const bool initialized = initialized_.IsSet();
TRACE_EVENT1("gpu", "GpuPersistentCache::StoreData", "persistent_cache_",
initialized);
// Track cache available for the 1st kMaxLoadStoreForTrackingCacheAvailable
// stores.
if (store_count_.fetch_add(1, std::memory_order_relaxed) <
kMaxLoadStoreForTrackingCacheAvailable) {
base::UmaHistogramBoolean(GetHistogramName("Store.CacheAvailable"),
initialized);
}
if (!initialized) {
timer.SetEnabled(false);
return;
}
std::string_view key_str(static_cast<const char*>(key), key_size);
RETURN_IF_ERROR(
persistent_cache_->Insert(
key_str, UNSAFE_TODO(base::span(static_cast<const uint8_t*>(value),
value_size))),
[](persistent_cache::TransactionError error) {
// TODO(crbug.com/377475540): Handle or at least address
// permanent errors.
return;
});
}
std::string GpuPersistentCache::GetHistogramName(
std::string_view metric) const {
return "GPU.PersistentCache." + cache_prefix_ + "." + std::string(metric);
}
} // namespace gpu