#include #include #include #include #include // stl #include #include #include #include #include #include // boost #include #include #include #include #define BOOST_CHRONO_HEADER_ONLY #include #include #include using namespace boost::chrono; using namespace mapnik; static unsigned test_num = 1; static bool dry_run = false; static std::set test_set; typedef process_cpu_clock clock_type; typedef clock_type::duration dur; template void benchmark(T test, std::string const& name) { try { bool should_run_test = true; if (!test_set.empty()) { should_run_test = test_set.find(test_num) != test_set.end(); } if (should_run_test || dry_run) { if (!test.validate()) { std::clog << "test did not validate: " << name << "\n"; //throw std::runtime_error(std::string("test did not validate: ") + name); } if (dry_run) { std::clog << test_num << ") " << (test.threads_ ? "threaded -> ": "") << name << "\n"; } else { process_cpu_clock::time_point start; dur elapsed; if (test.threads_ > 0) { boost::thread_group tg; for (unsigned i=0;i ": "") << name << ": " << boost::chrono::duration_cast(elapsed) << "\n"; } } } catch (std::exception const& ex) { std::clog << "test runner did not complete: " << ex.what() << "\n"; } test_num++; } bool compare_images(std::string const& src_fn,std::string const& dest_fn) { std::auto_ptr reader1(mapnik::get_image_reader(dest_fn,"png")); if (!reader1.get()) { throw mapnik::image_reader_exception("Failed to load: " + dest_fn); } boost::shared_ptr image_ptr1 = boost::make_shared(reader1->width(),reader1->height()); reader1->read(0,0,image_ptr1->data()); std::auto_ptr reader2(mapnik::get_image_reader(src_fn,"png")); if (!reader2.get()) { throw mapnik::image_reader_exception("Failed to load: " + src_fn); } boost::shared_ptr image_ptr2 = boost::make_shared(reader2->width(),reader2->height()); reader2->read(0,0,image_ptr2->data()); image_data_32 const& dest = image_ptr1->data(); image_data_32 const& src = image_ptr2->data(); unsigned int width = src.width(); unsigned int height = src.height(); if ((width != dest.width()) || height != dest.height()) return false; for (unsigned int y = 0; y < height; ++y) { const unsigned int* row_from = src.getRow(y); const unsigned int* row_to = dest.getRow(y); for (unsigned int x = 0; x < width; ++x) { if (row_from[x] != row_to[x]) return false; } } return true; } struct test1 { unsigned iter_; unsigned threads_; explicit test1(unsigned iterations, unsigned threads=0) : iter_(iterations), threads_(threads) {} bool validate() { return true; } void operator()() { mapnik::image_data_32 im(256,256); std::string out; for (unsigned i=0;i im_; explicit test2(unsigned iterations, unsigned threads=0) : iter_(iterations), threads_(threads), im_() { std::string filename("./benchmark/data/multicolor.png"); std::auto_ptr reader(mapnik::get_image_reader(filename,"png")); if (!reader.get()) { throw mapnik::image_reader_exception("Failed to load: " + filename); } im_ = boost::make_shared(reader->width(),reader->height()); reader->read(0,0,im_->data()); } bool validate() { std::string expected("./benchmark/data/multicolor-hextree-expected.png"); std::string actual("./benchmark/data/multicolor-hextree-actual.png"); mapnik::save_to_file(im_->data(),actual, "png8:m=h"); return compare_images(actual,expected); } void operator()() { std::string out; for (unsigned i=0;idata(),"png8:m=h"); } } }; struct test3 { unsigned iter_; unsigned threads_; double val_; explicit test3(unsigned iterations, unsigned threads=0) : iter_(iterations), threads_(threads), val_(-0.123) {} bool validate() { std::ostringstream s; s << val_; return (s.str() == "-0.123"); } void operator()() { std::string out; for (unsigned i=0;i(snprintf(&s[0], s.size()+1, "%g", val_)); if (n2 <= s.size()) { s.resize(n2); break; } s.resize(n2); } return true; } void operator()() { std::string out; for (unsigned i=0;i #include #include struct test6 { unsigned iter_; unsigned threads_; std::string src_; std::string dest_; mapnik::box2d from_; mapnik::box2d to_; bool defer_proj4_init_; explicit test6(unsigned iterations, unsigned threads, std::string const& src, std::string const& dest, mapnik::box2d from, mapnik::box2d to, bool defer_proj) : iter_(iterations), threads_(threads), src_(src), dest_(dest), from_(from), to_(to), defer_proj4_init_(defer_proj) {} bool validate() { mapnik::projection src(src_,defer_proj4_init_); mapnik::projection dest(dest_,defer_proj4_init_); mapnik::proj_transform tr(src,dest); mapnik::box2d bbox = from_; if (!tr.forward(bbox)) return false; return ((std::fabs(bbox.minx() - to_.minx()) < .5) && (std::fabs(bbox.maxx() - to_.maxx()) < .5) && (std::fabs(bbox.miny() - to_.miny()) < .5) && (std::fabs(bbox.maxy() - to_.maxy()) < .5) ); } void operator()() { unsigned count=0; for (int i=-180;i<180;++i) { for (int j=-85;j<85;++j) { mapnik::projection src(src_,defer_proj4_init_); mapnik::projection dest(dest_,defer_proj4_init_); mapnik::proj_transform tr(src,dest); mapnik::box2d box(i,j,i,j); if (!tr.forward(box)) throw std::runtime_error("could not transform coords"); ++count; } } } }; #include #include #include struct test7 { unsigned iter_; unsigned threads_; std::string expr_; explicit test7(unsigned iterations, unsigned threads, std::string const& expr) : iter_(iterations), threads_(threads), expr_(expr) {} bool validate() { mapnik::expression_ptr expr = mapnik::parse_expression(expr_,"utf-8"); return mapnik::to_expression_string(*expr) == expr_; } void operator()() { for (unsigned i=0;i struct test8 { unsigned iter_; unsigned threads_; std::string expr_; explicit test8(unsigned iterations, unsigned threads, std::string const& expr) : iter_(iterations), threads_(threads), expr_(expr) {} bool validate() { mapnik::expression_grammar expr_grammar(transcoder("utf-8")); mapnik::expression_ptr expr = mapnik::parse_expression(expr_,expr_grammar); return mapnik::to_expression_string(*expr) == expr_; } void operator()() { mapnik::expression_grammar expr_grammar(transcoder("utf-8")); for (unsigned i=0;i #include struct test9 { unsigned iter_; unsigned threads_; unsigned num_rules_; unsigned num_styles_; std::vector rules_; explicit test9(unsigned iterations, unsigned threads, unsigned num_rules, unsigned num_styles) : iter_(iterations), threads_(threads), num_rules_(num_rules), num_styles_(num_styles), rules_() { mapnik::rule r("test"); for (unsigned i=0;i rule_caches; for (unsigned i=0;i rule_ptrs; rule_cache_old() : if_rules_(), else_rules_(), also_rules_() {} void add_rule(rule const& r) { if (r.has_else_filter()) { else_rules_.push_back(&r); } else if (r.has_also_filter()) { also_rules_.push_back(&r); } else { if_rules_.push_back(&r); } } rule_ptrs const& get_if_rules() const { return if_rules_; } rule_ptrs const& get_else_rules() const { return else_rules_; } rule_ptrs const& get_also_rules() const { return also_rules_; } private: rule_ptrs if_rules_; rule_ptrs else_rules_; rule_ptrs also_rules_; }; struct test10 { unsigned iter_; unsigned threads_; unsigned num_rules_; unsigned num_styles_; std::vector rules_; explicit test10(unsigned iterations, unsigned threads, unsigned num_rules, unsigned num_styles) : iter_(iterations), threads_(threads), num_rules_(num_rules), num_styles_(num_styles), rules_() { mapnik::rule r("test"); for (unsigned i=0;i rule_caches; for (unsigned i=0;i rc(new rule_cache_old); for (unsigned i=0;iadd_rule(rules_[i]); } rule_caches.push_back(rc); } } } }; int main( int argc, char** argv) { if (argc > 0) { for (int i=0;i from(-180,-80,180,80); mapnik::box2d to(-20037508.3427892476,-15538711.0963092316,20037508.3427892476,15538711.0963092316); { // echo -180 -60 | cs2cs -f "%.10f" +init=epsg:4326 +to +init=epsg:3857 test6 runner(100000000,100, "+init=epsg:4326", "+init=epsg:3857", from,to,true); benchmark(runner,"lonlat -> merc coord transformation (epsg)"); } { test6 runner(100000000,100, "+init=epsg:3857", "+init=epsg:4326", to,from,true); benchmark(runner,"merc -> lonlat coord transformation (epsg)"); } { test6 runner(100000000,100, "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", from,to,true); benchmark(runner,"lonlat -> merc coord transformation (literal)"); } { test6 runner(100000000,100, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", to,from,true); benchmark(runner,"merc -> lonlat coord transformation (literal)"); } { test7 runner(10000,100,"([foo]=1)"); benchmark(runner,"expression parsing with grammer per parse"); } { test8 runner(10000,100,"([foo]=1)"); benchmark(runner,"expression parsing by re-using grammar"); } { // TODO - only run #if BOOST_VERSION >= 105300 test9 runner(1000,10,200,50); benchmark(runner,"rule caching using boost::move"); } { test10 runner(1000,10,200,50); benchmark(runner,"rule caching using heap allocation"); } std::cout << "...benchmark done\n"; return 0; } catch (std::exception const& ex) { std::clog << "test error: " << ex.what() << "\n"; return -1; } }