table: ContentStore benchmark
refs #2254
Change-Id: I422a7e6d4ca3ad17db2465460e67b8cd2130fd36
diff --git a/tests/other/cs-benchmark.cpp b/tests/other/cs-benchmark.cpp
new file mode 100644
index 0000000..71c9e10
--- /dev/null
+++ b/tests/other/cs-benchmark.cpp
@@ -0,0 +1,213 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2015, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "table/cs.hpp"
+#include <ndn-cxx/security/key-chain.hpp>
+
+#include "tests/test-common.hpp"
+
+namespace nfd {
+namespace tests {
+
+class CsBenchmarkFixture : public BaseFixture
+{
+protected:
+ CsBenchmarkFixture()
+ {
+#ifdef _DEBUG
+ BOOST_TEST_MESSAGE("Benchmark compiled in debug mode is unreliable, "
+ "please compile in release mode.");
+#endif // _DEBUG
+
+ cs.setLimit(CS_CAPACITY);
+ }
+
+ time::microseconds
+ timedRun(std::function<void()> f)
+ {
+ time::steady_clock::TimePoint t1 = time::steady_clock::now();
+ f();
+ time::steady_clock::TimePoint t2 = time::steady_clock::now();
+ return time::duration_cast<time::microseconds>(t2 - t1);
+ }
+
+protected:
+ typedef std::function<Name(size_t)> NameGenerator;
+
+ class SimpleNameGenerator
+ {
+ public:
+ explicit
+ SimpleNameGenerator(const Name& prefix = "/cs/benchmark")
+ : m_prefix(prefix)
+ {
+ }
+
+ Name
+ operator()(size_t i) const
+ {
+ Name name(m_prefix);
+ name.appendNumber(i % 4);
+ name.appendNumber(i);
+ return name;
+ }
+
+ private:
+ Name m_prefix;
+ };
+
+ std::vector<shared_ptr<Interest>>
+ makeInterestWorkload(size_t count, const NameGenerator& genName = SimpleNameGenerator())
+ {
+ std::vector<shared_ptr<Interest>> workload(count);
+ for (size_t i = 0; i < count; ++i) {
+ Name name = genName(i);
+ workload[i] = makeInterest(name);
+ }
+ return workload;
+ }
+
+ std::vector<shared_ptr<Data>>
+ makeDataWorkload(size_t count, const NameGenerator& genName = SimpleNameGenerator())
+ {
+ std::vector<shared_ptr<Data>> workload(count);
+ for (size_t i = 0; i < count; ++i) {
+ Name name = genName(i);
+ workload[i] = makeData(name);
+ }
+ return workload;
+ }
+
+protected:
+ Cs cs;
+ static const size_t CS_CAPACITY = 50000;
+};
+
+BOOST_FIXTURE_TEST_SUITE(TableCsBenchmark, CsBenchmarkFixture)
+
+// find miss, then insert
+BOOST_AUTO_TEST_CASE(FindMissInsert)
+{
+ std::vector<shared_ptr<Interest>> interestWorkload = makeInterestWorkload(CS_CAPACITY);
+ const size_t REPEAT = 4;
+ std::vector<shared_ptr<Data>> dataWorkload[REPEAT];
+ for (size_t j = 0; j < REPEAT; ++j) {
+ dataWorkload[j] = makeDataWorkload(CS_CAPACITY);
+ }
+
+ time::microseconds d = timedRun([&] {
+ for (size_t j = 0; j < REPEAT; ++j) {
+ for (size_t i = 0; i < CS_CAPACITY; ++i) {
+ cs.find(*interestWorkload[i]);
+ cs.insert(*dataWorkload[j][i], false);
+ }
+ }
+ });
+ BOOST_TEST_MESSAGE("find(miss)-insert " << (CS_CAPACITY * REPEAT) << ": " << d);
+}
+
+// insert, then find hit
+BOOST_AUTO_TEST_CASE(InsertFindHit)
+{
+ std::vector<shared_ptr<Interest>> interestWorkload = makeInterestWorkload(CS_CAPACITY);
+ const size_t REPEAT = 4;
+ std::vector<shared_ptr<Data>> dataWorkload[REPEAT];
+ for (size_t j = 0; j < REPEAT; ++j) {
+ dataWorkload[j] = makeDataWorkload(CS_CAPACITY);
+ }
+
+ time::microseconds d = timedRun([&] {
+ for (size_t j = 0; j < REPEAT; ++j) {
+ for (size_t i = 0; i < CS_CAPACITY; ++i) {
+ cs.insert(*dataWorkload[j][i], false);
+ cs.find(*interestWorkload[i]);
+ }
+ }
+ });
+ BOOST_TEST_MESSAGE("insert-find(hit) " << (CS_CAPACITY * REPEAT) << ": " << d);
+}
+
+// find(leftmost) hit
+BOOST_AUTO_TEST_CASE(Leftmost)
+{
+ const size_t N_CHILDREN = 10;
+ const size_t N_INTERESTS = CS_CAPACITY / N_CHILDREN;
+ std::vector<shared_ptr<Interest>> interestWorkload = makeInterestWorkload(N_INTERESTS);
+ for (auto&& interest : interestWorkload) {
+ interest->setChildSelector(0);
+ for (size_t j = 0; j < N_CHILDREN; ++j) {
+ Name name = interest->getName();
+ name.appendNumber(j);
+ shared_ptr<Data> data = makeData(name);
+ cs.insert(*data, false);
+ }
+ }
+ BOOST_REQUIRE(cs.size() == N_INTERESTS * N_CHILDREN);
+
+ const size_t REPEAT = 4;
+
+ time::microseconds d = timedRun([&] {
+ for (size_t j = 0; j < REPEAT; ++j) {
+ for (const auto& interest : interestWorkload) {
+ cs.find(*interest);
+ }
+ }
+ });
+ BOOST_TEST_MESSAGE("find(leftmost) " << (N_INTERESTS * N_CHILDREN * REPEAT) << ": " << d);
+}
+
+// find(rightmost) hit
+BOOST_AUTO_TEST_CASE(Rightmost)
+{
+ const size_t N_CHILDREN = 10;
+ const size_t N_INTERESTS = CS_CAPACITY / N_CHILDREN;
+ std::vector<shared_ptr<Interest>> interestWorkload = makeInterestWorkload(N_INTERESTS);
+ for (auto&& interest : interestWorkload) {
+ interest->setChildSelector(1);
+ for (size_t j = 0; j < N_CHILDREN; ++j) {
+ Name name = interest->getName();
+ name.appendNumber(j);
+ shared_ptr<Data> data = makeData(name);
+ cs.insert(*data, false);
+ }
+ }
+ BOOST_REQUIRE(cs.size() == N_INTERESTS * N_CHILDREN);
+
+ const size_t REPEAT = 4;
+
+ time::microseconds d = timedRun([&] {
+ for (size_t j = 0; j < REPEAT; ++j) {
+ for (const auto& interest : interestWorkload) {
+ cs.find(*interest);
+ }
+ }
+ });
+ BOOST_TEST_MESSAGE("find(rightmost) " << (N_INTERESTS * N_CHILDREN * REPEAT) << ": " << d);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace tests
+} // namespace nfd
diff --git a/tests/other/cs-smoketest.cpp b/tests/other/cs-smoketest.cpp
deleted file mode 100644
index 415d03d..0000000
--- a/tests/other/cs-smoketest.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
- * Copyright (c) 2014, Regents of the University of California,
- * Arizona Board of Regents,
- * Colorado State University,
- * University Pierre & Marie Curie, Sorbonne University,
- * Washington University in St. Louis,
- * Beijing Institute of Technology,
- * The University of Memphis
- *
- * This file is part of NFD (Named Data Networking Forwarding Daemon).
- * See AUTHORS.md for complete list of NFD authors and contributors.
- *
- * NFD is free software: you can redistribute it and/or modify it under the terms
- * of the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "table/cs.hpp"
-#include <ndn-cxx/security/key-chain.hpp>
-
-namespace nfd {
-namespace cs_smoketest {
-
-static void
-runStressTest()
-{
- shared_ptr<Data> dataWorkload[70000];
- shared_ptr<Interest> interestWorkload[70000];
-
- ndn::SignatureSha256WithRsa fakeSignature;
- fakeSignature.setValue(ndn::dataBlock(tlv::SignatureValue,
- reinterpret_cast<const uint8_t*>(0), 0));
-
- // 182 MB in memory
- for (int i = 0; i < 70000; i++) {
- Name name("/stress/test");
- name.appendNumber(i % 4);
- name.appendNumber(i);
-
- shared_ptr<Interest> interest = make_shared<Interest>(name);
- interestWorkload[i] = interest;
-
- shared_ptr<Data> data = make_shared<Data>(name);
- data->setSignature(fakeSignature);
- dataWorkload[i] = data;
- }
-
- time::duration<double, boost::nano> previousResult(0);
-
- for (size_t nInsertions = 1000; nInsertions < 10000000; nInsertions *= 2) {
- Cs cs;
- srand(time::toUnixTimestamp(time::system_clock::now()).count());
-
- time::steady_clock::TimePoint startTime = time::steady_clock::now();
-
- size_t workloadCounter = 0;
- for (size_t i = 0; i < nInsertions; i++) {
- if (workloadCounter > 69999)
- workloadCounter = 0;
-
- cs.find(*interestWorkload[workloadCounter]);
- Data& data = *dataWorkload[workloadCounter];
- data.setName(data.getName()); // reset data.m_fullName
- data.wireEncode();
- cs.insert(data);
-
- workloadCounter++;
- }
-
- time::steady_clock::TimePoint endTime = time::steady_clock::now();
-
- time::duration<double, boost::nano> runDuration = endTime - startTime;
- time::duration<double, boost::nano> perOperationTime = runDuration / nInsertions;
-
- std::cout << "nItem = " << nInsertions << std::endl;
- std::cout << "Total running time = "
- << time::duration_cast<time::duration<double> >(runDuration)
- << std::endl;
- std::cout << "Average per-operation time = "
- << time::duration_cast<time::duration<double, boost::micro> >(perOperationTime)
- << std::endl;
-
- if (previousResult > time::nanoseconds(1))
- std::cout << "Change compared to the previous: "
- << (100.0 * perOperationTime / previousResult) << "%" << std::endl;
-
- std::cout << "\n=================================\n" << std::endl;
-
- previousResult = perOperationTime;
- }
-}
-
-} // namespace cs_smoketest
-} // namespace nfd
-
-int
-main(int argc, char** argv)
-{
- nfd::cs_smoketest::runStressTest();
-
- return 0;
-}
diff --git a/tests/other/wscript b/tests/other/wscript
index 69aa2bb..51f8b6b 100644
--- a/tests/other/wscript
+++ b/tests/other/wscript
@@ -1,12 +1,13 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
"""
-Copyright (c) 2014 Regents of the University of California,
- Arizona Board of Regents,
- Colorado State University,
- University Pierre & Marie Curie, Sorbonne University,
- Washington University in St. Louis,
- Beijing Institute of Technology
+Copyright (c) 2014-2015, Regents of the University of California,
+ Arizona Board of Regents,
+ Colorado State University,
+ University Pierre & Marie Curie, Sorbonne University,
+ Washington University in St. Louis,
+ Beijing Institute of Technology,
+ The University of Memphis.
This file is part of NFD (Named Data Networking Forwarding Daemon).
See AUTHORS.md for complete list of NFD authors and contributors.
@@ -26,8 +27,8 @@
top = '../..'
def build(bld):
- bld.program(target="../../cs-smoketest",
- source="cs-smoketest.cpp",
- use='daemon-objects',
+ bld.program(target="../../cs-benchmark",
+ source="cs-benchmark.cpp",
+ use='daemon-objects unit-tests-main',
install_path=None,
)