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

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

@ -0,0 +1,16 @@
# Copyright 2018 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.
group("v8_benchmarks") {
testonly = true
data_deps = [
"../..:d8",
"../../tools:v8_testrunner",
]
data = [
"./",
]
}

View File

@ -0,0 +1,173 @@
# Copyright 2013 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[
[ALWAYS, {
# Too slow in Debug mode.
'octane/mandreel': [PASS, SLOW, ['mode == debug', SKIP]],
# TODO(turbofan): Too slow in debug mode for now.
'octane/pdfjs': [PASS, ['mode == debug', SKIP]],
# Slow tests.
'kraken/imaging-gaussian-blur': [PASS, SLOW],
'octane/box2d': [PASS, SLOW],
'octane/regexp': [PASS, SLOW],
'octane/splay': [PASS, SLOW],
'octane/typescript': [PASS, SLOW],
'octane/zlib': [PASS, SLOW],
# https://crbug.com/v8/11905
'kraken/stanford-crypto-pbkdf2': [PASS, SLOW],
# https://crbug.com/v8/11222
'octane/raytrace': [PASS, SLOW],
}], # ALWAYS
# Slow variants.
['variant in [jitless, nooptimization, stress]', {
# Slow tests.
'kraken/ai-astar': [PASS, SLOW],
'kraken/audio-beat-detection': [SLOW],
'kraken/audio-dft': [PASS, SLOW],
'kraken/audio-fft': [PASS, SLOW],
'kraken/audio-oscillator': [PASS, SLOW],
'kraken/imaging-darkroom': [PASS, SLOW],
'kraken/imaging-desaturate': [PASS, SLOW],
'octane/code-load': [PASS, SLOW],
'octane/crypto': [PASS, SLOW],
'octane/earley-boyer': [PASS, SLOW],
'octane/gbemu-part1': [PASS, SLOW],
'octane/navier-stokes': [PASS, SLOW],
'octane/pdfjs': [PASS, SLOW],
'octane/zlib': [PASS, SLOW, ['mode == debug', SKIP]],
}],
['variant == stress', {
# Too slow for stress mode.
'kraken/imaging-desaturate' : [PASS, ['mode == debug', SKIP]],
'kraken/imaging-gaussian-blur' : [PASS, ['mode == debug', SKIP]],
'octane/mandreel': [SKIP],
'octane/typescript': [SKIP],
'octane/raytrace': [PASS, SLOW, ['tsan', SKIP]],
# Too memory hungry on Odroid devices: https://crbug.com/v8/8963
'kraken/stanford-crypto-ccm': [PASS, ['arch == arm and not simulator_run', SKIP]],
}],
['variant == jitless', {
# Too slow for jitless mode.
'kraken/audio-fft': [PASS, ['mode == debug', SKIP]],
'kraken/imaging-desaturate' : [PASS, ['mode == debug', SKIP]],
'kraken/imaging-gaussian-blur' : [PASS, ['mode == debug', SKIP]],
'octane/zlib': [SKIP],
}],
['variant in [jitless, stress] and tsan', {
# Very slow tests.
'kraken/imaging-gaussian-blur': [SKIP],
'octane/mandreel': [SKIP],
}], # 'variant in [jitless, stress] and tsan'
['variant == nooptimization and mode == debug', {
# Too slow for nooptimization mode and debug.
'kraken/imaging-desaturate': [SKIP],
'kraken/imaging-gaussian-blur': [SKIP],
}],
['variant == stress_incremental_marking', {
# Too slow for stress_incremental_marking.
'octane/box2d': [SKIP],
'octane/typescript': [SKIP],
'octane/earley-boyer' : [PASS, SLOW, ['mode == debug', FAIL]],
}],
['gc_fuzzer', {
# Too slow for gc fuzzing.
'octane/earley-boyer' : [PASS, SLOW, ['mode == debug', SKIP]],
'octane/splay': [SKIP],
'octane/typescript': [SKIP],
}], # 'gc_fuzzer'
##############################################################################
['gc_fuzzer or deopt_fuzzer', {
# BUG(v8:12901) Skipped until bug is fixed.
'octane/gbemu-part1': [SKIP],
}], # gc_fuzzer or deopt_fuzzer
['verify_predictable', {
# https://crbug.com/v8/8537
'octane/typescript': [SKIP],
# https://crbug.com/42203172
'kraken/ai-astar': [SKIP],
'kraken/stanford-crypto-aes': [SKIP],
'kraken/stanford-crypto-ccm': [SKIP],
'kraken/stanford-crypto-pbkdf2': [SKIP],
'octane/box2d': [SKIP],
'octane/crypto': [SKIP],
'octane/earley-boyer': [SKIP],
'octane/gbemu-part1': [SKIP],
'octane/mandreel': [SKIP],
'octane/pdfjs': [SKIP],
'octane/regexp': [SKIP],
# https://crbug.com/v8/14512
'octane/raytrace': [SKIP],
}], # 'verify_predictable'
['variant == stress_snapshot', {
'*': [SKIP], # only relevant for mjsunit tests.
}],
['tsan', {
# Slow tests.
'kraken/audio-beat-detection': [SLOW],
'kraken/audio-dft': [SLOW],
'kraken/audio-fft': [SLOW],
'kraken/audio-oscillator': [SLOW],
'octane/pdfjs': [SLOW],
}], # 'tsan'
##############################################################################
['gc_fuzzer or deopt_fuzzer or interrupt_fuzzer', {
# BUG(v8:13808) Skipped until bug is fixed.
'octane/pdfjs': [SKIP],
}], # gc_fuzzer or deopt_fuzzer or interrupt_fuzzer
##############################################################################
['variant == jitless and mode == debug and tsan', {
# Too slow for jitless mode in tsan debug.
'kraken/ai-astar': [SKIP],
'kraken/audio-beat-detection': [SKIP],
'kraken/audio-dft': [SKIP],
'kraken/audio-oscillator': [SKIP],
'kraken/imaging-darkroom': [SKIP],
'octane/box2d': [SKIP],
'octane/crypto': [SKIP],
}], # 'variant == jitless and mode == debug and tsan'
]

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);
}
}

