From 5b3aea0191561698ede857473e79aab17651d3d2 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Mon, 16 Jan 2017 11:36:24 +0300 Subject: [PATCH] Added graphics benchmark --- drape_frontend/CMakeLists.txt | 2 + drape_frontend/drape_engine.cpp | 8 + drape_frontend/drape_engine.hpp | 5 +- drape_frontend/drape_frontend.pro | 2 + drape_frontend/frontend_renderer.cpp | 18 ++ drape_frontend/frontend_renderer.hpp | 5 + drape_frontend/scenario_manager.cpp | 139 +++++++++ drape_frontend/scenario_manager.hpp | 94 ++++++ map/CMakeLists.txt | 2 + map/benchmark_engine.cpp | 272 ------------------ map/benchmark_engine.hpp | 81 ------ map/benchmark_provider.cpp | 33 --- map/benchmark_provider.hpp | 15 - map/benchmark_tools.cpp | 166 +++++++++++ map/benchmark_tools.hpp | 8 + map/framework.cpp | 3 + map/map.pro | 2 + .../drape_frontend.xcodeproj/project.pbxproj | 8 + xcode/map/map.xcodeproj/project.pbxproj | 8 + 19 files changed, 469 insertions(+), 402 deletions(-) create mode 100644 drape_frontend/scenario_manager.cpp create mode 100644 drape_frontend/scenario_manager.hpp delete mode 100644 map/benchmark_engine.cpp delete mode 100644 map/benchmark_engine.hpp delete mode 100644 map/benchmark_provider.cpp delete mode 100644 map/benchmark_provider.hpp create mode 100644 map/benchmark_tools.cpp create mode 100644 map/benchmark_tools.hpp diff --git a/drape_frontend/CMakeLists.txt b/drape_frontend/CMakeLists.txt index 8195ee30df..7013f7bc53 100644 --- a/drape_frontend/CMakeLists.txt +++ b/drape_frontend/CMakeLists.txt @@ -150,6 +150,8 @@ set( route_shape.hpp rule_drawer.cpp rule_drawer.hpp + scenario_manager.cpp + scenario_manager.hpp screen_animations.cpp screen_animations.hpp screen_operations.cpp diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 4f8e2c899d..953748b5f9 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -574,4 +574,12 @@ void DrapeEngine::SetFontScaleFactor(double scaleFactor) VisualParams::Instance().SetFontScale(scaleFactor); } +void DrapeEngine::RunScenario(ScenarioManager::Scenario && scenario, + ScenarioManager::OnFinishHandler const & handler) +{ + auto const & manager = m_frontend->GetScenarioManager(); + if (manager != nullptr) + manager->RunScenario(move(scenario), handler); +} + } // namespace df diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 381f3f0a4e..57359552e0 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -4,6 +4,7 @@ #include "drape_frontend/color_constants.hpp" #include "drape_frontend/frontend_renderer.hpp" #include "drape_frontend/route_shape.hpp" +#include "drape_frontend/scenario_manager.hpp" #include "drape_frontend/selection_shape.hpp" #include "drape_frontend/threads_commutator.hpp" @@ -176,6 +177,9 @@ public: void SetFontScaleFactor(double scaleFactor); + void RunScenario(ScenarioManager::Scenario && scenario, + ScenarioManager::OnFinishHandler const & handler); + private: void AddUserEvent(drape_ptr && e); void ModelViewChanged(ScreenBase const & screen); @@ -188,7 +192,6 @@ private: void RecacheGui(bool needResetOldGui); void RecacheMapShapes(); -private: drape_ptr m_frontend; drape_ptr m_backend; drape_ptr m_threadCommutator; diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index b65e2f9ce9..dc89b16712 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -76,6 +76,7 @@ SOURCES += \ route_renderer.cpp \ route_shape.cpp \ rule_drawer.cpp \ + scenario_manager.cpp \ screen_animations.cpp \ screen_operations.cpp \ selection_shape.cpp \ @@ -180,6 +181,7 @@ HEADERS += \ route_renderer.hpp \ route_shape.hpp \ rule_drawer.hpp \ + scenario_manager.hpp \ screen_animations.hpp \ screen_operations.hpp \ selection_shape.hpp \ diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 94572c324d..adcbf297f2 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -5,6 +5,7 @@ #include "drape_frontend/framebuffer.hpp" #include "drape_frontend/frontend_renderer.hpp" #include "drape_frontend/message_subclasses.hpp" +#include "drape_frontend/scenario_manager.hpp" #include "drape_frontend/screen_operations.hpp" #include "drape_frontend/transparent_layer.hpp" #include "drape_frontend/visual_params.hpp" @@ -135,6 +136,9 @@ FrontendRenderer::FrontendRenderer(Params const & params) , m_needRestoreSize(false) , m_needRegenerateTraffic(false) , m_trafficEnabled(params.m_trafficEnabled) +#ifdef SCENARIO_ENABLE + , m_scenarioManager(new ScenarioManager(this)) +#endif { #ifdef DRAW_INFO m_tpf = 0.0; @@ -163,6 +167,7 @@ FrontendRenderer::~FrontendRenderer() void FrontendRenderer::Teardown() { + m_scenarioManager.reset(); StopThread(); #ifdef DEBUG m_isTeardowned = true; @@ -429,6 +434,10 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::GpsInfo: { +#ifdef SCENARIO_ENABLE + if (m_scenarioManager->IsRunning()) + break; +#endif ref_ptr msg = message; m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(), m_userEventStream.GetCurrentScreen()); @@ -1808,6 +1817,10 @@ void FrontendRenderer::ReleaseResources() void FrontendRenderer::AddUserEvent(drape_ptr && event) { +#ifdef SCENARIO_ENABLE + if (m_scenarioManager->IsRunning() && event->GetType() == UserEvent::EventType::Touch) + return; +#endif m_userEventStream.AddEvent(move(event)); if (IsInInfinityWaiting()) CancelMessageWaiting(); @@ -1904,6 +1917,11 @@ void FrontendRenderer::OnCacheRouteArrows(int routeIndex, vector c MessagePriority::Normal); } +drape_ptr const & FrontendRenderer::GetScenarioManager() const +{ + return m_scenarioManager; +} + FrontendRenderer::RenderLayer::RenderLayerID FrontendRenderer::RenderLayer::GetLayerID(dp::GLState const & state) { if (state.GetDepthLayer() == dp::GLState::OverlayLayer) diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index d4c6603f96..e416cffd30 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -54,6 +54,7 @@ class SelectionShape; class Framebuffer; class TransparentLayer; class SelectObjectMessage; +class ScenarioManager; struct TapInfo { @@ -154,6 +155,8 @@ public: void ChangeModelView(double autoScale, m2::PointD const & userPos, double azimuth, m2::PointD const & pxZero, TAnimationCreator const & parallelAnimCreator) override; + drape_ptr const & GetScenarioManager() const; + protected: void AcceptMessage(ref_ptr message) override; unique_ptr CreateRoutine() override; @@ -346,6 +349,8 @@ private: bool m_needRegenerateTraffic; bool m_trafficEnabled; + drape_ptr m_scenarioManager; + #ifdef DEBUG bool m_isTeardowned; #endif diff --git a/drape_frontend/scenario_manager.cpp b/drape_frontend/scenario_manager.cpp new file mode 100644 index 0000000000..d9855592e2 --- /dev/null +++ b/drape_frontend/scenario_manager.cpp @@ -0,0 +1,139 @@ +#include "drape_frontend/scenario_manager.hpp" + +#include "drape_frontend/user_event_stream.hpp" + +namespace df +{ + +ScenarioManager::ScenarioManager(FrontendRenderer * frontendRenderer) + : m_frontendRenderer(frontendRenderer) + , m_needInterrupt(false) + , m_isFinished(false) +{ + ASSERT(m_frontendRenderer != nullptr, ()); +} + +ScenarioManager::~ScenarioManager() +{ + std::lock_guard lock(m_mutex); + if (m_thread != nullptr) + { + m_thread->join(); + m_thread.reset(); + } +} + +void ScenarioManager::Interrupt() +{ + std::lock_guard lock(m_mutex); + InterruptImpl(); +} + +bool ScenarioManager::RunScenario(Scenario && scenario, OnFinishHandler const & handler) +{ + std::lock_guard lock(m_mutex); + if (m_thread != nullptr) + { + if (m_isFinished) + InterruptImpl(); + else + return false; // The only scenatio can be executed currently. + } + + std::swap(m_scenario, scenario); + m_onFinishHandler = handler; + m_thread = my::make_unique(&ScenarioManager::ThreadRoutine, this); +#ifdef DEBUG + m_threadId = m_thread->get_id(); +#endif + return true; +} + +bool ScenarioManager::IsRunning() +{ + std::lock_guard lock(m_mutex); + if (m_thread == nullptr) + return false; + + if (m_isFinished) + { + InterruptImpl(); + return false; + } + return true; +} + +void ScenarioManager::ThreadRoutine() +{ + for (auto const & action : m_scenario) + { + // Interrupt scenario if it's necessary. + { + std::lock_guard lock(m_mutex); + if (m_needInterrupt) + { + m_needInterrupt = false; + break; + } + } + + switch(action->GetType()) + { + case ActionType::CenterViewport: + { + CenterViewportAction * centerViewportAction = static_cast(action.get()); + m_frontendRenderer->AddUserEvent(make_unique_dp(centerViewportAction->GetCenter(), + centerViewportAction->GetZoomLevel(), + true)); + break; + } + + case ActionType::WaitForTime: + { + WaitForTimeAction * waitForTimeAction = static_cast(action.get()); + std::this_thread::sleep_for(waitForTimeAction->GetDuration()); + break; + } + + default: + LOG(LINFO, ("Unknown action in scenario")); + } + } + + OnFinishHandler handler = nullptr; + { + std::lock_guard lock(m_mutex); + m_scenario.clear(); + m_isFinished = true; + if (m_onFinishHandler != nullptr) + { + handler = m_onFinishHandler; + m_onFinishHandler = nullptr; + } + } + + if (handler != nullptr) + handler(); +} + +void ScenarioManager::InterruptImpl() +{ + if (m_thread == nullptr) + return; + + ASSERT_NOT_EQUAL(m_threadId, std::this_thread::get_id(), ()); + + if (m_isFinished) + { + m_thread->join(); + m_thread.reset(); + m_isFinished = false; + m_needInterrupt = false; + } + else + { + m_needInterrupt = true; + } +} + +} // namespace df diff --git a/drape_frontend/scenario_manager.hpp b/drape_frontend/scenario_manager.hpp new file mode 100644 index 0000000000..0388a8a8c4 --- /dev/null +++ b/drape_frontend/scenario_manager.hpp @@ -0,0 +1,94 @@ +#pragma once + +#include "drape_frontend/frontend_renderer.hpp" + +#include "geometry/point2d.hpp" + +#include "base/stl_add.hpp" +#include "base/thread.hpp" + +#include +#include +#include +#include +#include + +#define SCENARIO_ENABLE + +namespace df +{ + +class ScenarioManager +{ +public: + enum class ActionType + { + CenterViewport, + WaitForTime + }; + + class Action + { + public: + virtual ~Action() {} + virtual ActionType GetType() = 0; + }; + + class CenterViewportAction : public Action + { + public: + CenterViewportAction(m2::PointD const & pt, int zoomLevel) + : m_center(pt), m_zoomLevel(zoomLevel) {} + + ActionType GetType() override { return ActionType::CenterViewport; } + + m2::PointD const & GetCenter() const { return m_center; } + int GetZoomLevel() const { return m_zoomLevel; } + private: + m2::PointD const m_center; + int const m_zoomLevel; + }; + + class WaitForTimeAction : public Action + { + public: + using Duration = std::chrono::steady_clock::duration; + + WaitForTimeAction(Duration const & duration) + : m_duration(duration) {} + + ActionType GetType() override { return ActionType::WaitForTime; } + + Duration const & GetDuration() const { return m_duration; } + private: + Duration m_duration; + }; + + using Scenario = std::vector>; + using OnFinishHandler = std::function; + + ScenarioManager(FrontendRenderer * frontendRenderer); + ~ScenarioManager(); + + bool RunScenario(Scenario && scenario, OnFinishHandler const & handler); + void Interrupt(); + bool IsRunning(); + +private: + void ThreadRoutine(); + void InterruptImpl(); + + FrontendRenderer * m_frontendRenderer; + + std::mutex m_mutex; + Scenario m_scenario; + bool m_needInterrupt; + bool m_isFinished; + OnFinishHandler m_onFinishHandler; +#ifdef DEBUG + std::thread::id m_threadId; +#endif + std::unique_ptr m_thread; +}; + +} // namespace df diff --git a/map/CMakeLists.txt b/map/CMakeLists.txt index 9085909490..c62a9dccf9 100644 --- a/map/CMakeLists.txt +++ b/map/CMakeLists.txt @@ -15,6 +15,8 @@ set( address_finder.cpp api_mark_point.cpp api_mark_point.hpp + benchmark_tools.hpp + benchmark_tools.cpp bookmark_manager.cpp bookmark_manager.hpp bookmark.cpp diff --git a/map/benchmark_engine.cpp b/map/benchmark_engine.cpp deleted file mode 100644 index 08ac130052..0000000000 --- a/map/benchmark_engine.cpp +++ /dev/null @@ -1,272 +0,0 @@ -#include "map/benchmark_engine.hpp" -#include "map/framework.hpp" - -#include "indexer/data_header.hpp" - -#include "platform/settings.hpp" - -#include "coding/file_container.hpp" -#include "coding/reader_streambuf.hpp" - -#include "std/fstream.hpp" - - -class DoGetBenchmarks -{ - set m_processed; - - BenchmarkEngine & m_engine; - -public: - explicit DoGetBenchmarks(BenchmarkEngine & engine) : m_engine(engine) {} - - void operator() (vector const & v) - { - if (v[0][0] == '#') - return; - - BenchmarkEngine::Benchmark b; - b.m_name = v[1]; - - m2::RectD r; - if (m_processed.insert(v[0]).second) - { - try - { - feature::DataHeader header(v[0]); - r = header.GetBounds(); - } - catch (RootException const & e) - { - LOG(LINFO, ("Can't add", v[0], "file to benchmark:", e.Msg())); - return; - } - } - - int lastScale; - if (v.size() > 3) - { - double lat1, lon1, lat2, lon2; - CHECK(strings::to_double(v[2], lat1), (v[2])); - CHECK(strings::to_double(v[3], lon1), (v[3])); - CHECK(strings::to_double(v[4], lat2), (v[4])); - CHECK(strings::to_double(v[5], lon2), (v[5])); - - r = m2::RectD(m2::PointD(MercatorBounds::LonToX(lon1), MercatorBounds::LatToY(lat1)), - m2::PointD(MercatorBounds::LonToX(lon2), MercatorBounds::LatToY(lat2))); - CHECK(strings::to_int(v[6], lastScale), (v[6])); - } - else - CHECK(strings::to_int(v[2], lastScale), (v[2])); - - ASSERT ( r != m2::RectD::GetEmptyRect(), (r) ); - - Navigator & nav = m_engine.m_framework->GetNavigator(); - - nav.SetFromRect(m2::AnyRectD(r)); - r = nav.Screen().GlobalRect().GetGlobalRect(); - - b.m_provider.reset(new BenchmarkRectProvider(nav.GetDrawScale(), r, lastScale)); - - m_engine.m_benchmarks.push_back(b); - } -}; - -template -void ForEachBenchmarkRecord(ToDo & toDo) -{ - try - { - string configPath; - if (!Settings::Get("BenchmarkConfig", configPath)) - return; - - ReaderStreamBuf buffer(GetPlatform().GetReader(configPath, "w")); - istream stream(&buffer); - - string line; - while (stream.good()) - { - getline(stream, line); - - vector parts; - strings::SimpleTokenizer it(line, " \t"); - while (it) - { - parts.push_back(*it); - ++it; - } - - if (!parts.empty()) - toDo(parts); - } - } - catch (RootException const & e) - { - LOG(LERROR, ("Error reading benchmarks:", e.Msg())); - } -} - -struct MapsCollector -{ - vector m_maps; - - void operator() (vector const & v) - { - ASSERT(!v[0].empty(), ()); - if (v[0][0] != '#') - m_maps.push_back(v[0]); - } -}; - -void BenchmarkEngine::PrepareMaps() -{ - // Deregister all previously registered maps in framework constructor. - m_framework->DeregisterAllMaps(); - - // add only maps needed for benchmarks - MapsCollector collector; - ForEachBenchmarkRecord(collector); - for (string const & map : collector.m_maps) - { - LOG(LINFO, ("Looking for:", map)); - m_framework->RegisterMap(platform::LocalCountryFile::MakeForTesting(map)); - } -} - -BenchmarkEngine::BenchmarkEngine(Framework * fw) - : m_paintDuration(0), - m_maxDuration(0), - m_framework(fw) -{ -} - -void BenchmarkEngine::BenchmarkCommandFinished() -{ - double duration = m_paintDuration; - - if (duration > m_maxDuration) - { - m_maxDuration = duration; - m_maxDurationRect = m_curBenchmarkRect; - } - - BenchmarkResult res; - res.m_name = m_benchmarks[m_curBenchmark].m_name; - res.m_rect = m_curBenchmarkRect; - res.m_time = duration; - m_benchmarkResults.push_back(res); - - if (m_benchmarkResults.size() > 100) - SaveBenchmarkResults(); - - m_paintDuration = 0; -} - -void BenchmarkEngine::SaveBenchmarkResults() -{ - string resultsPath; - Settings::Get("BenchmarkResults", resultsPath); - - ofstream fout(GetPlatform().WritablePathForFile(resultsPath).c_str(), ios::app); - for (size_t i = 0; i < m_benchmarkResults.size(); ++i) - { - /// @todo Place correct version here from bundle (platform). - - fout << GetPlatform().DeviceName() << " " - << "3.0.0" << " " - << m_startTime << " " - << m_benchmarkResults[i].m_name << " " - << m_benchmarkResults[i].m_rect.minX() << " " - << m_benchmarkResults[i].m_rect.minY() << " " - << m_benchmarkResults[i].m_rect.maxX() << " " - << m_benchmarkResults[i].m_rect.maxY() << " " - << m_benchmarkResults[i].m_time << endl; - } - - m_benchmarkResults.clear(); -} - -void BenchmarkEngine::SendBenchmarkResults() -{ -} - -void BenchmarkEngine::MarkBenchmarkResultsEnd() -{ - string resultsPath; - Settings::Get("BenchmarkResults", resultsPath); - ofstream fout(GetPlatform().WritablePathForFile(resultsPath).c_str(), ios::app); - fout << "END " << m_startTime << endl; -} - -void BenchmarkEngine::MarkBenchmarkResultsStart() -{ - string resultsPath; - Settings::Get("BenchmarkResults", resultsPath); - ofstream fout(GetPlatform().WritablePathForFile(resultsPath).c_str(), ios::app); - fout << "START " << m_startTime << endl; -} - -bool BenchmarkEngine::NextBenchmarkCommand() -{ -#ifndef USE_DRAPE - if (m_benchmarks[m_curBenchmark].m_provider->hasRect() || ++m_curBenchmark < m_benchmarks.size()) - { - double const s = m_benchmarksTimer.ElapsedSeconds(); - - int const fenceID = m_framework->GetRenderPolicy()->InsertBenchmarkFence(); - - m_framework->ShowRect(m_benchmarks[m_curBenchmark].m_provider->nextRect()); - m_curBenchmarkRect = m_framework->GetCurrentViewport(); - - m_framework->GetRenderPolicy()->JoinBenchmarkFence(fenceID); - - m_paintDuration += m_benchmarksTimer.ElapsedSeconds() - s; - BenchmarkCommandFinished(); - - return true; - } - else - { - SaveBenchmarkResults(); - MarkBenchmarkResultsEnd(); - SendBenchmarkResults(); - - LOG(LINFO, ("Bechmarks took", m_benchmarksTimer.ElapsedSeconds(), "seconds to complete")); - return false; - } -#else - return false; -#endif // USE_DRAPE -} - -void BenchmarkEngine::Start() -{ - m_thread.Create(make_unique(*this)); -} - -BenchmarkEngine::Routine::Routine(BenchmarkEngine & engine) : m_engine(engine) {} - -void BenchmarkEngine::Routine::Do() -{ - m_engine.PrepareMaps(); - - int benchMarkCount = 1; - (void) Settings::Get("BenchmarkCyclesCount", benchMarkCount); - - for (int i = 0; i < benchMarkCount; ++i) - { - DoGetBenchmarks doGet(m_engine); - ForEachBenchmarkRecord(doGet); - - m_engine.m_curBenchmark = 0; - - m_engine.m_benchmarksTimer.Reset(); - m_engine.m_startTime = my::FormatCurrentTime(); - - m_engine.MarkBenchmarkResultsStart(); - while (m_engine.NextBenchmarkCommand()){}; - - m_engine.m_benchmarks.clear(); - } -} diff --git a/map/benchmark_engine.hpp b/map/benchmark_engine.hpp deleted file mode 100644 index 4ec5bf1648..0000000000 --- a/map/benchmark_engine.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once -#include "map/benchmark_provider.hpp" - -#include "geometry/rect2d.hpp" - -#include "base/timer.hpp" -#include "base/thread.hpp" - -#include "std/string.hpp" -#include "std/vector.hpp" -#include "std/shared_ptr.hpp" - - -class Framework; - -/// BenchmarkEngine is class which: -/// - Creates it's own thread -/// - Feeds the Framework with the paint tasks he wants to performs -/// - Wait until each tasks completion -/// - Measure the time of each task and save the result -class BenchmarkEngine -{ - threads::Thread m_thread; - - double m_paintDuration; - double m_maxDuration; - m2::RectD m_maxDurationRect; - m2::RectD m_curBenchmarkRect; - - string m_startTime; - - struct BenchmarkResult - { - string m_name; - m2::RectD m_rect; - double m_time; - }; - - vector m_benchmarkResults; - my::Timer m_benchmarksTimer; - - struct Benchmark - { - shared_ptr m_provider; - string m_name; - }; - - class Routine : public threads::IRoutine - { - public: - Routine(BenchmarkEngine & engine); - - // threads::IRoutine overrides: - void Do() override; - - private: - BenchmarkEngine & m_engine; - }; - - vector m_benchmarks; - size_t m_curBenchmark; - - Framework * m_framework; - - void BenchmarkCommandFinished(); - bool NextBenchmarkCommand(); - void SaveBenchmarkResults(); - void SendBenchmarkResults(); - - void MarkBenchmarkResultsStart(); - void MarkBenchmarkResultsEnd(); - - void PrepareMaps(); - - friend class DoGetBenchmarks; - -public: - BenchmarkEngine(Framework * fw); - - void Start(); -}; diff --git a/map/benchmark_provider.cpp b/map/benchmark_provider.cpp deleted file mode 100644 index 779325ab01..0000000000 --- a/map/benchmark_provider.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "base/SRC_FIRST.hpp" -#include "map/benchmark_provider.hpp" -#include "geometry/mercator.hpp" - -BenchmarkRectProvider::BenchmarkRectProvider(int startLevel, m2::RectD const & startRect, int endLevel) - : m_endLevel(endLevel) -{ - m_rects.push_back(make_pair(startRect, startLevel)); -} - -bool BenchmarkRectProvider::hasRect() const -{ - return !m_rects.empty(); -} - -m2::RectD const BenchmarkRectProvider::nextRect() -{ - pair const & f = m_rects.front(); - m2::RectD r = f.first; - - if (f.second < m_endLevel) - { - int nextLevel = f.second + 1; - - m_rects.push_back(make_pair(m2::RectD(r.minX(), r.minY(), r.minX() + r.SizeX() / 2, r.minY() + r.SizeY() / 2), nextLevel)); - m_rects.push_back(make_pair(m2::RectD(r.minX() + r.SizeX() / 2, r.minY(), r.maxX(), r.minY() + r.SizeY() / 2), nextLevel)); - m_rects.push_back(make_pair(m2::RectD(r.minX(), r.minY() + r.SizeY() / 2, r.minX() + r.SizeX() / 2, r.maxY()), nextLevel)); - m_rects.push_back(make_pair(m2::RectD(r.minX() + r.SizeX() / 2, r.minY() + r.SizeY() / 2, r.maxX(), r.maxY()), nextLevel)); - } - - m_rects.pop_front(); - return r; -} diff --git a/map/benchmark_provider.hpp b/map/benchmark_provider.hpp deleted file mode 100644 index 045fe8d5d9..0000000000 --- a/map/benchmark_provider.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "geometry/rect2d.hpp" -#include "std/list.hpp" - -struct BenchmarkRectProvider -{ - int m_endLevel; - list > m_rects; - BenchmarkRectProvider(int startLevel, m2::RectD const & startRect, int endLevel); - - bool hasRect() const; - m2::RectD const nextRect(); -}; - diff --git a/map/benchmark_tools.cpp b/map/benchmark_tools.cpp new file mode 100644 index 0000000000..c15401107a --- /dev/null +++ b/map/benchmark_tools.cpp @@ -0,0 +1,166 @@ +#include "map/benchmark_tools.hpp" +#include "map/framework.hpp" + +#include "drape_frontend/scenario_manager.hpp" + +#include "platform/http_client.hpp" +#include "platform/platform.hpp" + +#include "3party/jansson/myjansson.hpp" + +#include +#include +#include +#include +#include + +namespace +{ +struct ScenarioData +{ + std::string m_name; + df::ScenarioManager::Scenario m_scenario; +}; + +struct BenchmarkHandle +{ + std::vector m_scenariosRoRun; + size_t m_currentScenario = 0; + std::vector m_regionsToDownload; + size_t m_regionsToDownloadCounter = 0; +}; + +void RunScenario(Framework * framework, std::shared_ptr handle) +{ + if (handle->m_currentScenario >= handle->m_scenariosRoRun.size()) + return; + + auto & scenarioData = handle->m_scenariosRoRun[handle->m_currentScenario]; + framework->GetDrapeEngine()->RunScenario(std::move(scenarioData.m_scenario), [framework, handle] + { + GetPlatform().RunOnGuiThread([framework, handle]() + { + handle->m_currentScenario++; + RunScenario(framework, handle); + }); + }); +} +} // namespace + +namespace benchmark +{ +void RunGraphicsBenchmark(Framework * framework) +{ +#ifdef SCENARIO_ENABLE + using namespace df; + + // Request scenarios from the server. + platform::HttpClient request("http://osmz.ru/mwm/graphics_benchmark.json"); + if (!request.RunHttpRequest()) + return; + + std::shared_ptr handle = std::make_shared(); + + // Parse scenarios. + std::vector points; + string const & result = request.ServerResponse(); + try + { + my::Json root(result.c_str()); + json_t * scenariosNode = json_object_get(root.get(), "scenarios"); + if (scenariosNode == nullptr || !json_is_array(scenariosNode)) + return; + size_t const sz = json_array_size(scenariosNode); + handle->m_scenariosRoRun.resize(sz); + for (size_t i = 0; i < sz; ++i) + { + auto scenarioElem = json_array_get(scenariosNode, i); + if (scenarioElem == nullptr) + return; + my::FromJSONObject(scenarioElem, "name", handle->m_scenariosRoRun[i].m_name); + json_t * stepsNode = json_object_get(scenarioElem, "steps"); + if (stepsNode != nullptr && json_is_array(stepsNode)) + { + size_t const stepsCount = json_array_size(stepsNode); + auto & scenario = handle->m_scenariosRoRun[i].m_scenario; + scenario.reserve(stepsCount); + for (size_t j = 0; j < stepsCount; ++j) + { + auto stepElem = json_array_get(stepsNode, j); + if (stepElem == nullptr) + return; + string actionType; + my::FromJSONObject(stepElem, "actionType", actionType); + if (actionType == "waitForTime") + { + json_int_t timeInSeconds = 0; + my::FromJSONObject(stepElem, "time", timeInSeconds); + scenario.push_back(std::unique_ptr( + new ScenarioManager::WaitForTimeAction(seconds(timeInSeconds)))); + } + else if (actionType == "centerViewport") + { + json_t * centerNode = json_object_get(stepElem, "center"); + if (centerNode == nullptr) + return; + double x = 0.0, y = 0.0; + my::FromJSONObject(centerNode, "x", x); + my::FromJSONObject(centerNode, "y", y); + json_int_t zoomLevel = -1; + my::FromJSONObject(stepElem, "zoomLevel", zoomLevel); + m2::PointD const pt(x, y); + points.push_back(pt); + scenario.push_back(std::unique_ptr( + new ScenarioManager::CenterViewportAction(pt, static_cast(zoomLevel)))); + } + } + } + } + } + catch (my::Json::Exception const & e) + { + return; + } + if (handle->m_scenariosRoRun.empty()) + return; + + // Find out regions to download. + std::set regions; + for (m2::PointD const & pt : points) + regions.insert(framework->GetCountryInfoGetter().GetRegionCountryId(pt)); + + for (auto const & countryId : regions) + { + storage::NodeStatuses statuses; + framework->GetStorage().GetNodeStatuses(countryId, statuses); + if (statuses.m_status != storage::NodeStatus::OnDisk) + handle->m_regionsToDownload.push_back(countryId); + } + + // Download regions and run scenarios after downloading. + if (!handle->m_regionsToDownload.empty()) + { + framework->GetStorage().Subscribe([framework, handle](storage::TCountryId const & countryId) + { + if (std::find(handle->m_regionsToDownload.begin(), + handle->m_regionsToDownload.end(), countryId) != handle->m_regionsToDownload.end()) + { + handle->m_regionsToDownloadCounter++; + if (handle->m_regionsToDownloadCounter == handle->m_regionsToDownload.size()) + { + handle->m_regionsToDownload.clear(); + RunScenario(framework, handle); + } + } + }, [](storage::TCountryId const &, storage::MapFilesDownloader::TProgress const &){}); + + for (auto const & countryId : handle->m_regionsToDownload) + framework->GetStorage().DownloadNode(countryId); + return; + } + + // Run scenartios without downloading. + RunScenario(framework, handle); +#endif +} +} // namespace benchmark diff --git a/map/benchmark_tools.hpp b/map/benchmark_tools.hpp new file mode 100644 index 0000000000..2e084c4331 --- /dev/null +++ b/map/benchmark_tools.hpp @@ -0,0 +1,8 @@ +#pragma once + +class Framework; + +namespace benchmark +{ +void RunGraphicsBenchmark(Framework * framework); +} // namespace benchmark diff --git a/map/framework.cpp b/map/framework.cpp index 09a895f8cb..1cce5b23d4 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1,4 +1,5 @@ #include "map/framework.hpp" +#include "map/benchmark_tools.hpp" #include "map/chart_generator.hpp" #include "map/ge0_parser.hpp" #include "map/geourl_process.hpp" @@ -1731,6 +1732,8 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, m_drapeApi.SetEngine(make_ref(m_drapeEngine)); m_trafficManager.SetDrapeEngine(make_ref(m_drapeEngine)); + + benchmark::RunGraphicsBenchmark(this); } void Framework::OnRecoverGLContext(int width, int height) diff --git a/map/map.pro b/map/map.pro index 1816bd1e9a..44725e4043 100644 --- a/map/map.pro +++ b/map/map.pro @@ -12,6 +12,7 @@ include($$ROOT_DIR/common.pri) HEADERS += \ api_mark_point.hpp \ + benchmark_tools.hpp \ bookmark.hpp \ bookmark_manager.hpp \ chart_generator.hpp \ @@ -37,6 +38,7 @@ SOURCES += \ ../api/src/c/api-client.c \ address_finder.cpp \ api_mark_point.cpp \ + benchmark_tools.cpp \ bookmark.cpp \ bookmark_manager.cpp \ chart_generator.cpp \ diff --git a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj index c4c08aa8f5..f6b033793b 100644 --- a/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj +++ b/xcode/drape_frontend/drape_frontend.xcodeproj/project.pbxproj @@ -39,6 +39,8 @@ 454C19BB1CCE3EC0002A2C86 /* animation_constants.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 454C19B81CCE3EC0002A2C86 /* animation_constants.hpp */; }; 454C19BC1CCE3EC0002A2C86 /* animation_system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 454C19B91CCE3EC0002A2C86 /* animation_system.cpp */; }; 454C19BD1CCE3EC0002A2C86 /* animation_system.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 454C19BA1CCE3EC0002A2C86 /* animation_system.hpp */; }; + 45580ABA1E28DB2600CD535D /* scenario_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45580AB81E28DB2600CD535D /* scenario_manager.cpp */; }; + 45580ABB1E28DB2600CD535D /* scenario_manager.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45580AB91E28DB2600CD535D /* scenario_manager.hpp */; }; 45B4B8CB1CF5C16B00A54761 /* screen_animations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */; }; 45B4B8CC1CF5C16B00A54761 /* screen_animations.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */; }; 45B4B8CD1CF5C16B00A54761 /* screen_operations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45B4B8C91CF5C16B00A54761 /* screen_operations.cpp */; }; @@ -248,6 +250,8 @@ 454C19B81CCE3EC0002A2C86 /* animation_constants.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = animation_constants.hpp; sourceTree = ""; }; 454C19B91CCE3EC0002A2C86 /* animation_system.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = animation_system.cpp; sourceTree = ""; }; 454C19BA1CCE3EC0002A2C86 /* animation_system.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = animation_system.hpp; sourceTree = ""; }; + 45580AB81E28DB2600CD535D /* scenario_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scenario_manager.cpp; sourceTree = ""; }; + 45580AB91E28DB2600CD535D /* scenario_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = scenario_manager.hpp; sourceTree = ""; }; 45B4B8C71CF5C16B00A54761 /* screen_animations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = screen_animations.cpp; sourceTree = ""; }; 45B4B8C81CF5C16B00A54761 /* screen_animations.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = screen_animations.hpp; sourceTree = ""; }; 45B4B8C91CF5C16B00A54761 /* screen_operations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = screen_operations.cpp; sourceTree = ""; }; @@ -487,6 +491,8 @@ 6743D3681C3A9F090095054B /* arrow3d.hpp */, 6743D3691C3A9F090095054B /* framebuffer.cpp */, 6743D36A1C3A9F090095054B /* framebuffer.hpp */, + 45580AB91E28DB2600CD535D /* scenario_manager.hpp */, + 45580AB81E28DB2600CD535D /* scenario_manager.cpp */, 6743D36B1C3A9F090095054B /* transparent_layer.cpp */, 6743D36C1C3A9F090095054B /* transparent_layer.hpp */, F6B2830B1C1B04680081957A /* gps_track_point.hpp */, @@ -700,6 +706,7 @@ files = ( 670947971BDF9BE1005014C0 /* line_shape.hpp in Headers */, 56BF56DB1C7608C0006DD7CB /* choose_position_mark.hpp in Headers */, + 45580ABB1E28DB2600CD535D /* scenario_manager.hpp in Headers */, 670948031BDF9BF5005014C0 /* drape_engine.hpp in Headers */, 6709486A1BDF9C7F005014C0 /* brush_info.hpp in Headers */, 675D218E1BFB871D00717E4F /* rect.h in Headers */, @@ -913,6 +920,7 @@ F6B283131C1B04680081957A /* gps_track_shape.cpp in Sources */, 45B4B8CB1CF5C16B00A54761 /* screen_animations.cpp in Sources */, 6709483D1BDF9C48005014C0 /* copyright_label.cpp in Sources */, + 45580ABA1E28DB2600CD535D /* scenario_manager.cpp in Sources */, 670947C81BDF9BE1005014C0 /* text_shape.cpp in Sources */, 34C624C31DABDB0400510300 /* traffic_generator.cpp in Sources */, 670947CC1BDF9BE1005014C0 /* tile_info.cpp in Sources */, diff --git a/xcode/map/map.xcodeproj/project.pbxproj b/xcode/map/map.xcodeproj/project.pbxproj index bee4148a73..2984469e17 100644 --- a/xcode/map/map.xcodeproj/project.pbxproj +++ b/xcode/map/map.xcodeproj/project.pbxproj @@ -19,6 +19,8 @@ 34DDA1811DBE5DF40088A609 /* libpartners_api.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34DDA17F1DBE5DF40088A609 /* libpartners_api.a */; }; 34DDA1821DBE5DF40088A609 /* libtracking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 34DDA1801DBE5DF40088A609 /* libtracking.a */; }; 45201E931CE4AC90008A4842 /* api_mark_point.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45201E921CE4AC90008A4842 /* api_mark_point.cpp */; }; + 45580ABE1E2CBD5E00CD535D /* benchmark_tools.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45580ABC1E2CBD5E00CD535D /* benchmark_tools.cpp */; }; + 45580ABF1E2CBD5E00CD535D /* benchmark_tools.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 45580ABD1E2CBD5E00CD535D /* benchmark_tools.hpp */; }; 670E39401C46C5C700E9C0A6 /* gps_tracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 670E393E1C46C5C700E9C0A6 /* gps_tracker.cpp */; }; 670E39411C46C5C700E9C0A6 /* gps_tracker.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 670E393F1C46C5C700E9C0A6 /* gps_tracker.hpp */; }; 674231CB1DF984F600913FEB /* libtraffic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 674231CA1DF984F600913FEB /* libtraffic.a */; }; @@ -129,6 +131,8 @@ 34DDA17F1DBE5DF40088A609 /* libpartners_api.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libpartners_api.a; path = "/Users/igrechuhin/Repo/omim/xcode/partners_api/../../../omim-xcode-build/Debug/libpartners_api.a"; sourceTree = ""; }; 34DDA1801DBE5DF40088A609 /* libtracking.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtracking.a; path = "/Users/igrechuhin/Repo/omim/xcode/tracking/../../../omim-xcode-build/Debug/libtracking.a"; sourceTree = ""; }; 45201E921CE4AC90008A4842 /* api_mark_point.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api_mark_point.cpp; sourceTree = ""; }; + 45580ABC1E2CBD5E00CD535D /* benchmark_tools.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = benchmark_tools.cpp; sourceTree = ""; }; + 45580ABD1E2CBD5E00CD535D /* benchmark_tools.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = benchmark_tools.hpp; sourceTree = ""; }; 670E393E1C46C5C700E9C0A6 /* gps_tracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gps_tracker.cpp; sourceTree = ""; }; 670E393F1C46C5C700E9C0A6 /* gps_tracker.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = gps_tracker.hpp; sourceTree = ""; }; 674231CA1DF984F600913FEB /* libtraffic.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtraffic.a; path = "../../../omim-build/xcode/Debug/libtraffic.a"; sourceTree = ""; }; @@ -390,6 +394,8 @@ 675345BD1A4054AD00A0A8C3 /* map */ = { isa = PBXGroup; children = ( + 45580ABD1E2CBD5E00CD535D /* benchmark_tools.hpp */, + 45580ABC1E2CBD5E00CD535D /* benchmark_tools.cpp */, F63421F61DF9BF9100A96868 /* reachable_by_taxi_checker.cpp */, F63421F71DF9BF9100A96868 /* reachable_by_taxi_checker.hpp */, 347B60741DD9926D0050FA24 /* traffic_manager.cpp */, @@ -466,6 +472,7 @@ 675346651A4054E800A0A8C3 /* framework.hpp in Headers */, 674A2A381B2715FB001A525C /* osm_opening_hours.hpp in Headers */, 670E39411C46C5C700E9C0A6 /* gps_tracker.hpp in Headers */, + 45580ABF1E2CBD5E00CD535D /* benchmark_tools.hpp in Headers */, 342D833B1D5233E8000D8AEA /* displacement_mode_manager.hpp in Headers */, F6B283041C1B03320081957A /* gps_track_collection.hpp in Headers */, ); @@ -590,6 +597,7 @@ 6753463A1A4054E800A0A8C3 /* address_finder.cpp in Sources */, 670E39401C46C5C700E9C0A6 /* gps_tracker.cpp in Sources */, 6753464A1A4054E800A0A8C3 /* bookmark.cpp in Sources */, + 45580ABE1E2CBD5E00CD535D /* benchmark_tools.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };