msgQ test: Now also reports performance of STL-based variant of msg Q
[charm.git] / tests / charm++ / queue / pgm.C
index 3c0f1d1808cdc0e303711954774403fe7456ea23..9ac2168aecc57cd5f6ecd1a050acdf8fbdab1edf 100644 (file)
@@ -1,13 +1,18 @@
 #include <iostream>
 #include <cstdlib>
+#include <cstdio>
+#include <vector>
 
 using std::cerr;
 using std::endl;
 using std::sprintf;
 
 #include "queueing.h"
+#include "msgq.h"
 #include "main.decl.h"
 
+#define CmiFree free
+
 #define RUN_TEST(f) do { \
   ++tests; \
   if (f()) { \
@@ -24,7 +29,6 @@ bool test_empty()
 {
   Queue q = CqsCreate();
   bool result = (0 == CqsLength(q)) && (1 == CqsEmpty(q));
-  result &= CqsMaxLength(q) >= 0;
   CqsDelete(q);
   return result;
 }
@@ -40,7 +44,6 @@ bool test_one()
   CqsEnqueue(q, p);
   bool result = (1 == CqsLength(q)) && (0 == CqsEmpty(q));
   void *r;
-  result &= CqsMaxLength(q) >= 1;
   CqsDequeue(q, &r);
   result &= (r == p) 
     && (0 == CqsLength(q)) 
@@ -58,7 +61,6 @@ bool test_two()
   CqsEnqueue(q, i);
   CqsEnqueue(q, j);
   bool result = (2 == CqsLength(q));
-  result &= CqsMaxLength(q) >= 2;
   CqsDequeue(q, &r);
   CqsDequeue(q, &s);
   result &= (r == i && s == j) || (r == j && s == i);
@@ -136,10 +138,119 @@ bool test_enumerate()
   CqsEnumerateQueue(q, &e);
   int n = CqsLength(q);
   bool result = findEntry(e, n, i) && findEntry(e, n, j) && findEntry(e, n, k);
+  CmiFree(e);
+  CqsDelete(q);
+  return result;
+}
+
+bool test_general_fifo()
+{
+  Queue q = CqsCreate();
+  void *i = (char *)1, *j = (char *)2, *k = (char *)3;
+  CqsEnqueueGeneral(q, i, CQS_QUEUEING_FIFO, 1, 0);
+  CqsEnqueueGeneral(q, j, CQS_QUEUEING_FIFO, 2, 0);
+  CqsEnqueueGeneral(q, k, CQS_QUEUEING_FIFO, 42, 0);
+  void *r, *s, *t;
+  CqsDequeue(q, &r);
+  CqsDequeue(q, &s);
+  CqsDequeue(q, &t);
+  bool result = (r == i) && (s == j) && (t == k);
+  CqsDelete(q);
+  return result;
+}
+
+bool test_general_ififo()
+{
+  Queue q = CqsCreate();
+  void *i = (char *)1, *j = (char *)2, *k = (char *)3;
+  unsigned int a = -1, b = 0, c = 1;
+  CqsEnqueueGeneral(q, i, CQS_QUEUEING_IFIFO, 8*sizeof(int), &c);
+  CqsEnqueueGeneral(q, j, CQS_QUEUEING_IFIFO, 8*sizeof(int), &b);
+  CqsEnqueueGeneral(q, k, CQS_QUEUEING_IFIFO, 8*sizeof(int), &a);
+  void *r, *s, *t;
+  CqsDequeue(q, &r);
+  CqsDequeue(q, &s);
+  CqsDequeue(q, &t);
+  bool result = (r == k) && (s == j) && (t == i);
   CqsDelete(q);
   return result;
 }
 
+double timePerOp_general_ififo(int qBaseSize = 256)
+{
+  Queue q = CqsCreate();
+  int qBatchSize = 1<<4;
+  int numIters   = 1<<16;
+
+  std::vector<char> msgs(qBaseSize + qBatchSize);
+  std::vector<unsigned int> prios(qBaseSize + qBatchSize);
+
+  for (int i = 0; i < qBaseSize + qBatchSize; i++)
+      prios[i] = std::rand();
+
+  for (int i = 0; i < qBaseSize; i++)
+      CqsEnqueueGeneral(q, (void*)&msgs[i], CQS_QUEUEING_IFIFO, 8*sizeof(int), &prios[i]);
+
+  double startTime = CmiWallTimer();
+  for (int i = 0; i < numIters; i++)
+  {
+      for (int j = qBaseSize; j < qBaseSize+qBatchSize; j++)
+        CqsEnqueueGeneral(q, (void*)&msgs[j], CQS_QUEUEING_IFIFO, 8*sizeof(int), &prios[j]);
+      void *m;
+      for (int j = qBaseSize; j < qBaseSize+qBatchSize; j++)
+        CqsDequeue(q, &m);
+  }
+
+  CqsDelete(q);
+  return 1000000 * (CmiWallTimer() - startTime) / (numIters * qBatchSize * 2);
+}
+
+
+double timePerOp_stlQ(int qBaseSize = 256)
+{
+  msgQ<int> q;
+  int qBatchSize = 1<<4;
+  int numIters   = 1<<16;
+
+  std::vector<char> msgs(qBaseSize + qBatchSize);
+  std::vector<unsigned int> prios(qBaseSize + qBatchSize);
+
+  for (int i = 0; i < qBaseSize + qBatchSize; i++)
+      prios[i] = std::rand();
+
+  for (int i = 0; i < qBaseSize; i++)
+      q.enq((msg_t*)&msgs[i], prios[i]);
+
+  double startTime = CmiWallTimer();
+  for (int i = 0; i < numIters; i++)
+  {
+      for (int j = qBaseSize; j < qBaseSize+qBatchSize; j++)
+          q.enq((msg_t*)&msgs[j], prios[j]);
+      void *m;
+      for (int j = qBaseSize; j < qBaseSize+qBatchSize; j++)
+        q.deq();
+  }
+
+  return 1000000 * (CmiWallTimer() - startTime) / (numIters * qBatchSize * 2);
+}
+
+
+bool perftest_general_ififo()
+{
+  CkPrintf("Reporting time per enqueue / dequeue operation for charm's underlying mixed priority queue\n");
+  CkPrintf("\n  Q length     time/op(us)\n");
+  for (int i = 16; i <= 2048; i *= 2)
+    CkPrintf("%10d %15f\n", i, timePerOp_general_ififo(i));
+
+  printf("Reporting time per enqueue / dequeue operation for an STL version of the same Q functionality\n");
+  printf("\n  Q length     time/op(us)\n");
+  for (int i = 16; i <= 2048; i *= 2)
+    printf("%10d %15f\n", i, timePerOp_stlQ(i));
+
+  return true;
+}
+
+
 #if 0
 // Template for new harness-driven tests
 bool test_foo()
@@ -166,6 +277,9 @@ struct main : public CBase_main
     RUN_TEST(test_lifo);
     RUN_TEST(test_enqueue_mixed);
     RUN_TEST(test_enumerate);
+    RUN_TEST(test_general_fifo);
+    RUN_TEST(test_general_ififo);
+    RUN_TEST(perftest_general_ififo);
 
     if (fail) {
       sprintf(message, "%d/%d tests failed\n", fail, tests);