View File

@ -0,0 +1,43 @@
# CSuite: Local benchmarking help for V8 performance analysis
CSuite helps you make N averaged runs of a benchmark, then compare with
a different binary and/or different flags. It knows about the "classic"
benchmarks of SunSpider, Kraken and Octane, which are still useful for
investigating peak performance scenarios. It offers a default number of
runs, by default they are:
* SunSpider - 100 runs
* Kraken - 80 runs
* Octane - 10 runs
# Usage
Say you want to see how much optimization buys you:
./csuite.py kraken baseline ~/src/v8/out/d8 -x="--noturbofan"
./csuite.py kraken compare ~/src/v8/out/d8
Suppose you are comparing two binaries, and want a quick look at results.
Normally, Octane should have about 10 runs, but 3 will only take a few
minutes:
./csuite.py -r 3 octane baseline ~/src/v8/out-master/d8
./csuite.py -r 3 octane compare ~/src/v8/out-mine/d8
You can run from any place:
../../somewhere-strange/csuite.py sunspider baseline ./d8
../../somewhere-strange/csuite.py sunspider compare ./d8-better
Note that all output files are created in the directory where you run
from. A `_benchmark_runner_data` directory will be created to store run
output, and a `_results` directory as well for scores.
For more detailed documentation, see:
./csuite.py --help
Output from the runners is captured into files and cached, so you can cancel
and resume multi-hour benchmark runs with minimal loss of data/time. The -f
flag forces re-running even if these cached files still exist.

249
deps/v8/test/benchmarks/csuite/benchmark.py vendored Executable file
View File

