rlottie: refactor to use a local arena allocator for shadow tree creation
authorsubhransu mohanty <sub.mohanty@samsung.com>
Mon, 4 Nov 2019 01:11:23 +0000 (10:11 +0900)
committerJongmin Lee <jm105.lee@samsung.com>
Mon, 11 Nov 2019 20:58:15 +0000 (05:58 +0900)
This usecase is best suitable for local arena allocator as we have a fixed number
of objects to create and they all gets deleted at once. so by keeping a allocator
in the composition and use it to create all the objects using it will basically
flattened the memory layout of the shadow tree as all the memory comes from the one
memory allocator pool.
This improves the bencmark performance by 5%.

src/lottie/lottieitem.cpp
src/lottie/lottieitem.h

index 6f9c584..44f1350 100644 (file)
@@ -68,39 +68,24 @@ static bool strokeProp(rlottie::Property prop)
     }
 }
 
-LOTCompItem::LOTCompItem(LOTModel *model)
-    : mCurFrameNo(-1)
-{
-    mCompData = model->mRoot.get();
-    mRootLayer = createLayerItem(mCompData->mRootLayer.get());
-    mRootLayer->setComplexContent(false);
-    mViewSize = mCompData->size();
-}
-
-void LOTCompItem::setValue(const std::string &keypath, LOTVariant &value)
-{
-    LOTKeyPath key(keypath);
-    mRootLayer->resolveKeyPath(key, 0, value);
-}
-
-std::unique_ptr<LOTLayerItem> LOTCompItem::createLayerItem(
-    LOTLayerData *layerData)
+static LOTLayerItem*
+createLayerItem(LOTLayerData *layerData, VArenaAlloc *allocator)
 {
     switch (layerData->mLayerType) {
     case LayerType::Precomp: {
-        return std::make_unique<LOTCompLayerItem>(layerData);
+        return allocator->make<LOTCompLayerItem>(layerData, allocator);
     }
     case LayerType::Solid: {
-        return std::make_unique<LOTSolidLayerItem>(layerData);
+        return allocator->make<LOTSolidLayerItem>(layerData);
     }
     case LayerType::Shape: {
-        return std::make_unique<LOTShapeLayerItem>(layerData);
+        return allocator->make<LOTShapeLayerItem>(layerData, allocator);
     }
     case LayerType::Null: {
-        return std::make_unique<LOTNullLayerItem>(layerData);
+        return allocator->make<LOTNullLayerItem>(layerData);
     }
     case LayerType::Image: {
-        return std::make_unique<LOTImageLayerItem>(layerData);
+        return allocator->make<LOTImageLayerItem>(layerData);
     }
     default:
         return nullptr;
@@ -108,6 +93,21 @@ std::unique_ptr<LOTLayerItem> LOTCompItem::createLayerItem(
     }
 }
 
+LOTCompItem::LOTCompItem(LOTModel *model)
+    : mCurFrameNo(-1)
+{
+    mCompData = model->mRoot.get();
+    mRootLayer = createLayerItem(mCompData->mRootLayer.get(), &mAllocator);
+    mRootLayer->setComplexContent(false);
+    mViewSize = mCompData->size();
+}
+
+void LOTCompItem::setValue(const std::string &keypath, LOTVariant &value)
+{
+    LOTKeyPath key(keypath);
+    mRootLayer->resolveKeyPath(key, 0, value);
+}
+
 bool LOTCompItem::update(int frameNo, const VSize &size, bool keepAspectRatio)
 {
     // check if cached frame is same as requested frame.
@@ -433,7 +433,7 @@ void LOTLayerItem::preprocess(const VRect& clip)
     preprocessStage(clip);
 }
 
-LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel)
+LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel, VArenaAlloc* allocator)
     : LOTLayerItem(layerModel)
 {
     if (!mLayerData->mChildren.empty())
@@ -444,8 +444,8 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel)
     for (auto it = mLayerData->mChildren.crbegin();
          it != mLayerData->mChildren.rend(); ++it ) {
         auto model = static_cast<LOTLayerData *>((*it).get());
-        auto item = LOTCompItem::createLayerItem(model);
-        if (item) mLayers.push_back(std::move(item));
+        auto item = createLayerItem(model, allocator);
+        if (item) mLayers.push_back(item);
     }
 
     // 2. update parent layer
