Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

87
deps/v8/test/benchmarks/cpp/BUILD.gn vendored Normal file
View File

@ -0,0 +1,87 @@
# Copyright 2020 The V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("../../../gni/v8.gni")
group("gn_all") {
testonly = true
deps = []
if (v8_enable_google_benchmark) {
deps += [
":bindings_benchmark",
":dtoa_benchmark",
":empty_benchmark",
":fast_api_benchmark",
"cppgc:gn_all",
]
}
}
if (v8_enable_google_benchmark) {
v8_executable("empty_benchmark") {
testonly = true
configs = []
sources = [ "empty.cc" ]
deps = [
"//:v8_libbase",
"//third_party/google_benchmark_chrome:benchmark_main",
"//third_party/google_benchmark_chrome:google_benchmark",
]
}
v8_executable("dtoa_benchmark") {
testonly = true
configs = []
sources = [ "dtoa.cc" ]
deps = [
"//:v8_libbase",
"//third_party/google_benchmark_chrome:benchmark_main",
"//third_party/google_benchmark_chrome:google_benchmark",
]
}
v8_executable("bindings_benchmark") {
testonly = true
configs = []
sources = [
"benchmark-main.cc",
"benchmark-utils.cc",
"benchmark-utils.h",
"bindings.cc",
]
deps = [
"//:v8",
"//third_party/google_benchmark_chrome:google_benchmark",
]
}
v8_executable("fast_api_benchmark") {
testonly = true
configs = []
sources = [
"benchmark-main.cc",
"benchmark-utils.cc",
"benchmark-utils.h",
"fast-api.cc",
]
deps = [
"//:v8",
"//third_party/google_benchmark_chrome:google_benchmark",
]
}
}

8
deps/v8/test/benchmarks/cpp/DEPS vendored Normal file
View File

@ -0,0 +1,8 @@
include_rules = [
"+src/base",
"+third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h",
# TODO(chromium: 328117814) Temporarily allow internals until the API has
# landed.
"+src/api/api-inl.h",
"+src/objects/js-objects-inl.h",
]

View File

@ -0,0 +1,24 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/v8-initialization.h"
#include "test/benchmarks/cpp/benchmark-utils.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
// Expanded macro BENCHMARK_MAIN() to allow per-process setup.
int main(int argc, char** argv) {
v8::V8::InitializeICUDefaultLocation(argv[0]);
v8::V8::InitializeExternalStartupData(argv[0]);
v8::benchmarking::BenchmarkWithIsolate::InitializeProcess();
// Contents of BENCHMARK_MAIN().
{
::benchmark::Initialize(&argc, argv);
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
::benchmark::RunSpecifiedBenchmarks();
::benchmark::Shutdown();
}
v8::benchmarking::BenchmarkWithIsolate::ShutdownProcess();
return 0;
}

View File

@ -0,0 +1,49 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test/benchmarks/cpp/benchmark-utils.h"
#include "include/cppgc/platform.h"
#include "include/libplatform/libplatform.h"
#include "include/v8-array-buffer.h"
#include "include/v8-cppgc.h"
#include "include/v8-initialization.h"
namespace v8::benchmarking {
// static
v8::Platform* BenchmarkWithIsolate::platform_;
// static
v8::Isolate* BenchmarkWithIsolate::v8_isolate_;
// static
v8::ArrayBuffer::Allocator* BenchmarkWithIsolate::v8_ab_allocator_;
// static
void BenchmarkWithIsolate::InitializeProcess() {
v8::V8::SetFlagsFromString("--allow-natives-syntax");
platform_ = v8::platform::NewDefaultPlatform().release();
v8::V8::InitializePlatform(platform_);
v8::V8::Initialize();
cppgc::InitializeProcess(platform_->GetPageAllocator());
v8_ab_allocator_ = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
auto heap = v8::CppHeap::Create(platform_, v8::CppHeapCreateParams({}));
v8::Isolate::CreateParams create_params;
create_params.array_buffer_allocator = v8_ab_allocator_;
create_params.cpp_heap = heap.release();
v8_isolate_ = v8::Isolate::New(create_params);
v8_isolate_->Enter();
}
// static
void BenchmarkWithIsolate::ShutdownProcess() {
v8_isolate_->Exit();
v8_isolate_->Dispose();
cppgc::ShutdownProcess();
v8::V8::Dispose();
v8::V8::DisposePlatform();
delete v8_ab_allocator_;
}
} // namespace v8::benchmarking

View File

@ -0,0 +1,41 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TEST_BENCHMARK_CPP_BENCHMARK_UTILS_H_
#define TEST_BENCHMARK_CPP_BENCHMARK_UTILS_H_
#include "include/v8-array-buffer.h"
#include "include/v8-cppgc.h"
#include "include/v8-isolate.h"
#include "include/v8-platform.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
namespace v8::benchmarking {
static constexpr uint16_t kEmbedderId = 0;
static constexpr size_t kTypeOffset = 0;
static constexpr size_t kInstanceOffset = 1;
// BenchmarkWithIsolate is a basic benchmark fixture that sets up the process
// with a single Isolate.
class BenchmarkWithIsolate : public benchmark::Fixture {
public:
static void InitializeProcess();
static void ShutdownProcess();
protected:
V8_INLINE v8::Isolate* v8_isolate() { return v8_isolate_; }
V8_INLINE cppgc::AllocationHandle& allocation_handle() {
return v8_isolate_->GetCppHeap()->GetAllocationHandle();
}
private:
static v8::Platform* platform_;
static v8::Isolate* v8_isolate_;
static v8::ArrayBuffer::Allocator* v8_ab_allocator_;
};
} // namespace v8::benchmarking
#endif // TEST_BENCHMARK_CPP_BENCHMARK_UTILS_H_

