Skip to content

Commit

Permalink
Add lock wait time metrics for Memory Cache.
Browse files Browse the repository at this point in the history
  • Loading branch information
mar-cf committed Sep 17, 2024
1 parent 57e3bdb commit f9bb655
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 8 deletions.
32 changes: 26 additions & 6 deletions src/workerd/api/memory-cache.c++
Original file line number Diff line number Diff line change
Expand Up @@ -239,14 +239,34 @@ SharedMemoryCache::Use::~Use() noexcept(false) {
}

kj::Maybe<kj::Own<CacheValue>> SharedMemoryCache::Use::getWithoutFallback(
const kj::String& key) const {
auto data = cache->data.lockExclusive();
const kj::String& key, SpanBuilder& span) const {
kj::Locked<ThreadUnsafeData> data;
{
//auto memoryCacheTiming = tryCreateMemoryCacheTiming(IoContext::current().getMetrics().getMemoryCacheObserver(), span);
//auto memoryCacheLockRecord = MemoryCacheLockRecord(memoryCacheTiming);
kj::Maybe<kj::Own<MemoryCacheObserver::MemoryCacheLockTiming>> memoryCacheLockTiming;
KJ_IF_SOME(observer, IoContext::current().getMetrics().getMemoryCacheObserver()) {
memoryCacheLockTiming = observer->lock(span);
}
auto memoryCacheLockRecord =
MemoryCacheObserver::MemoryCacheLockRecord(kj::mv(memoryCacheLockTiming));
data = cache->data.lockExclusive();
}
return cache->getWhileLocked(*data, key);
}