@@ -455,7 +455,7 @@ LOTCompLayerItem::LOTCompLayerItem(LOTLayerData *layerModel)
             auto search =
                 std::find_if(mLayers.begin(), mLayers.end(),
                              [id](const auto &val) { return val->id() == id; });
-            if (search != mLayers.end()) layer->setParentLayer((*search).get());
+            if (search != mLayers.end()) layer->setParentLayer(*search);
         }
     }
 
@@ -511,13 +511,13 @@ void LOTCompLayerItem::renderHelper(VPainter *painter, const VRle &inheritMask,
     LOTLayerItem *matte = nullptr;
     for (const auto &layer : mLayers) {
         if (layer->hasMatte()) {
-            matte = layer.get();
+            matte = layer;
         } else {
             if (layer->visible()) {
                 if (matte) {
                     if (matte->visible())
                         renderMatteLayer(painter, mask, matteRle, matte,
-                                         layer.get());
+                                         layer);
                 } else {
                     layer->render(painter, mask, matteRle);
                 }
@@ -624,7 +624,7 @@ void LOTCompLayerItem::preprocessStage(const VRect &clip)
     LOTLayerItem *matte = nullptr;
     for (const auto &layer : mLayers) {
         if (layer->hasMatte()) {
-            matte = layer.get();
+            matte = layer;
         } else {
             if (layer->visible()) {
                 if (matte) {
@@ -728,67 +728,52 @@ LOTNullLayerItem::LOTNullLayerItem(LOTLayerData *layerData)
 }
 void LOTNullLayerItem::updateContent() {}
 
-LOTShapeLayerItem::LOTShapeLayerItem(LOTLayerData *layerData)
-    : LOTLayerItem(layerData),
-      mRoot(std::make_unique<LOTContentGroupItem>(nullptr))
-{
-    mRoot->addChildren(layerData);
-
-    std::vector<LOTPathDataItem *> list;
-    mRoot->processPaintItems(list);
-
-    if (layerData->hasPathOperator()) {
-        list.clear();
-        mRoot->processTrimItems(list);
-    }
-}
-
-std::unique_ptr<LOTContentItem> LOTShapeLayerItem::createContentItem(
-    LOTData *contentData)
+static LOTContentItem*
+createContentItem(LOTData *contentData, VArenaAlloc* allocator)
 {
     switch (contentData->type()) {
     case LOTData::Type::ShapeGroup: {
-        return std::make_unique<LOTContentGroupItem>(
-            static_cast<LOTGroupData *>(contentData));
+        return allocator->make<LOTContentGroupItem>(
+            static_cast<LOTGroupData *>(contentData), allocator);
     }
     case LOTData::Type::Rect: {
-        return std::make_unique<LOTRectItem>(
+        return allocator->make<LOTRectItem>(
             static_cast<LOTRectData *>(contentData));
     }
     case LOTData::Type::Ellipse: {
-        return std::make_unique<LOTEllipseItem>(
+        return allocator->make<LOTEllipseItem>(
             static_cast<LOTEllipseData *>(contentData));
     }
     case LOTData::Type::Shape: {
-        return std::make_unique<LOTShapeItem>(
+        return allocator->make<LOTShapeItem>(
             static_cast<LOTShapeData *>(contentData));
     }
     case LOTData::Type::Polystar: {
-        return std::make_unique<LOTPolystarItem>(
+        return allocator->make<LOTPolystarItem>(
             static_cast<LOTPolystarData *>(contentData));
     }
     case LOTData::Type::Fill: {
-        return std::make_unique<LOTFillItem>(
+        return allocator->make<LOTFillItem>(
             static_cast<LOTFillData *>(contentData));
     }
     case LOTData::Type::GFill: {
-        return std::make_unique<LOTGFillItem>(
+        return allocator->make<LOTGFillItem>(
             static_cast<LOTGFillData *>(contentData));
     }
     case LOTData::Type::Stroke: {
-        return std::make_unique<LOTStrokeItem>(
+        return allocator->make<LOTStrokeItem>(
             static_cast<LOTStrokeData *>(contentData));
     }
     case LOTData::Type::GStroke: {
-        return std::make_unique<LOTGStrokeItem>(
+        return allocator->make<LOTGStrokeItem>(
             static_cast<LOTGStrokeData *>(contentData));
     }
     case LOTData::Type::Repeater: {
-        return std::make_unique<LOTRepeaterItem>(
-            static_cast<LOTRepeaterData *>(contentData));
+        return allocator->make<LOTRepeaterItem>(
+            static_cast<LOTRepeaterData *>(contentData), allocator);
     }
     case LOTData::Type::Trim: {
-        return std::make_unique<LOTTrimItem>(
+        return allocator->make<LOTTrimItem>(
             static_cast<LOTTrimData *>(contentData));
     }
     default:
@@ -797,6 +782,21 @@ std::unique_ptr<LOTContentItem> LOTShapeLayerItem::createContentItem(
     }
 }
 
+LOTShapeLayerItem::LOTShapeLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator)
+    : LOTLayerItem(layerData),
+      mRoot(allocator->make<LOTContentGroupItem>(nullptr, allocator))
+{
+    mRoot->addChildren(layerData, allocator);
+
+    std::vector<LOTPathDataItem *> list;
+    mRoot->processPaintItems(list);
+
+    if (layerData->hasPathOperator()) {
+        list.clear();
+        mRoot->processTrimItems(list);
+    }
+}
+
 void LOTShapeLayerItem::updateContent()
 {
     mRoot->update(frameNo(), combinedMatrix(), combinedAlpha(), flag());
@@ -880,13 +880,13 @@ bool LOTStrokeItem::resolveKeyPath(LOTKeyPath &keyPath, uint depth,
     return false;
 }
 
-LOTContentGroupItem::LOTContentGroupItem(LOTGroupData *data)
+LOTContentGroupItem::LOTContentGroupItem(LOTGroupData *data, VArenaAlloc* allocator)
     : mData(data)
 {
-    addChildren(mData);
+    addChildren(mData, allocator);
 }
 
-void LOTContentGroupItem::addChildren(LOTGroupData *data)
+void LOTContentGroupItem::addChildren(LOTGroupData *data, VArenaAlloc* allocator)
 {
     if (!data) return;
 
@@ -896,9 +896,9 @@ void LOTContentGroupItem::addChildren(LOTGroupData *data)
     // as lottie model keeps it in front-to-back order.
     for (auto it = data->mChildren.crbegin(); it != data->mChildren.rend();
          ++it ) {
-        auto content = LOTShapeLayerItem::createContentItem((*it).get());
+        auto content = createContentItem((*it).get(), allocator);
         if (content) {
-            mContents.push_back(std::move(content));
+            mContents.push_back(content);
         }
     }
 }
@@ -937,7 +937,7 @@ void LOTContentGroupItem::update(int frameNo, const VMatrix &parentMatrix,
 void LOTContentGroupItem::applyTrim()
 {
     for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
-        auto content = (*i).get();
+        auto content = (*i);
         switch (content->type()) {
         case ContentType::Trim: {
             static_cast<LOTTrimItem *>(content)->update();
@@ -965,7 +965,7 @@ void LOTContentGroupItem::processPaintItems(
 {
     size_t curOpCount = list.size();
     for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
-        auto content = (*i).get();
+        auto content = (*i);
         switch (content->type()) {
         case ContentType::Path: {
             auto pathItem = static_cast<LOTPathDataItem *>(content);
@@ -993,7 +993,7 @@ void LOTContentGroupItem::processTrimItems(std::vector<LOTPathDataItem *> &list)
 {
     size_t curOpCount = list.size();
     for (auto i = mContents.rbegin(); i != mContents.rend(); ++i) {
-        auto content = (*i).get();
+        auto content = (*i);
 
         switch (content->type()) {
         case ContentType::Path: {
@@ -1395,7 +1395,7 @@ void LOTTrimItem::addPathItems(std::vector<LOTPathDataItem *> &list,
               back_inserter(mPathItems));
 }
 
-LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data) : mRepeaterData(data)
+LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data, VArenaAlloc* allocator) : mRepeaterData(data)
 {
     assert(mRepeaterData->content());
 
@@ -1403,9 +1403,9 @@ LOTRepeaterItem::LOTRepeaterItem(LOTRepeaterData *data) : mRepeaterData(data)
 
     for (int i = 0; i < mCopies; i++) {
         auto content =
-            std::make_unique<LOTContentGroupItem>(mRepeaterData->content());
+            allocator->make<LOTContentGroupItem>(mRepeaterData->content(), allocator);
         //content->setParent(this);
-        mContents.push_back(std::move(content));
+        mContents.push_back(content);
     }
 }
 
index 0ed30ce..b6cda32 100644 (file)
@@ -1,16 +1,16 @@
-/* 
+/*
  * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
@@ -32,6 +32,7 @@
 #include"vpainter.h"
 #include"vdrawable.h"
 #include"lottiekeypath.h"
+#include"varenaalloc.h"
 
 V_USE_NAMESPACE
 
@@ -64,7 +65,6 @@ class LOTCompItem
 {
 public:
    explicit LOTCompItem(LOTModel *model);
-   static std::unique_ptr<LOTLayerItem> createLayerItem(LOTLayerData *layerData);
    bool update(int frameNo, const VSize &size, bool keepAspectRatio);
    VSize size() const { return mViewSize;}
    void buildRenderTree();
@@ -76,7 +76,8 @@ private:
    VMatrix                                     mScaleMatrix;
    VSize                                       mViewSize;
    LOTCompositionData                         *mCompData;
-   std::unique_ptr<LOTLayerItem>               mRootLayer;
+   LOTLayerItem                               *mRootLayer;
+   VArenaAlloc                                 mAllocator{2048};
    int                                         mCurFrameNo;
    bool                                        mKeepAspectRatio{true};
 };
@@ -194,7 +195,7 @@ protected:
 class LOTCompLayerItem: public LOTLayerItem
 {
 public:
-   explicit LOTCompLayerItem(LOTLayerData *layerData);
+   explicit LOTCompLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator);
 
    void render(VPainter *painter, const VRle &mask, const VRle &matteRle) final;
    void buildLayerNode() final;
@@ -207,8 +208,8 @@ private:
     void renderMatteLayer(VPainter *painter, const VRle &inheritMask, const VRle &matteRle,
                           LOTLayerItem *layer, LOTLayerItem *src);
 private:
-   std::vector<std::unique_ptr<LOTLayerItem>>   mLayers;
-   std::unique_ptr<LOTClipperItem>              mClipper;
+   std::vector<LOTLayerItem*>            mLayers;
+   std::unique_ptr<LOTClipperItem>       mClipper;
 };
 
 class LOTSolidLayerItem: public LOTLayerItem
@@ -230,8 +231,7 @@ class LOTContentGroupItem;
 class LOTShapeLayerItem: public LOTLayerItem
 {
 public:
-   explicit LOTShapeLayerItem(LOTLayerData *layerData);
-   static std::unique_ptr<LOTContentItem> createContentItem(LOTData *contentData);
+   explicit LOTShapeLayerItem(LOTLayerData *layerData, VArenaAlloc* allocator);
    DrawableList renderList() final;
    void buildLayerNode() final;
    bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
@@ -239,7 +239,7 @@ protected:
    void preprocessStage(const VRect& clip) final;
    void updateContent() final;
    std::vector<VDrawable *>             mDrawableList;
-   std::unique_ptr<LOTContentGroupItem> mRoot;
+   LOTContentGroupItem                 *mRoot;
 };
 
 class LOTNullLayerItem: public LOTLayerItem
@@ -328,8 +328,9 @@ public:
 class LOTContentGroupItem: public LOTContentItem
 {
 public:
-   explicit LOTContentGroupItem(LOTGroupData *data=nullptr);
-   void addChildren(LOTGroupData *data);
+    LOTContentGroupItem() = default;
+   explicit LOTContentGroupItem(LOTGroupData *data, VArenaAlloc* allocator);
+   void addChildren(LOTGroupData *data, VArenaAlloc* allocator);
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) override;
    void applyTrim();
    void processTrimItems(std::vector<LOTPathDataItem *> &list);
@@ -345,7 +346,7 @@ public:
    bool resolveKeyPath(LOTKeyPath &keyPath, uint depth, LOTVariant &value) override;
 protected:
    LOTGroupData                                  *mData{nullptr};
-   std::vector<std::unique_ptr<LOTContentItem>>   mContents;
+   std::vector<LOTContentItem*>   mContents;
    VMatrix                                        mMatrix;
 };
 
@@ -542,7 +543,7 @@ private:
 class LOTRepeaterItem : public LOTContentGroupItem
 {
 public:
-   explicit LOTRepeaterItem(LOTRepeaterData *data);
+   explicit LOTRepeaterItem(LOTRepeaterData *data, VArenaAlloc* allocator);
    void update(int frameNo, const VMatrix &parentMatrix, float parentAlpha, const DirtyFlag &flag) final;
    void renderList(std::vector<VDrawable *> &list) final;
 private: