[PATCH v2 1/3 kvm-unit-tests] Add dirty logging performance test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Can be used to check how long it takes to get dirty log according to
the number of dirty pages as follows:

  $ ./api/dirty-log-perf
  rip 804a3fa
  rip 804a3fa
  get dirty log:      80824 ns for          1 dirty pages
  rip 804a3fa
  get dirty log:      60077 ns for          2 dirty pages
  rip 804a3fa
  get dirty log:      51745 ns for          4 dirty pages
  ...
  rip 804a3fa
  get dirty log:    2008468 ns for      65536 dirty pages
  rip 804a3fa
  get dirty log:    3402165 ns for     131072 dirty pages
  rip 804a3fa
  get dirty log:    5614625 ns for     262144 dirty pages

Signed-off-by: Takuya Yoshikawa <takuya.yoshikawa@xxxxxxxxx>
---
 api/dirty-log-perf.cc |   93 +++++++++++++++++++++++++++++++++++++++++++++++++
 config-x86-common.mak |    5 ++-
 2 files changed, 97 insertions(+), 1 deletions(-)
 create mode 100644 api/dirty-log-perf.cc

diff --git a/api/dirty-log-perf.cc b/api/dirty-log-perf.cc
new file mode 100644
index 0000000..b9e9796
--- /dev/null
+++ b/api/dirty-log-perf.cc
@@ -0,0 +1,93 @@
+#include "kvmxx.hh"
+#include "memmap.hh"
+#include "identity.hh"
+#include <boost/thread/thread.hpp>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+namespace {
+
+const int page_size		= 4096;
+const int64_t nr_total_pages	= 256 * 1024;
+
+// Return the current time in nanoseconds.
+uint64_t time_ns()
+{
+    struct timespec ts;
+
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    return ts.tv_sec * (uint64_t)1000000000 + ts.tv_nsec;
+}
+
+// Update nr_to_write pages selected from nr_pages pages.
+void write_mem(void* slot_head, int64_t nr_to_write, int64_t nr_pages)
+{
+    char* var = static_cast<char*>(slot_head);
+    int64_t interval = nr_pages / nr_to_write;
+
+    for (int64_t i = 0; i < nr_to_write; ++i) {
+        ++(*var);
+        var += interval * page_size;
+    }
+}
+
+using boost::ref;
+using std::tr1::bind;
+
+// Let the guest update nr_to_write pages selected from nr_pages pages.
+void do_guest_write(kvm::vcpu& vcpu, void* slot_head,
+                    int64_t nr_to_write, int64_t nr_pages)
+{
+    identity::vcpu guest_write_thread(vcpu, bind(write_mem, ref(slot_head),
+                                                 nr_to_write, nr_pages));
+    vcpu.run();
+}
+
+// Check how long it takes to update dirty log.
+void check_dirty_log(kvm::vcpu& vcpu, mem_slot& slot, void* slot_head)
+{
+    slot.set_dirty_logging(true);
+    slot.update_dirty_log();
+
+    for (int64_t i = 1; i <= nr_total_pages; i *= 2) {
+        do_guest_write(vcpu, slot_head, i, nr_total_pages);
+
+        uint64_t start_ns = time_ns();
+        slot.update_dirty_log();
+        uint64_t end_ns = time_ns();
+
+        printf("get dirty log: %10lld ns for %10lld dirty pages\n",
+               end_ns - start_ns, i);
+    }
+
+    slot.set_dirty_logging(false);
+}
+
+}
+
+int main(int ac, char **av)
+{
+    kvm::system sys;
+    kvm::vm vm(sys);
+    mem_map memmap(vm);
+
+    void* mem_head;
+    int64_t mem_size = nr_total_pages * page_size;
+    if (posix_memalign(&mem_head, page_size, mem_size)) {
+        printf("dirty-log-perf: Could not allocate guest memory.\n");
+        exit(1);
+    }
+    uint64_t mem_addr = reinterpret_cast<uint64_t>(mem_head);
+
+    identity::hole hole(mem_head, mem_size);
+    identity::vm ident_vm(vm, memmap, hole);
+    kvm::vcpu vcpu(vm, 0);
+
+    mem_slot slot(memmap, mem_addr, mem_size, mem_head);
+
+    // pre-allocate shadow pages
+    do_guest_write(vcpu, mem_head, nr_total_pages, nr_total_pages);
+    check_dirty_log(vcpu, slot, mem_head);
+    return 0;
+}
diff --git a/config-x86-common.mak b/config-x86-common.mak
index 1cbc7c6..a093b8d 100644
--- a/config-x86-common.mak
+++ b/config-x86-common.mak
@@ -39,6 +39,7 @@ tests-common = $(TEST_DIR)/vmexit.flat $(TEST_DIR)/tsc.flat \
 ifdef API
 tests-common += api/api-sample
 tests-common += api/dirty-log
+tests-common += api/dirty-log-perf
 endif
 
 tests_and_config = $(TEST_DIR)/*.flat $(TEST_DIR)/unittests.cfg
@@ -93,7 +94,7 @@ arch_clean:
 
 api/%.o: CFLAGS += -m32
 
-api/%: LDLIBS += -lstdc++ -lboost_thread-mt -lpthread
+api/%: LDLIBS += -lstdc++ -lboost_thread-mt -lpthread -lrt
 api/%: LDFLAGS += -m32
 
 api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o
@@ -102,3 +103,5 @@ api/libapi.a: api/kvmxx.o api/identity.o api/exception.o api/memmap.o
 api/api-sample: api/api-sample.o api/libapi.a
 
 api/dirty-log: api/dirty-log.o api/libapi.a
+
+api/dirty-log-perf: api/dirty-log-perf.o api/libapi.a
-- 
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux