Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

performance.now() must return excatly what Date.now() returns. #617

Merged
merged 2 commits into from
May 6, 2023
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
6 changes: 3 additions & 3 deletions src/workerd/api/global-scope.c++
Original file line number Diff line number Diff line change
Expand Up @@ -712,9 +712,9 @@ jsg::Promise<jsg::Ref<Response>> ServiceWorkerGlobalScope::fetch(
}

double Performance::now() {
// Time never progresses outside of an IoContext.
if (!IoContext::hasCurrent()) return 0.0;
return IoContext::current().performanceNow();
// We define performance.now() for compatibility purposes, but due to spectre concerns it
// returns exactly what Date.now() returns.
return dateNow();
}

} // namespace workerd::api
14 changes: 12 additions & 2 deletions src/workerd/api/global-scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,18 @@ class Navigator: public jsg::Object {
class Performance: public jsg::Object {
public:
double getTimeOrigin() { return 0.0; }
// We always return a time origin of 0. For us this represents the time at which the
// IoContext was created.
// 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
// when we start snapshotting applications after startup and then starting instances from that
// snapshot, what would the right time origin be? The time when the snapshot was created? This
// seems to leak implementation details in a weird way.
//
// Note that the purpose of `timeOrigin` is normally to allow `now()` to return a more-precise
// measurement. Measuring against a recent time allows the values returned by `now()` to be
// smaller in magnitude, which allows them to be more precise due to the nature of floating
// point numbers. In our case, though, we don't return precise measurements from this interface
// anyway, for Spectre reasons -- it returns the same as Date.now().

double now();

Expand Down
9 changes: 0 additions & 9 deletions src/workerd/io/io-context.c++
Original file line number Diff line number Diff line change
Expand Up @@ -825,15 +825,6 @@ kj::Date IoContext::now() {
return now(getCurrentIncomingRequest());
}

double IoContext::performanceNow() {
// If there are no incoming requests, this should always return 0.0.
// Otherwise, the time origin for an incoming request should always be set.
if (!incomingRequests.empty()) {
return (now() - kj::UNIX_EPOCH) / kj::NANOSECONDS * 1e-6;
}
return 0.0;
}

kj::Own<WorkerInterface> IoContext::getSubrequestNoChecks(
kj::FunctionParam<kj::Own<WorkerInterface>(SpanBuilder&, IoChannelFactory&)> func,
SubrequestOptions options) {
Expand Down
2 changes: 0 additions & 2 deletions src/workerd/io/io-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -700,8 +700,6 @@ class IoContext final: public kj::Refcounted, private kj::TaskSet::ErrorHandler
kj::Date now();
// Access the event loop's current time point. This will remain constant between ticks.

double performanceNow();

kj::Promise<void> atTime(kj::Date when) { return getIoChannelFactory().getTimer().atTime(when); }
// Returns a promise that resolves once `now() >= when`.

Expand Down