Changeset 899f2d2b74c6a8e1d8fc9a0ede60f226f83d551d

Show
Ignore:
Timestamp:
11/20/11 01:11:20 (2 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1321751480 -0500
git-parent:

[c149f8ad1d420218a0016f2b672b26236b8b3033]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1321751480 -0500
Message:

Performance enhancement populating check metrics from json in lua.
(as in, don't do it in lua, do it all in C). 1.6x speedup.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/modules-lua/noit/module/resmon.lua

    r74f72b1 r899f2d2  
    249249    if string.find(hdrs_in["content-type"] or '', 'json') ~= nil or 
    250250       string.find(hdrs_in["content-type"] or '', 'javascript') ~= nil then 
    251         jsondoc = noit.parsejson(output) 
    252         if jsondoc == nil then 
    253             noit.log("debug", "bad json: %s", output
    254             check.status("json parse error"
    255             return 
    256         end 
    257     end 
    258  
    259     if jsondoc ~= nil then 
    260         json_to_metrics(check, jsondoc) 
    261         return 
     251      services = check.metric_json(output) 
     252      if(services >= 0) then 
     253        check.available(
     254        check.metric_uint32("services", services
     255        if services > 0 then check.good() else check.bad() end 
     256        check.status("services=" .. services) 
     257      else 
     258        noit.log("debug", "bad json: %s", output) 
     259        check.status("json parse error") 
     260      end 
     261      return 
    262262    end 
    263263 
  • src/modules/lua.c

    r33b7efe r899f2d2  
    305305} 
    306306static int 
     307noit_lua_set_metric_json(lua_State *L) { 
     308  noit_check_t *check; 
     309  noit_lua_check_info_t *ci; 
     310  const char *json; 
     311  size_t jsonlen; 
     312  int rv; 
     313 
     314  if(lua_gettop(L) != 1) luaL_error(L, "wrong number of arguments"); 
     315  check = lua_touserdata(L, lua_upvalueindex(1)); 
     316  ci = check->closure; 
     317  if(!lua_isstring(L, 1)) luaL_error(L, "argument #1 must be a string"); 
     318  json = lua_tolstring(L, 1, &jsonlen); 
     319  rv = noit_check_stats_from_json_str(&ci->current, json, (int)jsonlen); 
     320  lua_pushinteger(L, rv); 
     321  return 1; 
     322} 
     323static int 
    307324noit_lua_set_metric(lua_State *L) { 
    308325  noit_check_t *check; 
     
    438455      else IF_METRIC_BLOCK("metric_uint64", METRIC_UINT64) 
    439456      else IF_METRIC_BLOCK("metric_double", METRIC_DOUBLE) 
     457      else if(!strcmp(k, "metric_json")) { 
     458        lua_pushlightuserdata(L, check); 
     459        lua_pushcclosure(L, noit_lua_set_metric_json, 1); 
     460      } 
    440461      else break; 
    441462      return 1; 
  • src/noit_check.c

    rdd420f2 r899f2d2  
    940940 
    941941static size_t 
    942 noit_metric_sizes(metric_type_t type, void *value) { 
     942noit_metric_sizes(metric_type_t type, const void *value) { 
    943943  switch(type) { 
    944944    case METRIC_INT32: 
     
    10761076int 
    10771077noit_stats_populate_metric(metric_t *m, const char *name, metric_type_t type, 
    1078                            void *value) { 
     1078                           const void *value) { 
    10791079  void *replacement = NULL; 
    10801080  if(type == METRIC_GUESS) 
     
    10961096void 
    10971097noit_stats_set_metric(stats_t *newstate, const char *name, metric_type_t type, 
    1098                       void *value) { 
     1098                      const void *value) { 
    10991099  metric_t *m = calloc(1, sizeof(*m)); 
    11001100  if(noit_stats_populate_metric(m, name, type, value)) { 
     
    11031103  } 
    11041104  __stats_add_metric(newstate, m); 
     1105} 
     1106void 
     1107noit_stats_set_metric_coerce(stats_t *stat, const char *name, metric_type_t t, 
     1108                             const char *v) { 
     1109  char *endptr; 
     1110  if(v == NULL) { 
     1111   bogus: 
     1112    noit_stats_set_metric(stat, name, t, NULL); 
     1113    return; 
     1114  } 
     1115  switch(t) { 
     1116    case METRIC_STRING: 
     1117      noit_stats_set_metric(stat, name, t, v); 
     1118      break; 
     1119    case METRIC_INT32: 
     1120    { 
     1121      int32_t val; 
     1122      val = strtol(v, &endptr, 10); 
     1123      if(endptr == v) goto bogus; 
     1124      noit_stats_set_metric(stat, name, t, &val); 
     1125      break; 
     1126    } 
     1127    case METRIC_UINT32: 
     1128    { 
     1129      u_int32_t val; 
     1130      val = strtoul(v, &endptr, 10); 
     1131      if(endptr == v) goto bogus; 
     1132      noit_stats_set_metric(stat, name, t, &val); 
     1133      break; 
     1134    } 
     1135    case METRIC_INT64: 
     1136    { 
     1137      int64_t val; 
     1138      val = strtoll(v, &endptr, 10); 
     1139      if(endptr == v) goto bogus; 
     1140      noit_stats_set_metric(stat, name, t, &val); 
     1141      break; 
     1142    } 
     1143    case METRIC_UINT64: 
     1144    { 
     1145      u_int64_t val; 
     1146      val = strtoull(v, &endptr, 10); 
     1147      if(endptr == v) goto bogus; 
     1148      noit_stats_set_metric(stat, name, t, &val); 
     1149      break; 
     1150    } 
     1151    case METRIC_DOUBLE: 
     1152    { 
     1153      double val; 
     1154      val = strtod(v, &endptr); 
     1155      if(endptr == v) goto bogus; 
     1156      noit_stats_set_metric(stat, name, t, &val); 
     1157      break; 
     1158    } 
     1159    case METRIC_GUESS: 
     1160      noit_stats_set_metric(stat, name, t, v); 
     1161      break; 
     1162  } 
    11051163} 
    11061164void 
  • src/noit_check.h

    r16b1bdd r899f2d2  
    244244 
    245245API_EXPORT(void) 
    246   noit_stats_set_metric(stats_t *, const char *, metric_type_t, void *); 
     246  noit_stats_set_metric(stats_t *, const char *, metric_type_t, const void *); 
     247 
     248API_EXPORT(void) 
     249  noit_stats_set_metric_coerce(stats_t *, const char *, metric_type_t, 
     250                               const char *); 
    247251 
    248252API_EXPORT(void) 
  • src/noit_check_tools.c

    rf207009 r899f2d2  
    3636#include "noit_check_tools_shared.h" 
    3737#include "utils/noit_str.h" 
     38#include "json-lib/json.h" 
    3839 
    3940#include <assert.h> 
     
    153154} 
    154155 
     156static int 
     157populate_stats_from_resmon_formatted_json(stats_t *s, struct json_object *o, 
     158                                          const char *prefix) { 
     159  int count = 0; 
     160  char keybuff[256]; 
     161#define MKKEY(fmt, arg) do { \ 
     162  if(prefix) snprintf(keybuff, sizeof(keybuff), "%s`" fmt, prefix, arg); \ 
     163  else snprintf(keybuff, sizeof(keybuff), fmt, arg); \ 
     164} while(0) 
     165  switch(json_object_get_type(o)) { 
     166    /* sub callers */ 
     167    case json_type_array: 
     168    { 
     169      int i, alen = json_object_array_length(o); 
     170      for(i=0;i<alen;i++) { 
     171        struct json_object *item = json_object_array_get_idx(o, i); 
     172        MKKEY("%d", i); 
     173        count += populate_stats_from_resmon_formatted_json(s, item, keybuff); 
     174      } 
     175    } 
     176    break; 
     177    case json_type_object: 
     178    { 
     179      struct lh_table *lh; 
     180      struct lh_entry *el; 
     181      struct json_object *has_type = NULL, *has_value = NULL; 
     182      lh = json_object_get_object(o); 
     183      lh_foreach(lh, el) { 
     184        if(!strcmp(el->k, "_type")) has_type = (struct json_object *)el->v; 
     185        else if(!strcmp(el->k, "_value")) has_value = (struct json_object *)el->v; 
     186        else { 
     187          struct json_object *item = (struct json_object *)el->v; 
     188          MKKEY("%s", (const char *)el->k); 
     189          count += populate_stats_from_resmon_formatted_json(s, item, keybuff); 
     190        } 
     191      } 
     192      if(prefix && has_type && has_value && 
     193         json_object_is_type(has_type, json_type_string) && 
     194         json_object_is_type(has_value, json_type_string)) { 
     195        const char *type_str = json_object_get_string(has_type); 
     196        const char *value_str = json_object_get_string(has_value); 
     197        switch(*type_str) { 
     198          case METRIC_INT32: 
     199          case METRIC_UINT32: 
     200          case METRIC_INT64: 
     201          case METRIC_UINT64: 
     202          case METRIC_DOUBLE: 
     203          case METRIC_STRING: 
     204            noit_stats_set_metric_coerce(s, prefix, 
     205                                         (metric_type_t)*type_str, value_str); 
     206            count++; 
     207          default: 
     208            break; 
     209        } 
     210      } 
     211      break; 
     212    } 
     213 
     214    /* directs */ 
     215    case json_type_string: 
     216      if(prefix) { 
     217        noit_stats_set_metric(s, prefix, METRIC_GUESS, 
     218                              (char *)json_object_get_string(o)); 
     219        count++; 
     220      } 
     221      break; 
     222    case json_type_boolean: 
     223      if(prefix) { 
     224        int val = json_object_get_boolean(o) ? 1 : 0; 
     225        noit_stats_set_metric(s, prefix, METRIC_INT32, &val); 
     226        count++; 
     227      } 
     228      break; 
     229    case json_type_null: 
     230      if(prefix) { 
     231        noit_stats_set_metric(s, prefix, METRIC_STRING, NULL); 
     232        count++; 
     233      } 
     234      break; 
     235    case json_type_double: 
     236      if(prefix) { 
     237        double val = json_object_get_double(o); 
     238        noit_stats_set_metric(s, prefix, METRIC_DOUBLE, &val); 
     239        count++; 
     240      } 
     241      break; 
     242    case json_type_int: 
     243      if(prefix) { 
     244        int64_t i64; 
     245        uint64_t u64; 
     246        switch(json_object_get_int_overflow(o)) { 
     247          case json_overflow_int: 
     248            i64 = json_object_get_int(o); 
     249            noit_stats_set_metric(s, prefix, METRIC_INT64, &i64); 
     250            count++; 
     251            break; 
     252          case json_overflow_int64: 
     253            i64 = json_object_get_int64(o); 
     254            noit_stats_set_metric(s, prefix, METRIC_INT64, &i64); 
     255            count++; 
     256            break; 
     257          case json_overflow_uint64: 
     258            u64 = json_object_get_uint64(o); 
     259            noit_stats_set_metric(s, prefix, METRIC_UINT64, &u64); 
     260            count++; 
     261            break; 
     262        } 
     263      } 
     264  } 
     265  return count; 
     266} 
     267int 
     268noit_check_stats_from_json_str(stats_t *s, const char *json_str, int len) { 
     269  int rv = -1; 
     270  struct json_tokener *tok = NULL; 
     271  struct json_object *root = NULL; 
     272  tok = json_tokener_new(); 
     273  root = json_tokener_parse_ex(tok, json_str, len); 
     274  if(root) rv = populate_stats_from_resmon_formatted_json(s, root, NULL); 
     275  if(tok) json_tokener_free(tok); 
     276  if(root) json_object_put(root); 
     277  return rv; 
     278} 
  • src/noit_check_tools.h

    rf91ddca r899f2d2  
    5959  noit_check_run_full_asynch(noit_check_t *check, eventer_func_t callback); 
    6060 
     61API_EXPORT(int) 
     62  noit_check_stats_from_json_str(stats_t *s, const char *json_str, int len); 
     63 
    6164#define INITIATE_CHECK(func, self, check, cause) do { \ 
    6265  if(once) { \