1 /*
2  * Copyright (C) 2015 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 #include "Benchmark.h"
18 #include "BenchmarkGen.h"
19 #include "VolumeManager.h"
20 #include "ResponseCode.h"
21 
22 #include <android-base/file.h>
23 #include <android-base/logging.h>
24 #include <cutils/iosched_policy.h>
25 #include <private/android_filesystem_config.h>
26 
27 #include <sys/time.h>
28 #include <sys/resource.h>
29 #include <unistd.h>
30 
31 #define ENABLE_DROP_CACHES 1
32 
33 using android::base::ReadFileToString;
34 using android::base::WriteStringToFile;
35 
36 namespace android {
37 namespace vold {
38 
notifyResult(const std::string & path,int64_t create_d,int64_t drop_d,int64_t run_d,int64_t destroy_d)39 static void notifyResult(const std::string& path, int64_t create_d,
40         int64_t drop_d, int64_t run_d, int64_t destroy_d) {
41     std::string res(path +
42             + " " + BenchmarkIdent()
43             + " " + std::to_string(create_d)
44             + " " + std::to_string(drop_d)
45             + " " + std::to_string(run_d)
46             + " " + std::to_string(destroy_d));
47     VolumeManager::Instance()->getBroadcaster()->sendBroadcast(
48             ResponseCode::BenchmarkResult, res.c_str(), false);
49 }
50 
benchmark(const std::string & path)51 static nsecs_t benchmark(const std::string& path) {
52     errno = 0;
53     int orig_prio = getpriority(PRIO_PROCESS, 0);
54     if (errno != 0) {
55         PLOG(ERROR) << "Failed to getpriority";
56         return -1;
57     }
58     if (setpriority(PRIO_PROCESS, 0, -10) != 0) {
59         PLOG(ERROR) << "Failed to setpriority";
60         return -1;
61     }
62 
63     IoSchedClass orig_clazz = IoSchedClass_NONE;
64     int orig_ioprio = 0;
65     if (android_get_ioprio(0, &orig_clazz, &orig_ioprio)) {
66         PLOG(ERROR) << "Failed to android_get_ioprio";
67         return -1;
68     }
69     if (android_set_ioprio(0, IoSchedClass_RT, 0)) {
70         PLOG(ERROR) << "Failed to android_set_ioprio";
71         return -1;
72     }
73 
74     char orig_cwd[PATH_MAX];
75     if (getcwd(orig_cwd, PATH_MAX) == NULL) {
76         PLOG(ERROR) << "Failed getcwd";
77         return -1;
78     }
79     if (chdir(path.c_str()) != 0) {
80         PLOG(ERROR) << "Failed chdir";
81         return -1;
82     }
83 
84     sync();
85 
86     LOG(INFO) << "Benchmarking " << path;
87     nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
88 
89     BenchmarkCreate();
90     sync();
91     nsecs_t create = systemTime(SYSTEM_TIME_BOOTTIME);
92 
93 #if ENABLE_DROP_CACHES
94     LOG(VERBOSE) << "Before drop_caches";
95     if (!WriteStringToFile("3", "/proc/sys/vm/drop_caches")) {
96         PLOG(ERROR) << "Failed to drop_caches";
97     }
98     LOG(VERBOSE) << "After drop_caches";
99 #endif
100     nsecs_t drop = systemTime(SYSTEM_TIME_BOOTTIME);
101 
102     BenchmarkRun();
103     sync();
104     nsecs_t run = systemTime(SYSTEM_TIME_BOOTTIME);
105 
106     BenchmarkDestroy();
107     sync();
108     nsecs_t destroy = systemTime(SYSTEM_TIME_BOOTTIME);
109 
110     if (chdir(orig_cwd) != 0) {
111         PLOG(ERROR) << "Failed to chdir";
112     }
113     if (android_set_ioprio(0, orig_clazz, orig_ioprio)) {
114         PLOG(ERROR) << "Failed to android_set_ioprio";
115     }
116     if (setpriority(PRIO_PROCESS, 0, orig_prio) != 0) {
117         PLOG(ERROR) << "Failed to setpriority";
118     }
119 
120     nsecs_t create_d = create - start;
121     nsecs_t drop_d = drop - create;
122     nsecs_t run_d = run - drop;
123     nsecs_t destroy_d = destroy - run;
124 
125     LOG(INFO) << "create took " << nanoseconds_to_milliseconds(create_d) << "ms";
126     LOG(INFO) << "drop took " << nanoseconds_to_milliseconds(drop_d) << "ms";
127     LOG(INFO) << "run took " << nanoseconds_to_milliseconds(run_d) << "ms";
128     LOG(INFO) << "destroy took " << nanoseconds_to_milliseconds(destroy_d) << "ms";
129 
130     notifyResult(path, create_d, drop_d, run_d, destroy_d);
131 
132     return run_d;
133 }
134 
BenchmarkPrivate(const std::string & path)135 nsecs_t BenchmarkPrivate(const std::string& path) {
136     std::string benchPath(path);
137     benchPath += "/misc";
138     if (android::vold::PrepareDir(benchPath, 01771, AID_SYSTEM, AID_MISC)) {
139         return -1;
140     }
141     benchPath += "/vold";
142     if (android::vold::PrepareDir(benchPath, 0700, AID_ROOT, AID_ROOT)) {
143         return -1;
144     }
145     benchPath += "/bench";
146     if (android::vold::PrepareDir(benchPath, 0700, AID_ROOT, AID_ROOT)) {
147         return -1;
148     }
149     return benchmark(benchPath);
150 }
151 
152 }  // namespace vold
153 }  // namespace android
154