Skip to content

Commit

Permalink
Merge pull request #1446 from cloudflare/jsnell/workerd-perfetto
Browse files Browse the repository at this point in the history
Experimental perfetto support for workerd
  • Loading branch information
harrishancock authored Dec 8, 2023
2 parents 7ede63c + 3ca4b76 commit d2e127c
Show file tree
Hide file tree
Showing 16 changed files with 480 additions and 5 deletions.
30 changes: 29 additions & 1 deletion WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,31 @@ new_git_repository(
shallow_since = "1697047535 +0000",
)

git_repository(
name = "perfetto",
commit = "d136f355bb32288122dd2a0273e4fab280654d3a",
remote = "https://android.googlesource.com/platform/external/perfetto.git",
patches = [
"//:patches/perfetto/0001-Rename-ui-build-to-ui-build.sh-to-allow-bazel-build-.patch",
],
patch_args = ["-p1"],
repo_mapping = {"@perfetto_dep_zlib" : "@zlib"},
)

# For use with perfetto
new_git_repository(
name = "com_google_protobuf",
commit = "6a59a2ad1f61d9696092f79b6d74368b4d7970a3",
remote = "https://chromium.googlesource.com/external/github.com/google/protobuf"
)

# For use with perfetto
new_local_repository(
name = "perfetto_cfg",
path = "build/perfetto",
build_file_content = ""
)

