@cryptotaxi247 / netdata-1 / commits / 6faa02d1a

eliminate another file descriptor loop in apps.plugin

Costa Tsaousis (ktsaou) committed Jan 22, 2017 at 05:39 UTC 6faa02d1a3c053f9a572fd589bbdd6edfbeffe37
1 file changed +153 -109
src/apps_plugin.c
+153 -109
@@ -13,7 +13,7 @@
13 // etc.
14 #define RATES_DETAIL 10000ULL
15
16 -#define MAX_SPARE_FDS 10
16 +#define MAX_SPARE_FDS 1
17
18 int debug = 0;
19
@@ -1023,70 +1023,60 @@ static inline void file_descriptor_not_used(int id)
1023 else error("Request to decrease counter of fd %d, which is outside the array size (1 to %d)", id, all_files_size);
1024 }
1025
1026 -static inline int file_descriptor_find_or_add(const char *name)
1027 -{
1028 - static int last_pos = 0;
1029 - uint32_t hash = simple_hash(name);
1026 +static inline void all_files_grow() {
1027 + void *old = all_files;
1028 + int i;
1029
1030 + // there is no empty slot
1031 if(unlikely(debug))
1032 - fprintf(stderr, "apps.plugin: adding or finding name '%s' with hash %u\n", name, hash);
1032 + fprintf(stderr, "apps.plugin: extending fd array to %d entries\n", all_files_size + FILE_DESCRIPTORS_INCREASE_STEP);
1033
1034 - struct file_descriptor *fd = file_descriptor_find(name, hash);
1035 - if(fd) {
1036 - // found
1037 - if(unlikely(debug))
1038 - fprintf(stderr, "apps.plugin: >> found on slot %d\n", fd->pos);
1034 + all_files = reallocz(all_files, (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP) * sizeof(struct file_descriptor));
1035
1040 - fd->count++;
1041 - return fd->pos;
1042 - }
1043 - // not found
1036 + // if the address changed, we have to rebuild the index
1037 + // since all pointers are now invalid
1038
1045 - // check we have enough memory to add it
1046 - if(!all_files || all_files_len == all_files_size) {
1047 - void *old = all_files;
1048 - int i;
1049 -
1050 - // there is no empty slot
1039 + if(unlikely(old && old != (void *)all_files)) {
1040 if(unlikely(debug))
1052 - fprintf(stderr, "apps.plugin: extending fd array to %d entries\n", all_files_size + FILE_DESCRIPTORS_INCREASE_STEP);
1041 + fprintf(stderr, "apps.plugin: >> re-indexing.\n");
1042
1054 - all_files = reallocz(all_files, (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP) * sizeof(struct file_descriptor));
1043 + all_files_index.root = NULL;
1044 + for(i = 0; i < all_files_size; i++) {
1045 + if(!all_files[i].count) continue;
1046 + if(unlikely(file_descriptor_add(&all_files[i]) != (void *)&all_files[i]))
1047 + error("INTERNAL ERROR: duplicate indexing of fd during realloc.");
1048 + }
1049
1056 - // if the address changed, we have to rebuild the index
1057 - // since all pointers are now invalid
1058 - if(old && old != (void *)all_files) {
1059 - if(unlikely(debug))
1060 - fprintf(stderr, "apps.plugin: >> re-indexing.\n");
1050 + if(unlikely(debug))
1051 + fprintf(stderr, "apps.plugin: >> re-indexing done.\n");
1052 + }
1053
1062 - all_files_index.root = NULL;
1063 - for(i = 0; i < all_files_size; i++) {
1064 - if(!all_files[i].count) continue;
1065 - if(unlikely(file_descriptor_add(&all_files[i]) != (void *)&all_files[i]))
1066 - error("INTERNAL ERROR: duplicate indexing of fd during realloc.");
1067 - }
1054 + // initialize the newly added entries
1055
1069 - if(unlikely(debug))
1070 - fprintf(stderr, "apps.plugin: >> re-indexing done.\n");
1071 - }
1072 -
1073 - for(i = all_files_size; i < (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP); i++) {
1074 - all_files[i].count = 0;
1075 - all_files[i].name = NULL;
1056 + for(i = all_files_size; i < (all_files_size + FILE_DESCRIPTORS_INCREASE_STEP); i++) {
1057 + all_files[i].count = 0;
1058 + all_files[i].name = NULL;
1059 #ifdef NETDATA_INTERNAL_CHECKS
1077 - all_files[i].magic = 0x00000000;
1060 + all_files[i].magic = 0x00000000;
1061 #endif /* NETDATA_INTERNAL_CHECKS */
1079 - all_files[i].pos = i;
1080 - }
1081 -
1082 - if(!all_files_size) all_files_len = 1;
1083 - all_files_size += FILE_DESCRIPTORS_INCREASE_STEP;
1062 + all_files[i].pos = i;
1063 }
1064
1065 + if(unlikely(!all_files_size)) all_files_len = 1;
1066 + all_files_size += FILE_DESCRIPTORS_INCREASE_STEP;
1067 +}
1068 +
1069 +static inline int file_descriptor_set_on_empty_slot(const char *name, uint32_t hash, int type) {
1070 + // check we have enough memory to add it
1071 + if(!all_files || all_files_len == all_files_size)
1072 + all_files_grow();
1073 +
1074 if(unlikely(debug))
1075 fprintf(stderr, "apps.plugin: >> searching for empty slot.\n");
1076
1077 // search for an empty slot
1078 +
1079 + static int last_pos = 0;
1080 int i, c;
1081 for(i = 0, c = last_pos ; i < all_files_size ; i++, c++) {
1082 if(c >= all_files_size) c = 0;
@@ -1104,23 +1094,58 @@ static inline int file_descriptor_find_or_add(const char *name)
1094 if(unlikely(debug))
1095 fprintf(stderr, "apps.plugin: >> %s fd position %d for %s (last name: %s)\n", all_files[c].name?"re-using":"using", c, name, all_files[c].name);
1096
1107 - if(all_files[c].name) freez((void *)all_files[c].name);
1097 + freez((void *)all_files[c].name);
1098 all_files[c].name = NULL;
1099 last_pos = c;
1100 break;
1101 }
1102 }
1103 +
1104 + all_files_len++;
1105 +
1106 if(i == all_files_size) {
1107 fatal("We should find an empty slot, but there isn't any");
1108 exit(1);
1109 }
1110 + // else we have an empty slot in 'c'
1111
1112 if(unlikely(debug))
1113 fprintf(stderr, "apps.plugin: >> updating slot %d.\n", c);
1114
1121 - all_files_len++;
1115 + all_files[c].name = strdupz(name);
1116 + all_files[c].hash = hash;
1117 + all_files[c].type = type;
1118 + all_files[c].pos = c;
1119 + all_files[c].count = 1;
1120 +#ifdef NETDATA_INTERNAL_CHECKS
1121 + all_files[c].magic = 0x0BADCAFE;
1122 +#endif /* NETDATA_INTERNAL_CHECKS */
1123 + if(unlikely(file_descriptor_add(&all_files[c]) != (void *)&all_files[c]))
1124 + error("INTERNAL ERROR: duplicate indexing of fd.");
1125
1123 - // else we have an empty slot in 'c'
1126 + if(unlikely(debug))
1127 + fprintf(stderr, "apps.plugin: using fd position %d (name: %s)\n", c, all_files[c].name);
1128 +
1129 + return c;
1130 +}
1131 +
1132 +static inline int file_descriptor_find_or_add(const char *name)
1133 +{
1134 + uint32_t hash = simple_hash(name);
1135 +
1136 + if(unlikely(debug))
1137 + fprintf(stderr, "apps.plugin: adding or finding name '%s' with hash %u\n", name, hash);
1138 +
1139 + struct file_descriptor *fd = file_descriptor_find(name, hash);
1140 + if(fd) {
1141 + // found
1142 + if(unlikely(debug))
1143 + fprintf(stderr, "apps.plugin: >> found on slot %d\n", fd->pos);
1144 +
1145 + fd->count++;
1146 + return fd->pos;
1147 + }
1148 + // not found
1149
1150 int type;
1151 if(name[0] == '/') type = FILETYPE_FILE;
@@ -1144,21 +1169,7 @@ static inline int file_descriptor_find_or_add(const char *name)
1169 type = FILETYPE_OTHER;
1170 }
1171
1147 - all_files[c].name = strdupz(name);
1148 - all_files[c].hash = hash;
1149 - all_files[c].type = type;
1150 - all_files[c].pos = c;
1151 - all_files[c].count = 1;
1152 -#ifdef NETDATA_INTERNAL_CHECKS
1153 - all_files[c].magic = 0x0BADCAFE;
1154 -#endif /* NETDATA_INTERNAL_CHECKS */
1155 - if(unlikely(file_descriptor_add(&all_files[c]) != (void *)&all_files[c]))
1156 - error("INTERNAL ERROR: duplicate indexing of fd.");
1157 -
1158 - if(unlikely(debug))
1159 - fprintf(stderr, "apps.plugin: using fd position %d (name: %s)\n", c, all_files[c].name);
1160 -
1161 - return c;
1172 + return file_descriptor_set_on_empty_slot(name, hash, type);
1173 }
1174
1175 static inline int read_pid_file_descriptors(struct pid_stat *p) {
@@ -1189,10 +1200,6 @@ static inline int read_pid_file_descriptors(struct pid_stat *p) {
1200 fprintf(stderr, "apps.plugin: extending fd memory slots for %s from %d to %d\n", p->comm, p->fds_size, fdid + MAX_SPARE_FDS);
1201
1202 p->fds = reallocz(p->fds, (fdid + MAX_SPARE_FDS) * sizeof(int));
1192 - if(!p->fds) {
1193 - fatal("Cannot re-allocate fds for %s", p->comm);
1194 - break;
1195 - }
1203
1204 // and initialize it
1205 for(c = p->fds_size ; c < (fdid + MAX_SPARE_FDS) ; c++) p->fds[c] = 0;
@@ -1972,10 +1979,58 @@ static inline void reallocate_target_fds(struct target *w) {
1979 w->target_fds_size = all_files_size;
1980 }
1981
1975 -static inline void aggregate_pid_fds_on_target(struct target *w, struct pid_stat *p) {
1976 - if(unlikely(!w->target_fds || w->target_fds_size < all_files_size))
1982 +static inline void add_fd_on_target(int type, struct target *w) {
1983 + switch(type) {
1984 + case FILETYPE_FILE:
1985 + w->openfiles++;
1986 + break;
1987 +
1988 + case FILETYPE_PIPE:
1989 + w->openpipes++;
1990 + break;
1991 +
1992 + case FILETYPE_SOCKET:
1993 + w->opensockets++;
1994 + break;
1995 +
1996 + case FILETYPE_INOTIFY:
1997 + w->openinotifies++;
1998 + break;
1999 +
2000 + case FILETYPE_EVENTFD:
2001 + w->openeventfds++;
2002 + break;
2003 +
2004 + case FILETYPE_TIMERFD:
2005 + w->opentimerfds++;
2006 + break;
2007 +
2008 + case FILETYPE_SIGNALFD:
2009 + w->opensignalfds++;
2010 + break;
2011 +
2012 + case FILETYPE_EVENTPOLL:
2013 + w->openeventpolls++;
2014 + break;
2015 +
2016 + default:
2017 + w->openother++;
2018 + break;
2019 + }
2020 +}
2021 +
2022 +static inline void aggregate_pid_fds_on_targets(struct pid_stat *p) {
2023 + struct target *w = p->target, *u = p->user_target, *g = p->group_target;
2024 +
2025 + if(unlikely(w && (!w->target_fds || w->target_fds_size < all_files_size)))
2026 reallocate_target_fds(w);
2027
2028 + if(unlikely(u && (!u->target_fds || u->target_fds_size < all_files_size)))
2029 + reallocate_target_fds(u);
2030 +
2031 + if(unlikely(g && (!g->target_fds || g->target_fds_size < all_files_size)))
2032 + reallocate_target_fds(g);
2033 +
2034 int c, size = p->fds_size, *fds = p->fds;
2035 for(c = 0; c < size ;c++) {
2036 int fd = fds[c];
@@ -1983,45 +2038,26 @@ static inline void aggregate_pid_fds_on_target(struct target *w, struct pid_stat
2038 if(likely(fd <= 0 || fd >= all_files_size))
2039 continue;
2040
1986 - if(unlikely(!w->target_fds[fd])) {
1987 - switch(all_files[fd].type) {
1988 - case FILETYPE_FILE:
1989 - w->openfiles++;
1990 - break;
1991 -
1992 - case FILETYPE_PIPE:
1993 - w->openpipes++;
1994 - break;
1995 -
1996 - case FILETYPE_SOCKET:
1997 - w->opensockets++;
1998 - break;
2041 + if(likely(w)) {
2042 + if(unlikely(!w->target_fds[fd]))
2043 + add_fd_on_target(all_files[fd].type, w);
2044
2000 - case FILETYPE_INOTIFY:
2001 - w->openinotifies++;
2002 - break;
2003 -
2004 - case FILETYPE_EVENTFD:
2005 - w->openeventfds++;
2006 - break;
2045 + w->target_fds[fd]++;
2046 + }
2047
2008 - case FILETYPE_TIMERFD:
2009 - w->opentimerfds++;
2010 - break;
2048 + if(likely(u)) {
2049 + if(unlikely(!u->target_fds[fd]))
2050 + add_fd_on_target(all_files[fd].type, u);
2051
2012 - case FILETYPE_SIGNALFD:
2013 - w->opensignalfds++;
2014 - break;
2052 + u->target_fds[fd]++;
2053 + }
2054
2016 - case FILETYPE_EVENTPOLL:
2017 - w->openeventpolls++;
2018 - break;
2055 + if(likely(g)) {
2056 + if(unlikely(!g->target_fds[fd]))
2057 + add_fd_on_target(all_files[fd].type, g);
2058
2020 - default:
2021 - w->openother++;
2022 - }
2059 + g->target_fds[fd]++;
2060 }
2024 - w->target_fds[fd]++;
2061 }
2062 }
2063
@@ -2062,8 +2098,6 @@ static inline void aggregate_pid_on_target(struct target *w, struct pid_stat *p,
2098 w->processes++;
2099 w->num_threads += p->num_threads;
2100
2065 - aggregate_pid_fds_on_target(w, p);
2066 -
2101 if(unlikely(debug || w->debug))
2102 fprintf(stderr, "apps.plugin: \taggregating '%s' pid %d on target '%s' utime=%llu, stime=%llu, gtime=%llu, cutime=%llu, cstime=%llu, cgtime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu\n", p->comm, p->pid, w->name, p->utime, p->stime, p->gtime, p->cutime, p->cstime, p->cgtime, p->minflt, p->majflt, p->cminflt, p->cmajflt);
2103 }
@@ -2082,9 +2116,11 @@ static void calculate_netdata_statistics(void) {
2116
2117 // concentrate everything on the apps_groups_targets
2118 for(p = root_of_pids; p ; p = p->next) {
2119 + if(!p->updated) continue;
2120
2121 // --------------------------------------------------------------------
2087 - // apps_groups targets
2122 + // assign apps_groups target
2123 +
2124 if(likely(p->target))
2125 aggregate_pid_on_target(p->target, p, NULL);
2126 else
@@ -2092,7 +2128,8 @@ static void calculate_netdata_statistics(void) {
2128
2129
2130 // --------------------------------------------------------------------
2095 - // user targets
2131 + // assign user target
2132 +
2133 o = p->user_target;
2134 if(likely(p->user_target && p->user_target->uid == p->uid))
2135 w = p->user_target;
@@ -2110,7 +2147,8 @@ static void calculate_netdata_statistics(void) {
2147
2148
2149 // --------------------------------------------------------------------
2113 - // group targets
2150 + // assign group target
2151 +
2152 o = p->group_target;
2153 if(likely(p->group_target && p->group_target->gid == p->gid))
2154 w = p->group_target;
@@ -2126,6 +2164,12 @@ static void calculate_netdata_statistics(void) {
2164 else
2165 error("pid %d %s was left without a group target!", p->pid, p->comm);
2166
2167 +
2168 + // --------------------------------------------------------------------
2169 + // aggregate all file descriptors
2170 +
2171 + if(enable_file_charts)
2172 + aggregate_pid_fds_on_targets(p);
2173 }
2174
2175 cleanup_exited_pids();