Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/workerd/api/global-scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ class ServiceWorkerGlobalScope: public WorkerGlobalScope {
}

jsg::Ref<Performance> getPerformance(jsg::Lock& js) {
return js.alloc<Performance>();
return js.alloc<Performance>(Worker::Isolate::from(js).getLimitEnforcer());
}

jsg::Ref<Cloudflare> getCloudflare(jsg::Lock& js) {
Expand Down
11 changes: 8 additions & 3 deletions src/workerd/api/performance.c++
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
#include "performance.h"

#include <workerd/io/io-util.h>
#include <workerd/io/worker.h>

#include <kj/encoding.h>

namespace workerd::api {

double Performance::now() {
double Performance::now(jsg::Lock& js) {
// We define performance.now() for compatibility purposes, but due to Spectre concerns it
// returns exactly what Date.now() returns.
isolateLimitEnforcer.markPerfEvent("performance_now"_kjc);
return dateNow();
}

Expand Down Expand Up @@ -165,7 +167,9 @@ kj::ArrayPtr<jsg::Ref<PerformanceEntry>> PerformanceObserverEntryList::getEntrie

jsg::Ref<PerformanceMark> Performance::mark(
jsg::Lock& js, kj::String name, jsg::Optional<PerformanceMark::Options> options) {
double startTime = now();
// TODO(someday): Include `name` in the perf event name?
isolateLimitEnforcer.markPerfEvent("performance_mark"_kjc);
double startTime = dateNow();
KJ_IF_SOME(opts, options) {
KJ_IF_SOME(time, opts.startTime) {
startTime = time;
Expand All @@ -188,7 +192,8 @@ jsg::Ref<PerformanceMeasure> Performance::measure(jsg::Lock& js,
kj::String measureName,
kj::OneOf<PerformanceMeasure::Options, kj::String> measureOptionsOrStartMark,
jsg::Optional<kj::String> maybeEndMark) {
double startTime = now();
isolateLimitEnforcer.markPerfEvent("performance_measure"_kjc);
double startTime = dateNow();
double endTime = startTime;

KJ_SWITCH_ONEOF(measureOptionsOrStartMark) {
Expand Down
7 changes: 6 additions & 1 deletion src/workerd/api/performance.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <workerd/api/basics.h>
#include <workerd/io/compatibility-date.capnp.h>
#include <workerd/io/limit-enforcer.h>
#include <workerd/jsg/jsg.h>

namespace workerd::api {
Expand Down Expand Up @@ -404,6 +405,9 @@ class Performance: public EventTarget {
public:
static jsg::Ref<Performance> constructor() = delete;

explicit Performance(const IsolateLimitEnforcer& isolateLimitEnforcer)
: isolateLimitEnforcer(isolateLimitEnforcer) {}

// We always return a time origin of 0, making performance.now() equivalent to Date.now(). There
// is no other appropriate time origin to use given that the Worker platform is intended to be
// treated like one big computer rather than many individual instances. In particular, if and
Expand All @@ -422,7 +426,7 @@ class Performance: public EventTarget {

jsg::Ref<EventCounts> getEventCounts(jsg::Lock& js);

double now();
double now(jsg::Lock& js);

void clearMarks(jsg::Optional<kj::String> name);
void clearMeasures(jsg::Optional<kj::String> name);
Expand Down Expand Up @@ -483,6 +487,7 @@ class Performance: public EventTarget {
}

private:
const IsolateLimitEnforcer& isolateLimitEnforcer;
kj::Vector<jsg::Ref<PerformanceEntry>> entries;
};

Expand Down
10 changes: 10 additions & 0 deletions src/workerd/io/limit-enforcer.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ class IsolateLimitEnforcer: public kj::Refcounted {
}

virtual bool hasExcessivelyExceededHeapLimit() const = 0;

// Inserts a custom mark event named `name` into this isolate's perf event data stream. At
// present, this is only implemented internally. Call this function from various APIs to be able
// to correlate perf event data with usage of those APIs.
//
// TODO(cleanup): This isn't strictly related to limit enforcement, so it's a bit odd here. It's
// observability-related. However, our internal perf event observability is fairly tightly
// coupled with our CPU time limiting system, so adding this function here is a path of least
// resistance.
virtual void markPerfEvent(kj::LiteralStringConst name) const {};
};

// Abstract interface that enforces resource limits on a IoContext.
Expand Down