Permalink
Browse files

Optimize writeArrayMessage(int, StaticString, ...) and add an optimiz…

…ed version writeArrayMessage(int, StatciString args, int nargs).

Both optimizations prevent creation of vector objects when not necessary.
  • Loading branch information...
1 parent b15d8b0 commit e9c6ab3dfef05bdd72d6ccc65946556963747f19 @FooBarWidget FooBarWidget committed Sep 11, 2011
Showing with 113 additions and 9 deletions.
  1. +60 −6 ext/common/Utils/MessageIO.h
  2. +53 −3 test/cxx/MessageIOTest.cpp
@@ -426,19 +426,67 @@ writeArrayMessage(int fd, const Collection &args, unsigned long long *timeout =
}
inline void
+writeArrayMessage(int fd, const StaticString args[], unsigned int nargs, unsigned long long *timeout = NULL) {
+ unsigned int i;
+ uint16_t bodySize = 0;
+
+ for (i = 0; i < nargs; i++) {
+ bodySize += args[i].size() + 1;
+ }
+
+ scoped_array<char> data(new char[sizeof(uint16_t) + bodySize]);
+ uint16_t header = htons(bodySize);
+ memcpy(data.get(), &header, sizeof(uint16_t));
+
+ char *dataEnd = data.get() + sizeof(uint16_t);
+ for (i = 0; i < nargs; i++) {
+ memcpy(dataEnd, args[i].data(), args[i].size());
+ dataEnd += args[i].size();
+ *dataEnd = '\0';
+ dataEnd++;
+ }
+
+ writeExact(fd, data.get(), sizeof(uint16_t) + bodySize, timeout);
+}
+
+inline void
writeArrayMessage(int fd, const StaticString &name, va_list &ap, unsigned long long *timeout = NULL) {
- vector<StaticString> args;
+ StaticString args[10];
+ unsigned int nargs = 1;
+ bool done = false;
- args.push_back(name);
- while (true) {
+ args[0] = name;
+ do {
const char *arg = va_arg(ap, const char *);
if (arg == NULL) {
- break;
+ done = true;
} else {
- args.push_back(arg);
+ args[nargs] = arg;
+ nargs++;
}
+ } while (!done && nargs < sizeof(args) / sizeof(StaticString));
+
+ if (done) {
+ writeArrayMessage(fd, args, nargs, timeout);
+ } else {
+ // Arguments don't fit in static array. Use dynamic
+ // array instead.
+ vector<StaticString> dyn_args;
+
+ for (unsigned int i = 0; i < nargs; i++) {
+ dyn_args.push_back(args[i]);
+ }
+ do {
+ const char *arg = va_arg(ap, const char *);
+ if (arg == NULL) {
+ done = true;
+ } else {
+ dyn_args.push_back(arg);
+ }
+ } while (!done);
+
+ writeArrayMessage(fd, dyn_args, timeout);
}
- writeArrayMessage(fd, args, timeout);
}
struct _VaGuard {
@@ -464,6 +512,12 @@ writeArrayMessage(int fd, const StaticString &name, ...) {
writeArrayMessage(fd, name, ap);
}
+inline void
+writeArrayMessage(int fd, const char *name) {
+ StaticString str = name;
+ writeArrayMessage(fd, &str, 1, NULL);
+}
+
/** Version of writeArrayMessage() that accepts a variadic list of 'const char *'
* arguments as message elements, with timeout support. The list must be terminated
* with a NULL.
@@ -155,7 +155,7 @@ namespace tut {
/***** Test readArrayMessage() and writeArrayMessage() *****/
TEST_METHOD(20) {
- // They work.
+ // Test <= 10 arguments.
writeArrayMessage(pipes[1], "ab", "cd", "efg", NULL);
writeArrayMessage(pipes[1], "ab", "cd", "efh", NULL);
@@ -182,6 +182,56 @@ namespace tut {
}
TEST_METHOD(21) {
+ // Test > 10 arguments.
+ writeArrayMessage(pipes[1], "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "a", "b", NULL);
+ writeArrayMessage(pipes[1], "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", NULL);
+
+ unsigned char buf[26];
+ readExact(pipes[0], buf, 26);
+ ensure_equals(buf[0], 0u);
+ ensure_equals(buf[1], 24u);
+ ensure_equals(buf[2], '1');
+ ensure_equals(buf[3], '\0');
+ ensure_equals(buf[4], '2');
+ ensure_equals(buf[5], '\0');
+ ensure_equals(buf[6], '3');
+ ensure_equals(buf[7], '\0');
+ ensure_equals(buf[8], '4');
+ ensure_equals(buf[9], '\0');
+ ensure_equals(buf[10], '5');
+ ensure_equals(buf[11], '\0');
+ ensure_equals(buf[12], '6');
+ ensure_equals(buf[13], '\0');
+ ensure_equals(buf[14], '7');
+ ensure_equals(buf[15], '\0');
+ ensure_equals(buf[16], '8');
+ ensure_equals(buf[17], '\0');
+ ensure_equals(buf[18], '9');
+ ensure_equals(buf[19], '\0');
+ ensure_equals(buf[20], '0');
+ ensure_equals(buf[21], '\0');
+ ensure_equals(buf[22], 'a');
+ ensure_equals(buf[23], '\0');
+ ensure_equals(buf[24], 'b');
+ ensure_equals(buf[25], '\0');
+
+ vector<string> args = readArrayMessage(pipes[0]);
+ ensure_equals(args.size(), 12u);
+ ensure_equals(args[0], "c");
+ ensure_equals(args[1], "d");
+ ensure_equals(args[2], "e");
+ ensure_equals(args[3], "f");
+ ensure_equals(args[4], "g");
+ ensure_equals(args[5], "h");
+ ensure_equals(args[6], "i");
+ ensure_equals(args[7], "j");
+ ensure_equals(args[8], "k");
+ ensure_equals(args[9], "l");
+ ensure_equals(args[10], "m");
+ ensure_equals(args[11], "n");
+ }
+
+ TEST_METHOD(22) {
// readArrayMessage() throws EOFException on premature EOF.
writeExact(pipes[1], "\x00");
pipes[1].close();
@@ -201,7 +251,7 @@ namespace tut {
}
}
- TEST_METHOD(22) {
+ TEST_METHOD(23) {
// Test timeout.
unsigned long long timeout = 30000;
unsigned long long startTime = SystemTime::getUsec();
@@ -228,7 +278,7 @@ namespace tut {
}
}
- /***** Test readArrayMessage() and writeArrayMessage() *****/
+ /***** Test readScalarMessage() and writeScalarMessage() *****/
TEST_METHOD(30) {
// They work.

0 comments on commit e9c6ab3

Please sign in to comment.