@ -0,0 +1,249 @@
#!/usr/bin/python3
# Copyright 2018 the V8 project authors. All rights reserved.
'''
python %prog -c <command> [options]
Local benchmark runner.
The -c option is mandatory.
'''
# for py2/py3 compatibility
from __future__ import print_function
import math
from optparse import OptionParser
import os
import re
import subprocess
import sys
import time
def GeometricMean(numbers):
log = sum([math.log(n) for n in numbers])
return math.pow(math.e, log / len(numbers))
class BenchmarkSuite(object):
def __init__(self, name):
self.name = name
self.results = {}
self.tests = []
self.memoryresults = []
self.nummemory = 0
self.avgresult = {}
self.sigmaresult = {}
self.numresult = {}
self.kClassicScoreSuites = ["SunSpider", "Kraken"]
self.kGeometricScoreSuites = ["Octane"]
def RecordResult(self, test, result):
if test not in self.tests:
self.tests += [test]
self.results[test] = []
self.results[test] += [int(result)]
def RecordMemory(self, result):
self.memoryresults += [int(result)]
def ThrowAwayWorstResult(self, results):
if len(results) <= 1: return
if self.name in self.kClassicScoreSuites:
results.pop()
elif self.name in self.kGeometricScoreSuites:
del results[0]
def ComputeResults(self, results):
if len(results) == 0:
return (0.0, 0.0, 0)
results.sort()
self.ThrowAwayWorstResult(results)
count = len(results)
mean = sum(results) * 1.0 / count
sigma = math.sqrt(sum(
(x - mean)**2 for x in results) / (count - 1)) if count > 1 else 0.0
return (mean, sigma, count)
def ProcessResults(self, opts):
for test in self.tests:
(self.avgresult[test], self.sigmaresult[test],
self.numresult[test]) = self.ComputeResults(self.results[test])
if opts.verbose:
if not test in ["Octane"]:
print("%s,%.1f,%.2f,%d" %
(test, self.avgresult[test],
self.sigmaresult[test], self.numresult[test]))
def ProcessMemory(self):
if (len(self.memoryresults)) == 0:
return
(self.avgmemory, self.sigmamemory,
self.nummemory) = self.ComputeResults(self.memoryresults)
def ComputeScoreGeneric(self):
self.score = 0
self.sigma = 0
for test in self.tests:
self.score += self.avgresult[test]
self.sigma += self.sigmaresult[test]
self.num = self.numresult[test]
def ComputeScoreV8Octane(self, name):
# The score for the run is stored with the form
# "Octane-octane2.1(Score): <score>"
found_name = ''
for s in self.avgresult.keys():
if re.search("^Octane", s):
found_name = s
break
self.score = self.avgresult[found_name]
self.sigma = 0
for test in self.tests:
self.sigma += self.sigmaresult[test]
self.num = self.numresult[test]
self.sigma /= len(self.tests)
def ComputeScore(self):
if self.name in self.kClassicScoreSuites:
self.ComputeScoreGeneric()
elif self.name in self.kGeometricScoreSuites:
self.ComputeScoreV8Octane(self.name)
else:
print("Don't know how to compute score for suite: '%s'" % self.name)
def IsBetterThan(self, other):
if self.name in self.kClassicScoreSuites:
return self.score < other.score
elif self.name in self.kGeometricScoreSuites:
return self.score > other.score
else:
print("Don't know how to compare score for suite: '%s'" % self.name)
class BenchmarkRunner(object):
def __init__(self, args, current_directory, opts):
self.best = {}
self.second_best = {}
self.args = args
self.opts = opts
self.current_directory = current_directory
self.outdir = os.path.join(opts.cachedir, "_benchmark_runner_data")
def Run(self):
if not os.path.exists(self.outdir):
os.mkdir(self.outdir)
self.RunCommand()
# Figure out the suite from the command line (heuristic) or the current
# working directory.
teststr = opts.command.lower() + " " + self.current_directory.lower()
if teststr.find('octane') >= 0:
suite = 'Octane'
elif teststr.find('sunspider') >= 0:
suite = 'SunSpider'
elif teststr.find('kraken') >= 0:
suite = 'Kraken'
else:
suite = 'Generic'
self.ProcessOutput(suite)
def RunCommand(self):
for i in range(self.opts.runs):
outfile = "%s/out.%d.txt" % (self.outdir, i)
if os.path.exists(outfile) and not self.opts.force:
continue
print("run #%d" % i)
cmdline = "%s > %s" % (self.opts.command, outfile)
subprocess.call(cmdline, shell=True)
time.sleep(self.opts.sleep)
def ProcessLine(self, line):
# Octane puts this line in before score.
if line == "----":
return (None, None)
# Retrieve peak memory usage if available
g = re.match("System peak.*: (?P<peak_memory>\d+)", line)
if g != None:
return ("memory", g.group('peak_memory'))
# Kraken or Sunspider?
g = re.match("(?P<test_name>\w+(-\w+)*)\(RunTime\): (?P<score>\d+) ms\.", \
line)
if g is None:
# Octane?
g = re.match("(?P<test_name>\w+): (?P<score>\d+)", line)
if g is None:
g = re.match("Score \(version [0-9]+\): (?P<score>\d+)", line)
if g is not None:
return ('Octane', g.group('score'))
else:
# Generic?
g = re.match("(?P<test_name>\w+)\W+(?P<score>\d+)", line)
if g is None:
return (None, None)
return (g.group('test_name'), g.group('score'))
def ProcessOutput(self, suitename):
suite = BenchmarkSuite(suitename)
for i in range(self.opts.runs):
outfile = "%s/out.%d.txt" % (self.outdir, i)
with open(outfile, 'r') as f:
for line in f:
(test, result) = self.ProcessLine(line)
if test is not None:
if test == "memory":
suite.RecordMemory(result)
else:
suite.RecordResult(test, result)
suite.ProcessResults(self.opts)
suite.ProcessMemory()
suite.ComputeScore()
if suite.nummemory > 0:
print(("PeakMemory,%.1f,%.2f,%d " %
(suite.avgmemory, suite.sigmamemory, suite.nummemory)))
print(("%s,%.1f,%.2f,%d " %
(suite.name, suite.score, suite.sigma, suite.num)), end='')
if self.opts.verbose:
print("")
print("")
if __name__ == '__main__':
parser = OptionParser(usage=__doc__)
parser.add_option("-c", "--command", dest="command",
help="Command to run the test suite.")
parser.add_option("-r", "--runs", dest="runs", default=4,
help="Number of runs")
parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
default=False, help="Print results for each test")
parser.add_option("-f", "--force", dest="force", action="store_true",
default=False,
help="Force re-run even if output files exist")
parser.add_option("-z", "--sleep", dest="sleep", default=0,
help="Number of seconds to sleep between runs")
parser.add_option("-d", "--run-directory", dest="cachedir",
help="Directory where a cache directory will be created")
(opts, args) = parser.parse_args()
opts.runs = int(opts.runs)
opts.sleep = int(opts.sleep)
if not opts.command:
print("You must specify the command to run (-c). Aborting.")
sys.exit(1)
cachedir = os.path.abspath(os.getcwd())
if not opts.cachedir:
opts.cachedir = cachedir
if not os.path.exists(opts.cachedir):
print("Directory " + opts.cachedir + " is not valid. Aborting.")
sys.exit(1)
br = BenchmarkRunner(args, os.getcwd(), opts)
br.Run()

