123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- #include <fcntl.h>
- #include <linux/fs.h>
- #include <sys/stat.h>
- #include <sys/swap.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <chrono>
- #include <iostream>
- #include <numeric>
- #include <vector>
- using namespace std;
- static const size_t kPageSize = sysconf(_SC_PAGESIZE);
- static constexpr char kZramBlkdevPath[] = "/dev/block/zram0";
- static constexpr size_t kPatternSize = 4;
- static constexpr size_t kSectorSize = 512;
- void fillPageRand(uint32_t *page) {
- uint32_t start = rand();
- for (int i = 0; i < kPageSize / sizeof(start); i++) {
- page[i] = start+i;
- }
- }
- void fillPageCompressible(void* page) {
- uint32_t val = rand() & 0xfff;
- auto page_ptr = reinterpret_cast<typeof(val)*>(page);
- std::vector<typeof(val)> pattern(kPatternSize, 0);
- for (auto i = 0u; i < kPatternSize; i++) {
- pattern[i] = val + i;
- }
- // fill in ABCD... pattern
- for (int i = 0; i < kPageSize / sizeof(val); i += kPatternSize) {
- std::copy_n(pattern.data(), kPatternSize, (page_ptr + i));
- }
- }
- 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 block size failed" << endl;
- }
- return blockSize * kSectorSize;
- }
- ~BlockFd() {
- if (m_fd >= 0) {
- close(m_fd);
- }
- }
- void fillWithCompressible() {
- size_t devSize = getSize();
- AlignedAlloc page(kPageSize, kPageSize);
- for (uint64_t offset = 0; offset < devSize; offset += kPageSize) {
- fillPageCompressible((uint32_t*)page.ptr());
- ssize_t ret = write(m_fd, page.ptr(), kPageSize);
- if (ret != kPageSize) {
- 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(kPageSize, kPageSize);
- start = chrono::high_resolution_clock::now();
- for (int i = 0; i < passes; i++) {
- for (uint64_t offset = 0; offset < devSize; offset += kPageSize) {
- if (offset == 0)
- lseek(m_fd, offset, SEEK_SET);
- ssize_t ret = read(m_fd, page.ptr(), kPageSize);
- if (ret != kPageSize) {
- 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(kPageSize, kPageSize);
- start = chrono::high_resolution_clock::now();
- for (int i = 0; i < passes; i++) {
- for (uint64_t offset = 0; offset < devSize; offset += kPageSize) {
- fillPageCompressible((uint32_t*)page.ptr());
- if (offset == 0)
- lseek(m_fd, offset, SEEK_SET);
- ssize_t ret = write(m_fd, page.ptr(), kPageSize);
- if (ret != kPageSize) {
- 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{kZramBlkdevPath, direct};
- zramDev.fillWithCompressible();
- zramDev.benchSequentialRead();
- zramDev.benchSequentialWrite();
- return 0;
- }
- int main(int argc, char *argv[])
- {
- int result = swapoff(kZramBlkdevPath);
- if (result < 0) {
- cout << "swapoff failed: " << strerror(errno) << endl;
- }
- bench(1);
- result = system((string("mkswap ") + string(kZramBlkdevPath)).c_str());
- if (result < 0) {
- cout << "mkswap failed: " << strerror(errno) << endl;
- return -1;
- }
- result = swapon(kZramBlkdevPath, 0);
- if (result < 0) {
- cout << "swapon failed: " << strerror(errno) << endl;
- return -1;
- }
- return 0;
- }
|