418
deps/v8/test/benchmarks/cpp/bindings.cc vendored Normal file
View File

@ -0,0 +1,418 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/cppgc/allocation.h"
#include "include/v8-context.h"
#include "include/v8-internal.h"
#include "include/v8-local-handle.h"
#include "include/v8-persistent-handle.h"
#include "include/v8-sandbox.h"
#include "include/v8-template.h"
#include "src/api/api-inl.h"
#include "src/base/macros.h"
#include "src/objects/js-objects-inl.h"
#include "test/benchmarks/cpp/benchmark-utils.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
namespace {
v8::Local<v8::String> v8_str(const char* x) {
return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x).ToLocalChecked();
}
struct WrapperTypeInfo {
uint16_t embedder_id;
};
struct PerContextData {
cppgc::AllocationHandle& allocation_handle;
std::map<WrapperTypeInfo*, v8::Global<v8::ObjectTemplate>> object_templates;
};
class ManagedWrappableBase
: public cppgc::GarbageCollected<ManagedWrappableBase> {
public:
virtual WrapperTypeInfo* GetWrapperTypeInfo() = 0;
void SetWrapper(v8::Isolate* isolate, v8::Local<v8::Value> value) {
wrapper_.Reset(isolate, value);
}
virtual void Trace(cppgc::Visitor* visitor) const {
visitor->Trace(wrapper_);
}
private:
v8::TracedReference<v8::Value> wrapper_;
};
class ManagedWrappableValue : public ManagedWrappableBase {
public:
static WrapperTypeInfo wrapper_type_info;
WrapperTypeInfo* GetWrapperTypeInfo() override { return &wrapper_type_info; }
};
WrapperTypeInfo ManagedWrappableValue::wrapper_type_info{
v8::benchmarking::kEmbedderId};
class ManagedGlobalWrappable : public ManagedWrappableBase {
public:
static WrapperTypeInfo wrapper_type_info;
WrapperTypeInfo* GetWrapperTypeInfo() override { return &wrapper_type_info; }
ManagedWrappableValue* GetWrappableValue(
cppgc::AllocationHandle& allocation_Handle) {
return cppgc::MakeGarbageCollected<ManagedWrappableValue>(
allocation_Handle);
}
uint16_t GetSmiNumber() { return 17; }
};
WrapperTypeInfo ManagedGlobalWrappable::wrapper_type_info{
v8::benchmarking::kEmbedderId};
class UnmanagedWrappableBase {
public:
virtual ~UnmanagedWrappableBase() = default;
virtual WrapperTypeInfo* GetWrapperTypeInfo() = 0;
void SetWrapper(v8::Isolate* isolate, v8::Local<v8::Value> value) {
wrapper_.Reset(isolate, value);
wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter);
}
private:
static void FirstWeakCallback(
const v8::WeakCallbackInfo<UnmanagedWrappableBase>& data) {
UnmanagedWrappableBase* wrappable = data.GetParameter();
wrappable->wrapper_.Reset();
data.SetSecondPassCallback(SecondWeakCallback);
}
static void SecondWeakCallback(
const v8::WeakCallbackInfo<UnmanagedWrappableBase>& data) {
UnmanagedWrappableBase* wrappable = data.GetParameter();
delete wrappable;
}
v8::Global<v8::Value> wrapper_;
};
class UnmanagedWrappableValue : public UnmanagedWrappableBase {
public:
static WrapperTypeInfo wrapper_type_info;
WrapperTypeInfo* GetWrapperTypeInfo() override { return &wrapper_type_info; }
};
WrapperTypeInfo UnmanagedWrappableValue::wrapper_type_info{
v8::benchmarking::kEmbedderId};
class UnmanagedGlobalWrappable : public UnmanagedWrappableBase {
public:
static WrapperTypeInfo wrapper_type_info;
WrapperTypeInfo* GetWrapperTypeInfo() override { return &wrapper_type_info; }
UnmanagedWrappableValue* GetWrappableValue() {
return new UnmanagedWrappableValue;
}
uint16_t GetSmiNumber() { return 17; }
};
WrapperTypeInfo UnmanagedGlobalWrappable::wrapper_type_info{
v8::benchmarking::kEmbedderId};
template <typename WrappableValueType>
v8::Local<v8::ObjectTemplate> GetInstanceTemplateForContext(
v8::Isolate* isolate, PerContextData* data,
WrapperTypeInfo* wrapper_type_info, int number_of_internal_fields) {
auto it =
data->object_templates.find((&WrappableValueType::wrapper_type_info));
v8::Local<v8::ObjectTemplate> instance_tpl;
if (it == data->object_templates.end()) {
v8::Local<v8::FunctionTemplate> function_template =
v8::FunctionTemplate::New(isolate);
auto object_template = function_template->InstanceTemplate();
object_template->SetInternalFieldCount(number_of_internal_fields);
data->object_templates.emplace(
&WrappableValueType::wrapper_type_info,
v8::Global<v8::ObjectTemplate>(isolate, object_template));
instance_tpl = object_template;
} else {
instance_tpl = it->second.Get(isolate);
}
return instance_tpl;
}
template <typename ConcreteBindings>
class BindingsBenchmarkBase : public v8::benchmarking::BenchmarkWithIsolate {
public:
static void AccessorReturningWrapper(
const v8::FunctionCallbackInfo<v8::Value>& info) {
// Preamble.
auto* isolate = info.GetIsolate();
auto ctx = isolate->GetCurrentContext();
auto* data = reinterpret_cast<PerContextData*>(
ctx->GetAlignedPointerFromEmbedderData(v8::benchmarking::kEmbedderId));
// Unwrap: Get the C++ instance pointer.
typename ConcreteBindings::GlobalWrappable* receiver =
ConcreteBindings::template Unwrap<
typename ConcreteBindings::GlobalWrappable>(isolate, info.This());
// Invoke the actual operation.
typename ConcreteBindings::WrappableValue* return_value =
ConcreteBindings::GetWrappableValue(data, receiver);
// Wrap the C++ value with a JS value.
auto v8_wrapper = ConcreteBindings::Wrap(
isolate, ctx, data, return_value,
&ConcreteBindings::WrappableValue::wrapper_type_info);
// Return the JS value back to V8.
info.GetReturnValue().SetNonEmpty(v8_wrapper);
}
static void AccessorReturningSmi(
const v8::FunctionCallbackInfo<v8::Value>& info) {
// Preamble.
auto* isolate = info.GetIsolate();
// Unwrap: Get the C++ instance pointer.
typename ConcreteBindings::GlobalWrappable* receiver =
ConcreteBindings::template Unwrap<
typename ConcreteBindings::GlobalWrappable>(isolate, info.This());
// Invoke the actual operation.
uint16_t return_value = receiver->GetSmiNumber();
// Return Smi.
info.GetReturnValue().Set(return_value);
}
void SetUp(::benchmark::State& state) override {
auto* isolate = v8_isolate();
v8::HandleScope handle_scope(isolate);
auto proxy_template_function = v8::FunctionTemplate::New(isolate);
auto object_template = proxy_template_function->InstanceTemplate();
ConcreteBindings::SetupContextTemplate(object_template);
object_template->SetAccessorProperty(
v8_str("accessorReturningWrapper"),
v8::FunctionTemplate::New(isolate, &AccessorReturningWrapper));
object_template->SetAccessorProperty(
v8_str("accessorReturningSmi"),
v8::FunctionTemplate::New(isolate, &AccessorReturningSmi));
v8::Local<v8::Context> context =
v8::Context::New(isolate, nullptr, object_template);
auto* per_context_data = new PerContextData{allocation_handle(), {}};
context->SetAlignedPointerInEmbedderData(0, per_context_data);
auto* global_wrappable =
ConcreteBindings::CreateGlobalWrappable(per_context_data);
CHECK(context->Global()->IsApiWrapper());
ConcreteBindings::AssociateWithWrapper(
isolate, context->Global(),
&ConcreteBindings::GlobalWrappable::wrapper_type_info,
global_wrappable);
context_.Reset(isolate, context);
context->Enter();
}
void TearDown(::benchmark::State& state) override {
auto* isolate = v8_isolate();
v8::HandleScope handle_scope(isolate);
auto context = context_.Get(isolate);
delete reinterpret_cast<PerContextData*>(
context->GetAlignedPointerFromEmbedderData(
v8::benchmarking::kEmbedderId));
context->Exit();
context_.Reset();
}
v8::Local<v8::Script> CompileBenchmarkScript(const char* source) {
v8::EscapableHandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::String> v8_source = v8_str(source);
v8::Local<v8::Script> script =
v8::Script::Compile(context, v8_source).ToLocalChecked();
return handle_scope.Escape(script);
}
protected:
v8::Local<v8::Context> v8_context() { return context_.Get(v8_isolate()); }
v8::Global<v8::Context> context_;
};
class UnmanagedBindings : public BindingsBenchmarkBase<UnmanagedBindings> {
public:
using WrappableBase = UnmanagedWrappableBase;
using WrappableValue = UnmanagedWrappableValue;
using GlobalWrappable = UnmanagedGlobalWrappable;
static V8_INLINE WrappableValue* GetWrappableValue(
PerContextData* data, GlobalWrappable* receiver) {
return receiver->GetWrappableValue();
}
static V8_INLINE GlobalWrappable* CreateGlobalWrappable(PerContextData*) {
return new GlobalWrappable;
}
static V8_INLINE v8::Local<v8::Object> Wrap(v8::Isolate* isolate,
v8::Local<v8::Context>& context,
PerContextData* data,
WrappableBase* wrappable,
WrapperTypeInfo* info) {
// Allocate a new JS wrapper.
v8::Local<v8::ObjectTemplate> wrapper_instance_tpl =
GetInstanceTemplateForContext<WrappableValue>(
isolate, data, &WrappableValue::wrapper_type_info, 2);
auto v8_wrapper =
wrapper_instance_tpl->NewInstance(context).ToLocalChecked();
AssociateWithWrapper(isolate, v8_wrapper, info, wrappable);
return v8_wrapper;
}
static V8_INLINE void AssociateWithWrapper(v8::Isolate* isolate,
v8::Local<v8::Object> v8_wrapper,
WrapperTypeInfo* info,
WrappableBase* wrappable) {
// Set V8 to C++ reference.
int indices[] = {v8::benchmarking::kTypeOffset,
v8::benchmarking::kInstanceOffset};
void* values[] = {info, wrappable};
v8_wrapper->SetAlignedPointerInInternalFields(2, indices, values);
// Set C++ to V8 reference.
wrappable->SetWrapper(isolate, v8_wrapper);
}
template <typename T>
static V8_INLINE T* Unwrap(v8::Isolate* isolate, v8::Local<v8::Object> thiz) {
return reinterpret_cast<T*>(thiz->GetAlignedPointerFromInternalField(
v8::benchmarking::kInstanceOffset));
}
static void SetupContextTemplate(
v8::Local<v8::ObjectTemplate>& object_template) {
object_template->SetInternalFieldCount(2);
}
};
class ManagedBindings : public BindingsBenchmarkBase<ManagedBindings> {
public:
using WrappableBase = ManagedWrappableBase;
using WrappableValue = ManagedWrappableValue;
using GlobalWrappable = ManagedGlobalWrappable;
static V8_INLINE WrappableValue* GetWrappableValue(
PerContextData* data, GlobalWrappable* receiver) {
return receiver->GetWrappableValue(data->allocation_handle);
}
static V8_INLINE GlobalWrappable* CreateGlobalWrappable(
PerContextData* per_context_data) {
return cppgc::MakeGarbageCollected<GlobalWrappable>(
per_context_data->allocation_handle);
}
static V8_INLINE v8::Local<v8::Object> Wrap(v8::Isolate* isolate,
v8::Local<v8::Context>& context,
PerContextData* data,
WrappableBase* wrappable,
WrapperTypeInfo* info) {
// Allocate a new JS wrapper.
v8::Local<v8::ObjectTemplate> wrapper_instance_tpl =
GetInstanceTemplateForContext<WrappableValue>(
isolate, data, &WrappableValue::wrapper_type_info, 0);
auto v8_wrapper =
wrapper_instance_tpl->NewInstance(context).ToLocalChecked();
AssociateWithWrapper(isolate, v8_wrapper, info, wrappable);
return v8_wrapper;
}
static V8_INLINE void AssociateWithWrapper(v8::Isolate* isolate,
v8::Local<v8::Object> v8_wrapper,
WrapperTypeInfo* info,
WrappableBase* wrappable) {
// Set V8 to C++ reference.
v8::Object::Wrap<v8::CppHeapPointerTag::kDefaultTag>(isolate, v8_wrapper,
wrappable);
// Set C++ to V8 reference.
wrappable->SetWrapper(isolate, v8_wrapper);
}
template <typename T>
static V8_INLINE T* Unwrap(v8::Isolate* isolate, v8::Local<v8::Object> thiz) {
return v8::Object::Unwrap<v8::CppHeapPointerTag::kDefaultTag, T>(isolate,
thiz);
}
static void SetupContextTemplate(
v8::Local<v8::ObjectTemplate>& object_template) {}
};
} // namespace
const char* kScriptInvocingAccessorReturingWrapper =
"function invoke() { globalThis.accessorReturningWrapper; }"
"for (var i =0; i < 1_000; i++) invoke();";
BENCHMARK_F(UnmanagedBindings, AccessorReturningWrapper)(benchmark::State& st) {
v8::HandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::Script> script =
CompileBenchmarkScript(kScriptInvocingAccessorReturingWrapper);
v8::HandleScope benchmark_handle_scope(v8_isolate());
for (auto _ : st) {
USE(_);
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
benchmark::DoNotOptimize(result);
}
}
BENCHMARK_F(ManagedBindings, AccessorReturningWrapper)(benchmark::State& st) {
v8::HandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::Script> script =
CompileBenchmarkScript(kScriptInvocingAccessorReturingWrapper);
v8::HandleScope benchmark_handle_scope(v8_isolate());
for (auto _ : st) {
USE(_);
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
benchmark::DoNotOptimize(result);
}
}
const char* kScriptInvocingAccessorReturingSmi =
"function invoke() { globalThis.accessorReturningSmi; }"
"for (var i =0; i < 1_000; i++) invoke();";
BENCHMARK_F(UnmanagedBindings, AccessorReturningSmi)(benchmark::State& st) {
v8::HandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::Script> script =
CompileBenchmarkScript(kScriptInvocingAccessorReturingSmi);
v8::HandleScope benchmark_handle_scope(v8_isolate());
for (auto _ : st) {
USE(_);
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
benchmark::DoNotOptimize(result);
}
}
BENCHMARK_F(ManagedBindings, AccessorReturningSmi)(benchmark::State& st) {
v8::HandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::Script> script =
CompileBenchmarkScript(kScriptInvocingAccessorReturingSmi);
v8::HandleScope benchmark_handle_scope(v8_isolate());
for (auto _ : st) {
USE(_);
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
benchmark::DoNotOptimize(result);
}
}