View File

@ -0,0 +1,267 @@
#!/usr/bin/python3
# Copyright 2018 the V8 project authors. All rights reserved.
'''
python %prog [options] [baseline_files]
Compare benchmark results from the benchmark runner against one or
more baselines. You can either pipe the result of the benchmark
runner directly into this script or specify the results file with
the -f option.
'''
# for py2/py3 compatibility
from __future__ import print_function
import csv
import math
from optparse import OptionParser
import os
import sys
PERCENT_CONSIDERED_SIGNIFICANT = 0.5
PROBABILITY_CONSIDERED_SIGNIFICANT = 0.02
PROBABILITY_CONSIDERED_MEANINGLESS = 0.05
RESET_SEQ = "\033[0m"
RED_SEQ = "\033[31m"
GREEN_SEQ = "\033[32m"
BLUE_SEQ = "\033[34m"
BOLD_SEQ = "\033[1m"
v8_benchmarks = ["V8", "Octane", "Richards", "DeltaBlue", "Crypto",
"EarleyBoyer", "RayTrace", "RegExp", "Splay", "SplayLatency",
"NavierStokes", "PdfJS", "Mandreel", "MandreelLatency",
"Gameboy", "CodeLoad", "Box2D", "zlib", "Typescript"]
suite_names = ["V8", "Octane", "Kraken-Orig", "Kraken-Once", "Kraken",
"SunSpider", "SunSpider-Once", "SunSpider-Orig"]
def ColorText(opts, text):
if opts.no_color:
result = text.replace("$RESET", "")
result = result.replace("$BLUE", "")
result = result.replace("$RED", "")
result = result.replace("$GREEN", "")
result = result.replace("$BOLD", "")
else:
if opts.html:
result = text.replace("$RESET", "</font></b>")
result = result.replace("$BLUE", "<font COLOR=\"0000DD\">")
result = result.replace("$RED", "<font COLOR=\"DD0000\">")
result = result.replace("$GREEN", "<font COLOR=\"00DD00\">")
result = result.replace("$BOLD", "<b>")
else:
result = text.replace("$RESET", RESET_SEQ)
result = result.replace("$BLUE", BLUE_SEQ)
result = result.replace("$RED", RED_SEQ)
result = result.replace("$GREEN", GREEN_SEQ)
result = result.replace("$BOLD", BOLD_SEQ)
return result
def NormalizedSigmaToString(normalized_sigma):
assert normalized_sigma >= 0
if normalized_sigma < PROBABILITY_CONSIDERED_SIGNIFICANT:
return "|"
return "S"
def ComputeZ(baseline_avg, baseline_sigma, mean, n):
if baseline_sigma == 0:
return 1000.0;
return abs((mean - baseline_avg) / (baseline_sigma / math.sqrt(n)))
# Values from http://www.fourmilab.ch/rpkp/experiments/analysis/zCalc.html
def ComputeProbability(z):
if z > 2.575829: # p 0.005: two sided < 0.01
return 0
if z > 2.326348: # p 0.010
return 0.01
if z > 2.170091: # p 0.015
return 0.02
if z > 2.053749: # p 0.020
return 0.03
if z > 1.959964: # p 0.025: two sided < 0.05
return 0.04
if z > 1.880793: # p 0.030
return 0.05
if z > 1.811910: # p 0.035
return 0.06
if z > 1.750686: # p 0.040
return 0.07
if z > 1.695397: # p 0.045
return 0.08
if z > 1.644853: # p 0.050: two sided < 0.10
return 0.09
if z > 1.281551: # p 0.100: two sided < 0.20
return 0.10
return 0.20 # two sided p >= 0.20
def PercentColor(change_percent, flakyness):
result = ""
if change_percent >= PERCENT_CONSIDERED_SIGNIFICANT:
result = "$GREEN"
elif change_percent <= -PERCENT_CONSIDERED_SIGNIFICANT:
result = "$RED"
else:
return ""
if flakyness < PROBABILITY_CONSIDERED_SIGNIFICANT:
result += "$BOLD"
elif flakyness > PROBABILITY_CONSIDERED_MEANINGLESS:
result = ""
return result
def ProcessOneResultLine(opts, suite, testname, time, sigma, num, baselines):
time = float(time)
sigma = float(sigma)
num = int(num)
if testname in suite_names:
base_color = "$BOLD"
else:
base_color = ""
if opts.html:
line_out = ("<tr><td>%s%s$RESET</td><td>%s%8.1f$RESET</td>" %
(base_color, testname, base_color, time))
else:
sigma_string = NormalizedSigmaToString(sigma / time)
line_out = ("%s%40s$RESET: %s%8.1f$RESET %s" %
(base_color, testname, base_color, time, sigma_string))
for baseline in baselines:
raw_score = ""
compare_score = ""
found = False
if suite in baseline[1]:
baseline_results = baseline[1][suite]
for item in baseline_results:
if testname == item[0]:
found = True
raw_score_num = float(item[1])
raw_sigma_num = float(item[2])
raw_score = "%7.1f" % raw_score_num
compare_num = 0
compare_score = ""
percent_color = ""
if testname in v8_benchmarks:
compare_num = 100*time/raw_score_num - 100
else:
compare_num = 100*raw_score_num/time - 100
if abs(compare_num) > 0.1:
compare_score = "%3.1f" % (compare_num)
z = ComputeZ(raw_score_num, raw_sigma_num, time, num)
p = ComputeProbability(z)
percent_color = PercentColor(compare_num, p)
sigma_string = NormalizedSigmaToString(raw_sigma_num / raw_score_num)
if opts.html:
format_string = "<td>%s%8s$RESET</td><td>%s%6s$RESET</td>"
else:
format_string = " %s%8s$RESET %s %s%6s$RESET |"
line_out += (format_string %
(base_color, raw_score, sigma_string,
percent_color, compare_score))
if not found:
if opts.html:
line_out += "<td></td><td></td>"
else:
line_out += "| | "
if opts.html:
line_out += "</tr>"
print(ColorText(opts, line_out))
def PrintSeparator(opts, baselines, big):
if not opts.html:
if big:
separator = "==================================================="
else:
separator = "---------------------------------------------------"
for baseline in baselines:
if big:
separator += "+==========+========"
else:
separator += "+----------+--------"
separator += "+"
print(separator)
def ProcessResults(opts, results, baselines):
for suite in suite_names:
if suite in results:
for result in results[suite]:
ProcessOneResultLine(opts, suite, result[0], result[1], result[2],
result[3], baselines);
PrintSeparator(opts, baselines, False)
def ProcessFile(file_path):
file_reader = csv.reader(open(file_path, 'r'), delimiter=',')
benchmark_results = {}
current_rows = []
for row in file_reader:
if len(row) > 1:
current_rows.append(row)
for suite in suite_names:
if row[0] == suite:
benchmark_results[row[0]] = current_rows
current_rows = []
return benchmark_results
def ProcessStdIn():
benchmark_results = {}
current_rows = []
for line_in in sys.stdin:
line_in = line_in.rstrip()
row = line_in.split(",")
if len(row) > 1:
current_rows.append(row)
for suite in suite_names:
if row[0] == suite:
benchmark_results[row[0]] = current_rows
current_rows = []
return benchmark_results
def CompareFiles(opts, args):
results = []
baselines = []
for file_path in args:
baseline = ProcessFile(file_path)
baselines.append((os.path.basename(file_path), baseline))
if opts.html:
header = "<tr><th>benchmark</th><th>score</th>"
else:
header = "%40s: %8s " % ("benchmark", "score")
for baseline in baselines:
(baseline_name, baseline_results) = baseline
if opts.html:
header += ("<th>%s</th><th>%s</th>") % (baseline_name[0:7], "%")
else:
header += "| %8s | %6s " % (baseline_name[0:7], "%")
if opts.html:
header += "</tr>\n"
else:
header += "|"
print(header)
PrintSeparator(opts, baselines, True)
if opts.filename:
file_reader = csv.reader(open(opts.filename, 'rb'), delimiter=',')
results = ProcessFile(opts.filename)
else:
results = ProcessStdIn()
ProcessResults(opts, results, baselines)
if __name__ == '__main__':
parser = OptionParser(usage=__doc__)
parser.add_option("-f", "--filename", dest="filename",
help="Specifies the filename for the results to "\
"compare to the baselines rather than reading from stdin.")
parser.add_option("-b", "--baselines", dest="baselines",
help="Specifies a directory of baseline files to "\
"compare against.")
parser.add_option("-n", "--no-color", action="store_true",
dest="no_color", default=False,
help="Generates output without escape codes that "\
"add color highlights.")
parser.add_option("--html", action="store_true",
dest="html", default=False,
help="Generates output as a HTML table ")
(opts, args) = parser.parse_args()
if opts.baselines:
args.extend(map(lambda x: (opts.baselines + "/" + x),
(os.listdir(opts.baselines))))
args = reversed(sorted(args))
CompareFiles(opts, args)