new_git_repository(
name = "com_googlesource_chromium_base_trace_event_common",
build_file = "@v8//:bazel/BUILD.trace_event_common",
Expand Down Expand Up @@ -445,11 +470,14 @@ bind(
# We indirect through `@workerd-v8` to allow dependents to override how and where `v8` is built.
#
# TODO(cleanup): There must be a better way to do this?
# TODO(soon): Figure out how to build v8 with perfetto enabled. It does not appear
# as if the v8 bazel build currently includes support for building with
# perfetto enabled as an option.
new_local_repository(
name = "workerd-v8",
build_file_content = """cc_library(
name = "v8",
deps = ["@v8//:v8_icu", "@workerd//:icudata-embed"],
deps = [ "@v8//:v8_icu", "@workerd//:icudata-embed" ],
visibility = ["//visibility:public"])""",
path = "empty",
)
Expand Down
139 changes: 139 additions & 0 deletions build/perfetto/perfetto_cfg.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Copyright (C) 2019 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Noop function used to override rules we don't want to support in standalone.
def _noop_override(**kwargs):
pass

PERFETTO_CONFIG = struct(
# This is used to refer to deps within perfetto's BUILD files.
# In standalone and bazel-based embedders use '//', because perfetto has its
# own repository, and //xxx would be relative to @perfetto//xxx.
# In Google internal builds, instead, this is set to //third_party/perfetto,
# because perfetto doesn't have its own repository there.
root = "//",

# These variables map dependencies to perfetto third-party projects. This is
# to allow perfetto embedders (e.g. gapid) and google internal builds to
# override paths and target names to their own third_party.
deps = struct(
# Target exposing the build config header. It should be a valid
# cc_library dependency as it will become a dependency of every
# perfetto_cc_library target. It needs to expose a
# "perfetto_build_flags.h" file that can be included via:
# #include "perfetto_build_flags.h".
build_config = ["//:build_config_hdr"],

# Target exposing the PERFETTO_VERSION_STRING() and
# PERFETTO_VERSION_SCM_REVISION() macros. This is overridden in google
# internal builds.
version_header = ["//:cc_perfetto_version_header"],

# Target exposing platform-specific functionality for base. This is
# overriden in Google internal builds.
base_platform = ["//:perfetto_base_default_platform"],

zlib = ["@perfetto_dep_zlib//:zlib"],
jsoncpp = ["@perfetto_dep_jsoncpp//:jsoncpp"],
linenoise = ["@perfetto_dep_linenoise//:linenoise"],
sqlite = ["@perfetto_dep_sqlite//:sqlite"],
sqlite_ext_percentile = ["@perfetto_dep_sqlite_src//:percentile_ext"],
protoc = ["@com_google_protobuf//:protoc"],
protoc_lib = ["@com_google_protobuf//:protoc_lib"],
protobuf_lite = ["@com_google_protobuf//:protobuf_lite"],
protobuf_full = ["@com_google_protobuf//:protobuf"],
protobuf_descriptor_proto = ["@com_google_protobuf//:descriptor_proto"],

# The Python targets are empty on the standalone build because we assume
# any relevant deps are installed on the system or are not applicable.
protobuf_py = [],
pandas_py = [],
tp_vendor_py = [],

# There are multiple configurations for the function name demangling
# logic in trace processor:
# (1) The following defaults include a subset of demangling sources
# from llvm-project. This is the most complete implementation.
# (2) You can avoid the llvm dependency by setting "llvm_demangle = []"
# here and PERFETTO_LLVM_DEMANGLE to false in your
# perfetto_build_flags.h. Then the implementation will use a
# demangler from the c++ runtime, which will most likely handle
# only itanium mangling, and is unavailable on some platforms (e.g.
# Windows, where it becomes a nop).
# (3) You can override the whole demangle_wrapper below, and provide
# your own demangling implementation.
demangle_wrapper = [ "//:src_trace_processor_demangle" ],
llvm_demangle = ["@perfetto_dep_llvm_demangle//:llvm_demangle"],
),

# This struct allows embedders to customize the cc_opts for Perfetto
# 3rd party dependencies. They only have an effect if the dependencies are
# initialized with the Perfetto build files (i.e. via perfetto_deps()).
deps_copts = struct(
zlib = [],
jsoncpp = [],
linenoise = [],
sqlite = [],
llvm_demangle = [],
),

# Allow Bazel embedders to change the visibility of "public" targets.
# This variable has been introduced to limit the change to Bazel and avoid
# making the targets fully public in the google internal tree.
public_visibility = [
"//visibility:public",
],

# Allow Bazel embedders to change the visibility of the proto targets.
# This variable has been introduced to limit the change to Bazel and avoid
# making the targets public in the google internal tree.
proto_library_visibility = "//visibility:private",

# Allow Bazel embedders to change the visibility of the Go protos.
# Go protos have all sorts of strange behaviour in Google3 so need special
# handling as the rules for other languages do not work for Go.
go_proto_library_visibility = "//visibility:private",

# This struct allows the embedder to customize copts and other args passed
# to rules like cc_binary. Prefixed rules (e.g. perfetto_cc_binary) will
# look into this struct before falling back on native.cc_binary().
# This field is completely optional, the embedder can omit the whole
# |rule_overrides| or invidivual keys. They are assigned to None or noop
# actions here just for documentation purposes.
rule_overrides = struct(
proto_library = None,

cc_binary = None,
cc_library = None,
cc_proto_library = None,

# Supporting java rules pulls in the JDK and generally is not something
# we need for most embedders.
java_proto_library = _noop_override,
java_lite_proto_library = _noop_override,

py_binary = None,
py_library = None,
py_proto_library = None,

go_proto_library = None,

jspb_proto_library = None,
),

# The default copts which we use to compile C++ code.
default_copts = [
"-std=c++17",
]
)
5 changes: 5 additions & 0 deletions compile_flags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
-Ibazel-bin/external/dawn/include
-Ibazel-bin/external/ada-url/_virtual_includes/ada-url/
-Ibazel-bin/external/com_cloudflare_lol_html/_virtual_includes/lolhtml
-Iexternal/perfetto-sdk/sdk/
-Iexternal/ada-url/
-Iexternal/com_google_benchmark/include/
-Iexternal/dawn/include
Expand Down Expand Up @@ -44,6 +45,7 @@
-isystemexternal/v8/include
-isystemexternal/zlib
-isystemexternal/sqlite3
-isystemexternal/perfetto-sdk/sdk
-D_FORTIFY_SOURCE=1
-DCAPNP_VERSION=11000
-DDEBUG
Expand Down Expand Up @@ -86,6 +88,9 @@
-DV8_TARGET_ARCH_X64
-DV8_TARGET_OS_LINUX
-DV8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64
-DV8_USE_PERFETTO
-DWORKERD_USE_PERFETTO
-DPERFETTO_ENABLE_LEGACY_TRACE_EVENTS=1
-DWORKERD_ICU_DATA_EMBED
-Wall
-Werror=dangling
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
From ce2bc7a2ee9ce1a52f2c17b3b9a83329b58bf2f7 Mon Sep 17 00:00:00 2001
From: James M Snell <[email protected]>
Date: Tue, 5 Dec 2023 08:04:46 -0800
Subject: [PATCH] Rename ui/build to ui/build.sh to allow bazel build to work

---
ui/{build => build.sh} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename ui/{build => build.sh} (100%)

diff --git a/ui/build b/ui/build.sh
similarity index 100%
rename from ui/build
rename to ui/build.sh
--
2.40.1

2 changes: 2 additions & 0 deletions src/workerd/api/global-scope.c++
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <workerd/api/hibernatable-web-socket.h>
#include <workerd/api/util.h>
#include <workerd/util/stream-utils.h>
#include <workerd/util/use-perfetto-categories.h>

namespace workerd::api {

Expand Down Expand Up @@ -103,6 +104,7 @@ kj::Promise<DeferredProxy<void>> ServiceWorkerGlobalScope::request(
kj::AsyncInputStream& requestBody, kj::HttpService::Response& response,
kj::Maybe<kj::StringPtr> cfBlobJson,
Worker::Lock& lock, kj::Maybe<ExportedHandler&> exportedHandler) {
TRACE_EVENT("workerd", "ServiceWorkerGlobalScope::request()");
// To construct a ReadableStream object, we're supposed to pass in an Own<AsyncInputStream>, so
// that it can drop the reference whenever it gets GC'd. But in this case the stream's lifetime
// is not under our control -- it's attached to the request. So, we wrap it in a
Expand Down
1 change: 1 addition & 0 deletions src/workerd/io/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ wd_cc_library(
visibility = ["//visibility:public"],
deps = [
":capnp",
"//src/workerd/util:perfetto",
"//src/workerd/util:own-util",
"//src/workerd/util:thread-scopes",
"@capnp-cpp//src/kj:kj-async",
Expand Down
3 changes: 3 additions & 0 deletions src/workerd/io/io-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#include <kj/function.h>
#include <capnp/dynamic.h>
#include <workerd/util/weak-refs.h>
#include <workerd/io/limit-enforcer.h>
#include <workerd/io/io-channels.h>
#include <workerd/util/perfetto-tracing.h>

namespace capnp { class HttpOverCapnpFactory; }

Expand Down
4 changes: 4 additions & 0 deletions src/workerd/io/worker-entrypoint.c++
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <workerd/api/util.h>
#include <workerd/util/sentry.h>
#include <workerd/util/thread-scopes.h>
#include <workerd/util/use-perfetto-categories.h>
#include <kj/compat/http.h>

namespace workerd {
Expand Down Expand Up @@ -174,6 +175,7 @@ void WorkerEntrypoint::init(
kj::Own<IoChannelFactory> ioChannelFactory,
kj::Own<RequestObserver> metrics,
kj::Maybe<kj::Own<WorkerTracer>> workerTracer) {
TRACE_EVENT("workerd", "WorkerEntrypoint::init()");
// We need to construct the IoContext -- unless this is an actor and it already has a
// IoContext, in which case we reuse it.

Expand Down Expand Up @@ -208,6 +210,7 @@ void WorkerEntrypoint::init(
kj::Promise<void> WorkerEntrypoint::request(
kj::HttpMethod method, kj::StringPtr url, const kj::HttpHeaders& headers,
kj::AsyncInputStream& requestBody, Response& response) {
TRACE_EVENT("workerd", "WorkerEntrypoint::request()");
auto incomingRequest = kj::mv(KJ_REQUIRE_NONNULL(this->incomingRequest,
"request() can only be called once"));
this->incomingRequest = kj::none;
Expand Down Expand Up @@ -254,6 +257,7 @@ kj::Promise<void> WorkerEntrypoint::request(
&metrics = incomingRequest->getMetrics(),
&wrappedResponse = *wrappedResponse, entrypointName = entrypointName]
(Worker::Lock& lock) mutable {
TRACE_EVENT("workerd", "WorkerEntrypoint::request() main");
jsg::AsyncContextFrame::StorageScope traceScope = context.makeAsyncTraceScope(lock);

return lock.getGlobalScope().request(
Expand Down
2 changes: 2 additions & 0 deletions src/workerd/server/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ wd_cc_binary(
":server",
":workerd-meta_capnp",
":workerd_capnp",
"//src/workerd/util:perfetto",
"@capnp-cpp//src/capnp:capnpc",
] + select({
"@platforms//os:windows": [],
Expand Down Expand Up @@ -99,6 +100,7 @@ wd_cc_library(
"//src/workerd/api:rtti",
"//src/workerd/io",
"//src/workerd/jsg",
"//src/workerd/util:perfetto",
],
)

Expand Down
Loading

0 comments on commit d2e127c

Please sign in to comment.