View File

@ -0,0 +1,77 @@
# Copyright 2020 The V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("../../../../gni/v8.gni")
group("gn_all") {
testonly = true
deps = []
if (v8_enable_google_benchmark) {
deps += [ ":cppgc_basic_benchmarks" ]
}
}
if (v8_enable_google_benchmark) {
v8_source_set("cppgc_benchmark_support") {
testonly = true
configs = [
"../../../..:external_config",
"../../../..:internal_config_base",
"../../../..:cppgc_base_config",
]
sources = [
"../../../../test/unittests/heap/cppgc/test-platform.cc",
"../../../../test/unittests/heap/cppgc/test-platform.h",
"benchmark_main.cc",
"benchmark_utils.cc",
"benchmark_utils.h",
]
public_deps = [ "//third_party/google_benchmark_chrome:google_benchmark" ]
if (cppgc_is_standalone) {
deps = [ "../../../..:cppgc_for_testing" ]
} else {
deps = [ "../../../..:v8_for_testing" ]
}
}
v8_executable("cppgc_basic_benchmarks") {
testonly = true
configs = [
"../../../..:external_config",
"../../../..:internal_config_base",
"../../../..:cppgc_base_config",
]
sources = [
"allocation_perf.cc",
"trace_perf.cc",
]
deps = [ ":cppgc_benchmark_support" ]
if (cppgc_is_standalone) {
deps += [ "../../../..:cppgc_for_testing" ]
} else {
deps += [ "../../../..:v8_for_testing" ]
}
}
v8_executable("cppgc_binary_trees_perf") {
testonly = true
configs = [
"../../../..:external_config",
"../../../..:internal_config_base",
"../../../..:cppgc_base_config",
]
sources = [ "binary-trees_perf.cc" ]
deps = [ ":cppgc_benchmark_support" ]
if (cppgc_is_standalone) {
deps += [ "../../../..:cppgc_for_testing" ]
} else {
deps += [ "../../../..:v8_for_testing" ]
}
}
}

