13 const char zram_blkdev_path[] = "/dev/block/zram0";
14 const size_t sector_size = 512;
15 const size_t page_size = 4096;
17 void fillPageRand(uint32_t *page) {
19 for (int i = 0; i < page_size / sizeof(int); i++) {
23 void fillPageCompressible(uint32_t *page) {
24 int val = rand() & 0xfff;
25 for (int i = 0; i < page_size / sizeof(int); i++) {
33 AlignedAlloc(size_t size, size_t align) {
34 posix_memalign(&m_ptr, align, size);
47 BlockFd(const char *path, bool direct) {
48 m_fd = open(path, O_RDWR | (direct ? O_DIRECT : 0));
52 int result = ioctl(m_fd, BLKGETSIZE, &blockSize);
54 cout << "ioctl failed" << endl;
56 return blockSize * sector_size;
63 void fillWithCompressible() {
64 size_t devSize = getSize();
65 AlignedAlloc page(page_size, page_size);
66 for (uint64_t offset = 0; offset < devSize; offset += page_size) {
67 fillPageCompressible((uint32_t*)page.ptr());
68 ssize_t ret = write(m_fd, page.ptr(), page_size);
69 if (ret != page_size) {
70 cout << "write() failed" << endl;
74 void benchSequentialRead() {
75 chrono::time_point<chrono::high_resolution_clock> start, end;
76 size_t devSize = getSize();
78 AlignedAlloc page(page_size, page_size);
80 start = chrono::high_resolution_clock::now();
81 for (int i = 0; i < passes; i++) {
82 for (uint64_t offset = 0; offset < devSize; offset += page_size) {
84 lseek(m_fd, offset, SEEK_SET);
85 ssize_t ret = read(m_fd, page.ptr(), page_size);
86 if (ret != page_size) {
87 cout << "read() failed" << endl;
91 end = chrono::high_resolution_clock::now();
92 size_t duration = chrono::duration_cast<chrono::microseconds>(end - start).count();
93 cout << "read: " << (double)devSize * passes / 1024.0 / 1024.0 / (duration / 1000.0 / 1000.0) << "MB/s" << endl;
95 void benchSequentialWrite() {
96 chrono::time_point<chrono::high_resolution_clock> start, end;
97 size_t devSize = getSize();
99 AlignedAlloc page(page_size, page_size);
101 start = chrono::high_resolution_clock::now();
102 for (int i = 0; i < passes; i++) {
103 for (uint64_t offset = 0; offset < devSize; offset += page_size) {
104 fillPageCompressible((uint32_t*)page.ptr());
106 lseek(m_fd, offset, SEEK_SET);
107 ssize_t ret = write(m_fd, page.ptr(), page_size);
108 if (ret != page_size) {
109 cout << "write() failed" << endl;
113 end = chrono::high_resolution_clock::now();
114 size_t duration = chrono::duration_cast<chrono::microseconds>(end - start).count();
115 cout << "write: " << (double)devSize * passes / 1024.0 / 1024.0 / (duration / 1000.0 / 1000.0) << "MB/s" << endl;
120 int bench(bool direct)
122 BlockFd zramDev{zram_blkdev_path, direct};
124 zramDev.fillWithCompressible();
125 zramDev.benchSequentialRead();
126 zramDev.benchSequentialWrite();
130 int main(int argc, char *argv[])
132 int result = swapoff(zram_blkdev_path);
134 cout << "swapoff failed: " << strerror(errno) << endl;
139 result = system((string("mkswap ") + string(zram_blkdev_path)).c_str());
141 cout << "mkswap failed: " << strerror(errno) << endl;
145 result = swapon(zram_blkdev_path, 0);
147 cout << "swapon failed: " << strerror(errno) << endl;