| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8de6425 commit 41f5a29
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,45 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + const { createBenchmark } = require('../common.js'); | ||
| 4 | + | ||
| 5 | + const { connect, createServer } = require('net'); | ||
| 6 | + const { open } = require('fs'); | ||
| 7 | + | ||
| 8 | + const bench = createBenchmark(main, { | ||
| 9 | + handlesCount: [1e4], | ||
| 10 | + requestsCount: [1e4], | ||
| 11 | + timeoutsCount: [1e4], | ||
| 12 | + immediatesCount: [1e4], | ||
| 13 | + n: [1e5], | ||
| 14 | + }); | ||
| 15 | + | ||
| 16 | + function main({ handlesCount, requestsCount, timeoutsCount, immediatesCount, n }) { | ||
| 17 | + const server = createServer().listen(); | ||
| 18 | + const clients = []; | ||
| 19 | + for (let i = 0; i < handlesCount; i++) { | ||
| 20 | + clients.push(connect({ port: server.address().port })); | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + for (let i = 0; i < requestsCount; i++) { | ||
| 24 | + open(__filename, 'r', () => {}); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + for (let i = 0; i < timeoutsCount; ++i) { | ||
| 28 | + setTimeout(() => {}, 1); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + for (let i = 0; i < immediatesCount; ++i) { | ||
| 32 | + setImmediate(() => {}); | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + bench.start(); | ||
| 36 | + for (let i = 0; i < n; ++i) { | ||
| 37 | + process.getActiveResourcesInfo(); | ||
| 38 | + } | ||
| 39 | + bench.end(n); | ||
| 40 | + | ||
| 41 | + for (const client of clients) { | ||
| 42 | + client.destroy(); | ||
| 43 | + } | ||
| 44 | + server.close(); | ||
| 45 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -55,9 +55,6 @@ | |||
| 55 | 55 | setupPrepareStackTrace(); | |
| 56 | 56 | ||
| 57 | 57 | const { | |
| 58 | - Array, | ||
| 59 | - ArrayPrototypeFill, | ||
| 60 | - ArrayPrototypePushApply, | ||
| 61 | 58 | FunctionPrototypeCall, | |
| 62 | 59 | JSONParse, | |
| 63 | 60 | ObjectDefineProperty, | |
@@ -192,15 +189,7 @@ const rawMethods = internalBinding('process_methods'); | |||
| 192 | 189 | // TODO(joyeecheung): either remove them or make them public | |
| 193 | 190 | process._getActiveRequests = rawMethods._getActiveRequests; | |
| 194 | 191 | process._getActiveHandles = rawMethods._getActiveHandles; | |
| 195 | - | ||
| 196 | - process.getActiveResourcesInfo = function() { | ||
| 197 | - const timerCounts = internalTimers.getTimerCounts(); | ||
| 198 | - const info = rawMethods._getActiveRequestsInfo(); | ||
| 199 | - ArrayPrototypePushApply(info, rawMethods._getActiveHandlesInfo()); | ||
| 200 | - ArrayPrototypePushApply(info, ArrayPrototypeFill(new Array(timerCounts.timeoutCount), 'Timeout')); | ||
| 201 | - ArrayPrototypePushApply(info, ArrayPrototypeFill(new Array(timerCounts.immediateCount), 'Immediate')); | ||
| 202 | - return info; | ||
| 203 | - }; | ||
| 192 | + process.getActiveResourcesInfo = rawMethods.getActiveResourcesInfo; | ||
| 204 | 193 | ||
| 205 | 194 | // TODO(joyeecheung): remove these | |
| 206 | 195 | process.reallyExit = rawMethods.reallyExit; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -87,6 +87,7 @@ const { | |||
| 87 | 87 | toggleTimerRef, | |
| 88 | 88 | getLibuvNow, | |
| 89 | 89 | immediateInfo, | |
| 90 | + timeoutInfo, | ||
| 90 | 91 | toggleImmediateRef | |
| 91 | 92 | } = internalBinding('timers'); | |
| 92 | 93 | ||
@@ -137,7 +138,11 @@ let timerListId = NumberMIN_SAFE_INTEGER; | |||
| 137 | 138 | const kRefed = Symbol('refed'); | |
| 138 | 139 | ||
| 139 | 140 | let nextExpiry = Infinity; | |
| 140 | - let refCount = 0; | ||
| 141 | + // timeoutInfo is an Int32Array that contains the reference count of Timeout | ||
| 142 | + // objects at index 0. This is a TypedArray so that GetActiveResourcesInfo() in | ||
| 143 | + // `src/node_process_methods.cc` is able to access this value without crossing | ||
| 144 | + // the JS-C++ boundary, which is slow at the time of writing. | ||
| 145 | + timeoutInfo[0] = 0; | ||
| 141 | 146 | ||
| 142 | 147 | // This is a priority queue with a custom sorting function that first compares | |
| 143 | 148 | // the expiry times of two lists and if they're the same then compares their | |
@@ -302,12 +307,12 @@ class ImmediateList { | |||
| 302 | 307 | const immediateQueue = new ImmediateList(); | |
| 303 | 308 | ||
| 304 | 309 | function incRefCount() { | |
| 305 | - if (refCount++ === 0) | ||
| 310 | + if (timeoutInfo[0]++ === 0) | ||
| 306 | 311 | toggleTimerRef(true); | |
| 307 | 312 | } | |
| 308 | 313 | ||
| 309 | 314 | function decRefCount() { | |
| 310 | - if (--refCount === 0) | ||
| 315 | + if (--timeoutInfo[0] === 0) | ||
| 311 | 316 | toggleTimerRef(false); | |
| 312 | 317 | } | |
| 313 | 318 | ||
@@ -498,7 +503,7 @@ function getTimerCallbacks(runNextTicks) { | |||
| 498 | 503 | while ((list = timerListQueue.peek()) != null) { | |
| 499 | 504 | if (list.expiry > now) { | |
| 500 | 505 | nextExpiry = list.expiry; | |
| 501 | - return refCount > 0 ? nextExpiry : -nextExpiry; | ||
| 506 | + return timeoutInfo[0] > 0 ? nextExpiry : -nextExpiry; | ||
| 502 | 507 | } | |
| 503 | 508 | if (ranAtLeastOneList) | |
| 504 | 509 | runNextTicks(); | |
@@ -544,7 +549,7 @@ function getTimerCallbacks(runNextTicks) { | |||
| 544 | 549 | timer._destroyed = true; | |
| 545 | 550 | ||
| 546 | 551 | if (timer[kRefed]) | |
| 547 | - refCount--; | ||
| 552 | + timeoutInfo[0]--; | ||
| 548 | 553 | ||
| 549 | 554 | if (destroyHooksExist()) | |
| 550 | 555 | emitDestroy(asyncId); | |
@@ -572,7 +577,7 @@ function getTimerCallbacks(runNextTicks) { | |||
| 572 | 577 | timer._destroyed = true; | |
| 573 | 578 | ||
| 574 | 579 | if (timer[kRefed]) | |
| 575 | - refCount--; | ||
| 580 | + timeoutInfo[0]--; | ||
| 576 | 581 | ||
| 577 | 582 | if (destroyHooksExist()) | |
| 578 | 583 | emitDestroy(asyncId); | |
@@ -643,13 +648,6 @@ class Immediate { | |||
| 643 | 648 | } | |
| 644 | 649 | } | |
| 645 | 650 | ||
| 646 | - function getTimerCounts() { | ||
| 647 | - return { | ||
| 648 | - timeoutCount: refCount, | ||
| 649 | - immediateCount: immediateInfo[kRefCount], | ||
| 650 | - }; | ||
| 651 | - } | ||
| 652 | - | ||
| 653 | 651 | module.exports = { | |
| 654 | 652 | TIMEOUT_MAX, | |
| 655 | 653 | kTimeout: Symbol('timeout'), // For hiding Timeouts on other internals. | |
@@ -676,5 +674,4 @@ module.exports = { | |||
| 676 | 674 | timerListQueue, | |
| 677 | 675 | decRefCount, | |
| 678 | 676 | incRefCount, | |
| 679 | - getTimerCounts, | ||
| 680 | 677 | }; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -323,6 +323,10 @@ inline ImmediateInfo* Environment::immediate_info() { | |||
| 323 | 323 | return &immediate_info_; | |
| 324 | 324 | } | |
| 325 | 325 | ||
| 326 | + inline AliasedInt32Array& Environment::timeout_info() { | ||
| 327 | + return timeout_info_; | ||
| 328 | + } | ||
| 329 | + | ||
| 326 | 330 | inline TickInfo* Environment::tick_info() { | |
| 327 | 331 | return &tick_info_; | |
| 328 | 332 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -649,6 +649,7 @@ Environment::Environment(IsolateData* isolate_data, | |||
| 649 | 649 | isolate_data_(isolate_data), | |
| 650 | 650 | async_hooks_(isolate, MAYBE_FIELD_PTR(env_info, async_hooks)), | |
| 651 | 651 | immediate_info_(isolate, MAYBE_FIELD_PTR(env_info, immediate_info)), | |
| 652 | + timeout_info_(isolate_, 1, MAYBE_FIELD_PTR(env_info, timeout_info)), | ||
| 652 | 653 | tick_info_(isolate, MAYBE_FIELD_PTR(env_info, tick_info)), | |
| 653 | 654 | timer_base_(uv_now(isolate_data->event_loop())), | |
| 654 | 655 | exec_argv_(exec_args), | |
@@ -1603,6 +1604,7 @@ EnvSerializeInfo Environment::Serialize(SnapshotCreator* creator) { | |||
| 1603 | 1604 | ||
| 1604 | 1605 | info.async_hooks = async_hooks_.Serialize(ctx, creator); | |
| 1605 | 1606 | info.immediate_info = immediate_info_.Serialize(ctx, creator); | |
| 1607 | + info.timeout_info = timeout_info_.Serialize(ctx, creator); | ||
| 1606 | 1608 | info.tick_info = tick_info_.Serialize(ctx, creator); | |
| 1607 | 1609 | info.performance_state = performance_state_->Serialize(ctx, creator); | |
| 1608 | 1610 | info.exiting = exiting_.Serialize(ctx, creator); | |
@@ -1649,6 +1651,7 @@ void Environment::DeserializeProperties(const EnvSerializeInfo* info) { | |||
| 1649 | 1651 | builtins_in_snapshot = info->builtins; | |
| 1650 | 1652 | async_hooks_.Deserialize(ctx); | |
| 1651 | 1653 | immediate_info_.Deserialize(ctx); | |
| 1654 | + timeout_info_.Deserialize(ctx); | ||
| 1652 | 1655 | tick_info_.Deserialize(ctx); | |
| 1653 | 1656 | performance_state_->Deserialize(ctx); | |
| 1654 | 1657 | exiting_.Deserialize(ctx); | |
@@ -1845,6 +1848,7 @@ void Environment::MemoryInfo(MemoryTracker* tracker) const { | |||
| 1845 | 1848 | tracker->TrackField("cleanup_queue", cleanup_queue_); | |
| 1846 | 1849 | tracker->TrackField("async_hooks", async_hooks_); | |
| 1847 | 1850 | tracker->TrackField("immediate_info", immediate_info_); | |
| 1851 | + tracker->TrackField("timeout_info", timeout_info_); | ||
| 1848 | 1852 | tracker->TrackField("tick_info", tick_info_); | |
| 1849 | 1853 | tracker->TrackField("principal_realm", principal_realm_); | |
| 1850 | 1854 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -460,6 +460,7 @@ struct EnvSerializeInfo { | |||
| 460 | 460 | AsyncHooks::SerializeInfo async_hooks; | |
| 461 | 461 | TickInfo::SerializeInfo tick_info; | |
| 462 | 462 | ImmediateInfo::SerializeInfo immediate_info; | |
| 463 | + AliasedBufferIndex timeout_info; | ||
| 463 | 464 | performance::PerformanceState::SerializeInfo performance_state; | |
| 464 | 465 | AliasedBufferIndex exiting; | |
| 465 | 466 | AliasedBufferIndex stream_base_state; | |
@@ -667,6 +668,7 @@ class Environment : public MemoryRetainer { | |||
| 667 | 668 | ||
| 668 | 669 | inline AsyncHooks* async_hooks(); | |
| 669 | 670 | inline ImmediateInfo* immediate_info(); | |
| 671 | + inline AliasedInt32Array& timeout_info(); | ||
| 670 | 672 | inline TickInfo* tick_info(); | |
| 671 | 673 | inline uint64_t timer_base() const; | |
| 672 | 674 | inline std::shared_ptr<KVStore> env_vars(); | |
@@ -988,6 +990,7 @@ class Environment : public MemoryRetainer { | |||
| 988 | 990 | ||
| 989 | 991 | AsyncHooks async_hooks_; | |
| 990 | 992 | ImmediateInfo immediate_info_; | |
| 993 | + AliasedInt32Array timeout_info_; | ||
| 991 | 994 | TickInfo tick_info_; | |
| 992 | 995 | const uint64_t timer_base_; | |
| 993 | 996 | std::shared_ptr<KVStore> env_vars_; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -258,21 +258,6 @@ static void GetActiveRequests(const FunctionCallbackInfo<Value>& args) { | |||
| 258 | 258 | Array::New(env->isolate(), request_v.data(), request_v.size())); | |
| 259 | 259 | } | |
| 260 | 260 | ||
| 261 | - static void GetActiveRequestsInfo(const FunctionCallbackInfo<Value>& args) { | ||
| 262 | - Environment* env = Environment::GetCurrent(args); | ||
| 263 | - | ||
| 264 | - std::vector<Local<Value>> requests_info; | ||
| 265 | - for (ReqWrapBase* req_wrap : *env->req_wrap_queue()) { | ||
| 266 | - AsyncWrap* w = req_wrap->GetAsyncWrap(); | ||
| 267 | - if (w->persistent().IsEmpty()) continue; | ||
| 268 | - requests_info.emplace_back(OneByteString(env->isolate(), | ||
| 269 | - w->MemoryInfoName().c_str())); | ||
| 270 | - } | ||
| 271 | - | ||
| 272 | - args.GetReturnValue().Set( | ||
| 273 | - Array::New(env->isolate(), requests_info.data(), requests_info.size())); | ||
| 274 | - } | ||
| 275 | - | ||
| 276 | 261 | // Non-static, friend of HandleWrap. Could have been a HandleWrap method but | |
| 277 | 262 | // implemented here for consistency with GetActiveRequests(). | |
| 278 | 263 | void GetActiveHandles(const FunctionCallbackInfo<Value>& args) { | |
@@ -288,18 +273,37 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) { | |||
| 288 | 273 | Array::New(env->isolate(), handle_v.data(), handle_v.size())); | |
| 289 | 274 | } | |
| 290 | 275 | ||
| 291 | - void GetActiveHandlesInfo(const FunctionCallbackInfo<Value>& args) { | ||
| 276 | + static void GetActiveResourcesInfo(const FunctionCallbackInfo<Value>& args) { | ||
| 292 | 277 | Environment* env = Environment::GetCurrent(args); | |
| 278 | + std::vector<Local<Value>> resources_info; | ||
| 279 | + | ||
| 280 | + // Active requests | ||
| 281 | + for (ReqWrapBase* req_wrap : *env->req_wrap_queue()) { | ||
| 282 | + AsyncWrap* w = req_wrap->GetAsyncWrap(); | ||
| 283 | + if (w->persistent().IsEmpty()) continue; | ||
| 284 | + resources_info.emplace_back( | ||
| 285 | + OneByteString(env->isolate(), w->MemoryInfoName().c_str())); | ||
| 286 | + } | ||
| 293 | 287 | ||
| 294 | - std::vector<Local<Value>> handles_info; | ||
| 288 | + // Active handles | ||
| 295 | 289 | for (HandleWrap* w : *env->handle_wrap_queue()) { | |
| 296 | 290 | if (w->persistent().IsEmpty() || !HandleWrap::HasRef(w)) continue; | |
| 297 | - handles_info.emplace_back(OneByteString(env->isolate(), | ||
| 298 | - w->MemoryInfoName().c_str())); | ||
| 291 | + resources_info.emplace_back( | ||
| 292 | + OneByteString(env->isolate(), w->MemoryInfoName().c_str())); | ||
| 299 | 293 | } | |
| 300 | 294 | ||
| 295 | + // Active timeouts | ||
| 296 | + resources_info.insert(resources_info.end(), | ||
| 297 | + env->timeout_info()[0], | ||
| 298 | + OneByteString(env->isolate(), "Timeout")); | ||
| 299 | + | ||
| 300 | + // Active immediates | ||
| 301 | + resources_info.insert(resources_info.end(), | ||
| 302 | + env->immediate_info()->ref_count(), | ||
| 303 | + OneByteString(env->isolate(), "Immediate")); | ||
| 304 | + | ||
| 301 | 305 | args.GetReturnValue().Set( | |
| 302 | - Array::New(env->isolate(), handles_info.data(), handles_info.size())); | ||
| 306 | + Array::New(env->isolate(), resources_info.data(), resources_info.size())); | ||
| 303 | 307 | } | |
| 304 | 308 | ||
| 305 | 309 | static void ResourceUsage(const FunctionCallbackInfo<Value>& args) { | |
@@ -578,10 +582,9 @@ static void Initialize(Local<Object> target, | |||
| 578 | 582 | SetMethod(context, target, "resourceUsage", ResourceUsage); | |
| 579 | 583 | ||
| 580 | 584 | SetMethod(context, target, "_debugEnd", DebugEnd); | |
| 581 | - SetMethod(context, target, "_getActiveRequestsInfo", GetActiveRequestsInfo); | ||
| 582 | 585 | SetMethod(context, target, "_getActiveRequests", GetActiveRequests); | |
| 583 | 586 | SetMethod(context, target, "_getActiveHandles", GetActiveHandles); | |
| 584 | - SetMethod(context, target, "_getActiveHandlesInfo", GetActiveHandlesInfo); | ||
| 587 | + SetMethod(context, target, "getActiveResourcesInfo", GetActiveResourcesInfo); | ||
| 585 | 588 | SetMethod(context, target, "_kill", Kill); | |
| 586 | 589 | SetMethod(context, target, "_rawDebug", RawDebug); | |
| 587 | 590 | ||
@@ -609,9 +612,8 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | |||
| 609 | 612 | registry->Register(ResourceUsage); | |
| 610 | 613 | ||
| 611 | 614 | registry->Register(GetActiveRequests); | |
| 612 | - registry->Register(GetActiveRequestsInfo); | ||
| 613 | 615 | registry->Register(GetActiveHandles); | |
| 614 | - registry->Register(GetActiveHandlesInfo); | ||
| 616 | + registry->Register(GetActiveResourcesInfo); | ||
| 615 | 617 | registry->Register(Kill); | |
| 616 | 618 | ||
| 617 | 619 | registry->Register(Cwd); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -120,6 +120,7 @@ std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) { | |||
| 120 | 120 | << "// -- async_hooks ends --\n" | |
| 121 | 121 | << i.tick_info << ", // tick_info\n" | |
| 122 | 122 | << i.immediate_info << ", // immediate_info\n" | |
| 123 | + << i.timeout_info << ", // timeout_info\n" | ||
| 123 | 124 | << "// -- performance_state begins --\n" | |
| 124 | 125 | << i.performance_state << ",\n" | |
| 125 | 126 | << "// -- performance_state ends --\n" | |
@@ -734,6 +735,7 @@ EnvSerializeInfo FileReader::Read() { | |||
| 734 | 735 | result.async_hooks = Read<AsyncHooks::SerializeInfo>(); | |
| 735 | 736 | result.tick_info = Read<TickInfo::SerializeInfo>(); | |
| 736 | 737 | result.immediate_info = Read<ImmediateInfo::SerializeInfo>(); | |
| 738 | + result.timeout_info = Read<AliasedBufferIndex>(); | ||
| 737 | 739 | result.performance_state = | |
| 738 | 740 | Read<performance::PerformanceState::SerializeInfo>(); | |
| 739 | 741 | result.exiting = Read<AliasedBufferIndex>(); | |
@@ -755,6 +757,7 @@ size_t FileWriter::Write(const EnvSerializeInfo& data) { | |||
| 755 | 757 | written_total += Write<AsyncHooks::SerializeInfo>(data.async_hooks); | |
| 756 | 758 | written_total += Write<TickInfo::SerializeInfo>(data.tick_info); | |
| 757 | 759 | written_total += Write<ImmediateInfo::SerializeInfo>(data.immediate_info); | |
| 760 | + written_total += Write<AliasedBufferIndex>(data.timeout_info); | ||
| 758 | 761 | written_total += Write<performance::PerformanceState::SerializeInfo>( | |
| 759 | 762 | data.performance_state); | |
| 760 | 763 | written_total += Write<AliasedBufferIndex>(data.exiting); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -59,6 +59,12 @@ void Initialize(Local<Object> target, | |||
| 59 | 59 | FIXED_ONE_BYTE_STRING(env->isolate(), "immediateInfo"), | |
| 60 | 60 | env->immediate_info()->fields().GetJSArray()) | |
| 61 | 61 | .Check(); | |
| 62 | + | ||
| 63 | + target | ||
| 64 | + ->Set(context, | ||
| 65 | + FIXED_ONE_BYTE_STRING(env->isolate(), "timeoutInfo"), | ||
| 66 | + env->timeout_info().GetJSArray()) | ||
| 67 | + .Check(); | ||
| 62 | 68 | } | |
| 63 | 69 | } // anonymous namespace | |
| 64 | 70 | void RegisterTimerExternalReferences(ExternalReferenceRegistry* registry) { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments