* [PATCH v2 1/3 kvm-unit-tests] Add dirty logging performance test
2012-01-15 3:41 [PATCH 0/3 kvm-unit-tests] Dirty logging performance test Takuya Yoshikawa
@ 2012-01-15 3:43 ` Takuya Yoshikawa
2012-01-15 3:44 ` [PATCH 2/3 kvm-unit-tests] dirty-log-perf: Split guest memory into two slots Takuya Yoshikawa
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Takuya Yoshikawa @ 2012-01-15 3:43 UTC (permalink / raw)
To: avi, mtosatti; +Cc: kvm
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@gmail.com>
---
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
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/3 kvm-unit-tests] dirty-log-perf: Split guest memory into two slots
2012-01-15 3:41 [PATCH 0/3 kvm-unit-tests] Dirty logging performance test Takuya Yoshikawa
2012-01-15 3:43 ` [PATCH v2 1/3 kvm-unit-tests] Add dirty " Takuya Yoshikawa
@ 2012-01-15 3:44 ` Takuya Yoshikawa
2012-01-15 3:45 ` [PATCH 3/3 kvm-unit-tests] dirty-log-perf: Take slot size from command line Takuya Yoshikawa
2012-01-18 13:50 ` [PATCH 0/3 kvm-unit-tests] Dirty logging performance test Marcelo Tosatti
3 siblings, 0 replies; 5+ messages in thread
From: Takuya Yoshikawa @ 2012-01-15 3:44 UTC (permalink / raw)
To: avi, mtosatti; +Cc: kvm
VGA frame buffer logging may be affected by other large slots like RAM,
so make it possible to test such cases.
E.g. 8K pages for the logged slot and 256K pages for the entire memory
space can be considered as 32MB framebuffer in 1GB memory space.
Signed-off-by: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
---
api/dirty-log-perf.cc | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/api/dirty-log-perf.cc b/api/dirty-log-perf.cc
index b9e9796..f48bc95 100644
--- a/api/dirty-log-perf.cc
+++ b/api/dirty-log-perf.cc
@@ -10,6 +10,7 @@ namespace {
const int page_size = 4096;
const int64_t nr_total_pages = 256 * 1024;
+const int64_t nr_slot_pages = 256 * 1024;
// Return the current time in nanoseconds.
uint64_t time_ns()
@@ -50,8 +51,8 @@ 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);
+ for (int64_t i = 1; i <= nr_slot_pages; i *= 2) {
+ do_guest_write(vcpu, slot_head, i, nr_slot_pages);
uint64_t start_ns = time_ns();
slot.update_dirty_log();
@@ -84,7 +85,11 @@ int main(int ac, char **av)
identity::vm ident_vm(vm, memmap, hole);
kvm::vcpu vcpu(vm, 0);
- mem_slot slot(memmap, mem_addr, mem_size, mem_head);
+ uint64_t slot_size = nr_slot_pages * page_size;
+ uint64_t next_addr = mem_addr + slot_size;
+ uint64_t next_size = mem_size - slot_size;
+ mem_slot slot(memmap, mem_addr, slot_size, mem_head);
+ mem_slot other_slot(memmap, next_addr, next_size, (void *)next_addr);
// pre-allocate shadow pages
do_guest_write(vcpu, mem_head, nr_total_pages, nr_total_pages);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/3 kvm-unit-tests] dirty-log-perf: Take slot size from command line
2012-01-15 3:41 [PATCH 0/3 kvm-unit-tests] Dirty logging performance test Takuya Yoshikawa
2012-01-15 3:43 ` [PATCH v2 1/3 kvm-unit-tests] Add dirty " Takuya Yoshikawa
2012-01-15 3:44 ` [PATCH 2/3 kvm-unit-tests] dirty-log-perf: Split guest memory into two slots Takuya Yoshikawa
@ 2012-01-15 3:45 ` Takuya Yoshikawa
2012-01-18 13:50 ` [PATCH 0/3 kvm-unit-tests] Dirty logging performance test Marcelo Tosatti
3 siblings, 0 replies; 5+ messages in thread
From: Takuya Yoshikawa @ 2012-01-15 3:45 UTC (permalink / raw)
To: avi, mtosatti; +Cc: kvm
Dirty logging is used both for VGA, small slot, and live migration,
large slot, so make the slot size changeable as follows:
$ ./api/dirty-log-perf -n 8K
dirty-log-perf: 8192 slot pages / 262144 mem pages
Note: though we can also change the size of the entire memory space, by
using -m, we observed that this test did not work well under the
following condition:
16 < nr_total_pages < 221K
But thinking that we sometimes want to test slots larger than the
default, we have decided to keep the option.
Signed-off-by: Takuya Yoshikawa <takuya.yoshikawa@gmail.com>
---
api/dirty-log-perf.cc | 54 +++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/api/dirty-log-perf.cc b/api/dirty-log-perf.cc
index f48bc95..ada831e 100644
--- a/api/dirty-log-perf.cc
+++ b/api/dirty-log-perf.cc
@@ -8,9 +8,9 @@
namespace {
-const int page_size = 4096;
-const int64_t nr_total_pages = 256 * 1024;
-const int64_t nr_slot_pages = 256 * 1024;
+const int page_size = 4096;
+int64_t nr_total_pages = 256 * 1024;
+int64_t nr_slot_pages = 256 * 1024;
// Return the current time in nanoseconds.
uint64_t time_ns()
@@ -67,12 +67,58 @@ void check_dirty_log(kvm::vcpu& vcpu, mem_slot& slot, void* slot_head)
}
+void parse_options(int ac, char **av)
+{
+ int opt;
+ char *endptr;
+
+ while ((opt = getopt(ac, av, "n:m:")) != -1) {
+ switch (opt) {
+ case 'n':
+ errno = 0;
+ nr_slot_pages = strtol(optarg, &endptr, 10);
+ if (errno || endptr == optarg) {
+ printf("dirty-log-perf: Invalid number: -n %s\n", optarg);
+ exit(1);
+ }
+ if (*endptr == 'k' || *endptr == 'K') {
+ nr_slot_pages *= 1024;
+ }
+ break;
+ case 'm':
+ errno = 0;
+ nr_total_pages = strtol(optarg, &endptr, 10);
+ if (errno || endptr == optarg) {
+ printf("dirty-log-perf: Invalid number: -m %s\n", optarg);
+ exit(1);
+ }
+ if (*endptr == 'k' || *endptr == 'K') {
+ nr_total_pages *= 1024;
+ }
+ break;
+ default:
+ printf("dirty-log-perf: Invalid option\n");
+ exit(1);
+ }
+ }
+
+ if (nr_slot_pages > nr_total_pages) {
+ printf("dirty-log-perf: Invalid setting: slot %lld > mem %lld\n",
+ nr_slot_pages, nr_total_pages);
+ exit(1);
+ }
+ printf("dirty-log-perf: %lld slot pages / %lld mem pages\n",
+ nr_slot_pages, nr_total_pages);
+}
+
int main(int ac, char **av)
{
kvm::system sys;
kvm::vm vm(sys);
mem_map memmap(vm);
+ parse_options(ac, av);
+
void* mem_head;
int64_t mem_size = nr_total_pages * page_size;
if (posix_memalign(&mem_head, page_size, mem_size)) {
@@ -86,8 +132,8 @@ int main(int ac, char **av)
kvm::vcpu vcpu(vm, 0);
uint64_t slot_size = nr_slot_pages * page_size;
- uint64_t next_addr = mem_addr + slot_size;
uint64_t next_size = mem_size - slot_size;
+ uint64_t next_addr = mem_addr + slot_size;
mem_slot slot(memmap, mem_addr, slot_size, mem_head);
mem_slot other_slot(memmap, next_addr, next_size, (void *)next_addr);
--
1.7.5.4
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 0/3 kvm-unit-tests] Dirty logging performance test
2012-01-15 3:41 [PATCH 0/3 kvm-unit-tests] Dirty logging performance test Takuya Yoshikawa
` (2 preceding siblings ...)
2012-01-15 3:45 ` [PATCH 3/3 kvm-unit-tests] dirty-log-perf: Take slot size from command line Takuya Yoshikawa
@ 2012-01-18 13:50 ` Marcelo Tosatti
3 siblings, 0 replies; 5+ messages in thread
From: Marcelo Tosatti @ 2012-01-18 13:50 UTC (permalink / raw)
To: Takuya Yoshikawa; +Cc: avi, kvm
On Sun, Jan 15, 2012 at 12:41:31PM +0900, Takuya Yoshikawa wrote:
> My 32 bit host running on an intel core i3 box said:
>
> $ ./api/dirty-log-perf
> dirty-log-perf: 262144 slot pages / 262144 mem pages
> rip 804a74a
> rip 804a74a
> get dirty log: 51571 ns for 1 dirty pages
> rip 804a74a
> get dirty log: 81190 ns for 2 dirty pages
> rip 804a74a
> get dirty log: 66606 ns for 4 dirty pages
> rip 804a74a
> get dirty log: 60408 ns for 8 dirty pages
> rip 804a74a
> get dirty log: 46711 ns for 16 dirty pages
> rip 804a74a
> get dirty log: 83563 ns for 32 dirty pages
> rip 804a74a
> get dirty log: 74367 ns for 64 dirty pages
> rip 804a74a
> get dirty log: 87240 ns for 128 dirty pages
> rip 804a74a
> get dirty log: 140161 ns for 256 dirty pages
> rip 804a74a
> get dirty log: 191288 ns for 512 dirty pages
> rip 804a74a
> get dirty log: 981045 ns for 1024 dirty pages
> rip 804a74a
> get dirty log: 1000755 ns for 2048 dirty pages
> rip 804a74a
> get dirty log: 1122837 ns for 4096 dirty pages
> rip 804a74a
> get dirty log: 1362598 ns for 8192 dirty pages
> rip 804a74a
> get dirty log: 1202789 ns for 16384 dirty pages
> rip 804a74a
> get dirty log: 1598484 ns for 32768 dirty pages
> rip 804a74a
> get dirty log: 2456946 ns for 65536 dirty pages
> rip 804a74a
> get dirty log: 3366358 ns for 131072 dirty pages
> rip 804a74a
> get dirty log: 5634134 ns for 262144 dirty pages
>
> Takuya Yoshikawa (3):
> Add dirty logging performance test
> dirty-log-perf: Split guest memory into two slots
> dirty-log-perf: Take slot size from command line
>
> api/dirty-log-perf.cc | 144 +++++++++++++++++++++++++++++++++++++++++++++++++
> config-x86-common.mak | 5 ++-
> 2 files changed, 148 insertions(+), 1 deletions(-)
> create mode 100644 api/dirty-log-perf.cc
Applied, thanks.
^ permalink raw reply [flat|nested] 5+ messages in thread