Skip to content

Commit 50e8ee7

Browse files
Mark SalyzynGerrit Code Review
authored andcommitted
Merge "Yet another disk performance benchmark."
2 parents 7434d1f + 6e61ea9 commit 50e8ee7

File tree

2 files changed

+190
-0
lines changed

2 files changed

+190
-0
lines changed

mmap-perf/Android.mk

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#
2+
# Copyright (C) 2014 The Android Open Source Project
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
17+
LOCAL_PATH:= $(call my-dir)
18+
19+
include $(CLEAR_VARS)
20+
LOCAL_MODULE := mmapPerf
21+
LOCAL_SRC_FILES := mmapPerf.cpp
22+
LOCAL_CLANG := true
23+
LOCAL_CFLAGS += -g -Wall -Werror -std=c++11 -Wno-missing-field-initializers -Wno-sign-compare -O3
24+
LOCAL_FORCE_STATIC_EXECUTABLE := true
25+
LOCAL_CXX_STL := libc++_static
26+
LOCAL_STATIC_LIBRARIES := libc
27+
include $(BUILD_EXECUTABLE)

mmap-perf/mmapPerf.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#include <string>
2+
#include <cstring>
3+
#include <cstdlib>
4+
#include <cstdio>
5+
#include <iostream>
6+
#include <vector>
7+
#include <tuple>
8+
9+
#include <unistd.h>
10+
#include <sys/stat.h>
11+
#include <fcntl.h>
12+
#include <sys/mman.h>
13+
14+
using namespace std;
15+
static const size_t pageSize = 4096;
16+
17+
class Fd {
18+
int m_fd = -1;
19+
public:
20+
int get() { return m_fd; }
21+
void set(int fd) { m_fd = fd; }
22+
Fd() {}
23+
Fd(int fd) : m_fd{fd} {}
24+
~Fd() {
25+
if (m_fd >= 0)
26+
close(m_fd);
27+
}
28+
};
29+
30+
int dummy = 0;
31+
32+
void fillPageJunk(void *ptr)
33+
{
34+
uint64_t seed = (unsigned long long)rand() | ((unsigned long long)rand() << 32);
35+
uint64_t *target = (uint64_t*)ptr;
36+
for (int i = 0; i < pageSize / sizeof(uint64_t); i++) {
37+
*target = seed ^ (uint64_t)(uintptr_t)target;
38+
seed = (seed << 1) | ((seed >> 63) & 1);
39+
target++;
40+
}
41+
}
42+
43+
class FileMap {
44+
string m_name;
45+
size_t m_size;
46+
void *m_ptr = nullptr;
47+
Fd m_fileFd;
48+
public:
49+
enum Hint {
50+
FILE_MAP_HINT_NONE,
51+
FILE_MAP_HINT_RAND,
52+
FILE_MAP_HINT_LINEAR,
53+
};
54+
FileMap(const string &name, size_t size, Hint hint = FILE_MAP_HINT_NONE) : m_name{name}, m_size{size} {
55+
int fd = open(name.c_str(), O_CREAT | O_RDWR, S_IRWXU);
56+
if (fd < 0) {
57+
cerr << "open failed: " << fd << endl;
58+
return;
59+
}
60+
m_fileFd.set(fd);
61+
fallocate(m_fileFd.get(), 0, 0, size);
62+
unlink(name.c_str());
63+
m_ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fileFd.get(), 0);
64+
if ((int)(uintptr_t)m_ptr == -1) {
65+
cerr << "mmap failed: " << (int)(uintptr_t)m_ptr << endl;
66+
m_ptr = nullptr;
67+
return;
68+
}
69+
switch (hint) {
70+
case FILE_MAP_HINT_NONE: break;
71+
case FILE_MAP_HINT_RAND:
72+
madvise(m_ptr, m_size, MADV_RANDOM);
73+
break;
74+
case FILE_MAP_HINT_LINEAR:
75+
madvise(m_ptr, m_size, MADV_SEQUENTIAL);
76+
break;
77+
}
78+
for (int i = 0; i < m_size / pageSize; i++) {
79+
uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * i;
80+
fillPageJunk(targetPtr);
81+
}
82+
}
83+
void benchRandom(bool write) {
84+
size_t pagesTotal = m_size / pageSize;
85+
size_t pagesToHit = pagesTotal / 128;
86+
uint64_t nsTotal = 0;
87+
88+
chrono::time_point<chrono::high_resolution_clock> start, end;
89+
start = chrono::high_resolution_clock::now();
90+
for (int j = 0; j < pagesToHit; j++) {
91+
int targetPage = rand() % pagesTotal;
92+
uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * targetPage;
93+
if (write) {
94+
*targetPtr = dummy;
95+
}
96+
else {
97+
dummy += *targetPtr;
98+
}
99+
}
100+
end = chrono::high_resolution_clock::now();
101+
nsTotal += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
102+
//cout << "random: " << nsTotal / 1000.0 / (pagesToHit) << "us/page" << endl;
103+
cout << "random " << (write ? "write" : "read") << ": " << ((4096.0 * pagesToHit) / (1 << 20)) / (nsTotal / 1.0E9) << "MB/s" << endl;
104+
}
105+
void benchLinear(bool write) {
106+
int pagesTotal = m_size / pageSize;
107+
int iterations = 4;
108+
uint64_t nsTotal = 0;
109+
110+
chrono::time_point<chrono::high_resolution_clock> start, end;
111+
start = chrono::high_resolution_clock::now();
112+
for (int i = 0; i < iterations; i++) {
113+
for (int j = 0; j < pagesTotal; j++) {
114+
uint8_t *targetPtr = (uint8_t*)m_ptr + 4096ull * j;
115+
if (write) {
116+
*targetPtr = dummy;
117+
}
118+
else {
119+
dummy += *targetPtr;
120+
}
121+
}
122+
}
123+
end = chrono::high_resolution_clock::now();
124+
nsTotal += chrono::duration_cast<chrono::nanoseconds>(end - start).count();
125+
//cout << "linear: " << nsTotal / 1000.0 / (pagesTotal * iterations) << "us/page" << endl;
126+
cout << "linear " << (write ? "write" : "read") << ": " << ((4096.0 * pagesTotal * iterations) / (1 << 20)) / (nsTotal / 1.0E9 ) << "MB/s" << endl;
127+
}
128+
void dropCache() {
129+
int ret1 = msync(m_ptr, m_size, MS_SYNC | MS_INVALIDATE);
130+
madvise(m_ptr, m_size, MADV_DONTNEED);
131+
(void)ret1;
132+
}
133+
~FileMap() {
134+
if (m_ptr)
135+
munmap(m_ptr, m_size);
136+
}
137+
138+
};
139+
140+
int main(int argc, char *argv[])
141+
{
142+
(void)argc;
143+
(void)argv;
144+
srand(0);
145+
146+
{
147+
FileMap file{"/data/local/tmp/mmap_test", 16000 * (1ull << 20)};
148+
file.benchRandom(false);
149+
}
150+
{
151+
FileMap file{"/data/local/tmp/mmap_test", 16000 * (1ull << 20)};
152+
file.benchLinear(false);
153+
}
154+
{
155+
FileMap file{"/data/local/tmp/mmap_test", 16000 * (1ull << 20)};
156+
file.benchRandom(true);
157+
}
158+
{
159+
FileMap file{"/data/local/tmp/mmap_test", 16000 * (1ull << 20)};
160+
file.benchLinear(true);
161+
}
162+
return 0;
163+
}

0 commit comments

Comments
 (0)