View File

@ -0,0 +1,7 @@
include_rules = [
"+include/cppgc",
"+src/base",
"+src/heap/cppgc",
"+test/unittests/heap/cppgc",
"+third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h",
]

View File

@ -0,0 +1,55 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/cppgc/allocation.h"
#include "include/cppgc/garbage-collected.h"
#include "include/cppgc/heap-consistency.h"
#include "src/base/macros.h"
#include "src/heap/cppgc/globals.h"
#include "src/heap/cppgc/heap.h"
#include "test/benchmarks/cpp/cppgc/benchmark_utils.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
namespace cppgc {
namespace internal {
namespace {
using Allocate = testing::BenchmarkWithHeap;
class TinyObject final : public cppgc::GarbageCollected<TinyObject> {
public:
void Trace(cppgc::Visitor*) const {}
};
BENCHMARK_F(Allocate, Tiny)(benchmark::State& st) {
subtle::NoGarbageCollectionScope no_gc(*Heap::From(&heap()));
for (auto _ : st) {
USE(_);
TinyObject* result =
cppgc::MakeGarbageCollected<TinyObject>(heap().GetAllocationHandle());
benchmark::DoNotOptimize(result);
}
st.SetBytesProcessed(st.iterations() * sizeof(TinyObject));
}
class LargeObject final : public GarbageCollected<LargeObject> {
public:
void Trace(cppgc::Visitor*) const {}
char padding[kLargeObjectSizeThreshold + 1];
};
BENCHMARK_F(Allocate, Large)(benchmark::State& st) {
subtle::NoGarbageCollectionScope no_gc(*Heap::From(&heap()));
for (auto _ : st) {
USE(_);
LargeObject* result =
cppgc::MakeGarbageCollected<LargeObject>(heap().GetAllocationHandle());
benchmark::DoNotOptimize(result);
}
st.SetBytesProcessed(st.iterations() * sizeof(LargeObject));
}
} // namespace
} // namespace internal
} // namespace cppgc

