From 1028c669d99d70f23d1b4c78d3ba885a64b92903 Mon Sep 17 00:00:00 2001 From: mpv Date: Fri, 7 Dec 2018 18:01:52 +0300 Subject: [PATCH] Improve performance in the Sketch edition. --- src/Model/Model_AttributeRefList.cpp | 132 ++++++++++++----------- src/Model/Model_AttributeRefList.h | 13 ++- src/Model/Model_Data.cpp | 4 +- src/ModelAPI/ModelAPI_AttributeRefList.h | 2 +- src/ModelAPI/ModelAPI_Result.cpp | 6 +- 5 files changed, 84 insertions(+), 73 deletions(-) diff --git a/src/Model/Model_AttributeRefList.cpp b/src/Model/Model_AttributeRefList.cpp index 4d77a91f7..4c152b929 100644 --- a/src/Model/Model_AttributeRefList.cpp +++ b/src/Model/Model_AttributeRefList.cpp @@ -44,6 +44,12 @@ void Model_AttributeRefList::append(ObjectPtr theObject) myExtDocRef->Append(anEntry); } else return; // something is wrong + if (myHashUsed) { + myHashObjects.insert(theObject); + myHashIndex[myRef->Extent() - 1] = theObject; + myHashIndexNoEmpty[int(myHashIndexNoEmpty.size())] = theObject; + } + // do it before the transaction finish to make just created/removed objects know dependencies // and reference from composite feature is removed automatically ADD_BACK_REF(theObject); @@ -52,6 +58,7 @@ void Model_AttributeRefList::append(ObjectPtr theObject) void Model_AttributeRefList::remove(ObjectPtr theObject) { + eraseHash(); if (theObject.get() != NULL) { if (owner()->document() == theObject->document()) { std::shared_ptr aData; @@ -79,7 +86,7 @@ void Model_AttributeRefList::remove(ObjectPtr theObject) if (anExtIter.Value() == anIdString.str().c_str()) { TDataStd_ListIteratorOfListOfExtendedString anExtIter2 = anExtIter; anExtIter2.Next(); - if (anExtIter2.Value() == anEntry) { // fully maches, so, remove(don't copy) + if (anExtIter2.Value() == anEntry) { // fully matches, so, remove(don't copy) aFound = true; continue; } @@ -117,6 +124,7 @@ void Model_AttributeRefList::remove(ObjectPtr theObject) void Model_AttributeRefList::clear() { + eraseHash(); std::list anOldList = list(); myRef->Clear(); std::list::iterator anOldIter = anOldList.begin(); @@ -131,6 +139,10 @@ int Model_AttributeRefList::size(const bool theWithEmpty) const { if (theWithEmpty) return myRef->Extent(); + + if (myHashUsed) + return int(myHashIndexNoEmpty.size()); + int aResult = 0; const TDF_LabelList& aList = myRef->List(); for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { @@ -177,15 +189,11 @@ ObjectPtr Model_AttributeRefList::iteratedObject(TDF_ListIteratorOfLabelList& th std::list Model_AttributeRefList::list() { + createHash(); std::list aResult; - std::shared_ptr aDoc = std::dynamic_pointer_cast( - owner()->document()); - if (aDoc) { - const TDF_LabelList& aList = myRef->List(); - TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List()); - for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { - aResult.push_back(iteratedObject(aLIter, anExtIter, aDoc)); - } + std::map::iterator aHashIter = myHashIndex.begin(); + for(; aHashIter != myHashIndex.end(); aHashIter++) { + aResult.push_back(aHashIter->second); } return aResult; } @@ -195,65 +203,24 @@ bool Model_AttributeRefList::isInList(const ObjectPtr& theObj) if(!theObj.get()) { return false; } - if (theObj->document() == owner()->document()) { // this document object - std::shared_ptr aDoc = std::dynamic_pointer_cast( - owner()->document()); - if (aDoc) { - std::shared_ptr aData = std::dynamic_pointer_cast(theObj->data()); - if (aData.get() && aData->isValid()) { - TDF_Label anObjLab = aData->label().Father(); - const TDF_LabelList& aList = myRef->List(); - for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { - if (aLIter.Value().IsEqual(anObjLab)) { - return true; - } - } - } - } - } else { // external document object - // create new lists because for the current moment remove one of the duplicated elements - // from the list is buggy - std::ostringstream anIdString; // string with document Id - anIdString<document()->id(); - std::shared_ptr aData = std::dynamic_pointer_cast(theObj->data()); - TCollection_AsciiString anEntry; - TDF_Tool::Entry(aData->label().Father(), anEntry); - bool aFound = false; - TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List()); - for (; anExtIter.More(); anExtIter.Next()) { - if (anExtIter.Value() == anIdString.str().c_str()) { - anExtIter.Next(); - if (anExtIter.Value() == anEntry) { // fully maches - return true; - } - } else { - anExtIter.Next(); - } - } - } - return false; + createHash(); + return myHashObjects.count(theObj) != 0; } -ObjectPtr Model_AttributeRefList::object(const int theIndex, const bool theWithEmpty) const +ObjectPtr Model_AttributeRefList::object(const int theIndex, const bool theWithEmpty) { - std::shared_ptr aDoc = - std::dynamic_pointer_cast(owner()->document()); - if (aDoc) { - int anIndex = -1; - TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List()); - for (TDF_ListIteratorOfLabelList aLIter(myRef->List()); aLIter.More(); aLIter.Next()) { - if (theWithEmpty || (!aLIter.Value().IsNull() && !aLIter.Value().IsRoot())) - anIndex++; - if (anIndex == theIndex) { - return iteratedObject(aLIter, anExtIter, aDoc); - } - if (aLIter.Value() == myRef->Label()) { - anExtIter.Next(); - anExtIter.Next(); - } - } + createHash(); + std::map::iterator aFind; + if (theWithEmpty) { + aFind = myHashIndex.find(theIndex); + if (aFind == myHashIndex.end()) + return ObjectPtr(); + } else { + aFind = myHashIndexNoEmpty.find(theIndex); + if (aFind == myHashIndexNoEmpty.end()) + return ObjectPtr(); } - return ObjectPtr(); + return aFind->second; } void Model_AttributeRefList::substitute(const ObjectPtr& theCurrent, const ObjectPtr& theNew) @@ -273,6 +240,7 @@ void Model_AttributeRefList::substitute(const ObjectPtr& theCurrent, const Objec aNewLab = aCurrentLab.Root(); // root means null object } // do the substitution + eraseHash(); ADD_BACK_REF(theNew); if (myRef->InsertAfter(aNewLab, aCurrentLab)) { myRef->Remove(aCurrentLab); @@ -295,6 +263,7 @@ void Model_AttributeRefList::exchange(const ObjectPtr& theObject1, const ObjectP std::shared_ptr aData2 = std::dynamic_pointer_cast(theObject2->data()); if (aData2.get() && aData2->isValid()) { + eraseHash(); TDF_Label aLab2 = aData2->label().Father(); // do the substitution: use the temporary label, as usually in exchange TDF_Label aTmpLab = aLab1.Root(); @@ -321,6 +290,7 @@ void Model_AttributeRefList::removeLast() if (aDoc && !myRef->IsEmpty()) { ObjectPtr anObj = aDoc->objects()->object(myRef->Last()); if (anObj.get()) { + eraseHash(); myRef->Remove(myRef->Last()); REMOVE_BACK_REF(anObj); owner()->data()->sendAttributeUpdated(this); @@ -333,7 +303,7 @@ void Model_AttributeRefList::remove(const std::set& theIndices) std::shared_ptr aDoc = std::dynamic_pointer_cast( owner()->document()); if (aDoc && !myRef->IsEmpty()) { - // collet labels that will be removed + // collect labels that will be removed TDF_LabelList aLabelsToRemove; TDF_ListIteratorOfLabelList aLabIter(myRef->List()); for(int aCurrent = 0; aLabIter.More(); aLabIter.Next(), aCurrent++) { @@ -348,6 +318,7 @@ void Model_AttributeRefList::remove(const std::set& theIndices) REMOVE_BACK_REF(anObj); } } + eraseHash(); if (!aLabelsToRemove.IsEmpty()) { owner()->data()->sendAttributeUpdated(this); } @@ -369,4 +340,35 @@ void Model_AttributeRefList::reinit() if (!myLab.FindAttribute(TDataStd_ExtStringList::GetID(), myExtDocRef)) { myExtDocRef = TDataStd_ExtStringList::Set(myLab); } + eraseHash(); +} + +void Model_AttributeRefList::createHash() +{ + if (myHashUsed) + return; + std::shared_ptr aDoc = std::dynamic_pointer_cast( + owner()->document()); + if (aDoc) { + const TDF_LabelList& aList = myRef->List(); + TDataStd_ListIteratorOfListOfExtendedString anExtIter(myExtDocRef->List()); + for (TDF_ListIteratorOfLabelList aLIter(aList); aLIter.More(); aLIter.Next()) { + ObjectPtr anObj = iteratedObject(aLIter, anExtIter, aDoc); + myHashIndex[int(myHashIndex.size())] = anObj; + if (anObj.get()) { + myHashIndexNoEmpty[int(myHashIndexNoEmpty.size())] = anObj; + myHashObjects.insert(anObj); + } + } + myHashUsed = true; + } +} + + +void Model_AttributeRefList::eraseHash() +{ + myHashObjects.clear(); + myHashIndex.clear(); + myHashIndexNoEmpty.clear(); + myHashUsed = false; } diff --git a/src/Model/Model_AttributeRefList.h b/src/Model/Model_AttributeRefList.h index 1964c7d58..da674ff49 100644 --- a/src/Model/Model_AttributeRefList.h +++ b/src/Model/Model_AttributeRefList.h @@ -37,11 +37,16 @@ class Model_AttributeRefList : public ModelAPI_AttributeRefList { TDF_Label myLab; ///< the main label of this attribute + Handle_TDataStd_ReferenceList myRef; ///< references to the features labels /// pairs of doc ID and entries if reference is to external object, appends some in this list if /// something in myRef is empty Handle_TDataStd_ExtStringList myExtDocRef; - public: + bool myHashUsed; ///< true if the hash stored is valid + std::set myHashObjects; ///< hashed information: objects existing in the list + std::map myHashIndex; ///< index to object in the list + std::map myHashIndexNoEmpty; ///< index to not empty object in the list +public: /// Appends the feature to the end of a list MODEL_EXPORT virtual void append(ObjectPtr theObject); @@ -64,7 +69,7 @@ class Model_AttributeRefList : public ModelAPI_AttributeRefList /// Returns the list of features ///\param theIndex zero-based index in the list ///\param theWithEmpty if it is false, counts the not-empty referenced objects only - MODEL_EXPORT virtual ObjectPtr object(const int theIndex, const bool theWithEmpty = true) const; + MODEL_EXPORT virtual ObjectPtr object(const int theIndex, const bool theWithEmpty = true); /// Substitutes the feature by another one. Does nothing if such object is not found. /// Does not support the external documents objects yet. @@ -94,6 +99,10 @@ class Model_AttributeRefList : public ModelAPI_AttributeRefList ObjectPtr iteratedObject(TDF_ListIteratorOfLabelList& theLIter, TDataStd_ListIteratorOfListOfExtendedString& theExtIter, std::shared_ptr theDoc) const; + /// Creates the hash-objects containers (does nothing if hash is already correct) + void createHash(); + /// Erases the hashed objects caused by complicated modifications in the list + void eraseHash(); friend class Model_Data; }; diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index d75a917de..bfc463057 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -346,10 +346,10 @@ void Model_Data::sendAttributeUpdated(ModelAPI_Attribute* theAttr) } } else { // trim: need to redisplay - if (myObject) { + /*if (myObject) { static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent); - } + }*/ } } diff --git a/src/ModelAPI/ModelAPI_AttributeRefList.h b/src/ModelAPI/ModelAPI_AttributeRefList.h index 78d8ba769..27b2427b9 100644 --- a/src/ModelAPI/ModelAPI_AttributeRefList.h +++ b/src/ModelAPI/ModelAPI_AttributeRefList.h @@ -64,7 +64,7 @@ class ModelAPI_AttributeRefList : public ModelAPI_Attribute /// Returns the referenced object by the zero-based index ///\param theIndex zero-based index in the list ///\param theWithEmpty if it is false, counts the not-empty referenced objects only - virtual ObjectPtr object(const int theIndex, const bool theWithEmpty = true) const = 0; + virtual ObjectPtr object(const int theIndex, const bool theWithEmpty = true) = 0; /// Substitutes the object by another one. Does nothing if such object is not found. virtual void substitute(const ObjectPtr& theCurrent, const ObjectPtr& theNew) = 0; diff --git a/src/ModelAPI/ModelAPI_Result.cpp b/src/ModelAPI/ModelAPI_Result.cpp index 588d138bf..e0f0f8c87 100644 --- a/src/ModelAPI/ModelAPI_Result.cpp +++ b/src/ModelAPI/ModelAPI_Result.cpp @@ -35,9 +35,9 @@ void ModelAPI_Result::initAttributes() { // append the color attribute. It is empty, the attribute will be filled by a request DataPtr aData = data(); - aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId()); - aData->addAttribute(DEFLECTION_ID(), ModelAPI_AttributeDouble::typeId()); - aData->addAttribute(TRANSPARENCY_ID(), ModelAPI_AttributeDouble::typeId()); + aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId())->setIsArgument(false); + aData->addAttribute(DEFLECTION_ID(), ModelAPI_AttributeDouble::typeId())->setIsArgument(false); + aData->addAttribute(TRANSPARENCY_ID(), ModelAPI_AttributeDouble::typeId())->setIsArgument(false); } bool ModelAPI_Result::setDisabled(std::shared_ptr theThis, const bool theFlag) -- 2.39.2