kj::OneOf<kj::Own<CacheValue>, kj::Promise<SharedMemoryCache::Use::GetWithFallbackOutcome>>
SharedMemoryCache::Use::getWithFallback(const kj::String& key) const {
auto data = cache->data.lockExclusive();
SharedMemoryCache::Use::getWithFallback(const kj::String& key, SpanBuilder& span) const {
kj::Locked<ThreadUnsafeData> data;
{
kj::Maybe<kj::Own<MemoryCacheObserver::MemoryCacheLockTiming>> memoryCacheLockTiming;
KJ_IF_SOME(observer, IoContext::current().getMetrics().getMemoryCacheObserver()) {
memoryCacheLockTiming = observer->lock(span);
}
auto memoryCacheLockRecord =
MemoryCacheObserver::MemoryCacheLockRecord(kj::mv(memoryCacheLockTiming));
data = cache->data.lockExclusive();
}
KJ_IF_SOME(existingValue, cache->getWhileLocked(*data, key)) {
return kj::mv(existingValue);
} else KJ_IF_SOME(existingInProgress, data->inProgress.find(key)) {
Expand Down Expand Up @@ -373,7 +393,7 @@ jsg::Promise<jsg::JsRef<jsg::JsValue>> MemoryCache::read(jsg::Lock& js,
auto readSpan = IoContext::current().makeTraceSpan("memory_cache_read"_kjc);

KJ_IF_SOME(fallback, optionalFallback) {
KJ_SWITCH_ONEOF(cacheUse.getWithFallback(key.value)) {
KJ_SWITCH_ONEOF(cacheUse.getWithFallback(key.value, readSpan)) {
KJ_CASE_ONEOF(result, kj::Own<CacheValue>) {
// Optimization: Don't even release the isolate lock if the value is aleady in cache.
jsg::Deserializer deserializer(js, result->bytes.asPtr());
Expand Down Expand Up @@ -422,7 +442,7 @@ jsg::Promise<jsg::JsRef<jsg::JsValue>> MemoryCache::read(jsg::Lock& js,
}
KJ_UNREACHABLE;
} else {
KJ_IF_SOME(cacheValue, cacheUse.getWithoutFallback(key.value)) {
KJ_IF_SOME(cacheValue, cacheUse.getWithoutFallback(key.value, readSpan)) {
jsg::Deserializer deserializer(js, cacheValue->bytes.asPtr());
return js.resolvedPromise(jsg::JsRef(js, deserializer.readValue(js)));
}
Expand Down
6 changes: 4 additions & 2 deletions src/workerd/api/memory-cache.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include "workerd/io/trace.h"
#include <workerd/jsg/jsg.h>
#include <workerd/jsg/function.h>
#include <workerd/util/uuid.h>
Expand Down Expand Up @@ -175,7 +176,8 @@ class SharedMemoryCache: public kj::AtomicRefcounted {
// Returns a cached value for the given key if one exists (and has not
// expired). If no such value exists, nothing is returned, regardless of any
// in-progress fallbacks trying to produce such a value.
kj::Maybe<kj::Own<CacheValue>> getWithoutFallback(const kj::String& key) const;
kj::Maybe<kj::Own<CacheValue>> getWithoutFallback(
const kj::String& key, SpanBuilder& span) const;

struct FallbackResult {
kj::Own<CacheValue> value;
Expand All @@ -190,7 +192,7 @@ class SharedMemoryCache: public kj::AtomicRefcounted {
// or to a FallbackDoneCallback. In the latter case, the caller should
// invoke the fallback function.
kj::OneOf<kj::Own<CacheValue>, kj::Promise<GetWithFallbackOutcome>> getWithFallback(
const kj::String& key) const;
const kj::String& key, SpanBuilder& span) const;

private:
// Creates a new FallbackDoneCallback associated with the given
Expand Down
38 changes: 38 additions & 0 deletions src/workerd/io/observer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Defines abstract interfaces for observing the activity of various components of the system,
// e.g. to collect logs and metrics.

#include "kj/common.h"
#include <kj/string.h>
#include <kj/refcount.h>
#include <kj/exception.h>
Expand All @@ -29,6 +30,39 @@ class WebSocketObserver: public kj::Refcounted {
virtual void receivedMessage(size_t bytes) {};
};

// Collects metrics on memory cache, like lock wait time.
class MemoryCacheObserver: public kj::AtomicRefcounted {
public:
class MemoryCacheLockTiming {
public:
virtual void start() {}
virtual void stop() {}
virtual ~MemoryCacheLockTiming() noexcept(false) {}
};

class MemoryCacheLockRecord {
public:
//explicit MemoryCacheLockRecord(kj::Maybe<kj::Own<MemoryCacheObserver>> observer, SpanBuilder& span)
explicit MemoryCacheLockRecord(
kj::Maybe<kj::Own<MemoryCacheLockTiming>> memoryCacheLockTimingParam)
: memoryCacheLockTiming(kj::mv(memoryCacheLockTimingParam)) {
KJ_IF_SOME(timing, memoryCacheLockTiming) timing.get()->start();
}
~MemoryCacheLockRecord() noexcept(false) {
KJ_IF_SOME(timing, memoryCacheLockTiming) timing.get()->stop();
}
KJ_DISALLOW_COPY_AND_MOVE(MemoryCacheLockRecord);

private:
kj::Maybe<kj::Own<MemoryCacheLockTiming>> memoryCacheLockTiming;
};

virtual kj::Maybe<kj::Own<MemoryCacheLockTiming>> lock(SpanBuilder& span) {
return kj::none;
};
// Additional memory cache metrics
};

// Observes a specific request to a specific worker. Also observes outgoing subrequests.
//
// Observing anything is optional. Default implementations of all methods observe nothing.
Expand Down Expand Up @@ -109,6 +143,10 @@ class RequestObserver: public kj::Refcounted {
virtual uint64_t clockRead() {
return 0;
}

virtual kj::Maybe<kj::Own<MemoryCacheObserver>> getMemoryCacheObserver() {
return kj::none;
};
};

class IsolateObserver: public kj::AtomicRefcounted, public jsg::IsolateObserver {
Expand Down

0 comments on commit f9bb655

Please sign in to comment.