summaryrefslogtreecommitdiffstats
path: root/vespamalloc/src/tests/allocfree/allocfree.cpp
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /vespamalloc/src/tests/allocfree/allocfree.cpp
Publish
Diffstat (limited to 'vespamalloc/src/tests/allocfree/allocfree.cpp')
-rw-r--r--vespamalloc/src/tests/allocfree/allocfree.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/vespamalloc/src/tests/allocfree/allocfree.cpp b/vespamalloc/src/tests/allocfree/allocfree.cpp
new file mode 100644
index 00000000000..0f7b4d53c6f
--- /dev/null
+++ b/vespamalloc/src/tests/allocfree/allocfree.cpp
@@ -0,0 +1,115 @@
+// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+#include <vespa/log/log.h>
+#include <vespa/fastos/fastos.h>
+#include <vespa/vespalib/testkit/testapp.h>
+#include "producerconsumer.h"
+#include <map>
+
+using vespalib::Consumer;
+using vespalib::Producer;
+using vespalib::ProducerConsumer;
+
+LOG_SETUP("allocfree_test");
+
+TEST_SETUP(Test);
+
+//-----------------------------------------------------------------------------
+
+class FreeWorker : public Consumer {
+public:
+ FreeWorker(uint32_t maxQueue, bool inverse)
+ : Consumer (maxQueue, inverse) {}
+private:
+ virtual void consume(void * p) { free(p); }
+};
+
+//-----------------------------------------------------------------------------
+
+class MallocWorker : public Producer {
+public:
+ MallocWorker(uint32_t size, uint32_t cnt, FreeWorker &target)
+ : Producer(cnt, target), _size(size) {}
+private:
+ uint32_t _size;
+ virtual void * produce() { return malloc(_size); }
+};
+
+//-----------------------------------------------------------------------------
+
+class MallocFreeWorker : public ProducerConsumer {
+public:
+ MallocFreeWorker(uint32_t size, uint32_t cnt, bool inverse)
+ : ProducerConsumer(cnt, inverse), _size(size) { }
+private:
+ uint32_t _size;
+ virtual void * produce() { return malloc(_size); }
+ virtual void consume(void * p) { free(p); }
+};
+
+//-----------------------------------------------------------------------------
+
+int Test::Main() {
+ int duration = 10;
+ int numCrossThreadAlloc(2);
+ int numSameThreadAlloc(2);
+ if (_argc > 1) {
+ duration = atoi(_argv[1]);
+ }
+ if (_argc > 2) {
+ numCrossThreadAlloc = atoi(_argv[2]);
+ }
+ if (_argc > 3) {
+ numSameThreadAlloc = atoi(_argv[3]);
+ }
+ TEST_INIT("allocfree_test");
+
+ FastOS_ThreadPool pool(128000);
+
+ std::map<int, std::shared_ptr<FreeWorker> > freeWorkers;
+ std::map<int, std::shared_ptr<MallocWorker> > mallocWorkers;
+ std::map<int, std::shared_ptr<MallocFreeWorker> > mallocFreeWorkers;
+ for (int i(0); i < numCrossThreadAlloc; i++) {
+ freeWorkers[i] = std::shared_ptr<FreeWorker>(new FreeWorker(1024, (i%2) ? true : false));
+ mallocWorkers[i] = std::shared_ptr<MallocWorker>(new MallocWorker(400, 256, *freeWorkers[i]));
+ }
+ for(int i(0); i < numSameThreadAlloc; i++) {
+ mallocFreeWorkers[i] = std::shared_ptr<MallocFreeWorker>(new MallocFreeWorker(200, 16, (i%2) ? true : false));
+ }
+
+
+ for(std::map<int, std::shared_ptr<FreeWorker> >::iterator it(freeWorkers.begin()), mt(freeWorkers.end()); it != mt; it++) {
+ ASSERT_TRUE(pool.NewThread(it->second.get(), NULL) != NULL);
+ }
+ for(std::map<int, std::shared_ptr<MallocWorker> >::iterator it(mallocWorkers.begin()), mt(mallocWorkers.end()); it != mt; it++) {
+ ASSERT_TRUE(pool.NewThread(it->second.get(), NULL) != NULL);
+ }
+ for(std::map<int, std::shared_ptr<MallocFreeWorker> >::iterator it(mallocFreeWorkers.begin()), mt(mallocFreeWorkers.end()); it != mt; it++) {
+ ASSERT_TRUE(pool.NewThread(it->second.get(), NULL) != NULL);
+ }
+
+ for (; duration > 0; --duration) {
+ LOG(info, "%d seconds left...", duration);
+ FastOS_Thread::Sleep(1000);
+ }
+ pool.Close();
+ size_t numFreeOperations(0);
+ size_t numMallocOperations(0);
+ size_t numSameThreadMallocFreeOperations(0);
+ for(std::map<int, std::shared_ptr<FreeWorker> >::iterator it(freeWorkers.begin()), mt(freeWorkers.end()); it != mt; it++) {
+ numFreeOperations += it->second->operations();
+ }
+ for(std::map<int, std::shared_ptr<MallocWorker> >::iterator it(mallocWorkers.begin()), mt(mallocWorkers.end()); it != mt; it++) {
+ numMallocOperations += it->second->operations();
+ }
+ for(std::map<int, std::shared_ptr<MallocFreeWorker> >::iterator it(mallocFreeWorkers.begin()), mt(mallocFreeWorkers.end()); it != mt; it++) {
+ numSameThreadMallocFreeOperations += it->second->operationsConsumed();
+ }
+ EXPECT_EQUAL(numFreeOperations, numMallocOperations);
+ const size_t numCrossThreadMallocFreeOperations(numMallocOperations);
+
+ fprintf(stderr, "Did %" PRIu64 " Cross thread malloc/free operations\n", numCrossThreadMallocFreeOperations);
+ fprintf(stderr, "Did %" PRIu64 " Same thread malloc/free operations\n", numSameThreadMallocFreeOperations);
+ fprintf(stderr, "Did %" PRIu64 " Total operations\n", numCrossThreadMallocFreeOperations + numSameThreadMallocFreeOperations);
+
+ TEST_DONE();
+}