1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-26 16:09:27 -05:00

Optimize compile time by using asm.

Switches to using asm incbin to embed the V8 snapshot instead of
outputing C code and then compiling it.

Compile time for from_snapshot.o goes from 44s to 1s.
This commit is contained in:
Ryan Dahl 2018-07-26 23:21:10 -04:00
parent db8dc0e9f8
commit 6b6fac209c
7 changed files with 38 additions and 96 deletions

View file

@ -107,6 +107,12 @@ static_library("libdeno") {
sources = [
"src/from_snapshot.cc",
]
data = [
"$target_gen_dir/snapshot_deno.bin",
]
data_deps = [
":bundle",
]
deps = [
":create_snapshot_deno",
":deno_bindings",
@ -139,6 +145,9 @@ v8_source_set("deno_base_test") {
"src/from_snapshot.cc",
"src/mock_runtime_test.cc",
]
data = [
"$target_gen_dir/snapshot_mock_runtime.bin",
]
deps = [
":create_snapshot_mock_runtime",
":deno_base",

View file

@ -28,15 +28,15 @@ template("create_snapshot") {
])
tool = ":snapshot_creator"
visibility = [ ":*" ] # Only targets in this file can depend on this.
snapshot_out_cc = "$target_gen_dir/snapshot_$name.cc"
snapshot_out_bin = "$target_gen_dir/snapshot_$name.bin"
inputs = [
invoker.js,
]
outputs = [
snapshot_out_cc,
snapshot_out_bin,
]
args = [
rebase_path(snapshot_out_cc, root_build_dir),
rebase_path(snapshot_out_bin, root_build_dir),
rebase_path(invoker.js, root_build_dir),
]

View file

@ -9,28 +9,6 @@
namespace deno {
std::string BinaryContentAsC(const char* name, const std::string& data) {
char b[512];
std::string output;
// Write prefix.
snprintf(b, sizeof(b), "static const char %s_data[] = {\n", name);
output.append(b);
// Write actual data.
for (size_t i = 0; i < data.size(); ++i) {
if ((i & 0x1F) == 0x1F) output.append("\n");
if (i > 0) output.append(",");
snprintf(b, sizeof(b), "%hhu", static_cast<unsigned char>(data.at(i)));
output.append(b);
}
output.append("\n");
// Write suffix.
output.append("};\n");
snprintf(b, sizeof(b), "static const int %s_size = %" PRId64 ";\n", name,
static_cast<uint64_t>(data.size()));
output.append(b);
return output;
}
bool ReadFileToString(const char* fn, std::string* contents) {
std::ifstream file(fn, std::ios::binary);
if (file.fail()) {

View file

@ -7,7 +7,6 @@
namespace deno {
bool ReadFileToString(const char* fn, std::string* contents);
std::string Basename(std::string const& filename);
std::string BinaryContentAsC(const char* name, const std::string& data);
} // namespace deno
#endif // FILE_UTIL_H_

View file

@ -17,12 +17,5 @@ TEST(FileUtilTest, Basename) {
EXPECT_EQ("foo.txt", deno::Basename("C:\\home\\ryan\\foo.txt"));
}
TEST(FileUtilTest, BinaryContentAsC) {
auto c_code = deno::BinaryContentAsC("aaa", std::string("bbb"));
EXPECT_TRUE(c_code.find("static const char aaa_data[]") != std::string::npos);
EXPECT_TRUE(c_code.find("static const int aaa_size = 3;") !=
std::string::npos);
}
// TODO(ry) success unit test. Needs a tempfile or fixture.
// TEST(FileUtilTest, ReadFileToStringSuccess) { }

View file

@ -10,11 +10,21 @@
#include "deno.h"
#include "internal.h"
extern const char deno_snapshot_start asm("deno_snapshot_start");
extern const char deno_snapshot_end asm("deno_snapshot_end");
#ifdef DENO_MOCK_RUNTIME
#include "snapshot_mock_runtime.cc"
asm(".data\n"
"deno_snapshot_start: .incbin \"gen/snapshot_mock_runtime.bin\"\n"
"deno_snapshot_end:\n"
".globl deno_snapshot_start;\n"
".globl deno_snapshot_end;");
#else
#include "snapshot_deno.cc"
#endif
asm(".data\n"
"deno_snapshot_start: .incbin \"gen/snapshot_deno.bin\"\n"
"deno_snapshot_end:\n"
".globl deno_snapshot_start;\n"
".globl deno_snapshot_end;");
#endif // DENO_MOCK_RUNTIME
namespace deno {
@ -42,7 +52,13 @@ Deno* NewFromSnapshot(void* data, deno_recv_cb cb) {
params.array_buffer_allocator =
v8::ArrayBuffer::Allocator::NewDefaultAllocator();
params.external_references = external_references;
params.snapshot_blob = StartupBlob_snapshot();
CHECK_NE(&deno_snapshot_start, nullptr);
int snapshot_len =
static_cast<int>(&deno_snapshot_end - &deno_snapshot_start);
static v8::StartupData snapshot = {&deno_snapshot_start, snapshot_len};
params.snapshot_blob = &snapshot;
v8::Isolate* isolate = v8::Isolate::New(params);
AddIsolate(d, isolate);

View file

@ -40,72 +40,17 @@ v8::StartupData MakeSnapshot(const char* js_filename, const char* js_source) {
return snapshot_blob;
}
class StartupDataCppWriter {
public:
StartupDataCppWriter(const char* name, const char* filename,
const std::string& data)
: name_(name),
filename_(filename),
data_(data),
file_(filename_, std::ios::binary) {}
bool Write() {
if (file_.bad()) {
return false;
}
WritePrefix();
WriteData();
WriteSuffix();
file_.close();
// printf("Wrote %s %d %s \n", name_, data_.size(), filename_);
return !file_.bad();
}
private:
void WritePrefix() {
file_ << "// Autogenerated snapshot file. Do not edit.\n\n";
file_ << "#include \"third_party/v8/include/v8.h\"\n\n";
file_ << "namespace deno { \n\n";
}
void WriteSuffix() {
char buffer[500];
snprintf(buffer, sizeof(buffer), "v8::StartupData* StartupBlob_%s() {\n",
name_);
file_ << buffer;
snprintf(buffer, sizeof(buffer), " return &%s_blob;\n", name_);
file_ << buffer;
file_ << "}\n\n";
file_ << "} // namespace deno\n\n";
}
void WriteData() {
char buffer[500];
file_ << BinaryContentAsC(name_, data_);
snprintf(buffer, sizeof(buffer),
"static v8::StartupData %s_blob = { %s_data, %s_size };\n", name_,
name_, name_);
file_ << buffer;
}
const char* name_;
const char* filename_;
std::string data_;
std::ofstream file_;
};
} // namespace deno
int main(int argc, char** argv) {
const char* snapshot_out_cc = argv[1];
const char* snapshot_out_bin = argv[1];
const char* js_fn = argv[2];
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
CHECK_EQ(argc, 3);
CHECK_NE(js_fn, nullptr);
CHECK_NE(snapshot_out_cc, nullptr);
CHECK_NE(snapshot_out_bin, nullptr);
std::string js_source;
CHECK(deno::ReadFileToString(js_fn, &js_source));
@ -114,6 +59,8 @@ int main(int argc, char** argv) {
auto snapshot_blob = deno::MakeSnapshot(js_fn, js_source.c_str());
std::string snapshot_str(snapshot_blob.data, snapshot_blob.raw_size);
deno::StartupDataCppWriter writer("snapshot", snapshot_out_cc, snapshot_str);
CHECK(writer.Write());
std::ofstream file_(snapshot_out_bin, std::ios::binary);
file_ << snapshot_str;
file_.close();
return file_.bad();
}