174
deps/v8/test/benchmarks/csuite/csuite.py vendored Executable file
View File

@ -0,0 +1,174 @@
#!/usr/bin/python3
# Copyright 2018 the V8 project authors. All rights reserved.
'''
C S u i t e because who can remember?
-----------------------------------------------------------------------------
python csuite.py [options] <benchmark> <mode> <d8 path>
Arguments
benchmark: one of octane, sunspider or kraken.
mode: baseline or compare.
d8 path: a valid path to the d8 executable you want to use.
CSuite is a wrapper around benchmark.py and compare-baseline.py, old
friends in the d8 benchmarking world. Unlike those tools, it can be
run in any directory. It's also opinionated about which benchmarks it
will run, currently SunSpider, Octane and Kraken. Furthermore, it
runs the versions we pull into ./test/benchmarks/data.
Examples:
Say you want to see how much optimization buys you:
./csuite.py kraken baseline ~/src/v8/out/d8 -x="--noturbofan"
./csuite.py kraken compare ~/src/v8/out/d8
Suppose you are comparing two binaries, quick n' dirty style:
./csuite.py -r 3 octane baseline ~/src/v8/out-master/d8
./csuite.py -r 3 octane compare ~/src/v8/out-mine/d8
You can run from any place:
../../somewhere-strange/csuite.py sunspider baseline ./d8
../../somewhere-strange/csuite.py sunspider compare ./d8-better
'''
# for py2/py3 compatibility
from __future__ import print_function
import os
from optparse import OptionParser
import subprocess
import sys
if __name__ == '__main__':
parser = OptionParser(usage=__doc__)
parser.add_option("-r", "--runs", dest="runs",
help="Override the default number of runs for the benchmark.")
parser.add_option("-x", "--extra-arguments", dest="extra_args",
help="Pass these extra arguments to d8.")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
help="See more output about what magic csuite is doing.")
parser.add_option(
"-m",
"--memory",
action="store_true",
dest="memory",
help="Measure system memory usage.")
(opts, args) = parser.parse_args()
if len(args) < 3:
print('not enough arguments')
sys.exit(1)
suite = args[0]
mode = args[1]
if suite not in ['octane', 'sunspider', 'kraken']:
print('Suite must be octane, sunspider or kraken. Aborting.')
sys.exit(1)
if mode != 'baseline' and mode != 'compare':
print('mode must be baseline or compare. Aborting.')
sys.exit(1)
# Set up paths.
d8_path = os.path.abspath(args[2])
if not os.path.exists(d8_path):
print(d8_path + " is not valid.")
sys.exit(1)
csuite_path = os.path.dirname(os.path.abspath(__file__))
if not os.path.exists(csuite_path):
print("The csuite directory is invalid.")
sys.exit(1)
benchmark_py_path = os.path.join(csuite_path, "benchmark.py")
if not os.path.exists(benchmark_py_path):
print("Unable to find benchmark.py in " + csuite_path \
+ ". Aborting.")
sys.exit(1)
compare_baseline_py_path = os.path.join(csuite_path,
"compare-baseline.py")
if not os.path.exists(compare_baseline_py_path):
print("Unable to find compare-baseline.py in " + csuite_path \
+ ". Aborting.")
sys.exit(1)
benchmark_path = os.path.abspath(os.path.join(csuite_path, "../data"))
if not os.path.exists(benchmark_path):
print("I can't find the benchmark data directory. Aborting.")
sys.exit(1)
# Gather the remaining arguments into a string of extra args for d8.
extra_args = ""
if opts.extra_args:
extra_args = opts.extra_args
if opts.memory:
extra_args += " --dump-system-memory-stats"
if suite == "octane":
runs = 10
suite_path = os.path.join(benchmark_path, "octane")
cmd = "run.js"
elif suite == "kraken":
runs = 80
suite_path = os.path.join(benchmark_path, "kraken")
cmd = os.path.join(csuite_path, "run-kraken.js")
else:
runs = 100
suite_path = os.path.join(benchmark_path, "sunspider")
cmd = os.path.join(csuite_path, "sunspider-standalone-driver.js")
if opts.runs:
if (float(opts.runs) / runs) < 0.6:
print("Normally, %s requires %d runs to get stable results." \
% (suite, runs))
runs = int(opts.runs)
if opts.verbose:
print("Running and averaging %s %d times." % (suite, runs))
# Ensure output directory is setup
output_path_base = os.path.abspath(os.getcwd())
output_path = os.path.join(output_path_base, "_results")
output_file = os.path.join(output_path, "master_" + suite)
if not os.path.exists(output_path):
if opts.verbose:
print("Creating directory %s." % output_path)
os.mkdir(output_path)
if opts.verbose:
print("Working directory for runs is %s." % suite_path)
inner_command = " -c \"%s --expose-gc %s %s \"" \
% (d8_path, extra_args, cmd)
if opts.verbose:
print("calling d8 like so: %s." % inner_command)
cmdline_base = "python %s %s -fv -r %d -d %s" \
% (benchmark_py_path, inner_command, runs, output_path_base)
if mode == "baseline":
cmdline = "%s > %s" % (cmdline_base, output_file)
else:
output_file_compare = output_file + "_compare"
cmdline = "%s > %s" % (cmdline_base, output_file_compare)
if opts.verbose:
print("Spawning subprocess: %s." % cmdline)
return_code = subprocess.call(cmdline, shell=True, cwd=suite_path)
if return_code < 0:
print("Error return code: %d." % return_code)
if mode == "baseline":
print("Wrote %s." % output_file)
print("Run %s again with compare mode to see results." % suite)
else:
print("Wrote %s." % output_file_compare)
cmdline = "python %s %s -f %s" % (compare_baseline_py_path, output_file, output_file_compare)
if opts.verbose:
print("Spawning subprocess: %s." % cmdline)
return_code = subprocess.call(cmdline, shell=True, cwd=suite_path)
if return_code < 0:
print("Error return code: %d." % return_code)

