7
7
#include " node_api.h"
8
8
#include " uv.h"
9
9
#include " brotli/decode.h"
10
+ #include < atomic>
10
11
#if HAVE_OPENSSL
11
12
#include < openssl/err.h>
12
13
#include < openssl/ssl.h>
@@ -50,9 +51,54 @@ void TearDownOncePerProcess();
50
51
}
51
52
#endif
52
53
namespace boxednode {
54
+ namespace {
55
+ struct TimingEntry {
56
+ const char * const label;
57
+ uint64_t const time;
58
+ TimingEntry* next = nullptr ;
59
+ ~TimingEntry () {
60
+ delete next;
61
+ }
62
+ };
63
+ TimingEntry start_time_entry { " Process initialization" , uv_hrtime () };
64
+ std::atomic<TimingEntry*> current_time_entry { &start_time_entry };
65
+
66
+ void MarkTime (const char * label) {
67
+ TimingEntry* new_entry = new TimingEntry { label, uv_hrtime () };
68
+ do {
69
+ new_entry->next = current_time_entry.load ();
70
+ } while (!current_time_entry.compare_exchange_strong (new_entry->next , new_entry));
71
+ }
72
+ } // anonymous namespace
73
+
53
74
Local<String> GetBoxednodeMainScriptSource (Isolate* isolate);
54
75
Local<Uint8Array> GetBoxednodeCodeCacheBuffer (Isolate* isolate);
55
76
std::vector<char > GetBoxednodeSnapshotBlobVector ();
77
+
78
+ void GetTimingData (const FunctionCallbackInfo<Value>& info) {
79
+ Isolate* isolate = info.GetIsolate ();
80
+ TimingEntry* head = current_time_entry.load ();
81
+ std::vector<Local<Value>> entries;
82
+ while (head != nullptr ) {
83
+ Local<Value> elements[] = {
84
+ String::NewFromUtf8 (isolate, head->label ).ToLocalChecked (),
85
+ BigInt::NewFromUnsigned (isolate, head->time )
86
+ };
87
+ entries.push_back (Array::New (isolate, elements, sizeof (elements)/sizeof (elements[0 ])));
88
+ head = head->next ;
89
+ }
90
+ Local<Array> retval = Array::New (isolate, entries.data (), entries.size ());
91
+ info.GetReturnValue ().Set (retval);
92
+ }
93
+
94
+ void boxednode_linked_bindings_register (
95
+ Local<Object> exports,
96
+ Local<Value> module ,
97
+ Local<Context> context,
98
+ void * priv) {
99
+ NODE_SET_METHOD (exports, " getTimingData" , GetTimingData);
100
+ }
101
+
56
102
}
57
103
58
104
extern " C" {
@@ -97,13 +143,15 @@ static MaybeLocal<Value> LoadBoxednodeEnvironment(Local<Context> context) {
97
143
String::NewFromUtf8Literal (isolate, BOXEDNODE_CODE_CACHE_MODE),
98
144
boxednode::GetBoxednodeCodeCacheBuffer (isolate),
99
145
};
146
+ boxednode::MarkTime (" Calling entrypoint" );
100
147
if (entrypoint_ret.As <Function>()->Call (
101
148
context,
102
149
Null (isolate),
103
150
sizeof (trampoline_args) / sizeof (trampoline_args[0 ]),
104
151
trampoline_args).IsEmpty ()) {
105
152
return {}; // JS exception.
106
153
}
154
+ boxednode::MarkTime (" Called entrypoint" );
107
155
return Null (isolate);
108
156
}
109
157
#endif
@@ -160,15 +208,18 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
160
208
#else
161
209
loop = uv_default_loop ();
162
210
#endif
211
+ boxednode::MarkTime (" Initialized Loop" );
163
212
164
213
std::shared_ptr<ArrayBufferAllocator> allocator =
165
214
ArrayBufferAllocator::Create ();
166
215
167
216
#ifdef BOXEDNODE_CONSUME_SNAPSHOT
168
217
std::vector<char > snapshot_blob_vec = boxednode::GetBoxednodeSnapshotBlobVector ();
218
+ boxednode::MarkTime (" Decoded snapshot" );
169
219
assert (EmbedderSnapshotData::CanUseCustomSnapshotPerIsolate ());
170
220
node::EmbedderSnapshotData::Pointer snapshot_blob =
171
221
EmbedderSnapshotData::FromBlob (snapshot_blob_vec);
222
+ boxednode::MarkTime (" Read snapshot" );
172
223
Isolate* isolate = NewIsolate (allocator, loop, platform, snapshot_blob.get ());
173
224
#elif NODE_VERSION_AT_LEAST(14, 0, 0)
174
225
Isolate* isolate = NewIsolate (allocator, loop, platform);
@@ -179,6 +230,7 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
179
230
fprintf (stderr, " %s: Failed to initialize V8 Isolate\n " , args[0 ].c_str ());
180
231
return 1 ;
181
232
}
233
+ boxednode::MarkTime (" Created Isolate" );
182
234
183
235
{
184
236
Locker locker (isolate);
@@ -194,6 +246,7 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
194
246
),
195
247
node::FreeIsolateData);
196
248
249
+ boxednode::MarkTime (" Created IsolateData" );
197
250
HandleScope handle_scope (isolate);
198
251
Local<Context> context;
199
252
#ifndef BOXEDNODE_CONSUME_SNAPSHOT
@@ -209,6 +262,7 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
209
262
// node::LoadEnvironment() are being called.
210
263
Context::Scope context_scope (context);
211
264
#endif
265
+ boxednode::MarkTime (" Created Context" );
212
266
213
267
// Create a node::Environment instance that will later be released using
214
268
// node::FreeEnvironment().
@@ -222,6 +276,7 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
222
276
Context::Scope context_scope (context);
223
277
#endif
224
278
assert (isolate->InContext ());
279
+ boxednode::MarkTime (" Created Environment" );
225
280
226
281
const void * node_mod;
227
282
const void * napi_mod;
@@ -238,6 +293,11 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
238
293
AddLinkedBinding (env.get (), *static_cast <const napi_module*>(napi_mod));
239
294
#endif
240
295
}
296
+ AddLinkedBinding (
297
+ env.get (),
298
+ " boxednode_linked_bindings" ,
299
+ boxednode::boxednode_linked_bindings_register, nullptr );
300
+ boxednode::MarkTime (" Added bindings" );
241
301
242
302
// Set up the Node.js instance for execution, and run code inside of it.
243
303
// There is also a variant that takes a callback and provides it with
@@ -251,6 +311,7 @@ static int RunNodeInstance(MultiIsolatePlatform* platform,
251
311
if (LoadBoxednodeEnvironment (context).IsEmpty ()) {
252
312
return 1 ; // There has been a JS exception.
253
313
}
314
+ boxednode::MarkTime (" Loaded Environment, entering loop" );
254
315
255
316
{
256
317
// SealHandleScope protects against handle leaks from callbacks.
@@ -335,11 +396,13 @@ static int BoxednodeMain(std::vector<std::string> args) {
335
396
if (args.size () > 1 )
336
397
args.insert (args.begin () + 1 , " --openssl-shared-config" );
337
398
#endif
399
+ boxednode::MarkTime (" Start InitializeOncePerProcess" );
338
400
auto result = node::InitializeOncePerProcess (args, {
339
401
node::ProcessInitializationFlags::kNoInitializeV8 ,
340
402
node::ProcessInitializationFlags::kNoInitializeNodeV8Platform ,
341
403
node::ProcessInitializationFlags::kNoPrintHelpOrVersionOutput
342
404
});
405
+ boxednode::MarkTime (" Finished InitializeOncePerProcess" );
343
406
for (const std::string& error : result->errors ())
344
407
fprintf (stderr, " %s: %s\n " , args[0 ].c_str (), error.c_str ());
345
408
if (result->exit_code () != 0 ) {
@@ -364,6 +427,7 @@ static int BoxednodeMain(std::vector<std::string> args) {
364
427
V8::InitializePlatform (platform.get ());
365
428
V8::Initialize ();
366
429
430
+ boxednode::MarkTime (" Initialized V8" );
367
431
// See below for the contents of this function.
368
432
int ret = RunNodeInstance (platform.get (), args, exec_args);
369
433
@@ -412,6 +476,7 @@ int wmain(int argc, wchar_t* wargv[]) {
412
476
int main (int argc, char ** argv) {
413
477
argv = uv_setup_args (argc, argv);
414
478
std::vector<std::string> args (argv, argv + argc);
479
+ boxednode::MarkTime (" Enter BoxednodeMain" );
415
480
return BoxednodeMain (std::move (args));
416
481
}
417
482
#endif
0 commit comments