Ori.livneh has uploaded a new change for review. https://gerrit.wikimedia.org/r/104010
Change subject: perf: use strtok_r + strtod / strtoull instead of scanf ...................................................................... perf: use strtok_r + strtod / strtoull instead of scanf mwprof spends most of its time in scanf. Parsing the string by hand reduced CPU utilization by a third. Change-Id: Id4a3dab276ab826684c8c45589fb81955e1e0688 --- M Makefile M collector.c M mwprof.c M mwprof.h 4 files changed, 64 insertions(+), 45 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/operations/software/mwprof refs/changes/10/104010/1 diff --git a/Makefile b/Makefile index 9eebac9..586bc57 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -CFLAGS+=-Wall -g $(shell pkg-config --cflags --libs glib-2.0 gio-2.0 gthread-2.0 gio-unix-2.0) +CFLAGS+=-Wall -O2 -g $(shell pkg-config --cflags --libs glib-2.0 gio-2.0 gthread-2.0 gio-unix-2.0) LDLIBS+=$(shell pkg-config --libs glib-2.0 gio-2.0 gthread-2.0 gio-unix-2.0) all: mwprof diff --git a/collector.c b/collector.c index 5b84646..e735765 100644 --- a/collector.c +++ b/collector.c @@ -7,55 +7,86 @@ * License: public domain (as if there's something to protect ;-) */ #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <glib.h> #include "mwprof.h" /* Decides what to do with sample UDP message */ void -handleMessage(gchar *buffer, gssize length) { - gchar *p, *pp; - gchar host[128]; - gchar db[128]; - gchar task[1024]; - gchar stats[] = "stats/"; - gint n_fields; - +handleMessage(gchar *buffer) { + gchar *host, *db, *task; + gchar *line, *saveptr, *token; CallStats sample; - /* db host count cpu cpusq real realsq eventdescription */ - const char msgformat[]="%127s %127s %ld %lf %lf %lf %lf %1023[^\n]"; - - buffer[length] = 0; - pp = buffer; while (TRUE) { - p = strsep(&pp, "\r\n"); + line = strsep(&buffer, "\r\n"); - if (p == NULL) { + if (line == NULL) { break; - } else if (p[0] == '\0') { + } else if (line[0] == '\0') { continue; } - if (strcmp("-truncate", p) == 0) { + if (g_str_has_prefix(buffer, "-truncate")) { truncateData(); - return; + continue; } memset(&sample, '\0', sizeof(sample)); - n_fields = sscanf(p, msgformat, (char *) &db, (char *) &host, - &sample.count, &sample.cpu, &sample.cpu_sq, - &sample.real, &sample.real_sq, (char *) &task); - if (n_fields < 7) { + token = strtok_r(line, " ", &saveptr); + if (token == NULL || strnlen(token, 128) > 127) { + break; + } + db = token; + + token = strtok_r(NULL, " ", &saveptr); + if (token == NULL || strnlen(token, 128) > 127) { continue; } + host = token; + + token = strtok_r(NULL, " ", &saveptr); + if (token == NULL) { + continue; + } + sample.count = strtoull(token, NULL, 10); + + token = strtok_r(NULL, " ", &saveptr); + if (token == NULL) { + continue; + } + sample.cpu = g_ascii_strtod(token, NULL); + + token = strtok_r(NULL, " ", &saveptr); + if (token == NULL) { + continue; + } + sample.cpu_sq = g_ascii_strtod(token, NULL); + + token = strtok_r(NULL, " ", &saveptr); + if (token == NULL) { + continue; + } + sample.real = g_ascii_strtod(token, NULL); + + token = strtok_r(NULL, " ", &saveptr); + if (token == NULL) { + continue; + } + sample.real_sq = g_ascii_strtod(token, NULL); + + if (saveptr[0] == '\0' || strnlen(saveptr, 1024) > 1023) { + continue; + } + task = saveptr; // Update the DB-specific entry updateEntry(db, host, task, &sample); // Update the aggregate entry - if (strncmp(db, stats, sizeof(stats)-1) == 0) { + if (g_str_has_prefix(db, "stats/")) { updateEntry("stats/all", "-", task, &sample); } else { updateEntry("all", "-", task, &sample); @@ -69,10 +100,9 @@ CallStats *entry; snprintf(key, sizeof(key) - 1, "%s:%s:%s", db, host, task); - entry = g_hash_table_lookup(table, key); if (entry == NULL) { - entry = g_malloc0(sizeof(CallStats)); + entry = g_new0(CallStats, 1); g_mutex_init(&entry->mutex); g_mutex_lock(&entry->mutex); G_LOCK(table); diff --git a/mwprof.c b/mwprof.c index 28df8a6..05f7bef 100644 --- a/mwprof.c +++ b/mwprof.c @@ -46,31 +46,19 @@ FILE *temp; GInputStream *in; GOutputStream *out; - GError *error = NULL; - temp = tmpfile(); g_assert(temp != NULL); dumpData(temp); rewind(temp); - if (errno) { - g_error("rewind() failed: %s", g_strerror(errno)); - } - in = g_unix_input_stream_new(fileno(temp), TRUE); - + in = g_unix_input_stream_new(fileno(temp), FALSE); out = g_io_stream_get_output_stream(G_IO_STREAM(connection)); - g_output_stream_splice(out, in, G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | - G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, NULL, &error); - g_assert_no_error(error); - - g_input_stream_close(G_INPUT_STREAM(in), NULL, &error); - g_assert_no_error(error); + g_output_stream_splice(out, in, G_OUTPUT_STREAM_SPLICE_NONE, NULL, NULL); g_object_unref(in); - g_output_stream_close(out, NULL, &error); - g_assert_no_error(error); + fclose(temp); return FALSE; } @@ -83,7 +71,7 @@ GInetAddress *inet_address; GSocketAddress *address; gint port = GPOINTER_TO_INT(data); - gchar buffer[65535] = {0}; + gchar buf[65535] = {0}; gssize nbytes; stats_sock = g_socket_new(G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM, @@ -99,9 +87,10 @@ g_object_unref(address); while (TRUE) { - nbytes = g_socket_receive(stats_sock, buffer, 65535, NULL, &error); + nbytes = g_socket_receive(stats_sock, buf, sizeof(buf)-1, NULL, &error); g_assert_no_error(error); - handleMessage((char *) &buffer, (ssize_t) nbytes); + buf[nbytes] = '\0'; + handleMessage(buf); } } diff --git a/mwprof.h b/mwprof.h index 889935e..ad9c31f 100644 --- a/mwprof.h +++ b/mwprof.h @@ -30,7 +30,7 @@ void dumpData(FILE *fd); void truncateData(); -void handleMessage(char *buffer, ssize_t length); +void handleMessage(gchar *buffer); void updateEntry(char *db, char *host, char *task, CallStats *sample); #endif // MWPROF_H_ -- To view, visit https://gerrit.wikimedia.org/r/104010 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Id4a3dab276ab826684c8c45589fb81955e1e0688 Gerrit-PatchSet: 1 Gerrit-Project: operations/software/mwprof Gerrit-Branch: master Gerrit-Owner: Ori.livneh <o...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits