summaryrefslogtreecommitdiff
path: root/zram-perf
diff options
context:
space:
mode:
authorRiley Andrews <riandrews@google.com>2015-11-20 15:40:09 -0800
committerRiley Andrews <riandrews@google.com>2015-11-23 14:24:40 -0800
commit1199c51b5575613e74eb23f62309526ccb97ae49 (patch)
tree301559984ef51e3be607cb504cafec0f4241e178 /zram-perf
parentec18d7c116654c1254ef40ca6b59ee11709cf29b (diff)
downloadextras-1199c51b5575613e74eb23f62309526ccb97ae49.tar.gz
zram performance test.
Test dumps raw read and write performance to the zram device. It will turn off the swap, benchmark, and then restore the swap device during a successful run. Signed-off-by: Riley Andrews <riandrews@google.com> Change-Id: I9b5474b5f0a7556ca2093f3f0d1f792fa2fb1514
Diffstat (limited to 'zram-perf')
-rw-r--r--zram-perf/Android.mk11
-rw-r--r--zram-perf/zram-perf.cpp151
2 files changed, 162 insertions, 0 deletions
diff --git a/zram-perf/Android.mk b/zram-perf/Android.mk
new file mode 100644
index 00000000..f62e0a24
--- /dev/null
+++ b/zram-perf/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_CLANG := true
+LOCAL_MODULE := zram-perf
+LOCAL_CFLAGS += -g -Wall -Werror -std=c++11 -Wno-missing-field-initializers -Wno-sign-compare -Wno-unused-parameter
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/..
+LOCAL_SRC_FILES := \
+ zram-perf.cpp
+include $(BUILD_EXECUTABLE)
diff --git a/zram-perf/zram-perf.cpp b/zram-perf/zram-perf.cpp
new file mode 100644
index 00000000..32a03ad2
--- /dev/null
+++ b/zram-perf/zram-perf.cpp
@@ -0,0 +1,151 @@
+#include <iostream>
+#include <chrono>
+#include <numeric>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <unistd.h>
+#include <sys/swap.h>
+
+using namespace std;
+
+const char zram_blkdev_path[] = "/dev/block/zram0";
+const size_t sector_size = 512;
+const size_t page_size = 4096;
+
+void fillPageRand(uint32_t *page) {
+ int start = rand();
+ for (int i = 0; i < page_size / sizeof(int); i++) {
+ page[i] = start+i;
+ }
+}
+void fillPageCompressible(uint32_t *page) {
+ int val = rand() & 0xfff;
+ for (int i = 0; i < page_size / sizeof(int); i++) {
+ page[i] = val;
+ }
+}
+
+class AlignedAlloc {
+ void *m_ptr;
+public:
+ AlignedAlloc(size_t size, size_t align) {
+ posix_memalign(&m_ptr, align, size);
+ }
+ ~AlignedAlloc() {
+ free(m_ptr);
+ }
+ void *ptr() {
+ return m_ptr;
+ }
+};
+
+class BlockFd {
+ int m_fd = -1;
+public:
+ BlockFd(const char *path, bool direct) {
+ m_fd = open(path, O_RDWR | (direct ? O_DIRECT : 0));
+ }
+ size_t getSize() {
+ size_t blockSize = 0;
+ int result = ioctl(m_fd, BLKGETSIZE, &blockSize);
+ if (result < 0) {
+ cout << "ioctl failed" << endl;
+ }
+ return blockSize * sector_size;
+ }
+ ~BlockFd() {
+ if (m_fd >= 0) {
+ close(m_fd);
+ }
+ }
+ void fillWithCompressible() {
+ size_t devSize = getSize();
+ AlignedAlloc page(page_size, page_size);
+ for (uint64_t offset = 0; offset < devSize; offset += page_size) {
+ fillPageCompressible((uint32_t*)page.ptr());
+ ssize_t ret = write(m_fd, page.ptr(), page_size);
+ if (ret != page_size) {
+ cout << "write() failed" << endl;
+ }
+ }
+ }
+ void benchSequentialRead() {
+ chrono::time_point<chrono::high_resolution_clock> start, end;
+ size_t devSize = getSize();
+ size_t passes = 4;
+ AlignedAlloc page(page_size, page_size);
+
+ start = chrono::high_resolution_clock::now();
+ for (int i = 0; i < passes; i++) {
+ for (uint64_t offset = 0; offset < devSize; offset += page_size) {
+ if (offset == 0)
+ lseek(m_fd, offset, SEEK_SET);
+ ssize_t ret = read(m_fd, page.ptr(), page_size);
+ if (ret != page_size) {
+ cout << "read() failed" << endl;
+ }
+ }
+ }
+ end = chrono::high_resolution_clock::now();
+ size_t duration = chrono::duration_cast<chrono::microseconds>(end - start).count();
+ cout << "read: " << (double)devSize * passes / 1024.0 / 1024.0 / (duration / 1000.0 / 1000.0) << "MB/s" << endl;
+ }
+ void benchSequentialWrite() {
+ chrono::time_point<chrono::high_resolution_clock> start, end;
+ size_t devSize = getSize();
+ size_t passes = 4;
+ AlignedAlloc page(page_size, page_size);
+
+ start = chrono::high_resolution_clock::now();
+ for (int i = 0; i < passes; i++) {
+ for (uint64_t offset = 0; offset < devSize; offset += page_size) {
+ fillPageCompressible((uint32_t*)page.ptr());
+ if (offset == 0)
+ lseek(m_fd, offset, SEEK_SET);
+ ssize_t ret = write(m_fd, page.ptr(), page_size);
+ if (ret != page_size) {
+ cout << "write() failed" << endl;
+ }
+ }
+ }
+ end = chrono::high_resolution_clock::now();
+ size_t duration = chrono::duration_cast<chrono::microseconds>(end - start).count();
+ cout << "write: " << (double)devSize * passes / 1024.0 / 1024.0 / (duration / 1000.0 / 1000.0) << "MB/s" << endl;
+
+ }
+};
+
+int bench(bool direct)
+{
+ BlockFd zramDev{zram_blkdev_path, direct};
+
+ zramDev.fillWithCompressible();
+ zramDev.benchSequentialRead();
+ zramDev.benchSequentialWrite();
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int result = swapoff(zram_blkdev_path);
+ if (result < 0) {
+ cout << "swapoff failed: " << strerror(errno) << endl;
+ }
+
+ bench(1);
+
+ result = system((string("mkswap ") + string(zram_blkdev_path)).c_str());
+ if (result < 0) {
+ cout << "mkswap failed: " << strerror(errno) << endl;
+ return -1;
+ }
+
+ result = swapon(zram_blkdev_path, 0);
+ if (result < 0) {
+ cout << "swapon failed: " << strerror(errno) << endl;
+ return -1;
+ }
+ return 0;
+}