1 /** \example benchmark/benchmark_rmf.cpp
2 * \brief Benchmark typical creation, traversal and loading with different RMF
3 * backends.
4 *
5 * Copyright 2007-2021 IMP Inventors. All rights reserved.
6 */
7
8 #include <boost/iterator/iterator_facade.hpp>
9 #include <boost/filesystem/operations.hpp>
10 #include <boost/timer.hpp>
11 #include <exception>
12 #include <iostream>
13 #include <string>
14 #include <vector>
15
16 #include "RMF/BufferHandle.h"
17 #include "RMF/FileConstHandle.h"
18 #include "RMF/FileHandle.h"
19 #include "RMF/ID.h"
20 #include "RMF/NodeConstHandle.h"
21 #include "RMF/NodeHandle.h"
22 #include "RMF/Vector.h"
23 #include "RMF/decorator/physics.h"
24 #include "RMF/decorator/sequence.h"
25 #include "RMF/enums.h"
26 #include "RMF/infrastructure_macros.h"
27 #include "RMF/log.h"
28
29 namespace {
30 #ifndef NDEBUG
31 const int scale = 1;
32 #else
33 const int scale = 5;
34 #endif
35
show_size(unsigned int sz)36 std::string show_size(unsigned int sz) {
37 std::ostringstream oss;
38 if (sz > 1000000) {
39 oss << sz / 1000000 << "M";
40 } else if (sz > 1000) {
41 oss << sz / 1000 << "k";
42 } else {
43 oss << sz << "b";
44 }
45 return oss.str();
46 }
47
benchmark_size(std::string path,std::string type)48 void benchmark_size(std::string path, std::string type) {
49 unsigned int size = 0;
50 if (boost::filesystem::is_directory(path)) {
51 for (boost::filesystem::directory_iterator it(path);
52 it != boost::filesystem::directory_iterator(); it++) {
53 size += boost::filesystem::file_size(*it);
54 }
55 } else {
56 size = boost::filesystem::file_size(path);
57 }
58 std::cout << type << ", size, " << show_size(size) << ", " << size
59 << std::endl;
60 }
61
create_residue(RMF::NodeHandle nh,RMF::decorator::AtomFactory af,RMF::decorator::ParticleFactory pf)62 std::size_t create_residue(RMF::NodeHandle nh, RMF::decorator::AtomFactory af,
63 RMF::decorator::ParticleFactory pf) {
64 std::size_t total_size = 0;
65 for (unsigned int i = 0; i < 2 * scale; ++i) {
66 RMF::NodeHandle child = nh.add_child("CA", RMF::REPRESENTATION);
67 pf.get(child).set_static_mass(1);
68 pf.get(child).set_static_radius(1.0 + i / 18.77);
69 af.get(child).set_static_element(7);
70 total_size += sizeof(int) * 1 + sizeof(float) * 2;
71 }
72 return total_size;
73 }
create_chain(RMF::NodeHandle nh,RMF::decorator::ResidueFactory rf,RMF::decorator::AtomFactory af,RMF::decorator::ParticleFactory pf)74 std::size_t create_chain(RMF::NodeHandle nh, RMF::decorator::ResidueFactory rf,
75 RMF::decorator::AtomFactory af,
76 RMF::decorator::ParticleFactory pf) {
77 std::size_t total_size = 0;
78 for (unsigned int i = 0; i < 60 * scale; ++i) {
79 std::ostringstream oss;
80 oss << i;
81 RMF::NodeHandle child = nh.add_child(oss.str(), RMF::REPRESENTATION);
82 rf.get(child).set_static_residue_type("cys");
83 rf.get(child).set_static_residue_index(i);
84 total_size += sizeof(int) + 4;
85 total_size += create_residue(child, af, pf);
86 }
87 return total_size;
88 }
create_hierarchy(RMF::FileHandle file)89 std::size_t create_hierarchy(RMF::FileHandle file) {
90 RMF::decorator::ChainFactory cf(file);
91 RMF::decorator::AtomFactory af(file);
92 RMF::decorator::ResidueFactory rf(file);
93 RMF::decorator::ParticleFactory pf(file);
94 RMF::NodeHandle n = file.get_root_node();
95 std::size_t total_size = 0;
96 for (unsigned int i = 0; i < 3 * scale; ++i) {
97 std::ostringstream oss;
98 oss << i;
99 RMF::NodeHandle child = n.add_child(oss.str(), RMF::REPRESENTATION);
100 cf.get(child).set_static_chain_id(oss.str());
101 total_size += oss.str().size();
102 total_size += create_chain(child, rf, af, pf);
103 }
104 return total_size;
105 }
106
create_frame(RMF::FileHandle fh,RMF::decorator::ParticleFactory ipf,const RMF::NodeIDs & atoms,int frame)107 std::pair<double, std::size_t> create_frame(RMF::FileHandle fh,
108 RMF::decorator::ParticleFactory ipf,
109 const RMF::NodeIDs& atoms,
110 int frame) {
111 RMF::Vector3 ret(0, 0, 0);
112 std::size_t total_size = 0;
113 RMF_FOREACH(RMF::NodeID n, atoms) {
114 RMF::Vector3 v((n.get_index() + 0 + frame) / 17.0,
115 (n.get_index() + 1 + frame) / 19.0,
116 (n.get_index() + 2 + frame) / 23.0);
117 ret[0] += v[0];
118 ret[1] += v[1];
119 ret[2] += v[2];
120 ipf.get(fh.get_node(n)).set_frame_coordinates(v);
121 total_size += sizeof(float) * 3;
122 }
123 return std::make_pair(ret[0] + ret[1] + ret[2], total_size);
124 }
125
create(RMF::FileHandle file,RMF::NodeIDs & atoms)126 boost::tuple<std::size_t> create(RMF::FileHandle file, RMF::NodeIDs& atoms) {
127 std::size_t hierarchy_size = create_hierarchy(file);
128 RMF_FOREACH(RMF::NodeID n, file.get_node_ids()) {
129 if (file.get_node(n).get_children().empty()) {
130 atoms.push_back(n);
131 }
132 }
133 return boost::make_tuple(hierarchy_size);
134 }
135
create_frames(RMF::FileHandle file,const RMF::NodeIDs & atoms)136 boost::tuple<double, std::size_t> create_frames(RMF::FileHandle file,
137 const RMF::NodeIDs& atoms) {
138 RMF::decorator::ParticleFactory ipf(file);
139 double check_value = 0;
140 std::size_t frame_size = 0;
141 for (unsigned int i = 0; i < 20; ++i) {
142 file.add_frame("frame", RMF::FRAME);
143 std::pair<double, std::size_t> cur = create_frame(file, ipf, atoms, i);
144 check_value += cur.first;
145 frame_size += cur.second;
146 }
147 return boost::make_tuple(check_value, frame_size);
148 }
149
traverse(RMF::FileConstHandle file)150 double traverse(RMF::FileConstHandle file) {
151 double ret = 0;
152 RMF::NodeConstHandles queue(1, file.get_root_node());
153 RMF::decorator::ParticleFactory ipcf(file);
154 do {
155 RMF::NodeConstHandle cur = queue.back();
156 queue.pop_back();
157 if (ipcf.get_is(cur)) {
158 ret += ipcf.get(cur).get_radius();
159 }
160 RMF::NodeConstHandles children = cur.get_children();
161 queue.insert(queue.end(), children.begin(), children.end());
162 } while (!queue.empty());
163 return ret;
164 }
165
load(RMF::FileConstHandle file,const RMF::NodeIDs & nodes)166 double load(RMF::FileConstHandle file, const RMF::NodeIDs& nodes) {
167 RMF::decorator::IntermediateParticleFactory ipcf(file);
168 RMF::Vector3 v(0, 0, 0);
169 RMF_FOREACH(RMF::FrameID fr, file.get_frames()) {
170 file.set_current_frame(fr);
171 RMF_FOREACH(RMF::NodeID n, nodes) {
172 RMF::Vector3 cur = ipcf.get(file.get_node(n)).get_coordinates();
173 v[0] += cur[0];
174 v[1] += cur[1];
175 v[2] += cur[2];
176 }
177 }
178 return v[0] + v[1] + v[2];
179 }
180
benchmark_create(RMF::FileHandle file,std::string type)181 std::pair<std::size_t, std::size_t> benchmark_create(RMF::FileHandle file,
182 std::string type) {
183 RMF::NodeIDs atoms;
184 boost::timer timer;
185 boost::tuple<std::size_t> cur = create(file, atoms);
186 std::cout << type << ", create, " << timer.elapsed() << ", " << cur.get<0>()
187 << std::endl;
188 boost::timer frame_timer;
189 boost::tuple<double, std::size_t> frames = create_frames(file, atoms);
190 std::cout << type << ", create frame, " << frame_timer.elapsed() / 20.0
191 << ", " << frames.get<0>() << std::endl;
192 return std::make_pair(cur.get<0>(), frames.get<1>());
193 }
194
benchmark_traverse(RMF::FileConstHandle file,std::string type)195 void benchmark_traverse(RMF::FileConstHandle file, std::string type) {
196 file.set_current_frame(RMF::FrameID(0));
197 boost::timer timer;
198 double count = 0;
199 double t;
200 while (timer.elapsed() < 1) {
201 t = traverse(file);
202 ++count;
203 }
204 std::cout << type << ", traverse, " << timer.elapsed() / count << ", " << t
205 << std::endl;
206 }
207
benchmark_load(RMF::FileConstHandle file,std::string type)208 void benchmark_load(RMF::FileConstHandle file, std::string type) {
209 RMF::NodeIDs nodes;
210 RMF::decorator::ParticleFactory ipcf(file);
211 RMF_FOREACH(RMF::NodeID n, file.get_node_ids()) {
212 if (ipcf.get_is(file.get_node(n))) nodes.push_back(n);
213 }
214 boost::timer timer;
215 double dist = load(file, nodes);
216 std::cout << type << ", load, " << timer.elapsed() / 20.0 << ", " << dist
217 << std::endl;
218 }
219
benchmark_open(std::string path,std::string type)220 RMF::FileConstHandle benchmark_open(std::string path, std::string type) {
221 boost::timer timer;
222 RMF::FileConstHandle ret;
223 double count = 0;
224 while (timer.elapsed() < 1) {
225 ret = RMF::open_rmf_file_read_only(path);
226 ++count;
227 }
228 std::cout << type << ", open, " << timer.elapsed() / count << ", 0"
229 << std::endl;
230 return ret;
231 }
232 } // namespace
233
main(int,char **)234 int main(int, char**) {
235 try {
236 RMF::set_log_level("Off");
237 std::string name_base = RMF::internal::get_unique_path();
238 #ifndef NDEBUG
239 std::cout << name_base << std::endl;
240 #endif
241 {
242 const std::string name = name_base + ".rmf";
243 {
244 RMF::FileHandle fh = RMF::create_rmf_file(name);
245 std::pair<std::size_t, std::size_t> sizes = benchmark_create(fh, "rmf");
246 std::cout << "raw, total, " << show_size(sizes.first + sizes.second)
247 << ", " << (sizes.first + sizes.second) << std::endl;
248 std::cout << "raw, frame, " << show_size(sizes.second) << ", "
249 << sizes.second << std::endl;
250 }
251 {
252 RMF::FileConstHandle fh = benchmark_open(name, "rmf");
253 benchmark_traverse(fh, "rmf");
254 benchmark_load(fh, "rmf");
255 }
256 benchmark_size(name, "rmf");
257 }
258 {
259 const std::string name = name_base + ".rmfz";
260 {
261 RMF::FileHandle fh = RMF::create_rmf_file(name);
262 benchmark_create(fh, "rmfz");
263 }
264 {
265 RMF::FileConstHandle fh = benchmark_open(name, "rmfz");
266 benchmark_traverse(fh, "rmfz");
267 benchmark_load(fh, "rmfz");
268 }
269 benchmark_size(name, "rmfz");
270 }
271 {
272 RMF::BufferHandle buffer;
273 {
274 RMF::FileHandle fh = RMF::create_rmf_buffer(buffer);
275 benchmark_create(fh, "buffer");
276 }
277 {
278 boost::timer timer;
279 RMF::FileConstHandle fh = RMF::open_rmf_buffer_read_only(buffer);
280 std::cout << "buffer"
281 << ", open, " << timer.elapsed() << ", 0" << std::endl;
282 benchmark_traverse(fh, "buffer");
283 benchmark_load(fh, "buffer");
284 }
285 }
286 }
287 catch (const std::exception& e) {
288 std::cerr << "Exception thrown: " << e.what() << std::endl;
289 }
290 return 0;
291 }
292