View File

@ -0,0 +1,21 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/cppgc/platform.h"
#include "test/benchmarks/cpp/cppgc/benchmark_utils.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
// Expanded macro BENCHMARK_MAIN() to allow per-process setup.
int main(int argc, char** argv) {
cppgc::internal::testing::BenchmarkWithHeap::InitializeProcess();
// Contents of BENCHMARK_MAIN().
{
::benchmark::Initialize(&argc, argv);
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
::benchmark::RunSpecifiedBenchmarks();
::benchmark::Shutdown();
}
cppgc::internal::testing::BenchmarkWithHeap::ShutdownProcess();
return 0;
}

View File

@ -0,0 +1,31 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "test/benchmarks/cpp/cppgc/benchmark_utils.h"
#include "include/cppgc/platform.h"
#include "test/unittests/heap/cppgc/test-platform.h"
namespace cppgc {
namespace internal {
namespace testing {
// static
std::shared_ptr<testing::TestPlatform> BenchmarkWithHeap::platform_;
// static
void BenchmarkWithHeap::InitializeProcess() {
platform_ = std::make_shared<testing::TestPlatform>();
cppgc::InitializeProcess(platform_->GetPageAllocator());
}
// static
void BenchmarkWithHeap::ShutdownProcess() {
cppgc::ShutdownProcess();
platform_.reset();
}
} // namespace testing
} // namespace internal
} // namespace cppgc

