OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-booking / node_modules / bare-performance / binding.c

452 lines · c ref:
#include <assert.h>
#include <bare.h>
#include <hdr/hdr_histogram.h>
#include <js.h>
#include <stdlib.h>
#include <uv.h>

typedef struct {
  js_ref_t *ctx;

  struct hdr_histogram *histogram;
} bare_performance_histogram_t;

static js_value_t *
bare_performance_now(js_env_t *env, js_callback_info_t *info) {
  int err;

  js_value_t *result;
  err = js_create_double(env, uv_hrtime(), &result);
  assert(err == 0);

  return result;
}

static double
bare_performance_now_typed(js_value_t *receiver, js_typed_callback_info_t *info) {
  return uv_hrtime();
}

static js_value_t *
bare_performance_idle_time(js_env_t *env, js_callback_info_t *info) {
  int err;

  uv_loop_t *loop;
  err = js_get_env_loop(env, &loop);
  assert(err == 0);

  js_value_t *result;
  err = js_create_double(env, uv_metrics_idle_time(loop) / 1e6, &result);
  assert(err == 0);

  return result;
}

static double
bare_performance_idle_time_typed(js_value_t *receiver, js_typed_callback_info_t *info) {
  int err;

  js_env_t *env;
  err = js_get_typed_callback_info(info, &env, NULL);
  assert(err == 0);

  uv_loop_t *loop;
  err = js_get_env_loop(env, &loop);
  assert(err == 0);

  return uv_metrics_idle_time(loop) / 1e6;
}

static js_value_t *
bare_performance_metrics_info(js_env_t *env, js_callback_info_t *info) {
  int err;

  uv_loop_t *loop;
  err = js_get_env_loop(env, &loop);
  assert(err == 0);

  uv_metrics_t metrics;
  err = uv_metrics_info(loop, &metrics);
  assert(err == 0);

  js_value_t *result;
  err = js_create_object(env, &result);
  assert(err == 0);

#define V(name, property) \
  { \
    js_value_t *value; \
    err = js_create_int64(env, metrics.property, &value); \
    assert(err == 0); \
    err = js_set_named_property(env, result, name, value); \
    assert(err == 0); \
  }

  V("loopCount", loop_count)
  V("events", events)
  V("eventsWaiting", events_waiting)
#undef V

  return result;
}

static js_value_t *
bare_performance_histogram_init(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 4;
  js_value_t *argv[4];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 4);

  js_value_t *handle;

  bare_performance_histogram_t *histogram;
  err = js_create_arraybuffer(env, sizeof(bare_performance_histogram_t), (void **) &histogram, &handle);

  err = js_create_reference(env, argv[0], 1, &histogram->ctx);
  assert(err == 0);

  int64_t lowest;
  err = js_get_value_int64(env, argv[1], &lowest);
  assert(err == 0);

  int64_t highest;
  err = js_get_value_int64(env, argv[2], &highest);
  assert(err == 0);

  int64_t figures;
  err = js_get_value_int64(env, argv[3], &figures);
  assert(err == 0);

  err = hdr_init(lowest, highest, figures, &histogram->histogram);
  assert(err == 0);

  return handle;
}

static js_value_t *
bare_performance_histogram_percentiles(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 1;
  js_value_t *argv[1];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 1);

  bare_performance_histogram_t *histogram;
  err = js_get_arraybuffer_info(env, argv[0], (void **) &histogram, NULL);
  assert(err == 0);

  struct hdr_iter iter;
  hdr_iter_percentile_init(&iter, histogram->histogram, 1.0);

  js_value_t *result;
  err = js_create_array(env, &result);
  assert(err == 0);

  uint32_t i = 0;

  while (hdr_iter_next(&iter)) {
    js_value_t *pair;
    err = js_create_array_with_length(env, 2, &pair);
    assert(err == 0);

    js_value_t *key;
    err = js_create_double(env, iter.specifics.percentiles.percentile, &key);
    assert(err == 0);

    err = js_set_element(env, pair, 0, key);
    assert(err == 0);

    js_value_t *value;
    err = js_create_double(env, iter.value, &value);
    assert(err == 0);

    err = js_set_element(env, pair, 1, value);
    assert(err == 0);

    err = js_set_element(env, result, i++, pair);
    assert(err == 0);
  }

  return result;
}

