From 2ea45401909e1127ffef351f04f2f1a8f4a3d627 Mon Sep 17 00:00:00 2001 From: subhransu mohanty Date: Thu, 3 Jan 2019 14:27:29 +0900 Subject: [PATCH] lottie: reuse rendertask object to optimize memory allocation. Change-Id: I028f1ea5abec38511bf8413d00d94e425a1ae8db --- src/lottie/lottieanimation.cpp | 59 ++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/src/lottie/lottieanimation.cpp b/src/lottie/lottieanimation.cpp index 540b4d8..c49db2d 100644 --- a/src/lottie/lottieanimation.cpp +++ b/src/lottie/lottieanimation.cpp @@ -25,6 +25,16 @@ using namespace lottie; +struct RenderTask { + RenderTask() { receiver = sender.get_future(); } + std::promise sender; + std::future receiver; + AnimationImpl *playerImpl{nullptr}; + size_t frameNo{0}; + Surface surface; +}; +using SharedRenderTask = std::shared_ptr; + class AnimationImpl { public: @@ -36,13 +46,14 @@ public: size_t totalFrame() const {return mModel->frameDuration();} size_t frameAtPos(double pos) const {return mModel->frameAtPos(pos);} Surface render(size_t frameNo, const Surface &surface); - + std::future renderAsync(size_t frameNo, Surface &&surface); const LOTLayerNode * renderTree(size_t frameNo, const VSize &size); private: std::string mFilePath; std::shared_ptr mModel; std::unique_ptr mCompItem; + SharedRenderTask mTask; std::atomic mRenderInProgress; }; @@ -103,27 +114,19 @@ void AnimationImpl::init(const std::shared_ptr &model) * one it steals the task from it and executes. if it couldn't find one then it * just waits for new task on its own queue. */ -struct RenderTask { - RenderTask() { receiver = sender.get_future(); } - std::promise sender; - std::future receiver; - AnimationImpl *playerImpl{nullptr}; - size_t frameNo{0}; - Surface surface; -}; #include class RenderTaskScheduler { const unsigned _count{std::thread::hardware_concurrency()}; std::vector _threads; - std::vector> _q{_count}; + std::vector> _q{_count}; std::atomic _index{0}; void run(unsigned i) { - RenderTask task; while (true) { bool success = false; + SharedRenderTask task; for (unsigned n = 0; n != _count * 32; ++n) { if (_q[(i + n) % _count].try_pop(task)) { success = true; @@ -132,8 +135,8 @@ class RenderTaskScheduler { } if (!success && !_q[i].pop(task)) break; - auto result = task.playerImpl->render(task.frameNo, task.surface); - task.sender.set_value(result); + auto result = task->playerImpl->render(task->frameNo, task->surface); + task->sender.set_value(result); } } @@ -158,9 +161,9 @@ public: for (auto &e : _threads) e.join(); } - std::future async(RenderTask &&task) + std::future async(SharedRenderTask task) { - auto receiver = std::move(task.receiver); + auto receiver = std::move(task->receiver); auto i = _index++; for (unsigned n = 0; n != _count; ++n) { @@ -171,17 +174,23 @@ public: return receiver; } +}; - std::future render(AnimationImpl *impl, size_t frameNo, - Surface &&surface) - { - RenderTask task; - task.playerImpl = impl; - task.frameNo = frameNo; - task.surface = std::move(surface); - return async(std::move(task)); + +std::future AnimationImpl::renderAsync(size_t frameNo, Surface &&surface) +{ + if (!mTask) { + mTask = std::make_shared(); + } else { + mTask->sender = std::promise(); + mTask->receiver = mTask->sender.get_future(); } -}; + mTask->playerImpl = this; + mTask->frameNo = frameNo; + mTask->surface = std::move(surface); + + return RenderTaskScheduler::instance().async(mTask); +} /** * \breif Brief abput the Api. @@ -258,7 +267,7 @@ Animation::renderTree(size_t frameNo, size_t width, size_t height) const std::future Animation::render(size_t frameNo, Surface surface) { - return RenderTaskScheduler::instance().render(d.get(), frameNo, std::move(surface)); + return d->renderAsync(frameNo, std::move(surface)); } void Animation::renderSync(size_t frameNo, Surface surface) -- 2.7.4