View File

@ -0,0 +1,44 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef TEST_BENCHMARK_CPP_CPPGC_BENCHMARK_UTILS_H_
#define TEST_BENCHMARK_CPP_CPPGC_BENCHMARK_UTILS_H_
#include "include/cppgc/heap.h"
#include "test/unittests/heap/cppgc/test-platform.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
namespace cppgc {
namespace internal {
namespace testing {
class BenchmarkWithHeap : public benchmark::Fixture {
public:
static void InitializeProcess();
static void ShutdownProcess();
protected:
void SetUp(::benchmark::State& state) override {
heap_ = cppgc::Heap::Create(GetPlatform());
}
void TearDown(::benchmark::State& state) override { heap_.reset(); }
cppgc::Heap& heap() const { return *heap_.get(); }
private:
static std::shared_ptr<testing::TestPlatform> GetPlatform() {
return platform_;
}
static std::shared_ptr<testing::TestPlatform> platform_;
std::unique_ptr<cppgc::Heap> heap_;
};
} // namespace testing
} // namespace internal
} // namespace cppgc
#endif // TEST_BENCHMARK_CPP_CPPGC_BENCHMARK_UTILS_H_

View File

@ -0,0 +1,105 @@
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <iostream>
#include "include/cppgc/allocation.h"
#include "include/cppgc/garbage-collected.h"
#include "include/cppgc/heap.h"
#include "include/cppgc/persistent.h"
#include "include/cppgc/visitor.h"
#include "src/base/macros.h"
#include "src/heap/cppgc/object-allocator.h"
#include "test/benchmarks/cpp/cppgc/benchmark_utils.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
namespace {
// Implementation of the binary trees benchmark of the computer language
// benchmarks game. See
// https://benchmarksgame-team.pages.debian.net/benchmarksgame/performance/binarytrees.html
class BinaryTrees : public cppgc::internal::testing::BenchmarkWithHeap {
public:
BinaryTrees() { Iterations(1); }
};
class TreeNode final : public cppgc::GarbageCollected<TreeNode> {
public:
void Trace(cppgc::Visitor* visitor) const {
visitor->Trace(left_);
visitor->Trace(right_);
}
const TreeNode* left() const { return left_; }
void set_left(TreeNode* node) { left_ = node; }
const TreeNode* right() const { return right_; }
void set_right(TreeNode* node) { right_ = node; }
size_t Check() const {
return left() ? left()->Check() + right()->Check() + 1 : 1;
}
private:
cppgc::Member<TreeNode> left_;
cppgc::Member<TreeNode> right_;
};
TreeNode* CreateTree(cppgc::AllocationHandle& alloc_handle, size_t depth) {
auto* node = cppgc::MakeGarbageCollected<TreeNode>(alloc_handle);
if (depth > 0) {
node->set_left(CreateTree(alloc_handle, depth - 1));
node->set_right(CreateTree(alloc_handle, depth - 1));
}
return node;
}
void Loop(cppgc::AllocationHandle& alloc_handle, size_t iterations,
size_t depth) {
size_t check = 0;
for (size_t item = 0; item < iterations; ++item) {
check += CreateTree(alloc_handle, depth)->Check();
}
std::cout << iterations << "\t trees of depth " << depth
<< "\t check: " << check << std::endl;
}
void Trees(cppgc::AllocationHandle& alloc_handle, size_t max_depth) {
// Keep the long-lived tree in a Persistent to allow for concurrent GC to
// immediately find it.
cppgc::Persistent<TreeNode> long_lived_tree =
CreateTree(alloc_handle, max_depth);
constexpr size_t kMinDepth = 4;
const size_t max_iterations = 16 << max_depth;
for (size_t depth = kMinDepth; depth <= max_depth; depth += 2) {
const size_t iterations = max_iterations >> depth;
Loop(alloc_handle, iterations, depth);
}
std::cout << "long lived tree of depth " << max_depth << "\t "
<< "check: " << long_lived_tree->Check() << "\n";
}
void RunBinaryTrees(cppgc::Heap& heap) {
const size_t max_depth = 21;
auto& alloc_handle = heap.GetAllocationHandle();
const size_t stretch_depth = max_depth + 1;
std::cout << "stretch tree of depth " << stretch_depth << "\t "
<< "check: " << CreateTree(alloc_handle, stretch_depth)->Check()
<< std::endl;
Trees(alloc_handle, max_depth);
}
} // namespace
BENCHMARK_F(BinaryTrees, V1)(benchmark::State& st) {
for (auto _ : st) {
USE(_);
RunBinaryTrees(heap());
}
}

View File