View File

@ -0,0 +1,63 @@
// Copyright 2018 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file was copied from the output of
// http://hg.mozilla.org/projects/kraken/sunspider script.
var benchmarkPath = "";
var tests = [ "ai-astar", "audio-beat-detection", "audio-dft", "audio-fft", "audio-oscillator", "imaging-gaussian-blur", "imaging-darkroom", "imaging-desaturate", "json-parse-financial", "json-stringify-tinderbox", "stanford-crypto-aes", "stanford-crypto-ccm", "stanford-crypto-pbkdf2", "stanford-crypto-sha256-iterative" ];
var categories = [ "ai", "audio", "imaging", "json", "stanford" ];
var results = new Array();
var time = 0;
var times = [];
times.length = tests.length;
for (var krakenCounter = 0; krakenCounter < tests.length; krakenCounter++) {
var testBase = benchmarkPath + tests[krakenCounter];
var testName = testBase + ".js";
var testData = testBase + "-data.js";
// load test data
d8.file.execute(testData);
var startTime = new Date;
d8.file.execute(testName);
times[krakenCounter] = new Date() - startTime;
gc();
}
function recordResults(tests, times)
{
var output = "";
for (j = 0; j < tests.length; j++) {
output += tests[j] + '-orig(RunTime): ' + times[j] + ' ms.\n';
}
print(output);
}
recordResults(tests, times);

