Salome HOME
23514: EDF 16031 - SMESH freezes eap/23514
authoreap <eap@opencascade.com>
Thu, 30 Nov 2017 16:51:51 +0000 (19:51 +0300)
committereap <eap@opencascade.com>
Thu, 30 Nov 2017 16:51:51 +0000 (19:51 +0300)
Optimize loading a study with multiple mesh groups

src/DriverMED/DriverMED_Family.cxx
src/DriverMED/DriverMED_Family.h
src/DriverMED/DriverMED_R_SMESHDS_Mesh.cxx
src/DriverMED/DriverMED_R_SMESHDS_Mesh.h
src/SMESH_I/SMESH_Gen_i.cxx
src/SMESH_I/SMESH_Gen_i.hxx
src/SMESH_I/SMESH_PreMeshInfo.cxx
src/SMESH_I/SMESH_PreMeshInfo.hxx

index f6d67ea..a11ba48 100644 (file)
@@ -93,7 +93,7 @@ DriverMED_Family
   return myType; 
 }
 
-const std::set< SMDSAbs_ElementType >&
+const ElemTypeSet&
 DriverMED_Family
 ::GetTypes() const
 {
index 1325617..c71ea72 100644 (file)
@@ -36,6 +36,7 @@
 #include "SMESHDS_SubMesh.hxx"
 #include "MED_Common.hxx"
 
+#include <boost/container/flat_set.hpp>
 #include <boost/shared_ptr.hpp>
 #include <set>
 #include <limits>
 #define NIG_BALL_FAMILY    INT_MAX-5
 #define NIG_GROUP_PREFIX "NOT_IN_GRP"
 
-typedef std::list<DriverMED_FamilyPtr               > DriverMED_FamilyPtrList;
-typedef std::map<int,SMESHDS_SubMesh*               > SMESHDS_SubMeshPtrMap;
-typedef std::list<SMESHDS_GroupBase*                > SMESHDS_GroupBasePtrList;
-typedef std::set<const SMDS_MeshElement*,TIDCompare > ElementsSet;
+typedef std::list<DriverMED_FamilyPtr                   > DriverMED_FamilyPtrList;
+typedef std::map<int,SMESHDS_SubMesh*                   > SMESHDS_SubMeshPtrMap;
+typedef std::list<SMESHDS_GroupBase*                    > SMESHDS_GroupBasePtrList;
+typedef std::set<const SMDS_MeshElement*,TIDCompare     > ElementsSet;
+typedef boost::container::flat_set< SMDSAbs_ElementType > ElemTypeSet;
 
 class MESHDRIVERMED_EXPORT DriverMED_Family
 {
@@ -113,7 +115,7 @@ class MESHDRIVERMED_EXPORT DriverMED_Family
 
   void SetType(const SMDSAbs_ElementType theType);
   SMDSAbs_ElementType GetType();
-  const std::set< SMDSAbs_ElementType >& GetTypes() const;
+  const ElemTypeSet&  GetTypes() const;
 
   bool MemberOf(std::string theGroupName) const;
 
@@ -126,9 +128,8 @@ class MESHDRIVERMED_EXPORT DriverMED_Family
 
   //! Split <theSubMesh> on some parts (families) on the basis of the elements type.
   static
-  DriverMED_FamilyPtrList 
-  SplitByType(SMESHDS_SubMesh* theSubMesh,
-              const int        theId);
+  DriverMED_FamilyPtrList SplitByType(SMESHDS_SubMesh* theSubMesh,
+                                      const int        theId);
 
 
   /*! Remove from <Elements> elements, common with <by>,
@@ -143,12 +144,12 @@ class MESHDRIVERMED_EXPORT DriverMED_Family
 
 
  private:
-  int                           myId;
-  SMDSAbs_ElementType           myType;
-  ElementsSet                   myElements;
-  MED::TStringSet               myGroupNames;
-  int                           myGroupAttributVal;
-  std::set<SMDSAbs_ElementType> myTypes; // Issue 0020576
+  int                 myId;
+  SMDSAbs_ElementType myType;
+  ElementsSet         myElements;
+  MED::TStringSet     myGroupNames;
+  int                 myGroupAttributVal;
+  ElemTypeSet         myTypes; // Issue 0020576
 };
 
 #endif
index b3c91db..0003169 100644 (file)
@@ -1092,8 +1092,8 @@ list<TNameAndType> DriverMED_R_SMESHDS_Mesh::GetGroupNamesAndTypes()
     set<string>::const_iterator aGrNamesIter = aGroupNames.begin();
     for (; aGrNamesIter != aGroupNames.end(); aGrNamesIter++)
     {
-      const set< SMDSAbs_ElementType >& types = aFamily->GetTypes();
-      set< SMDSAbs_ElementType >::const_iterator type = types.begin();
+      const ElemTypeSet& types = aFamily->GetTypes();
+      ElemTypeSet::const_iterator type = types.begin();
       for ( ; type != types.end(); ++type )
       {
         TNameAndType aNameAndType = make_pair( *aGrNamesIter, *type );
@@ -1109,28 +1109,51 @@ list<TNameAndType> DriverMED_R_SMESHDS_Mesh::GetGroupNamesAndTypes()
 
 void DriverMED_R_SMESHDS_Mesh::GetGroup(SMESHDS_Group* theGroup)
 {
-  string aGroupName (theGroup->GetStoreName());
+  TFamilyVec * famVecPtr;
+
+  if ( myGroups2FamiliesMap.IsEmpty() ) // PAL23514
+  {
+    TFamilyVec famVector( 1 );
+    map<int, DriverMED_FamilyPtr>::iterator famIter = myFamilies.begin();
+    for ( ; famIter != myFamilies.end(); famIter++ )
+    {
+      DriverMED_FamilyPtr    family = famIter->second;
+      const MED::TStringSet& groups = family->GetGroupNames();
+      famVector[ 0 ] = family;
+      MED::TStringSet::const_iterator grpIter = groups.begin();
+      for ( ; grpIter != groups.end(); ++grpIter )
+      {
+        TCollection_AsciiString groupName = grpIter->c_str();
+        if (( famVecPtr = myGroups2FamiliesMap.ChangeSeek( groupName )))
+          famVecPtr->push_back( family );
+        else
+          myGroups2FamiliesMap.Bind( groupName, famVector );
+      }
+    }
+  }
+
+  const char* aGroupName = theGroup->GetStoreName();
   if(MYDEBUG) MESSAGE("Get Group " << aGroupName);
 
-  map<int, DriverMED_FamilyPtr>::iterator aFamsIter = myFamilies.begin();
-  for (; aFamsIter != myFamilies.end(); aFamsIter++)
+  if (( famVecPtr = myGroups2FamiliesMap.ChangeSeek( aGroupName )))
   {
-    DriverMED_FamilyPtr aFamily = (*aFamsIter).second;
-    if (aFamily->GetTypes().count( theGroup->GetType() ) && aFamily->MemberOf(aGroupName))
+    for ( size_t i = 0; i < famVecPtr->size(); ++i )
     {
-      const ElementsSet&           anElements = aFamily->GetElements();
-      ElementsSet::const_iterator anElemsIter = anElements.begin();
-      for (; anElemsIter != anElements.end(); anElemsIter++)
+      DriverMED_FamilyPtr aFamily = (*famVecPtr)[i];
+      if ( aFamily->GetTypes().count( theGroup->GetType() ))
       {
-        const SMDS_MeshElement * element = *anElemsIter;
-        if ( element->GetType() == theGroup->GetType() ) // Issue 0020576
-          theGroup->SMDSGroup().Add(element);
+        const ElementsSet&           anElements = aFamily->GetElements();
+        ElementsSet::const_iterator anElemsIter = anElements.begin();
+        for (; anElemsIter != anElements.end(); anElemsIter++)
+        {
+          const SMDS_MeshElement * element = *anElemsIter;
+          if ( element->GetType() == theGroup->GetType() ) // Issue 0020576
+            theGroup->SMDSGroup().Add(element);
+        }
+        int aGroupAttrVal = aFamily->GetGroupAttributVal();
+        if( aGroupAttrVal != 0 )
+          theGroup->SetColorGroup(aGroupAttrVal);
       }
-      int aGroupAttrVal = aFamily->GetGroupAttributVal();
-      if( aGroupAttrVal != 0)
-        theGroup->SetColorGroup(aGroupAttrVal);
-//       if ( element ) -- Issue 0020576
-//         theGroup->SetType( theGroup->SMDSGroup().GetType() );
     }
   }
 }
index bd8fa80..ba7994e 100644 (file)
 #include <list>
 #include <map>
 
+#include <NCollection_DataMap.hxx>
+#include <TCollection_AsciiString.hxx>
+
 class SMESHDS_Mesh;
 class SMESHDS_Group;
 class SMESHDS_SubMesh;
 
-typedef std::pair< std::string, SMDSAbs_ElementType > TNameAndType;
+typedef std::vector< DriverMED_FamilyPtr >                         TFamilyVec;
+typedef std::pair< std::string, SMDSAbs_ElementType >              TNameAndType;
+typedef NCollection_DataMap< TCollection_AsciiString, TFamilyVec > TName2Falilies;
 
 class MESHDRIVERMED_EXPORT DriverMED_R_SMESHDS_Mesh: public Driver_SMESHDS_Mesh
 {
@@ -56,9 +61,9 @@ class MESHDRIVERMED_EXPORT DriverMED_R_SMESHDS_Mesh: public Driver_SMESHDS_Mesh
   void SetMeshName(std::string theMeshName);
 
  private:
-  std::string myMeshName;
+  std::string                        myMeshName;
   std::map<int, DriverMED_FamilyPtr> myFamilies;
-
+  TName2Falilies                     myGroups2FamiliesMap;
 };
 
 #endif
index f6877fa..65d22da 100644 (file)
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
 
+#include <BRepPrimAPI_MakeBox.hxx>
+#include <BRepPrimAPI_MakeCylinder.hxx>
+#include <BRepPrimAPI_MakeSphere.hxx>
+#include <BRep_Tool.hxx>
+#include <OSD.hxx>
+#include <TColStd_MapOfAsciiString.hxx>
+#include <TCollection_AsciiString.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
 #include <TopoDS.hxx>
-#include <TopoDS_Iterator.hxx>
-#include <TopoDS_Compound.hxx>
 #include <TopoDS_CompSolid.hxx>
-#include <TopoDS_Solid.hxx>
-#include <TopoDS_Shell.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Wire.hxx>
+#include <TopoDS_Compound.hxx>
 #include <TopoDS_Edge.hxx>
-#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Iterator.hxx>
 #include <TopoDS_Shape.hxx>
-#include <TopTools_MapOfShape.hxx>
-#include <TopTools_IndexedMapOfShape.hxx>
-#include <TopTools_ListOfShape.hxx>
-#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Solid.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Wire.hxx>
 #include <gp_Pnt.hxx>
-#include <BRep_Tool.hxx>
-#include <TCollection_AsciiString.hxx>
-#include <OSD.hxx>
-#include <BRepPrimAPI_MakeSphere.hxx>
-#include <BRepPrimAPI_MakeCylinder.hxx>
-#include <BRepPrimAPI_MakeBox.hxx>
 
 
 #ifdef WIN32
@@ -4682,18 +4683,23 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         if ( aTopGroup->ExistInternalObject( name_group ) ) {
           aGroup = new HDFgroup( name_group, aTopGroup );
           aGroup->OpenOnDisk();
-          // get number of groups
-          int aNbSubObjects = aGroup->nInternalObjects();
-          for ( int j = 0; j < aNbSubObjects; j++ ) {
-            char name_dataset[ HDF_NAME_MAX_LEN+1 ];
-            aGroup->InternalObjectIndentify( j, name_dataset );
-            // check if it is an group
-            if ( string( name_dataset ).substr( 0, 5 ) == string( "Group" ) ) {
+          // PAL23514: get all names from the HDFgroup to avoid iteration on its contents
+          // within aGroup->ExistInternalObject( name )
+          std::vector< std::string > subNames;
+          TColStd_MapOfAsciiString mapOfNames;
+          aGroup->GetAllObjects( subNames );
+          for ( size_t iN = 0; iN < subNames.size(); ++iN )
+            mapOfNames.Add( subNames[ iN ].c_str() );
+          // loop on groups
+          for ( size_t j = 0; j < subNames.size(); j++ ) {
+            const std::string& name_dataset = subNames[ j ];
+            // check if it is a group
+            if ( name_dataset.substr( 0, 5 ) == "Group" ) {
               // --> get group id
-              int subid = atoi( string( name_dataset ).substr( 5 ).c_str() );
+              int subid = atoi( name_dataset.substr( 5 ).c_str() );
               if ( subid <= 0 )
                 continue;
-              aDataset = new HDFdataset( name_dataset, aGroup );
+              aDataset = new HDFdataset( name_dataset.c_str(), aGroup );
               aDataset->OpenOnDisk();
 
               // Retrieve actual group name
@@ -4706,7 +4712,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               TopoDS_Shape aShape;
               char aRefName[ 30 ];
               sprintf( aRefName, "Ref on shape %d", subid);
-              if ( aGroup->ExistInternalObject( aRefName ) ) {
+              if ( mapOfNames.Contains( aRefName ))
+              {
                 // load mesh "Ref on shape" - it's an entry to SObject
                 aDataset = new HDFdataset( aRefName, aGroup );
                 aDataset->OpenOnDisk();
@@ -4727,8 +4734,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               // Try to read a filter of SMESH_GroupOnFilter
               SMESH::Filter_var filter;
               SMESH_PredicatePtr predicate;
-              std::string hdfGrpName = "Filter " + SMESH_Comment(subid);
-              if ( aGroup->ExistInternalObject( hdfGrpName.c_str() ))
+              std::string hdfGrpName = ( SMESH_Comment( "Filter ") << subid );
+              if ( mapOfNames.Contains( hdfGrpName.c_str() ))
               {
                 aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup );
                 aDataset->OpenOnDisk();
@@ -4769,13 +4776,13 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               if ( !aGroupBaseDS )
                 continue;
 
-              aGroupBaseDS->SetStoreName( name_dataset );
+              aGroupBaseDS->SetStoreName( name_dataset.c_str() );
 
               // ouv : NPAL12872
               // Read color of the group
               char aGroupColorName[ 30 ];
               sprintf( aGroupColorName, "ColorGroup %d", subid);
-              if ( aGroup->ExistInternalObject( aGroupColorName ) )
+              if ( mapOfNames.Contains( aGroupColorName ))
               {
                 aDataset = new HDFdataset( aGroupColorName, aGroup );
                 aDataset->OpenOnDisk();
index 1e86946..ef98422 100644 (file)
@@ -49,6 +49,7 @@
 #include <TCollection_AsciiString.hxx>
 #include <Resource_DataMapOfAsciiStringAsciiString.hxx>
 #include <TColStd_HSequenceOfAsciiString.hxx>
+#include <NCollection_DataMap.hxx>
 
 #include <map>
 #include <sstream>
@@ -61,56 +62,53 @@ class SALOME_LifeCycleCORBA;
 // ==========================================================
 class SMESH_I_EXPORT StudyContext
 {
+  typedef NCollection_DataMap< int, std::string > TInt2StringMap;
+  typedef NCollection_DataMap< int, int >         TInt2IntMap;
 public:
   // constructor
   StudyContext() {}
-  // destructor
-  ~StudyContext()
-  {
-    mapIdToIOR.clear();
-    mapIdToId.clear();
-  }
+
   // register object in the internal map and return its id
   int addObject( std::string theIOR )
   {
     int nextId = getNextId();
-    mapIdToIOR[ nextId ]  = theIOR;
+    mapIdToIOR.Bind( nextId, theIOR );
     return nextId;
   }
   // find the object id in the internal map by the IOR
   int findId( std::string theIOR )
   {
-    std::map<int, std::string>::iterator imap;
+    TInt2StringMap::iterator imap;
     for ( imap = mapIdToIOR.begin(); imap != mapIdToIOR.end(); ++imap ) {
-      if ( imap->second == theIOR )
-        return imap->first;
+      if ( *imap == theIOR )
+        return imap.Iterator().Key();
     }
     return 0;
   }
   // get object's IOR by id
   std::string getIORbyId( const int theId )
   {
-    if ( mapIdToIOR.find( theId ) != mapIdToIOR.end() )
-      return mapIdToIOR[ theId ];
-    return std::string( "" );
+    if ( mapIdToIOR.IsBound( theId ) )
+      return mapIdToIOR( theId );
+    return std::string();
   }
   // get object's IOR by old id
   std::string getIORbyOldId( const int theOldId )
   {
-    if ( mapIdToId.find( theOldId ) != mapIdToId.end() )
-      return getIORbyId( mapIdToId[ theOldId ] );
-    return std::string( "" );
+    if ( mapIdToId.IsBound( theOldId ) )
+      return getIORbyId( mapIdToId( theOldId ));
+    return std::string();
   }
   // maps old object id to the new one (used when restoring data)
   void mapOldToNew( const int oldId, const int newId ) {
-    mapIdToId[ oldId ] = newId;
+    mapIdToId.Bind( oldId, newId );
   }
   // get old id by a new one
   int getOldId( const int newId ) {
-    std::map<int, int>::iterator imap;
+    TInt2IntMap::iterator imap;
     for ( imap = mapIdToId.begin(); imap != mapIdToId.end(); ++imap ) {
-      if ( imap->second == newId )
-        return imap->first;
+      if ( *imap == newId )
+        return imap.Iterator().Key();
     }
     return 0;
   }
@@ -120,13 +118,13 @@ private:
   int getNextId()
   {
     int id = 1;
-    while( mapIdToIOR.find( id ) != mapIdToIOR.end() )
+    while( mapIdToIOR.IsBound( id ) )
       id++;
     return id;
   }
 
-  std::map<int, std::string> mapIdToIOR; // persistent-to-transient map
-  std::map<int, int>         mapIdToId;  // to translate object from persistent to transient form
+  TInt2StringMap mapIdToIOR; // persistent-to-transient map
+  TInt2IntMap    mapIdToId;  // to translate object from persistent to transient form
 };
 
 // ===========================================================
@@ -565,7 +563,7 @@ public:
 
   // Return an object that previously had an oldID
   template<class TInterface>
-  typename TInterface::_var_type GetObjectByOldId( const int oldID )
+    typename TInterface::_var_type GetObjectByOldId( const int oldID )
   {
     if ( StudyContext* myStudyContext = GetCurrentStudyContext() ) {
       std::string ior = myStudyContext->getIORbyOldId( oldID );
index 3d8980f..c7e753d 100644 (file)
@@ -287,10 +287,12 @@ namespace
  */
 //================================================================================
 
-void SMESH_PreMeshInfo::hdf2meshInfo( const std::string& name,
-                                      HDFgroup*          hdfGroup)
+void SMESH_PreMeshInfo::hdf2meshInfo( const std::string&              name,
+                                      HDFgroup*                       hdfGroup,
+                                      const TColStd_MapOfAsciiString& allHdfNames)
 {
-  if ( hdfGroup->ExistInternalObject( name.c_str()) )
+  //if ( hdfGroup->ExistInternalObject( name.c_str()) ) PAL23514
+  if ( allHdfNames.Contains( name.c_str() ))
   {
     HDFdataset* dataset = new HDFdataset( name.c_str(), hdfGroup );
     dataset->OpenOnDisk();
@@ -419,7 +421,17 @@ bool SMESH_PreMeshInfo::readPreInfoFromHDF()
     HDFgroup* infoHdfGroup = new HDFgroup( hdfGroupName, aFile );
     infoHdfGroup->OpenOnDisk();
 
-    _mesh->changePreMeshInfo()->hdf2meshInfo( "Mesh", infoHdfGroup );
+    // PAL23514: get all names from the HDFgroup to avoid iteration on its contents
+    // within aGroup->ExistInternalObject( name )
+    TColStd_MapOfAsciiString mapOfNames;
+    {
+      std::vector< std::string > subNames;
+      infoHdfGroup->GetAllObjects( subNames );
+      for ( size_t iN = 0; iN < subNames.size(); ++iN )
+        mapOfNames.Add( subNames[ iN ].c_str() );
+    }
+
+    _mesh->changePreMeshInfo()->hdf2meshInfo( "Mesh", infoHdfGroup, mapOfNames );
 
     // read SMESH_PreMeshInfo of groups
     map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i2group = _mesh->_mapGroups.begin();
@@ -432,7 +444,7 @@ bool SMESH_PreMeshInfo::readPreInfoFromHDF()
         if ( SMESHDS_GroupBase* group = group_i->GetGroupDS() )
         {
           const std::string name = group->GetStoreName();
-          group_i->changePreMeshInfo()->hdf2meshInfo( name, infoHdfGroup );
+          group_i->changePreMeshInfo()->hdf2meshInfo( name, infoHdfGroup, mapOfNames );
         }
       }
     }
@@ -444,7 +456,9 @@ bool SMESH_PreMeshInfo::readPreInfoFromHDF()
       if ( SMESH_subMesh_i* sm = SMESH::DownCast<SMESH_subMesh_i*>( id2sm->second ))
       {
         sm->changePreMeshInfo() = newInstance();
-        sm->changePreMeshInfo()->hdf2meshInfo( SMESH_Comment( sm->GetId()), infoHdfGroup );
+        sm->changePreMeshInfo()->hdf2meshInfo( SMESH_Comment( sm->GetId()),
+                                               infoHdfGroup,
+                                               mapOfNames );
       }
     }
   }
index e0469a9..62492c7 100644 (file)
@@ -33,6 +33,7 @@
 #include CORBA_SERVER_HEADER(SALOMEDS)
 
 #include <TopAbs_ShapeEnum.hxx>
+#include <TColStd_MapOfAsciiString.hxx>
 
 class DriverMED_R_SMESHDS_Mesh;
 class HDFfile;
@@ -101,7 +102,9 @@ private:
 
   // reading from the new study, for which SaveToFile() was called
   bool readPreInfoFromHDF();
-  void hdf2meshInfo( const std::string& dataSetName, HDFgroup* infoHdfGroup );
+  void hdf2meshInfo( const std::string&              dataSetName,
+                     HDFgroup*                       infoHdfGroup,
+                     const TColStd_MapOfAsciiString& allHdfNames);
 
   // reading from the old study, for which SaveToFile() was not called
   bool readMeshInfo();