Skip to content

Commit d21be77

Browse files
committed
src: back snapshot I/O with a std::vector sink
1 parent b8b92ca commit d21be77

File tree

1 file changed

+74
-55
lines changed

1 file changed

+74
-55
lines changed

src/node_snapshotable.cc

Lines changed: 74 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "node_snapshotable.h"
33
#include <iostream>
44
#include <sstream>
5+
#include <vector>
56
#include "base_object-inl.h"
67
#include "debug_utils-inl.h"
78
#include "env-inl.h"
@@ -135,11 +136,10 @@ std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) {
135136
return output;
136137
}
137138

138-
class FileIO {
139+
class SnapshotSerializerDeserializer {
139140
public:
140-
explicit FileIO(FILE* file)
141-
: f(file),
142-
is_debug(per_process::enabled_debug_list.enabled(
141+
SnapshotSerializerDeserializer()
142+
: is_debug(per_process::enabled_debug_list.enabled(
143143
DebugCategory::MKSNAPSHOT)) {}
144144

145145
template <typename... Args>
@@ -181,14 +181,14 @@ class FileIO {
181181
return name;
182182
}
183183

184-
FILE* f = nullptr;
185184
bool is_debug = false;
186185
};
187186

188-
class FileReader : public FileIO {
187+
class SnapshotDeserializer : public SnapshotSerializerDeserializer {
189188
public:
190-
explicit FileReader(FILE* file) : FileIO(file) {}
191-
~FileReader() {}
189+
explicit SnapshotDeserializer(const std::vector<char>* s)
190+
: SnapshotSerializerDeserializer(), sink(s) {}
191+
~SnapshotDeserializer() {}
192192

193193
// Helper for reading numeric types.
194194
template <typename T>
@@ -233,19 +233,19 @@ class FileReader : public FileIO {
233233

234234
CHECK_GT(length, 0); // There should be no empty strings.
235235
MallocedBuffer<char> buf(length + 1);
236-
size_t r = fread(buf.data, 1, length + 1, f);
237-
CHECK_EQ(r, length + 1);
236+
memcpy(buf.data, sink->data() + read_total, length + 1);
238237
std::string result(buf.data, length); // This creates a copy of buf.data.
239238

240239
if (is_debug) {
241-
Debug("\"%s\", read %d bytes\n", result.c_str(), r);
240+
Debug("\"%s\", read %zu bytes\n", result.c_str(), length + 1);
242241
}
243242

244-
read_total += r;
243+
read_total += length + 1;
245244
return result;
246245
}
247246

248247
size_t read_total = 0;
248+
const std::vector<char>* sink = nullptr;
249249

250250
private:
251251
// Helper for reading an array of numeric types.
@@ -258,15 +258,15 @@ class FileReader : public FileIO {
258258
Debug("Read<%s>()(%d-byte), count=%d: ", name.c_str(), sizeof(T), count);
259259
}
260260

261-
size_t r = fread(out, sizeof(T), count, f);
262-
CHECK_EQ(r, count);
261+
size_t size = sizeof(T) * count;
262+
memcpy(out, sink->data() + read_total, size);
263263

264264
if (is_debug) {
265265
std::string str =
266266
"{ " + std::to_string(out[0]) + (count > 1 ? ", ... }" : " }");
267-
Debug("%s, read %d bytes\n", str.c_str(), r);
267+
Debug("%s, read %zu bytes\n", str.c_str(), size);
268268
}
269-
read_total += r;
269+
read_total += size;
270270
}
271271

272272
// Helper for reading numeric vectors.
@@ -300,10 +300,15 @@ class FileReader : public FileIO {
300300
}
301301
};
302302

303-
class FileWriter : public FileIO {
303+
class SnapshotSerializer : public SnapshotSerializerDeserializer {
304304
public:
305-
explicit FileWriter(FILE* file) : FileIO(file) {}
306-
~FileWriter() {}
305+
SnapshotSerializer() : SnapshotSerializerDeserializer() {
306+
// Currently the snapshot blob built with an empty script is around 4MB.
307+
// So use that as the default sink size.
308+
sink.reserve(4 * 1024 * 1024);
309+
}
310+
~SnapshotSerializer() {}
311+
std::vector<char> sink;
307312

308313
// Helper for writing numeric types.
309314
template <typename T>
@@ -349,15 +354,15 @@ class FileWriter : public FileIO {
349354
size_t written_total = Write<size_t>(data.size());
350355
if (is_debug) {
351356
std::string str = ToStr(data);
352-
Debug("WriteString(), length=%d: \"%s\"\n", data.size(), data.c_str());
357+
Debug("WriteString(), length=%zu: \"%s\"\n", data.size(), data.c_str());
353358
}
354359

355-
size_t r = fwrite(data.c_str(), 1, data.size() + 1, f);
356-
CHECK_EQ(r, data.size() + 1);
357-
written_total += r;
360+
// Write the null-terminated string.
361+
sink.insert(sink.end(), data.c_str(), data.c_str() + data.size() + 1);
362+
written_total += data.size();
358363

359364
if (is_debug) {
360-
Debug("WriteString() wrote %d bytes\n", written_total);
365+
Debug("WriteString() wrote %zu bytes\n", written_total);
361366
}
362367

363368
return written_total;
@@ -372,20 +377,21 @@ class FileWriter : public FileIO {
372377
std::string str =
373378
"{ " + std::to_string(data[0]) + (count > 1 ? ", ... }" : " }");
374379
std::string name = GetName<T>();
375-
Debug("Write<%s>() (%d-byte), count=%d: %s",
380+
Debug("Write<%s>() (%zu-byte), count=%zu: %s",
376381
name.c_str(),
377382
sizeof(T),
378383
count,
379384
str.c_str());
380385
}
381386

382-
size_t r = fwrite(data, sizeof(T), count, f);
383-
CHECK_EQ(r, count);
387+
size_t size = sizeof(T) * count;
388+
const char* pos = reinterpret_cast<const char*>(data);
389+
sink.insert(sink.end(), pos, pos + (sizeof(T) * count));
384390

385391
if (is_debug) {
386-
Debug(", wrote %d bytes\n", r);
392+
Debug(", wrote %zu bytes\n", size);
387393
}
388-
return r;
394+
return size;
389395
}
390396

391397
// Helper for writing numeric vectors.
@@ -418,19 +424,19 @@ class FileWriter : public FileIO {
418424
// [ 4/8 bytes ] length
419425
// [ |length| bytes ] contents
420426
template <>
421-
std::string FileReader::Read() {
427+
std::string SnapshotDeserializer::Read() {
422428
return ReadString();
423429
}
424430
template <>
425-
size_t FileWriter::Write(const std::string& data) {
431+
size_t SnapshotSerializer::Write(const std::string& data) {
426432
return WriteString(data);
427433
}
428434

429435
// Layout of v8::StartupData
430436
// [ 4/8 bytes ] raw_size
431437
// [ |raw_size| bytes ] contents
432438
template <>
433-
v8::StartupData FileReader::Read() {
439+
v8::StartupData SnapshotDeserializer::Read() {
434440
Debug("Read<v8::StartupData>()\n");
435441

436442
int raw_size = Read<int>();
@@ -445,7 +451,7 @@ v8::StartupData FileReader::Read() {
445451
}
446452

447453
template <>
448-
size_t FileWriter::Write(const v8::StartupData& data) {
454+
size_t SnapshotSerializer::Write(const v8::StartupData& data) {
449455
Debug("\nWrite<v8::StartupData>() size=%d\n", data.raw_size);
450456

451457
CHECK_GT(data.raw_size, 0); // There should be no startup data of size 0.
@@ -462,7 +468,7 @@ size_t FileWriter::Write(const v8::StartupData& data) {
462468
// [ 4/8 bytes ] length of module code cache
463469
// [ ... ] |length| bytes of module code cache
464470
template <>
465-
builtins::CodeCacheInfo FileReader::Read() {
471+
builtins::CodeCacheInfo SnapshotDeserializer::Read() {
466472
Debug("Read<builtins::CodeCacheInfo>()\n");
467473

468474
builtins::CodeCacheInfo result{ReadString(), ReadVector<uint8_t>()};
@@ -475,7 +481,7 @@ builtins::CodeCacheInfo FileReader::Read() {
475481
}
476482

477483
template <>
478-
size_t FileWriter::Write(const builtins::CodeCacheInfo& data) {
484+
size_t SnapshotSerializer::Write(const builtins::CodeCacheInfo& data) {
479485
Debug("\nWrite<builtins::CodeCacheInfo>() id = %s"
480486
", size=%d\n",
481487
data.id.c_str(),
@@ -495,7 +501,7 @@ size_t FileWriter::Write(const builtins::CodeCacheInfo& data) {
495501
// [ 4/8 bytes ] index in the snapshot blob, can be used with
496502
// GetDataFromSnapshotOnce().
497503
template <>
498-
PropInfo FileReader::Read() {
504+
PropInfo SnapshotDeserializer::Read() {
499505
Debug("Read<PropInfo>()\n");
500506

501507
PropInfo result;
@@ -512,7 +518,7 @@ PropInfo FileReader::Read() {
512518
}
513519

514520
template <>
515-
size_t FileWriter::Write(const PropInfo& data) {
521+
size_t SnapshotSerializer::Write(const PropInfo& data) {
516522
if (is_debug) {
517523
std::string str = ToStr(data);
518524
Debug("Write<PropInfo>() %s\n", str.c_str());
@@ -535,7 +541,7 @@ size_t FileWriter::Write(const PropInfo& data) {
535541
// [ ... ] snapshot indices of each element in
536542
// native_execution_async_resources
537543
template <>
538-
AsyncHooks::SerializeInfo FileReader::Read() {
544+
AsyncHooks::SerializeInfo SnapshotDeserializer::Read() {
539545
Debug("Read<AsyncHooks::SerializeInfo>()\n");
540546

541547
AsyncHooks::SerializeInfo result;
@@ -553,7 +559,7 @@ AsyncHooks::SerializeInfo FileReader::Read() {
553559
return result;
554560
}
555561
template <>
556-
size_t FileWriter::Write(const AsyncHooks::SerializeInfo& data) {
562+
size_t SnapshotSerializer::Write(const AsyncHooks::SerializeInfo& data) {
557563
if (is_debug) {
558564
std::string str = ToStr(data);
559565
Debug("Write<AsyncHooks::SerializeInfo>() %s\n", str.c_str());
@@ -573,7 +579,7 @@ size_t FileWriter::Write(const AsyncHooks::SerializeInfo& data) {
573579
// Layout of TickInfo::SerializeInfo
574580
// [ 4/8 bytes ] snapshot index of fields
575581
template <>
576-
TickInfo::SerializeInfo FileReader::Read() {
582+
TickInfo::SerializeInfo SnapshotDeserializer::Read() {
577583
Debug("Read<TickInfo::SerializeInfo>()\n");
578584

579585
TickInfo::SerializeInfo result;
@@ -588,7 +594,7 @@ TickInfo::SerializeInfo FileReader::Read() {
588594
}
589595

590596
template <>
591-
size_t FileWriter::Write(const TickInfo::SerializeInfo& data) {
597+
size_t SnapshotSerializer::Write(const TickInfo::SerializeInfo& data) {
592598
if (is_debug) {
593599
std::string str = ToStr(data);
594600
Debug("Write<TickInfo::SerializeInfo>() %s\n", str.c_str());
@@ -603,7 +609,7 @@ size_t FileWriter::Write(const TickInfo::SerializeInfo& data) {
603609
// Layout of TickInfo::SerializeInfo
604610
// [ 4/8 bytes ] snapshot index of fields
605611
template <>
606-
ImmediateInfo::SerializeInfo FileReader::Read() {
612+
ImmediateInfo::SerializeInfo SnapshotDeserializer::Read() {
607613
per_process::Debug(DebugCategory::MKSNAPSHOT,
608614
"Read<ImmediateInfo::SerializeInfo>()\n");
609615

@@ -617,7 +623,7 @@ ImmediateInfo::SerializeInfo FileReader::Read() {
617623
}
618624

619625
template <>
620-
size_t FileWriter::Write(const ImmediateInfo::SerializeInfo& data) {
626+
size_t SnapshotSerializer::Write(const ImmediateInfo::SerializeInfo& data) {
621627
if (is_debug) {
622628
std::string str = ToStr(data);
623629
Debug("Write<ImmediateInfo::SerializeInfo>() %s\n", str.c_str());
@@ -635,7 +641,7 @@ size_t FileWriter::Write(const ImmediateInfo::SerializeInfo& data) {
635641
// [ 4/8 bytes ] snapshot index of milestones
636642
// [ 4/8 bytes ] snapshot index of observers
637643
template <>
638-
performance::PerformanceState::SerializeInfo FileReader::Read() {
644+
performance::PerformanceState::SerializeInfo SnapshotDeserializer::Read() {
639645
per_process::Debug(DebugCategory::MKSNAPSHOT,
640646
"Read<PerformanceState::SerializeInfo>()\n");
641647

@@ -651,7 +657,7 @@ performance::PerformanceState::SerializeInfo FileReader::Read() {
651657
}
652658

653659
template <>
654-
size_t FileWriter::Write(
660+
size_t SnapshotSerializer::Write(
655661
const performance::PerformanceState::SerializeInfo& data) {
656662
if (is_debug) {
657663
std::string str = ToStr(data);
@@ -673,7 +679,7 @@ size_t FileWriter::Write(
673679
// [ 4/8 bytes ] length of template_values vector
674680
// [ ... ] |length| of PropInfo data
675681
template <>
676-
IsolateDataSerializeInfo FileReader::Read() {
682+
IsolateDataSerializeInfo SnapshotDeserializer::Read() {
677683
per_process::Debug(DebugCategory::MKSNAPSHOT,
678684
"Read<IsolateDataSerializeInfo>()\n");
679685

@@ -688,7 +694,7 @@ IsolateDataSerializeInfo FileReader::Read() {
688694
}
689695

690696
template <>
691-
size_t FileWriter::Write(const IsolateDataSerializeInfo& data) {
697+
size_t SnapshotSerializer::Write(const IsolateDataSerializeInfo& data) {
692698
if (is_debug) {
693699
std::string str = ToStr(data);
694700
Debug("Write<IsolateDataSerializeInfo>() %s\n", str.c_str());
@@ -702,7 +708,7 @@ size_t FileWriter::Write(const IsolateDataSerializeInfo& data) {
702708
}
703709

704710
template <>
705-
RealmSerializeInfo FileReader::Read() {
711+
RealmSerializeInfo SnapshotDeserializer::Read() {
706712
per_process::Debug(DebugCategory::MKSNAPSHOT, "Read<RealmSerializeInfo>()\n");
707713
RealmSerializeInfo result;
708714
result.builtins = ReadVector<std::string>();
@@ -713,7 +719,7 @@ RealmSerializeInfo FileReader::Read() {
713719
}
714720

715721
template <>
716-
size_t FileWriter::Write(const RealmSerializeInfo& data) {
722+
size_t SnapshotSerializer::Write(const RealmSerializeInfo& data) {
717723
if (is_debug) {
718724
std::string str = ToStr(data);
719725
Debug("\nWrite<RealmSerializeInfo>() %s\n", str.c_str());
@@ -730,7 +736,7 @@ size_t FileWriter::Write(const RealmSerializeInfo& data) {
730736
}
731737

732738
template <>
733-
EnvSerializeInfo FileReader::Read() {
739+
EnvSerializeInfo SnapshotDeserializer::Read() {
734740
per_process::Debug(DebugCategory::MKSNAPSHOT, "Read<EnvSerializeInfo>()\n");
735741
EnvSerializeInfo result;
736742
result.async_hooks = Read<AsyncHooks::SerializeInfo>();
@@ -747,7 +753,7 @@ EnvSerializeInfo FileReader::Read() {
747753
}
748754

749755
template <>
750-
size_t FileWriter::Write(const EnvSerializeInfo& data) {
756+
size_t SnapshotSerializer::Write(const EnvSerializeInfo& data) {
751757
if (is_debug) {
752758
std::string str = ToStr(data);
753759
Debug("\nWrite<EnvSerializeInfo>() %s\n", str.c_str());
@@ -780,7 +786,7 @@ size_t FileWriter::Write(const EnvSerializeInfo& data) {
780786
// [ ... ] |length| bytes of node platform
781787
// [ 4 bytes ] v8 cache version tag
782788
template <>
783-
SnapshotMetadata FileReader::Read() {
789+
SnapshotMetadata SnapshotDeserializer::Read() {
784790
per_process::Debug(DebugCategory::MKSNAPSHOT, "Read<SnapshotMetadata>()\n");
785791

786792
SnapshotMetadata result;
@@ -798,7 +804,7 @@ SnapshotMetadata FileReader::Read() {
798804
}
799805

800806
template <>
801-
size_t FileWriter::Write(const SnapshotMetadata& data) {
807+
size_t SnapshotSerializer::Write(const SnapshotMetadata& data) {
802808
if (is_debug) {
803809
std::string str = ToStr(data);
804810
Debug("\nWrite<SnapshotMetadata>() %s\n", str.c_str());
@@ -833,7 +839,7 @@ size_t FileWriter::Write(const SnapshotMetadata& data) {
833839
// [ ... ] code_cache
834840

835841
void SnapshotData::ToBlob(FILE* out) const {
836-
FileWriter w(out);
842+
SnapshotSerializer w;
837843
w.Debug("SnapshotData::ToBlob()\n");
838844

839845
size_t written_total = 0;
@@ -850,11 +856,24 @@ void SnapshotData::ToBlob(FILE* out) const {
850856
written_total += w.Write<EnvSerializeInfo>(env_info);
851857
w.Debug("Write code_cache\n");
852858
written_total += w.WriteVector<builtins::CodeCacheInfo>(code_cache);
859+
size_t num_written = fwrite(w.sink.data(), w.sink.size(), 1, out);
860+
CHECK_EQ(num_written, 1);
853861
w.Debug("SnapshotData::ToBlob() Wrote %d bytes\n", written_total);
854862
}
855863

856864
bool SnapshotData::FromBlob(SnapshotData* out, FILE* in) {
857-
FileReader r(in);
865+
CHECK_EQ(ftell(in), 0);
866+
int err = fseek(in, 0, SEEK_END);
867+
CHECK_EQ(err, 0);
868+
size_t size = ftell(in);
869+
err = fseek(in, 0, SEEK_SET);
870+
CHECK_EQ(err, 0);
871+
872+
std::vector<char> sink(size);
873+
size_t num_read = fread(sink.data(), size, 1, in);
874+
CHECK_EQ(num_read, 1);
875+
876+
SnapshotDeserializer r(&sink);
858877
r.Debug("SnapshotData::FromBlob()\n");
859878

860879
DCHECK_EQ(out->data_ownership, SnapshotData::DataOwnership::kOwned);

0 commit comments

Comments
 (0)