Skip to content

Instantly share code, notes, and snippets.

@rluvaton
Last active October 9, 2023 15:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rluvaton/0a082d4168203cf2dd0a6aef0948d8d1 to your computer and use it in GitHub Desktop.
Save rluvaton/0a082d4168203cf2dd0a6aef0948d8d1 to your computer and use it in GitHub Desktop.
v8 embedding benchmark creating 1M of objects

Benchmarks

  • cpp-creating-objects.cpp: 2000ms
  • js-creating-objects.cpp: 17ms
  • js-creating-object-in-cpp.cpp: 1800ms
// Copyright 2015 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 <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctime>
#include <iostream>
#include <map>
#include <string>
#include "include/libplatform/libplatform.h"
#include "include/v8-array-buffer.h"
#include "include/v8-context.h"
#include "include/v8-exception.h"
#include "include/v8-external.h"
#include "include/v8-function.h"
#include "include/v8-initialization.h"
#include "include/v8-isolate.h"
#include "include/v8-local-handle.h"
#include "include/v8-object.h"
#include "include/v8-persistent-handle.h"
#include "include/v8-primitive.h"
#include "include/v8-script.h"
#include "include/v8-snapshot.h"
#include "include/v8-template.h"
#include "include/v8-value.h"
#include <chrono>
#include <iostream>
#include <thread>
using std::string;
using v8::ArrayBuffer;
using v8::Context;
using v8::EscapableHandleScope;
using v8::External;
using v8::Function;
using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::MaybeLocal;
using v8::Name;
using v8::NamedPropertyHandlerConfiguration;
using v8::NewStringType;
using v8::Object;
using v8::ObjectTemplate;
using v8::Persistent;
using v8::PropertyCallbackInfo;
using v8::Script;
using v8::String;
using v8::TryCatch;
using v8::V8;
using v8::Value;
using namespace std::chrono_literals;
template <class result_t = std::chrono::milliseconds,
class clock_t = std::chrono::steady_clock,
class duration_t = std::chrono::milliseconds>
auto since(std::chrono::time_point<clock_t, duration_t> const& start) {
return std::chrono::duration_cast<result_t>(clock_t::now() - start);
}
int main(int argc, char* argv[]) {
// Initialize V8.
V8::InitializeICUDefaultLocation(argv[0]);
V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
V8::InitializePlatform(platform.get());
V8::Initialize();
// Create a new Isolate and make it the current one.
Isolate::CreateParams create_params;
create_params.array_buffer_allocator =
ArrayBuffer::Allocator::NewDefaultAllocator();
Isolate* isolate = Isolate::New(create_params);
{
Isolate::Scope isolate_scope(isolate);
// Create a stack-allocated handle scope.
HandleScope handle_scope(isolate);
Local<Context> context = Context::New(isolate);
// Enter the context for compiling and running the hello world script.
Context::Scope context_scope(context);
Local<String> source =
String::NewFromUtf8Literal(isolate, "'Hello' + ', World!'");
// Compile the source code.
Local<Script> script = Script::Compile(context, source).ToLocalChecked();
// Run the script to get the result.
Local<Value> result = script->Run(context).ToLocalChecked();
auto start = std::chrono::steady_clock::now();
Local<Object> o;
for (int i = 0; i < 1000000; i++) {
o = Object::New(isolate);
Local<Name> a_name =
String::NewFromUtf8(isolate, "a", NewStringType::kNormal)
.ToLocalChecked();
Local<String> a_value =
String::NewFromUtf8(isolate, "hello", NewStringType::kNormal)
.ToLocalChecked();
o->Set(context, a_name, a_value);
Local<Name> b_name =
String::NewFromUtf8(isolate, "b", NewStringType::kNormal)
.ToLocalChecked();
Local<String> b_value =
String::NewFromUtf8(isolate, "world", NewStringType::kNormal)
.ToLocalChecked();
o->Set(context, b_name, b_value);
Local<Name> c_name =
String::NewFromUtf8(isolate, "c", NewStringType::kNormal)
.ToLocalChecked();
Local<v8::Integer> c_value = v8::Integer::New(isolate, 1);
o->Set(context, c_name, c_value);
if (o.IsEmpty()) {
printf("o is empty\n");
}
}
printf("Elapsed(ms)=%d\n", since(start).count());
printf("o %d\n", o.IsEmpty());
}
// Dispose the isolate and tear down V8.
isolate->Dispose();
V8::Dispose();
V8::DisposePlatform();
delete create_params.array_buffer_allocator;
return 0;
}
// Copyright 2015 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 <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <chrono>
#include <ctime>
#include <iostream>
#include <map>
#include <string>
#include <thread>
#include "include/libplatform/libplatform.h"
#include "include/v8-array-buffer.h"
#include "include/v8-context.h"
#include "include/v8-exception.h"
#include "include/v8-external.h"
#include "include/v8-function.h"
#include "include/v8-initialization.h"
#include "include/v8-isolate.h"
#include "include/v8-local-handle.h"
#include "include/v8-object.h"
#include "include/v8-persistent-handle.h"
#include "include/v8-primitive.h"
#include "include/v8-script.h"
#include "include/v8-snapshot.h"
#include "include/v8-template.h"
#include "include/v8-value.h"
using std::string;
using v8::ArrayBuffer;
using v8::Context;
using v8::EscapableHandleScope;
using v8::External;
using v8::Function;
using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::MaybeLocal;
using v8::Name;
using v8::NamedPropertyHandlerConfiguration;
using v8::NewStringType;
using v8::Object;
using v8::ObjectTemplate;
using v8::Persistent;
using v8::PropertyCallbackInfo;
using v8::Script;
using v8::String;
using v8::TryCatch;
using v8::V8;
using v8::Value;
void LogCallback(const v8::FunctionCallbackInfo<Value>& info) {
if (info.Length() < 1) return;
Isolate* isolate = info.GetIsolate();
HandleScope scope(isolate);
Local<Value> arg = info[0];
String::Utf8Value value(isolate, arg);
printf("Logged: %s\n", *value);
}
void CreateObjectCallback(const v8::FunctionCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
HandleScope scope(isolate);
Local<Value> arg = info[0];
Local<Context> context = info.GetIsolate()->GetCurrentContext();
Local<Object> o = Object::New(isolate);
Local<Name> a_name = String::NewFromUtf8(isolate, "a",
NewStringType::kNormal)
.ToLocalChecked();
Local<String> a_value =
String::NewFromUtf8(isolate, "hello", NewStringType::kNormal)
.ToLocalChecked();
o->Set(context, a_name, a_value);
Local<Name> b_name = String::NewFromUtf8(isolate, "b",
NewStringType::kNormal)
.ToLocalChecked();
Local<String> b_value =
String::NewFromUtf8(isolate, "world", NewStringType::kNormal)
.ToLocalChecked();
o->Set(context, b_name, b_value);
Local<Name> c_name = String::NewFromUtf8(isolate, "c",
NewStringType::kNormal)
.ToLocalChecked();
Local<v8::Integer> c_value = v8::Integer::New(isolate, 1);
o->Set(context, c_name, c_value);
info.GetReturnValue().Set(o);
}
Local<Context> setupGlobals(Isolate* isolate) {
// Create a template for the global object and set the
// built-in global functions.
Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
global->Set(String::NewFromUtf8(isolate, "log").ToLocalChecked(),
FunctionTemplate::New(isolate, LogCallback));
global->Set(String::NewFromUtf8(isolate, "createObject").ToLocalChecked(),
FunctionTemplate::New(isolate, CreateObjectCallback),
v8::PropertyAttribute::ReadOnly);
// Create a new context.
return Context::New(isolate, nullptr, global);
}
int main(int argc, char* argv[]) {
// Initialize V8.
// V8::SetFlagsFromString("--log-all");
V8::InitializeICUDefaultLocation(argv[0]);
V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
V8::InitializePlatform(platform.get());
V8::Initialize();
// Create a new Isolate and make it the current one.
Isolate::CreateParams create_params;
create_params.array_buffer_allocator =
ArrayBuffer::Allocator::NewDefaultAllocator();
Isolate* isolate = Isolate::New(create_params);
{
Isolate::Scope isolate_scope(isolate);
// Create a stack-allocated handle scope.
HandleScope handle_scope(isolate);
Local<Context> context = setupGlobals(isolate);
// Enter the context for compiling and running the hello world script.
Context::Scope context_scope(context);
const char* source_raw =
"\
const start = Date.now(); \
let obj; \
for (let i = 0; i < 1_000_000; i++) { \
obj = createObject(); \
} \
if (!obj) { \
throw new Error(\"obj is null\"); \
} \
\
log(`elapsed ms ${Date.now() - start}`);";
Local<String> source =
String::NewFromUtf8(isolate, source_raw, NewStringType::kNormal)
.ToLocalChecked();
{
// Compile the source code.
Local<Script> script = Script::Compile(context, source).ToLocalChecked();
// Run the script to get the result.
Local<Value> result = script->Run(context).ToLocalChecked();
// Convert the result to an UTF8 string and print it.
String::Utf8Value utf8(isolate, result);
printf("%s\n", *utf8);
}
}
// Dispose the isolate and tear down V8.
isolate->Dispose();
V8::Dispose();
V8::DisposePlatform();
delete create_params.array_buffer_allocator;
return 0;
}
// Copyright 2015 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 <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <chrono>
#include <ctime>
#include <iostream>
#include <map>
#include <string>
#include <thread>
#include "include/libplatform/libplatform.h"
#include "include/v8-array-buffer.h"
#include "include/v8-context.h"
#include "include/v8-exception.h"
#include "include/v8-external.h"
#include "include/v8-function.h"
#include "include/v8-initialization.h"
#include "include/v8-isolate.h"
#include "include/v8-local-handle.h"
#include "include/v8-object.h"
#include "include/v8-persistent-handle.h"
#include "include/v8-primitive.h"
#include "include/v8-script.h"
#include "include/v8-snapshot.h"
#include "include/v8-template.h"
#include "include/v8-value.h"
using std::string;
using v8::ArrayBuffer;
using v8::Context;
using v8::EscapableHandleScope;
using v8::External;
using v8::Function;
using v8::FunctionTemplate;
using v8::Global;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::MaybeLocal;
using v8::Name;
using v8::NamedPropertyHandlerConfiguration;
using v8::NewStringType;
using v8::Object;
using v8::ObjectTemplate;
using v8::Persistent;
using v8::PropertyCallbackInfo;
using v8::Script;
using v8::String;
using v8::TryCatch;
using v8::V8;
using v8::Value;
void LogCallback(const v8::FunctionCallbackInfo<Value>& info) {
if (info.Length() < 1) return;
Isolate* isolate = info.GetIsolate();
HandleScope scope(isolate);
Local<Value> arg = info[0];
String::Utf8Value value(isolate, arg);
printf("Logged: %s\n", *value);
}
Local<Context> setupGlobals(Isolate* isolate) {
// Create a template for the global object and set the
// built-in global functions.
Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
global->Set(String::NewFromUtf8(isolate, "log").ToLocalChecked(),
FunctionTemplate::New(isolate, LogCallback));
// Create a new context.
return Context::New(isolate, nullptr, global);
}
int main(int argc, char* argv[]) {
// Initialize V8.
// V8::SetFlagsFromString("--log-all");
V8::InitializeICUDefaultLocation(argv[0]);
V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
V8::InitializePlatform(platform.get());
V8::Initialize();
// Create a new Isolate and make it the current one.
Isolate::CreateParams create_params;
create_params.array_buffer_allocator =
ArrayBuffer::Allocator::NewDefaultAllocator();
Isolate* isolate = Isolate::New(create_params);
{
Isolate::Scope isolate_scope(isolate);
// Create a stack-allocated handle scope.
HandleScope handle_scope(isolate);
Local<Context> context = setupGlobals(isolate);
// Enter the context for compiling and running the hello world script.
Context::Scope context_scope(context);
const char* source_raw =
"\
const start = Date.now(); \
let obj; \
for (let i = 0; i < 1_000_000; i++) { \
obj = {}; \
obj.a = \"hello\"; \
obj.b = \"world\"; \
obj.c = 1; \
} \
if (!obj) { \
throw new Error(\"obj is null\"); \
} \
\
log(`elapsed ms ${Date.now() - start}`);";
Local<String> source =
String::NewFromUtf8(isolate, source_raw, NewStringType::kNormal)
.ToLocalChecked();
{
// Compile the source code.
Local<Script> script = Script::Compile(context, source).ToLocalChecked();
// Run the script to get the result.
Local<Value> result = script->Run(context).ToLocalChecked();
// Convert the result to an UTF8 string and print it.
String::Utf8Value utf8(isolate, result);
printf("%s\n", *utf8);
}
}
// Dispose the isolate and tear down V8.
isolate->Dispose();
V8::Dispose();
V8::DisposePlatform();
delete create_params.array_buffer_allocator;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment