]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
add htsmsg/htsmsg_field to memoryinfo statistics
authorJaroslav Kysela <perex@perex.cz>
Sun, 13 Mar 2016 18:19:50 +0000 (19:19 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 14 Mar 2016 08:42:45 +0000 (09:42 +0100)
configure
src/htsmsg.c
src/htsmsg.h
src/htsmsg_binary.c
src/htsmsg_binary.h
src/htsmsg_xml.c
src/main.c
src/memoryinfo.h

index dac82a135d690383b186dd7151e0bbb0e0383f70..ff9ac8496572911688ecfce41e455ba2df42273e 100755 (executable)
--- a/configure
+++ b/configure
@@ -55,6 +55,7 @@ OPTIONS=(
   "android:no"
   "tsdebug:no"
   "gtimer_check:no"
+  "slow_memoryinfo:no"
   "libsystemd_daemon:no"
   "bintray_cache:yes"
 )
index 2238f04da0ba2d2cf3d8b273a68e378b67f01c95..844b14b3f52298676446ef54b90f9ba0630667b4 100644 (file)
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
+#include "build.h"
 #include "htsmsg.h"
 #include "misc/dbl.h"
 #include "htsmsg_json.h"
+#include "memoryinfo.h"
+
+#if ENABLE_SLOW_MEMORYINFO
+memoryinfo_t htsmsg_memoryinfo = { .my_name = "htsmsg" };
+memoryinfo_t htsmsg_field_memoryinfo = { .my_name = "htsmsg field" };
+#endif
 
 static void htsmsg_clear(htsmsg_t *msg);
-static htsmsg_t *
-htsmsg_field_get_msg ( htsmsg_field_t *f, int islist );
+static htsmsg_t *htsmsg_field_get_msg ( htsmsg_field_t *f, int islist );
 
 /**
  *
@@ -44,13 +50,21 @@ htsmsg_field_data_destroy(htsmsg_field_t *f)
     break;
 
   case HMF_STR:
-    if(f->hmf_flags & HMF_ALLOCED)
+    if(f->hmf_flags & HMF_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+      memoryinfo_remove(&htsmsg_field_memoryinfo, strlen(f->hmf_str) + 1);
+#endif
       free((void *)f->hmf_str);
+    }
     break;
 
   case HMF_BIN:
-    if(f->hmf_flags & HMF_ALLOCED)
+    if(f->hmf_flags & HMF_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+      memoryinfo_remove(&htsmsg_field_memoryinfo, f->hmf_binsize);
+#endif
       free((void *)f->hmf_bin);
+    }
     break;
   default:
     break;
@@ -64,12 +78,24 @@ htsmsg_field_data_destroy(htsmsg_field_t *f)
 void
 htsmsg_field_destroy(htsmsg_t *msg, htsmsg_field_t *f)
 {
+#if ENABLE_SLOW_MEMORYINFO
+  size_t asize = 0;
+#endif
+
   TAILQ_REMOVE(&msg->hm_fields, f, hmf_link);
 
   htsmsg_field_data_destroy(f);
 
-  if(f->hmf_flags & HMF_NAME_ALLOCED)
+  if (f->hmf_flags & HMF_NAME_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+    asize += strlen(f->hmf_name);
+#endif
     free((void *)f->hmf_name);
+  }
+#if ENABLE_SLOW_MEMORYINFO
+  memoryinfo_free(&htsmsg_field_memoryinfo,
+                  sizeof(*f) + f->hmf_edata_size + asize);
+#endif
   free(f);
 }
 
@@ -94,6 +120,9 @@ htsmsg_field_add(htsmsg_t *msg, const char *name, int type, int flags, size_t es
 {
   size_t nsize = 0;
   htsmsg_field_t *f;
+#if ENABLE_SLOW_MEMORYINFO
+  size_t asize = 0;
+#endif
   
   if((flags & HMF_NAME_INALLOCED) && name)
     nsize = strlen(name) + 1;
@@ -112,18 +141,32 @@ htsmsg_field_add(htsmsg_t *msg, const char *name, int type, int flags, size_t es
     if (name) {
       f->hmf_name = f->hmf_edata;
       strcpy(f->hmf_edata, name);
+    } else {
+      f->hmf_name = NULL;
     }
   } else if(flags & HMF_NAME_ALLOCED) {
     f->hmf_name = name ? strdup(name) : NULL;
+#if ENABLE_SLOW_MEMORYINFO
+    asize = name ? strlen(name) + 1 : 0;
+#endif
   } else {
     f->hmf_name = name;
   }
 
-  if(esize)
-    f->hmf_str = f->hmf_edata + nsize;
+  if(esize) {
+    if(type == HMF_STR)
+      f->hmf_str = f->hmf_edata + nsize;
+    else if(type == HMF_BIN)
+      f->hmf_bin = f->hmf_edata + nsize;
+  }
 
   f->hmf_type = type;
   f->hmf_flags = flags;
+#if ENABLE_SLOW_MEMORYINFO
+  f->hmf_edata_size = nsize + esize;
+  memoryinfo_alloc(&htsmsg_field_memoryinfo,
+                   sizeof(htsmsg_field_t) + f->hmf_edata_size + asize);
+#endif
   return f;
 }
 
@@ -196,9 +239,15 @@ htsmsg_create_map(void)
   htsmsg_t *msg;
 
   msg = malloc(sizeof(htsmsg_t));
-  TAILQ_INIT(&msg->hm_fields);
-  msg->hm_data = NULL;
-  msg->hm_islist = 0;
+  if (msg) {
+    TAILQ_INIT(&msg->hm_fields);
+    msg->hm_data = NULL;
+    msg->hm_data_size = 0;
+    msg->hm_islist = 0;
+#if ENABLE_SLOW_MEMORYINFO
+    memoryinfo_alloc(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
+  }
   return msg;
 }
 
@@ -211,9 +260,15 @@ htsmsg_create_list(void)
   htsmsg_t *msg;
 
   msg = malloc(sizeof(htsmsg_t));
-  TAILQ_INIT(&msg->hm_fields);
-  msg->hm_data = NULL;
-  msg->hm_islist = 1;
+  if (msg) {
+    TAILQ_INIT(&msg->hm_fields);
+    msg->hm_data = NULL;
+    msg->hm_data_size = 0;
+    msg->hm_islist = 1;
+#if ENABLE_SLOW_MEMORYINFO
+    memoryinfo_alloc(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
+  }
   return msg;
 }
 
@@ -224,11 +279,23 @@ htsmsg_create_list(void)
 void
 htsmsg_destroy(htsmsg_t *msg)
 {
+#if ENABLE_SLOW_MEMORYINFO
+  size_t size = 0;
+#endif
+
   if(msg == NULL)
     return;
 
   htsmsg_clear(msg);
-  free((void *)msg->hm_data);
+  if (msg->hm_data) {
+    free((void *)msg->hm_data);
+#if ENABLE_SLOW_MEMORYINFO
+    size += msg->hm_data_size;
+#endif
+  }
+#if ENABLE_SLOW_MEMORYINFO
+  memoryinfo_free(&htsmsg_memoryinfo, sizeof(htsmsg_t) + size);
+#endif
   free(msg);
 }
 
@@ -289,6 +356,7 @@ htsmsg_add_str(htsmsg_t *msg, const char *name, const char *str)
   htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_STR, HMF_NAME_INALLOCED,
                                        strlen(str) + 1);
   strcpy((char *)f->hmf_str, str);
+  f->hmf_flags |= HMF_INALLOCED;
 }
 
 /*
@@ -328,10 +396,24 @@ htsmsg_field_set_str(htsmsg_field_t *f, const char *str)
 {
   if (f->hmf_type != HMF_STR)
     return 1;
-  if (f->hmf_flags & HMF_ALLOCED)
+  if (f->hmf_flags & HMF_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+    memoryinfo_remove(&htsmsg_field_memoryinfo, strlen(f->hmf_str) + 1);
+#endif
     free((void *)f->hmf_str);
+  }
+  else if (f->hmf_flags & HMF_INALLOCED) {
+    if (strlen(f->hmf_str) >= strlen(str)) {
+      strcpy((char *)f->hmf_str, str);
+      return 0;
+    }
+    f->hmf_flags &= ~HMF_INALLOCED;
+  }
   f->hmf_flags |= HMF_ALLOCED;
   f->hmf_str = strdup(str);
+#if ENABLE_SLOW_MEMORYINFO
+  memoryinfo_alloc(&htsmsg_field_memoryinfo, strlen(str) + 1);
+#endif
   return 0;
 }
 
@@ -342,8 +424,10 @@ int
 htsmsg_set_str(htsmsg_t *msg, const char *name, const char *str)
 {
   htsmsg_field_t *f = htsmsg_field_find(msg, name);
-  if (!f)
-    f = htsmsg_field_add(msg, name, HMF_STR, HMF_NAME_INALLOCED, 0);
+  if (!f) {
+    htsmsg_add_str(msg, name, str);
+    return 0;
+  }
   return htsmsg_field_set_str(f, str);
 }
 
@@ -356,6 +440,7 @@ htsmsg_add_bin(htsmsg_t *msg, const char *name, const void *bin, size_t len)
   htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_BIN, HMF_NAME_INALLOCED, len);
   f->hmf_bin = f->hmf_str;
   f->hmf_binsize = len;
+  f->hmf_flags |= HMF_INALLOCED;
   memcpy((void *)f->hmf_bin, bin, len);
 }
 
@@ -379,8 +464,12 @@ htsmsg_field_set_msg(htsmsg_field_t *f, htsmsg_t *sub)
 {
   assert(sub->hm_data == NULL);
   f->hmf_msg.hm_data = NULL;
+  f->hmf_msg.hm_data_size = 0;
   f->hmf_msg.hm_islist = sub->hm_islist;
   TAILQ_MOVE(&f->hmf_msg.hm_fields, &sub->hm_fields, hmf_link);
+#if ENABLE_SLOW_MEMORYINFO
+  memoryinfo_free(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
   free(sub);
 
   if (f->hmf_type == (f->hmf_msg.hm_islist ? HMF_LIST : HMF_MAP))
@@ -429,8 +518,12 @@ htsmsg_add_msg_extname(htsmsg_t *msg, const char *name, htsmsg_t *sub)
 
   assert(sub->hm_data == NULL);
   f->hmf_msg.hm_data = NULL;
+  f->hmf_msg.hm_data_size = 0;
   TAILQ_MOVE(&f->hmf_msg.hm_fields, &sub->hm_fields, hmf_link);
   f->hmf_msg.hm_islist = sub->hm_islist;
+#if ENABLE_SLOW_MEMORYINFO
+  memoryinfo_free(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
   free(sub);
 }
 
@@ -688,21 +781,15 @@ htsmsg_field_get_string(htsmsg_field_t *f)
   case HMF_STR:
     break;
   case HMF_BOOL:
-    f->hmf_str = strdup(f->hmf_bool ? "true" : "false");
-    f->hmf_type = HMF_STR;
-    f->hmf_flags |= HMF_ALLOCED;
+    htsmsg_field_set_str(f, f->hmf_bool ? "true" : "false");
     break;
   case HMF_S64:
     snprintf(buf, sizeof(buf), "%"PRId64, f->hmf_s64);
-    f->hmf_str = strdup(buf);
-    f->hmf_type = HMF_STR;
-    f->hmf_flags |= HMF_ALLOCED;
+    htsmsg_field_set_str(f, buf);
     break;
   case HMF_DBL:
     snprintf(buf, sizeof(buf), "%lf", f->hmf_dbl);
-    f->hmf_str = strdup(buf);
-    f->hmf_type = HMF_STR;
-    f->hmf_flags |= HMF_ALLOCED;
+    htsmsg_field_set_str(f, buf);
     break;
   }
   return f->hmf_str;
@@ -816,11 +903,20 @@ htsmsg_field_get_msg ( htsmsg_field_t *f, int islist )
   /* Deserialize JSON (will keep either list or map) */
   if (f->hmf_type == HMF_STR) {
     if ((m = htsmsg_json_deserialize(f->hmf_str))) {
-      free((void*)f->hmf_str);
+      if (f->hmf_flags & HMF_ALLOCED) {
+#if ENABLE_SLOW_MEMORYINFO
+        memoryinfo_free(&htsmsg_field_memoryinfo, strlen(f->hmf_str) + 1);
+#endif
+        free((void*)f->hmf_str);
+      }
       f->hmf_type          = m->hm_islist ? HMF_LIST : HMF_MAP;
       f->hmf_msg.hm_islist = m->hm_islist;
       f->hmf_msg.hm_data   = NULL;
+      f->hmf_msg.hm_data_size = 0;
       TAILQ_MOVE(&f->hmf_msg.hm_fields, &m->hm_fields, hmf_link);
+#if ENABLE_SLOW_MEMORYINFO
+      memoryinfo_free(&htsmsg_memoryinfo, sizeof(htsmsg_t));
+#endif
       free(m);
     }
   }
@@ -1087,7 +1183,6 @@ htsmsg_list_2_csv(htsmsg_t *m, char delim, int human)
   const char *ssep;
   if (!m->hm_islist) return NULL;
 
-#define MAX(a,b) ((a) < (b)) ? (a) : (b)
 #define REALLOC(l)\
   if ((alloc - used) < l) {\
     alloc = MAX((l)*2, alloc*2);\
index 0d3cdf8100e6ec5cd0dc29669e5a221aaa07c3b2..0f899630752c40d198f4108d4425cdf16a843a13 100644 (file)
@@ -20,6 +20,7 @@
 #include <stdlib.h>
 #include <inttypes.h>
 #include "queue.h"
+#include "build.h"
 
 #define HTSMSG_ERR_FIELD_NOT_FOUND       -1
 #define HTSMSG_ERR_CONVERSION_IMPOSSIBLE -2
@@ -41,6 +42,7 @@ typedef struct htsmsg {
    * Data to be free'd when the message is destroyed
    */
   const void *hm_data;
+  size_t hm_data_size;
 } htsmsg_t;
 
 
@@ -59,8 +61,9 @@ typedef struct htsmsg_field {
   uint8_t hmf_flags;
 
 #define HMF_ALLOCED        0x1
-#define HMF_NAME_INALLOCED 0x2
-#define HMF_NAME_ALLOCED   0x4
+#define HMF_INALLOCED      0x2
+#define HMF_NAME_INALLOCED 0x4
+#define HMF_NAME_ALLOCED   0x8
 
   union {
     int64_t  s64;
@@ -73,6 +76,10 @@ typedef struct htsmsg_field {
     double dbl;
     int bool;
   } u;
+
+#if ENABLE_SLOW_MEMORYINFO
+  size_t hmf_edata_size;
+#endif
   char hmf_edata[0];
 } htsmsg_field_t;
 
@@ -418,3 +425,10 @@ const char *htsmsg_get_cdata(htsmsg_t *m, const char *field);
 char *htsmsg_list_2_csv(htsmsg_t *m, char delim, int human);
 
 htsmsg_t *htsmsg_csv_2_list(const char *str, char delim);
+
+/**
+ *
+ */
+struct memoryinfo;
+extern struct memoryinfo htsmsg_memoryinfo;
+extern struct memoryinfo htsmsg_field_memoryinfo;
index 074da77afe8b2f7edbcf8a31a574fbcc132a4396..0a835eaaeca8db3daa9cac855f0a5598bba80cbb 100644 (file)
@@ -24,6 +24,7 @@
 #include <string.h>
 
 #include "htsmsg_binary.h"
+#include "memoryinfo.h"
 
 /*
  *
 static int
 htsmsg_binary_des0(htsmsg_t *msg, const uint8_t *buf, size_t len)
 {
-  unsigned type, namelen, datalen;
+  uint_fast32_t type, namelen, datalen;
+  size_t tlen;
   htsmsg_field_t *f;
   htsmsg_t *sub;
-  char *n;
   uint64_t u64;
-  int i;
+  int i, bin = 0;
 
   while(len > 5) {
 
@@ -53,36 +54,43 @@ htsmsg_binary_des0(htsmsg_t *msg, const uint8_t *buf, size_t len)
     if(len < namelen + datalen)
       return -1;
 
-    f = malloc(sizeof(htsmsg_field_t));
+    tlen = sizeof(htsmsg_field_t) +
+           (namelen ? namelen + 1 : 0) +
+           (type == HMF_STR ? datalen + 1 : 0);
+    f = malloc(tlen);
+    if (f == NULL)
+      return -1;
+#if ENABLE_SLOW_MEMORYINFO
+    f->hmf_edata_size = tlen - sizeof(htsmsg_field_t);
+    memoryinfo_alloc(&htsmsg_field_memoryinfo, tlen);
+#endif
     f->hmf_type  = type;
 
     if(namelen > 0) {
-      n = malloc(namelen + 1);
-      memcpy(n, buf, namelen);
-      n[namelen] = 0;
+      f->hmf_name = f->hmf_edata;
+      memcpy(f->hmf_edata, buf, namelen);
+      f->hmf_edata[namelen] = 0;
 
       buf += namelen;
       len -= namelen;
-      f->hmf_flags = HMF_NAME_ALLOCED;
+      f->hmf_flags = HMF_NAME_INALLOCED;
 
     } else {
-      n = NULL;
+      f->hmf_name  = NULL;
       f->hmf_flags = 0;
     }
 
-    f->hmf_name  = n;
-
     switch(type) {
     case HMF_STR:
-      f->hmf_str = n = malloc(datalen + 1);
-      memcpy(n, buf, datalen);
-      n[datalen] = 0;
-      f->hmf_flags |= HMF_ALLOCED;
+      f->hmf_str = f->hmf_edata + (namelen ? namelen + 1 : 0);
+      memcpy((char *)f->hmf_str, buf, datalen);
+      ((char *)f->hmf_str)[datalen] = 0;
       break;
 
     case HMF_BIN:
       f->hmf_bin = (const void *)buf;
       f->hmf_binsize = datalen;
+      bin = 1;
       break;
 
     case HMF_S64:
@@ -97,11 +105,16 @@ htsmsg_binary_des0(htsmsg_t *msg, const uint8_t *buf, size_t len)
       sub = &f->hmf_msg;
       TAILQ_INIT(&sub->hm_fields);
       sub->hm_data = NULL;
-      if(htsmsg_binary_des0(sub, buf, datalen) < 0) {
-        free(n);
+      i = htsmsg_binary_des0(sub, buf, datalen);
+      if (i < 0) {
+#if ENABLE_SLOW_MEMORYINFO
+        memoryinfo_free(&htsmsg_field_memoryinfo, tlen);
+#endif
         free(f);
         return -1;
       }
+      if (i > 0)
+        bin = 1;
       break;
 
     case HMF_BOOL:
@@ -109,7 +122,9 @@ htsmsg_binary_des0(htsmsg_t *msg, const uint8_t *buf, size_t len)
       break;
 
     default:
-      free(n);
+#if ENABLE_SLOW_MEMORYINFO
+      memoryinfo_free(&htsmsg_field_memoryinfo, tlen);
+#endif
       free(f);
       return -1;
     }
@@ -118,7 +133,7 @@ htsmsg_binary_des0(htsmsg_t *msg, const uint8_t *buf, size_t len)
     buf += datalen;
     len -= datalen;
   }
-  return 0;
+  return bin;
 }
 
 
@@ -127,15 +142,21 @@ htsmsg_binary_des0(htsmsg_t *msg, const uint8_t *buf, size_t len)
  *
  */
 htsmsg_t *
-htsmsg_binary_deserialize(const void *data, size_t len, const void *buf)
+htsmsg_binary_deserialize(void *data, size_t len, const void *buf)
 {
   htsmsg_t *msg = htsmsg_create_map();
-  msg->hm_data = buf;
-
-  if(htsmsg_binary_des0(msg, data, len) < 0) {
+  int r = htsmsg_binary_des0(msg, data, len);
+  if (r < 0) {
     htsmsg_destroy(msg);
     return NULL;
   }
+  if (r > 0) {
+    msg->hm_data = buf;
+    msg->hm_data_size = len;
+#if ENABLE_SLOW_MEMORYINFO
+    memoryinfo_append(&htsmsg_memoryinfo, len);
+#endif
+  }
   return msg;
 }
 
index 74c0e125151c097147b8aaba81ed4798c3bb991c..55dc0895e62400219429b65879dea0c80b8526f9 100644 (file)
@@ -24,7 +24,7 @@
 /**
  * htsmsg_binary_deserialize
  */
-htsmsg_t *htsmsg_binary_deserialize(const void *data, size_t len,
+htsmsg_t *htsmsg_binary_deserialize(void *data, size_t len,
                                    const void *buf);
 
 int htsmsg_binary_serialize(htsmsg_t *msg, void **datap, size_t *lenp,
index b13f2d8022fc4246bd07dda1de1a977064fd12b8..c9edc1a0e16e10bfefecc639d1a22d5385103b42 100644 (file)
@@ -849,6 +849,7 @@ htsmsg_xml_deserialize(char *src, char *errbuf, size_t errbufsize)
 
   if(xp.xp_srcdataused) {
     m->hm_data = src0;
+    m->hm_data_size = strlen(src0) + 1;
   } else {
     free(src0);
   }
index 7c191a96929184325a9e909345b65777c1fa8359..5164a717eb328131373bfbfc0edac0b0d1b341e2 100644 (file)
@@ -1135,6 +1135,10 @@ main(int argc, char **argv)
 
   /* Memoryinfo */
   memoryinfo_register(&tasklet_memoryinfo);
+#if ENABLE_SLOW_MEMORYINFO
+  memoryinfo_register(&htsmsg_memoryinfo);
+  memoryinfo_register(&htsmsg_field_memoryinfo);
+#endif
   memoryinfo_register(&pkt_memoryinfo);
   memoryinfo_register(&pktbuf_memoryinfo);
   memoryinfo_register(&pktref_memoryinfo);
index 44d127f6bb65363399b7aa0816aa0a88146fd28c..f759a1637eba04efb273aad4b424137ebecf30b7 100644 (file)
@@ -75,5 +75,9 @@ static inline void memoryinfo_free(memoryinfo_t *my, int64_t size)
   atomic_dec_s64(&my->my_count, 1);
 }
 
+static inline void memoryinfo_remove(memoryinfo_t *my, int64_t size)
+{
+  atomic_dec_s64(&my->my_size, size);
+}
 
 #endif /* TVHEADEND_MEMORYINFO_H */