summaryrefslogtreecommitdiff
path: root/mmap-perf
diff options
context:
space:
mode:
authorRiley Andrews <riandrews@google.com>2015-09-03 17:25:14 -0700
committerMark Salyzyn <salyzyn@google.com>2015-09-18 13:08:42 -0700
commit6e61ea96f3d9765dd9cbf4fa248d90b856c5412a (patch)
tree2bf9bd742835770df7e7e0b19f3dcfcc13407959 /mmap-perf
parent7434d1f8c965669c4a65d35e79086d757b0eb6db (diff)
downloadextras-6e61ea96f3d9765dd9cbf4fa248d90b856c5412a.tar.gz
Yet another disk performance benchmark.
This does memory mapped i/o on huge files, and thus requires a 64 bit device. Change-Id: Id91dd59b8c32751b6cb14f166affbd57912f8d28
Diffstat (limited to 'mmap-perf')
-rw-r--r--mmap-perf/Android.mk27
-rw-r--r--mmap-perf/mmapPerf.cpp163
2 files changed, 190 insertions, 0 deletions
diff --git a/mmap-perf/Android.mk b/mmap-perf/Android.mk
new file mode 100644
index 00000000..f9a4a969
--- /dev/null
+++ b/mmap-perf/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := mmapPerf
+LOCAL_SRC_FILES := mmapPerf.cpp
+LOCAL_CLANG := true
+LOCAL_CFLAGS += -g -Wall -Werror -std=c++11 -Wno-missing-field-initializers -Wno-sign-compare -O3
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+LOCAL_CXX_STL := libc++_static
+LOCAL_STATIC_LIBRARIES := libc
+include $(BUILD_EXECUTABLE)
diff --git a/mmap-perf/mmapPerf.cpp b/mmap-perf/mmapPerf.cpp
new file mode 100644
index 00000000..16e0c76c
--- /dev/null
+++ b/mmap-perf/mmapPerf.cpp
@@ -0,0 +1,163 @@
+#include <string>
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+#include <iostream>
+#include <vector>
+#include <tuple>
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+using namespace std;
+static const size_t pageSize = 4096;
+
+class Fd {
+ int m_fd = -1;
+public:
+ int get() { return m_fd; }
+ void set(int fd) { m_fd = fd; }
+ Fd() {}
+ Fd(int fd) : m_fd{fd} {}
+ ~Fd() {
+ if (m_fd >= 0)
+ close(m_fd);
+ }
+};
+
+int dummy = 0;
+
+void fillPageJunk(void *ptr)
+{
+ uint64_t seed = (unsigned long long)rand() | ((unsigned long long)rand() << 32);
+ uint64_t *target = (uint64_t*)ptr;
+ for (int i = 0; i < pageSize / sizeof(uint64_t); i++) {
+ *target = seed ^ (uint64_t)(uintptr_t)target;
+ seed = (seed << 1) | ((seed >> 63) & 1);
+ target++;
+ }
+}
+
+class FileMap {
+ string m_name;
+ size_t m_size;
+ void *m_ptr = nullptr;
+ Fd m_fileFd;
+public:
+ enum Hint {
+ FILE_MAP_HINT_NONE,
+ FILE_MAP_HINT_RAND,
+ FILE_MAP_HINT_LINEAR,
+ };
+ FileMap(const string &name, size_t size, Hint hint = FILE_MAP_HINT_NONE) : m_name{name}, m_size{size} {
+ int fd = open(name.c_str(), O_CREAT | O_RDWR, S_IRWXU);
+ if (fd < 0) {
+ cerr << "open failed: " << fd << endl;
+ return;
+ }
+ m_fileFd.set(fd);
+ fallocate(m_fileFd.get(), 0, 0, size);
+ unlink(name.c_str());
+ m_ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fileFd.get(), 0);
+ if ((int)(uintptr_t)m_ptr == -1) {
+ cerr << "mmap failed: " << (int)(uintptr_t)m_ptr << endl;
+ m_ptr = nullptr;
+ return;
+ }
+ switch (hint) {
+ case FILE_MAP_HINT_NONE: break;
+ case FILE_MAP_HINT_RAND:
+ madvise(m_ptr, m_size, MADV_RANDOM);
+ break;
+ case FILE_MAP_HINT_LINEAR:
+ madvise(m_ptr, m_size, MADV_SEQUENTIAL);
+ break;
+ }
+ for (int i = 0; i < m_size / pageSize; i++) {
+ uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * i;
+ fillPageJunk(targetPtr);
+ }
+ }
+ void benchRandom(bool write) {
+ size_t pagesTotal = m_size / pageSize;
+ size_t pagesToHit = pagesTotal / 128;
+ uint64_t nsTotal = 0;
+
+ chrono::time_point<chrono::high_resolution_clock> start, end;
+ start = chrono::high_resolution_clock::now();
+ for (int j = 0; j < pagesToHit; j++) {
+ int targetPage = rand() % pagesTotal;
+ uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * targetPage;
+ if (write) {
+ *targetPtr = dummy;
+ }
+ else {
+ dummy += *targetPtr;
+ }
+ }
+ end = chrono::high_resolution_clock::now();
+ nsTotal += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
+ //cout << "random: " << nsTotal / 1000.0 / (pagesToHit) << "us/page" << endl;
+ cout << "random " << (write ? "write" : "read") << ": " << ((4096.0 * pagesToHit) / (1 << 20)) / (nsTotal / 1.0E9) << "MB/s" << endl;
+ }
+ void benchLinear(bool write) {
+ int pagesTotal = m_size / pageSize;
+ int iterations = 4;
+ uint64_t nsTotal = 0;
+
+ chrono::time_point<chrono::high_resolution_clock> start, end;
+ start = chrono::high_resolution_clock::now();
+ for (int i = 0; i < iterations; i++) {
+ for (int j = 0; j < pagesTotal; j++) {
+ uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * j;
+ if (write) {
+ *targetPtr = dummy;
+ }
+ else {
+ dummy += *targetPtr;
+ }
+ }
+ }
+ end = chrono::high_resolution_clock::now();
+ nsTotal += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
+ //cout << "linear: " << nsTotal / 1000.0 / (pagesTotal * iterations) << "us/page" << endl;
+ cout << "linear " << (write ? "write" : "read") << ": " << ((4096.0 * pagesTotal * iterations) / (1 << 20)) / (nsTotal / 1.0E9 ) << "MB/s" << endl;
+ }
+ void dropCache() {
+ int ret1 = msync(m_ptr, m_size, MS_SYNC | MS_INVALIDATE);
+ madvise(m_ptr, m_size, MADV_DONTNEED);
+ (void)ret1;
+ }
+ ~FileMap() {
+ if (m_ptr)
+ munmap(m_ptr, m_size);
+ }
+
+};
+
+int main(int argc, char *argv[])
+{
+ (void)argc;
+ (void)argv;
+ srand(0);
+
+ {
+ FileMap file{"/data/local/tmp/mmap_test", 16000 * (1ull << 20)};
+ file.benchRandom(false);
+ }
+ {
+ FileMap file{"/data/local/tmp/mmap_test", 16000 * (1ull << 20)};
+ file.benchLinear(false);
+ }
+ {
+ FileMap file{"/data/local/tmp/mmap_test", 16000 * (1ull << 20)};
+ file.benchRandom(true);
+ }
+ {
+ FileMap file{"/data/local/tmp/mmap_test", 16000 * (1ull << 20)};
+ file.benchLinear(true);
+ }
+ return 0;
+}