diff options
author | James M Snell <jasnell@gmail.com> | 2017-08-07 15:53:24 -0700 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2017-08-23 16:00:09 -0700 |
commit | 67269fd7f33279699b1ae71225f3d738518c844c (patch) | |
tree | 22f6a615c02ccb93c69355d101db87f36f08cf06 /src/node_perf.h | |
parent | e007f66ae211192f385dc253bfa19a84e7fc649a (diff) | |
download | android-node-v8-67269fd7f33279699b1ae71225f3d738518c844c.tar.gz android-node-v8-67269fd7f33279699b1ae71225f3d738518c844c.tar.bz2 android-node-v8-67269fd7f33279699b1ae71225f3d738518c844c.zip |
perf_hooks: implementation of the perf timing API
An initial implementation of the Performance Timing API for Node.js.
This is the same Performance Timing API implemented by modern browsers
with a number of Node.js specific properties. The User Timing mark()
and measure() APIs are implemented, garbage collection timing, and
node startup milestone timing.
```js
const { performance } = require('perf_hooks');
performance.mark('A');
setTimeout(() => {
performance.mark('B');
performance.measure('A to B', 'A', 'B');
const entry = performance.getEntriesByName('A to B', 'measure')[0];
console.log(entry.duration);
}, 10000);
```
The implementation is at the native layer and makes use of uv_hrtime().
This should enable *eventual* integration with things like Tracing
and Inspection.
The implementation is extensible and should allow us to add new
performance entry types as we go (e.g. for measuring i/o perf,
etc).
Documentation and a test are provided.
PR-URL: https://github.com/nodejs/node/pull/14680
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'src/node_perf.h')
-rw-r--r-- | src/node_perf.h | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/node_perf.h b/src/node_perf.h new file mode 100644 index 0000000000..412479c902 --- /dev/null +++ b/src/node_perf.h @@ -0,0 +1,174 @@ +#ifndef SRC_NODE_PERF_H_ +#define SRC_NODE_PERF_H_ + +#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#include "node.h" +#include "node_perf_common.h" +#include "env.h" +#include "base-object.h" +#include "base-object-inl.h" + +#include "v8.h" +#include "uv.h" + +#include <limits> +#include <string> + +namespace node { +namespace performance { + +using v8::FunctionCallbackInfo; +using v8::GCType; +using v8::Local; +using v8::Object; +using v8::Value; + +static inline PerformanceMilestone ToPerformanceMilestoneEnum(const char* str) { +#define V(name, label) \ + if (strcmp(str, label) == 0) return NODE_PERFORMANCE_MILESTONE_##name; + NODE_PERFORMANCE_MILESTONES(V) +#undef V + return NODE_PERFORMANCE_MILESTONE_INVALID; +} + +static inline PerformanceEntryType ToPerformanceEntryTypeEnum( + const char* type) { +#define V(name, label) \ + if (strcmp(type, label) == 0) return NODE_PERFORMANCE_ENTRY_TYPE_##name; + NODE_PERFORMANCE_ENTRY_TYPES(V) +#undef V + return NODE_PERFORMANCE_ENTRY_TYPE_INVALID; +} + +const double MAX_DOUBLE = std::numeric_limits<double>::max(); + +NODE_EXTERN inline void MarkPerformanceMilestone( + Environment* env, + PerformanceMilestone milestone) { + env->performance_state()->milestones[milestone] = PERFORMANCE_NOW(); + } + +class PerformanceEntry : public BaseObject { + public: + // Used for temporary storage of performance entry details when the + // object cannot be created immediately. + class Data { + public: + Data( + const char* name, + const char* type, + uint64_t startTime, + uint64_t endTime, + int data = 0) : + name_(name), + type_(type), + startTime_(startTime), + endTime_(endTime), + data_(data) {} + + std::string name() const { + return name_; + } + + std::string type() const { + return type_; + } + + uint64_t startTime() const { + return startTime_; + } + + uint64_t endTime() const { + return endTime_; + } + + int data() const { + return data_; + } + + private: + std::string name_; + std::string type_; + uint64_t startTime_; + uint64_t endTime_; + int data_; + }; + + static void NotifyObservers(Environment* env, PerformanceEntry* entry); + + static void New(const FunctionCallbackInfo<Value>& args); + + PerformanceEntry(Environment* env, + Local<Object> wrap, + const char* name, + const char* type, + uint64_t startTime, + uint64_t endTime) : + BaseObject(env, wrap), + name_(name), + type_(type), + startTime_(startTime), + endTime_(endTime) { + MakeWeak<PerformanceEntry>(this); + NotifyObservers(env, this); + } + + PerformanceEntry(Environment* env, + Local<Object> wrap, + Data* data) : + BaseObject(env, wrap), + name_(data->name()), + type_(data->type()), + startTime_(data->startTime()), + endTime_(data->endTime()) { + MakeWeak<PerformanceEntry>(this); + NotifyObservers(env, this); + } + + ~PerformanceEntry() {} + + std::string name() const { + return name_; + } + + std::string type() const { + return type_; + } + + double startTime() const { + return startTime_ / 1e6; + } + + double duration() const { + return durationNano() / 1e6; + } + + uint64_t startTimeNano() const { + return startTime_; + } + + uint64_t durationNano() const { + return endTime_ - startTime_; + } + + private: + std::string name_; + std::string type_; + uint64_t startTime_; + uint64_t endTime_; +}; + +enum PerformanceGCKind { + NODE_PERFORMANCE_GC_MAJOR = GCType::kGCTypeMarkSweepCompact, + NODE_PERFORMANCE_GC_MINOR = GCType::kGCTypeScavenge, + NODE_PERFORMANCE_GC_INCREMENTAL = GCType::kGCTypeIncrementalMarking, + NODE_PERFORMANCE_GC_WEAKCB = GCType::kGCTypeProcessWeakCallbacks +}; + +} // namespace performance +} // namespace node + +#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS + +#endif // SRC_NODE_PERF_H_ |