@ -0,0 +1,87 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/cppgc/allocation.h"
#include "include/cppgc/garbage-collected.h"
#include "include/cppgc/persistent.h"
#include "src/base/macros.h"
#include "src/heap/cppgc/globals.h"
#include "src/heap/cppgc/heap.h"
#include "test/benchmarks/cpp/cppgc/benchmark_utils.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
#include "v8config.h"
namespace cppgc {
namespace internal {
namespace {
using Trace = testing::BenchmarkWithHeap;
class GCed : public cppgc::GarbageCollected<GCed> {
public:
virtual void Trace(Visitor*) const {}
};
class OtherPayload {
public:
virtual void* DummyGetter() { return nullptr; }
};
class Mixin : public GarbageCollectedMixin {
public:
void Trace(Visitor*) const override {}
};
class GCedWithMixin final : public GCed, public OtherPayload, public Mixin {
public:
void Trace(Visitor* visitor) const final {
GCed::Trace(visitor);
Mixin::Trace(visitor);
}
};
class Holder : public cppgc::GarbageCollected<Holder> {
public:
explicit Holder(GCedWithMixin* object)
: base_ref(object), mixin_ref(object) {}
virtual void Trace(Visitor* visitor) const {
visitor->Trace(base_ref);
visitor->Trace(mixin_ref);
}
cppgc::Member<GCedWithMixin> base_ref;
cppgc::Member<Mixin> mixin_ref;
};
template <typename T>
V8_NOINLINE void DispatchTrace(Visitor* visitor, T& ref) {
visitor->Trace(ref);
}
BENCHMARK_F(Trace, Static)(benchmark::State& st) {
cppgc::Persistent<Holder> holder(cppgc::MakeGarbageCollected<Holder>(
heap().GetAllocationHandle(), cppgc::MakeGarbageCollected<GCedWithMixin>(
heap().GetAllocationHandle())));
VisitorBase visitor;
for (auto _ : st) {
USE(_);
DispatchTrace(&visitor, holder->base_ref);
}
}
BENCHMARK_F(Trace, Dynamic)(benchmark::State& st) {
cppgc::Persistent<Holder> holder(cppgc::MakeGarbageCollected<Holder>(
heap().GetAllocationHandle(), cppgc::MakeGarbageCollected<GCedWithMixin>(
heap().GetAllocationHandle())));
VisitorBase visitor;
for (auto _ : st) {
USE(_);
DispatchTrace(&visitor, holder->mixin_ref);
}
}
} // namespace
} // namespace internal
} // namespace cppgc

1069
deps/v8/test/benchmarks/cpp/dtoa.cc vendored Normal file

File diff suppressed because it is too large Load Diff

16
deps/v8/test/benchmarks/cpp/empty.cc vendored Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/base/macros.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
static void BM_Empty(benchmark::State& state) {
for (auto _ : state) {
USE(_);
}
}
// Register the function as a benchmark. The empty benchmark ensures that the
// framework compiles and links as expected.
BENCHMARK(BM_Empty);

226
deps/v8/test/benchmarks/cpp/fast-api.cc vendored Normal file
View File

