summaryrefslogtreecommitdiff
path: root/src/node_perf.h
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2017-08-07 15:53:24 -0700
committerJames M Snell <jasnell@gmail.com>2017-08-23 16:00:09 -0700
commit67269fd7f33279699b1ae71225f3d738518c844c (patch)
tree22f6a615c02ccb93c69355d101db87f36f08cf06 /src/node_perf.h
parente007f66ae211192f385dc253bfa19a84e7fc649a (diff)
downloadandroid-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.h174
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_