View File

@ -0,0 +1,75 @@
// Copyright 2018 the V8 project authors. All rights reserved.
/*
* Copyright (C) 2007 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var suitePath = "sunspider-0.9.1";
var tests = [ "3d-cube", "3d-morph", "3d-raytrace",
"access-binary-trees", "access-fannkuch",
"access-nbody", "access-nsieve",
"bitops-3bit-bits-in-byte", "bitops-bits-in-byte",
"bitops-bitwise-and", "bitops-nsieve-bits",
"controlflow-recursive", "crypto-aes",
"crypto-md5", "crypto-sha1", "date-format-tofte",
"date-format-xparb", "math-cordic", "math-partial-sums",
"math-spectral-norm", "regexp-dna", "string-base64",
"string-fasta", "string-tagcloud", "string-unpack-code",
"string-validate-input" ];
var categories = [ "3d", "access", "bitops", "controlflow", "crypto",
"date", "math", "regexp", "string" ];
var results = new Array();
(function(){
var time = 0;
var times = [];
times.length = tests.length;
for (var j = 0; j < tests.length; j++) {
var testName = tests[j] + ".js";
var startTime = new Date;
if (testName.indexOf('parse-only') >= 0)
checkSyntax(testName);
else
d8.file.execute(testName);
times[j] = new Date() - startTime;
gc();
}
function recordResults(tests, times)
{
var output = "";
// Changed original output to match test infrastructure.
for (j = 0; j < tests.length; j++) {
output += tests[j] + '-sunspider(RunTime): ' +
Math.max(times[j], 1) + ' ms.\n';
}
print(output);
}
recordResults(tests, times);
})();

137
deps/v8/test/benchmarks/testcfg.py vendored Normal file
View File

@ -0,0 +1,137 @@
# Copyright 2013 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import shutil
from testrunner.local import statusfile
from testrunner.local import testsuite
from testrunner.objects import testcase
class TestLoader(testsuite.TestLoader):
def _list_test_filenames(self):
return [
"kraken/ai-astar",
"kraken/audio-beat-detection",
"kraken/audio-dft",
"kraken/audio-fft",
"kraken/audio-oscillator",
"kraken/imaging-darkroom",
"kraken/imaging-desaturate",
"kraken/imaging-gaussian-blur",
"kraken/json-parse-financial",
"kraken/json-stringify-tinderbox",
"kraken/stanford-crypto-aes",
"kraken/stanford-crypto-ccm",
"kraken/stanford-crypto-pbkdf2",
"kraken/stanford-crypto-sha256-iterative",
"octane/box2d",
"octane/code-load",
"octane/crypto",
"octane/deltablue",
"octane/earley-boyer",
"octane/gbemu-part1",
"octane/mandreel",
"octane/navier-stokes",
"octane/pdfjs",
"octane/raytrace",
"octane/regexp",
"octane/richards",
"octane/splay",
"octane/typescript",
"octane/zlib",
"sunspider/3d-cube",
"sunspider/3d-morph",
"sunspider/3d-raytrace",
"sunspider/access-binary-trees",
"sunspider/access-fannkuch",
"sunspider/access-nbody",
"sunspider/access-nsieve",
"sunspider/bitops-3bit-bits-in-byte",
"sunspider/bitops-bits-in-byte",
"sunspider/bitops-bitwise-and",
"sunspider/bitops-nsieve-bits",
"sunspider/controlflow-recursive",
"sunspider/crypto-aes",
"sunspider/crypto-md5",
"sunspider/crypto-sha1",
"sunspider/date-format-tofte",
"sunspider/date-format-xparb",
"sunspider/math-cordic",
"sunspider/math-partial-sums",
"sunspider/math-spectral-norm",
"sunspider/regexp-dna",
"sunspider/string-base64",
"sunspider/string-fasta",
"sunspider/string-tagcloud",
"sunspider/string-unpack-code",
"sunspider/string-validate-input",
]
class TestSuite(testsuite.TestSuite):
def __init__(self, ctx, *args, **kwargs):
super(TestSuite, self).__init__(ctx, *args, **kwargs)
self.testroot = self.root / "data"
def _test_loader_class(self):
return TestLoader
def _test_class(self):
return TestCase
class TestCase(testcase.D8TestCase):
def _get_files_params(self):
path = self.path
testroot = self.suite.testroot
files = []
if path.parts[0] == "kraken":
files.append(testroot / f"{path}-data.js")
files.append(testroot / f"{path}.js")
elif path.parts[0] == "octane":
files.append(testroot / "octane/base.js")
files.append(testroot / f"{path}.js")
if path.parts[1] == "gbemu":
files.append(testroot / "octane/gbemu-part2.js")
elif path.parts[1] == "typescript":
files.append(testroot / "octane/typescript-compiler.js")
files.append(testroot / "octane/typescript-input.js")
elif path.parts[1] == "zlib":
files.append(testroot / "octane/zlib-data.js")
files += ["-e", "BenchmarkSuite.RunSuites({});"]
elif path.parts[0] == "sunspider":
files.append(self._get_source_path())
return files
def _get_source_path(self):
return self.suite.testroot / self.path_js