@ -0,0 +1,226 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/v8-context.h"
#include "include/v8-fast-api-calls.h"
#include "include/v8-internal.h"
#include "include/v8-local-handle.h"
#include "include/v8-persistent-handle.h"
#include "include/v8-template.h"
#include "src/base/macros.h"
#include "test/benchmarks/cpp/benchmark-utils.h"
#include "third_party/google_benchmark_chrome/src/include/benchmark/benchmark.h"
namespace {
v8::Local<v8::String> v8_str(const char* x) {
return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x).ToLocalChecked();
}
class FastApiBenchmark : public v8::benchmarking::BenchmarkWithIsolate {
public:
static void RegularCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
}
static void FastCallback(v8::Local<v8::Value> receiver,
v8::FastApiCallbackOptions& options) {}
static uint32_t FastStringValueView(v8::Local<v8::Value> receiver,
v8::Local<v8::Value> value,
v8::FastApiCallbackOptions& options) {
v8::Local<v8::String> str = value.As<v8::String>();
v8::String::ValueView view(options.isolate, str);
return view.length();
}
static uint32_t FastOneByteString(v8::Local<v8::Value> receiver,
const v8::FastOneByteString& str,
v8::FastApiCallbackOptions& options) {
return str.length;
}
static void RegularString(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Local<v8::String> str = info[0].As<v8::String>();
v8::String::ValueView view(info.GetIsolate(), str);
info.GetReturnValue().Set(view.length());
}
void SetUp(::benchmark::State& state) override {
auto* isolate = v8_isolate();
v8::HandleScope handle_scope(isolate);
auto proxy_template_function = v8::FunctionTemplate::New(isolate);
auto object_template = proxy_template_function->InstanceTemplate();
{
v8::CFunction fast_callback =
v8::CFunction::Make(FastApiBenchmark::FastCallback);
object_template->Set(
isolate, "fastApiCall",
v8::FunctionTemplate::New(
isolate, FastApiBenchmark::RegularCallback,
v8::Local<v8::Value>(), v8::Local<v8::Signature>(), 1,
v8::ConstructorBehavior::kThrow,
v8::SideEffectType::kHasSideEffect, &fast_callback));
}
{
object_template->Set(isolate, "regularApiCall",
v8::FunctionTemplate::New(
isolate, FastApiBenchmark::RegularCallback));
}
{
v8::CFunction fast_callback =
v8::CFunction::Make(FastApiBenchmark::FastOneByteString);
object_template->Set(
isolate, "fastOneByteString",
v8::FunctionTemplate::New(
isolate, FastApiBenchmark::RegularString, v8::Local<v8::Value>(),
v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kThrow,
v8::SideEffectType::kHasSideEffect, &fast_callback));
}
{
v8::CFunction fast_callback =
v8::CFunction::Make(FastApiBenchmark::FastStringValueView);
object_template->Set(
isolate, "fastStringValueView",
v8::FunctionTemplate::New(
isolate, FastApiBenchmark::RegularString, v8::Local<v8::Value>(),
v8::Local<v8::Signature>(), 1, v8::ConstructorBehavior::kThrow,
v8::SideEffectType::kHasSideEffect, &fast_callback));
}
{
object_template->Set(
isolate, "regularString",
v8::FunctionTemplate::New(isolate, FastApiBenchmark::RegularString));
}
v8::Local<v8::Context> context =
v8::Context::New(isolate, nullptr, object_template);
context_.Reset(isolate, context);
context->Enter();
}
void TearDown(::benchmark::State& state) override {
auto* isolate = v8_isolate();
v8::HandleScope handle_scope(isolate);
auto context = context_.Get(isolate);
context->Exit();
context_.Reset();
}
v8::Local<v8::Script> CompileBenchmarkScript(const char* source) {
v8::EscapableHandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::String> v8_source = v8_str(source);
v8::Local<v8::Script> script =
v8::Script::Compile(context, v8_source).ToLocalChecked();
return handle_scope.Escape(script);
}
protected:
v8::Local<v8::Context> v8_context() { return context_.Get(v8_isolate()); }
v8::Global<v8::Context> context_;
};
} // namespace
BENCHMARK_F(FastApiBenchmark, FastCallToEmptyCallback)(benchmark::State& st) {
const char* kScript =
"function invoke() { globalThis.fastApiCall(); }"
"\%PrepareFunctionForOptimization(invoke);"
"invoke();"
"\%OptimizeFunctionOnNextCall(invoke);"
"for (var i =0; i < 1_000_000; i++) invoke();";
v8::HandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::Script> script = CompileBenchmarkScript(kScript);
v8::HandleScope benchmark_handle_scope(v8_isolate());
for (auto _ : st) {
USE(_);
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
benchmark::DoNotOptimize(result);
}
}
BENCHMARK_F(FastApiBenchmark, RegularCallToEmptyCallback)
(benchmark::State& st) {
const char* kScript =
"function invoke() { globalThis.regularApiCall(); }"
"\%PrepareFunctionForOptimization(invoke);"
"invoke();"
"\%OptimizeFunctionOnNextCall(invoke);"
"for (var i =0; i < 1_000_000; i++) invoke();";
v8::HandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::Script> script = CompileBenchmarkScript(kScript);
v8::HandleScope benchmark_handle_scope(v8_isolate());
for (auto _ : st) {
USE(_);
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
benchmark::DoNotOptimize(result);
}
}
BENCHMARK_F(FastApiBenchmark, FastOneByteString)(benchmark::State& st) {
const char* kScript =
"function invoke() { globalThis.fastOneByteString('Hello World'); }"
"\%PrepareFunctionForOptimization(invoke);"
"invoke();"
"\%OptimizeFunctionOnNextCall(invoke);"
"for (var i =0; i < 1_000_000; i++) invoke();";
v8::HandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::Script> script = CompileBenchmarkScript(kScript);
v8::HandleScope benchmark_handle_scope(v8_isolate());
for (auto _ : st) {
USE(_);
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
benchmark::DoNotOptimize(result);
}
}
BENCHMARK_F(FastApiBenchmark, FastStringValueView)(benchmark::State& st) {
const char* kScript =
"function invoke() { globalThis.fastStringValueView('Hello World'); }"
"\%PrepareFunctionForOptimization(invoke);"
"invoke();"
"\%OptimizeFunctionOnNextCall(invoke);"
"for (var i =0; i < 1_000_000; i++) invoke();";
v8::HandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::Script> script = CompileBenchmarkScript(kScript);
v8::HandleScope benchmark_handle_scope(v8_isolate());
for (auto _ : st) {
USE(_);
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
benchmark::DoNotOptimize(result);
}
}
BENCHMARK_F(FastApiBenchmark, RegularString)(benchmark::State& st) {
const char* kScript =
"function invoke() { globalThis.regularString('Hello World'); }"
"\%PrepareFunctionForOptimization(invoke);"
"invoke();"
"\%OptimizeFunctionOnNextCall(invoke);"
"for (var i =0; i < 1_000_000; i++) invoke();";
v8::HandleScope handle_scope(v8_isolate());
v8::Local<v8::Context> context = v8_context();
v8::Local<v8::Script> script = CompileBenchmarkScript(kScript);
v8::HandleScope benchmark_handle_scope(v8_isolate());
for (auto _ : st) {
USE(_);
v8::Local<v8::Value> result = script->Run(context).ToLocalChecked();
benchmark::DoNotOptimize(result);
}
}