static js_value_t *
bare_performance_histogram_percentile(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 2;
  js_value_t *argv[2];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 2);

  bare_performance_histogram_t *histogram;
  err = js_get_arraybuffer_info(env, argv[0], (void **) &histogram, NULL);
  assert(err == 0);

  double percentile;
  err = js_get_value_double(env, argv[1], &percentile);
  assert(err == 0);

  js_value_t *result;
  err = js_create_int64(env, hdr_value_at_percentile(histogram->histogram, percentile), &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_performance_histogram_min(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 1;
  js_value_t *argv[1];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 1);

  bare_performance_histogram_t *histogram;
  err = js_get_arraybuffer_info(env, argv[0], (void **) &histogram, NULL);
  assert(err == 0);

  js_value_t *result;
  err = js_create_int64(env, hdr_min(histogram->histogram), &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_performance_histogram_max(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 1;
  js_value_t *argv[1];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 1);

  bare_performance_histogram_t *histogram;
  err = js_get_arraybuffer_info(env, argv[0], (void **) &histogram, NULL);
  assert(err == 0);

  js_value_t *result;
  err = js_create_int64(env, hdr_max(histogram->histogram), &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_performance_histogram_mean(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 1;
  js_value_t *argv[1];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 1);

  bare_performance_histogram_t *histogram;
  err = js_get_arraybuffer_info(env, argv[0], (void **) &histogram, NULL);
  assert(err == 0);

  js_value_t *result;
  err = js_create_double(env, hdr_mean(histogram->histogram), &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_performance_histogram_stddev(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 1;
  js_value_t *argv[1];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 1);

  bare_performance_histogram_t *histogram;
  err = js_get_arraybuffer_info(env, argv[0], (void **) &histogram, NULL);
  assert(err == 0);

  js_value_t *result;
  err = js_create_double(env, hdr_stddev(histogram->histogram), &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_performance_histogram_record(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 2;
  js_value_t *argv[2];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 2);

  bare_performance_histogram_t *histogram;
  err = js_get_arraybuffer_info(env, argv[0], (void **) &histogram, NULL);
  assert(err == 0);

  int64_t value;
  err = js_get_value_int64(env, argv[1], &value);
  assert(err == 0);

  js_value_t *result;
  err = js_get_boolean(env, hdr_record_value(histogram->histogram, value), &result);
  assert(err == 0);

  return result;
}

static js_value_t *
bare_performance_histogram_add(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 2;
  js_value_t *argv[2];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 2);

  bare_performance_histogram_t *histogram;
  err = js_get_arraybuffer_info(env, argv[0], (void **) &histogram, NULL);
  assert(err == 0);

  bare_performance_histogram_t *from;
  err = js_get_arraybuffer_info(env, argv[1], (void **) &from, NULL);
  assert(err == 0);

  hdr_add(histogram->histogram, from->histogram);

  return NULL;
}

static js_value_t *
bare_performance_histogram_reset(js_env_t *env, js_callback_info_t *info) {
  int err;

  size_t argc = 1;
  js_value_t *argv[1];

  err = js_get_callback_info(env, info, &argc, argv, NULL, NULL);
  assert(err == 0);

  assert(argc == 1);

  bare_performance_histogram_t *histogram;
  err = js_get_arraybuffer_info(env, argv[0], (void **) &histogram, NULL);
  assert(err == 0);

  hdr_reset(histogram->histogram);

  return NULL;
}

static js_value_t *
bare_performance_exports(js_env_t *env, js_value_t *exports) {
  int err;

  uv_loop_t *loop;
  err = js_get_env_loop(env, &loop);
  assert(err == 0);

  err = uv_loop_configure(loop, UV_METRICS_IDLE_TIME);
  assert(err == 0);

  js_value_t *time_origin;
  err = js_create_double(env, uv_hrtime() / 1e6, &time_origin);
  assert(err == 0);

  err = js_set_named_property(env, exports, "TIME_ORIGIN", time_origin);
  assert(err == 0);

#define V(name, untyped, signature, typed) \
  { \
    js_value_t *val; \
    if (signature) { \
      err = js_create_typed_function(env, name, -1, untyped, signature, typed, NULL, &val); \
      assert(err == 0); \
    } else { \
      err = js_create_function(env, name, -1, untyped, NULL, &val); \
      assert(err == 0); \
    } \
    err = js_set_named_property(env, exports, name, val); \
    assert(err == 0); \
  }

  V(
    "now",
    bare_performance_now,
    &((js_callback_signature_t) {
      .version = 0,
      .result = js_float64,
      .args_len = 1,
      .args = (int[]) {
        js_object,
      },
    }),
    bare_performance_now_typed
  );

  V(
    "idleTime",
    bare_performance_idle_time,
    &((js_callback_signature_t) {
      .version = 0,
      .result = js_float64,
      .args_len = 1,
      .args = (int[]) {
        js_object,
      },
    }),
    bare_performance_idle_time_typed
  );

  V("metricsInfo", bare_performance_metrics_info, NULL, NULL);

  V("histogramInit", bare_performance_histogram_init, NULL, NULL);
  V("histogramPercentiles", bare_performance_histogram_percentiles, NULL, NULL);
  V("histogramPercentile", bare_performance_histogram_percentile, NULL, NULL);
  V("histogramMin", bare_performance_histogram_min, NULL, NULL);
  V("histogramMax", bare_performance_histogram_max, NULL, NULL);
  V("histogramMean", bare_performance_histogram_mean, NULL, NULL);
  V("histogramStddev", bare_performance_histogram_stddev, NULL, NULL);
  V("histogramRecord", bare_performance_histogram_record, NULL, NULL);
  V("histogramAdd", bare_performance_histogram_add, NULL, NULL);
  V("histogramReset", bare_performance_histogram_reset, NULL, NULL);
#undef V

  return exports;
}

BARE_MODULE(bare_performance, bare_performance_exports)