0026203: Foundation Classes - provide method ::Swap() for NCollection_IndexedMap...
authordbp <dbp@opencascade.com>
Mon, 18 May 2015 12:42:30 +0000 (15:42 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 21 May 2015 10:31:46 +0000 (13:31 +0300)
Add new tests in group "perf ncollection".

src/NCollection/NCollection_IndexedDataMap.hxx
src/NCollection/NCollection_IndexedMap.hxx
src/QANCollection/QANCollection_Stl.cxx
tests/bugs/fclasses/bug24831 [new file with mode: 0644]
tests/perf/ncollection/A2 [new file with mode: 0644]
tests/perf/ncollection/A3 [new file with mode: 0644]

index 9673248..72baad7 100644 (file)
@@ -70,7 +70,7 @@ class NCollection_IndexedDataMap : public NCollection_BaseMap
     TheKeyType& Key1 (void)
     { return myKey1; }
     //! Key2
-    const Standard_Integer& Key2 (void)
+    Standard_Integer& Key2 (void)
     { return myKey2; }
     //! Next2
     IndexedDataMapNode*& Next2 (void)
@@ -345,6 +345,58 @@ class NCollection_IndexedDataMap : public NCollection_BaseMap
     myData1[iK1] = p;
   }
 
+  //! Swaps two elements with the given indices.
+  void Swap (const Standard_Integer theIndex1,
+             const Standard_Integer theIndex2)
+  {
+    Standard_OutOfRange_Raise_if (theIndex1 < 1 || theIndex1 > Extent()
+                               || theIndex2 < 1 || theIndex2 > Extent(), "NCollection_IndexedDataMap::Swap");
+
+    if (theIndex1 == theIndex2)
+    {
+      return;
+    }
+
+    const Standard_Integer aK1 = ::HashCode (theIndex1, NbBuckets());
+    const Standard_Integer aK2 = ::HashCode (theIndex2, NbBuckets());
+
+    IndexedDataMapNode* aP1 = (IndexedDataMapNode*) myData2[aK1];
+    IndexedDataMapNode* aP2 = (IndexedDataMapNode*) myData2[aK2];
+
+    if (aP1->Key2() == theIndex1)
+    {
+      myData2[aK1] = (IndexedDataMapNode *) aP1->Next2();
+    }
+    else
+    {
+      IndexedDataMapNode* aQ = aP1;
+      for (aP1 = aQ->Next2(); aP1->Key2() != theIndex1; aQ = aP1, aP1 = aQ->Next2()) { }
+
+      aQ->Next2() = aP1->Next2();
+    }
+
+    if (aP2->Key2() == theIndex2)
+    {
+      myData2[aK2] = (IndexedDataMapNode *) aP2->Next2();
+    }
+    else
+    {
+      IndexedDataMapNode* aQ = aP2;
+      for (aP2 = aQ->Next2(); aP2->Key2() != theIndex2; aQ = aP2, aP2 = aQ->Next2()) { }
+
+      aQ->Next2() = aP2->Next2();
+    }
+
+    std::swap (aP1->Key2(),
+               aP2->Key2());
+
+    aP1->Next2() = (IndexedDataMapNode*) myData2[aK2];
+    myData2[aK2] = aP1;
+
+    aP2->Next2() = (IndexedDataMapNode*) myData2[aK1];
+    myData2[aK1] = aP2;
+  }
+
   //! RemoveLast
   void RemoveLast (void)
   {
index 4c8bfd7..29628b9 100644 (file)
@@ -60,7 +60,7 @@ class NCollection_IndexedMap : public NCollection_BaseMap
     TheKeyType& Key1 (void)
     { return this->ChangeValue(); }
     //! Key2
-    const Standard_Integer& Key2 (void)
+    Standard_Integer& Key2 (void)
     { return myKey2; }
     //! Next2
     IndexedMapNode*& Next2 (void)
@@ -314,6 +314,58 @@ class NCollection_IndexedMap : public NCollection_BaseMap
     myData1[iK1] = p;
   }
 
+  //! Swaps two elements with the given indices.
+  void Swap (const Standard_Integer theIndex1,
+             const Standard_Integer theIndex2)
+  {
+    Standard_OutOfRange_Raise_if (theIndex1 < 1 || theIndex1 > Extent()
+                               || theIndex2 < 1 || theIndex2 > Extent(), "NCollection_IndexedMap::Swap");
+
+    if (theIndex1 == theIndex2)
+    {
+      return;
+    }
+
+    const Standard_Integer aK1 = ::HashCode (theIndex1, NbBuckets());
+    const Standard_Integer aK2 = ::HashCode (theIndex2, NbBuckets());
+
+    IndexedMapNode* aP1 = (IndexedMapNode*) myData2[aK1];
+    IndexedMapNode* aP2 = (IndexedMapNode*) myData2[aK2];
+
+    if (aP1->Key2() == theIndex1)
+    {
+      myData2[aK1] = (IndexedMapNode *) aP1->Next2();
+    }
+    else
+    {
+      IndexedMapNode* aQ = aP1;
+      for (aP1 = aQ->Next2(); aP1->Key2() != theIndex1; aQ = aP1, aP1 = aQ->Next2()) { }
+
+      aQ->Next2() = aP1->Next2();
+    }
+
+    if (aP2->Key2() == theIndex2)
+    {
+      myData2[aK2] = (IndexedMapNode *) aP2->Next2();
+    }
+    else
+    {
+      IndexedMapNode* aQ = aP2;
+      for (aP2 = aQ->Next2(); aP2->Key2() != theIndex2; aQ = aP2, aP2 = aQ->Next2()) { }
+
+      aQ->Next2() = aP2->Next2();
+    }
+
+    std::swap (aP1->Key2(),
+               aP2->Key2());
+
+    aP1->Next2() = (IndexedMapNode*) myData2[aK2];
+    myData2[aK2] = aP1;
+
+    aP2->Next2() = (IndexedMapNode*) myData2[aK1];
+    myData2[aK1] = aP2;
+  }
+
   //! RemoveLast
   void RemoveLast (void)
   {
index a4b94e2..adf58d1 100644 (file)
@@ -1143,13 +1143,13 @@ static Standard_Integer QANTestNCollectionPerformance (Draw_Interpretor& di, Sta
 
   di << "\n" << "std::vector vs NCollection_Array1 (sort):" << "\n\n";
   TestPerformanceRandomIterator<NCollection_Array1<double>, std::vector<double> >(di);
-  
+
   di << "\n" << "std::vector vs NCollection_Vector (sort):" << "\n\n";
   TestPerformanceRandomIterator<NCollection_Vector<double>, std::vector<double> >(di);
-  
+
   di << "\n" << "std::vector vs NCollection_Array1 (replace):" << "\n\n";
   TestPerformanceForwardIterator<NCollection_Array1<double>, std::vector<double> >(di);
-  
+
   di << "\n" << "std::vector vs NCollection_Vector (replace):" << "\n\n";
   TestPerformanceForwardIterator<NCollection_Vector<double>, std::vector<double> >(di);
 
@@ -1167,7 +1167,193 @@ static Standard_Integer QANTestNCollectionPerformance (Draw_Interpretor& di, Sta
 
   di << "\n" << "std::set vs NCollection_IndexedMap (search):" << "\n\n";
   TestPerformanceMapAccess<NCollection_IndexedMap<int>, int>(di);
-  
+
+  return 0;
+}
+
+//=======================================================================
+//function : QANTestNCollectionIndexedMap
+//purpose  :
+//=======================================================================
+static Standard_Integer QANTestNCollectionIndexedMap (Draw_Interpretor& di, Standard_Integer, const char**)
+{
+  OSD_Timer aTimer;
+
+  std::vector<Standard_Integer>            aIndxs;
+  std::vector<Standard_Integer>            aItems;
+  NCollection_IndexedMap<Standard_Integer> aIndxMap;
+
+  const Standard_Integer aNbItems = 1000000;
+
+  srand (1);
+  for (Standard_Integer anId = 1; anId <= aNbItems; ++anId)
+  {
+    const Standard_Integer aVal = anId * 2;
+
+    aIndxs.push_back (anId);
+    aItems.push_back (aVal);
+
+    aIndxMap.Add  (aVal);
+  }
+
+  aTimer.Start();
+  for (Standard_Integer anId = 0; anId < aNbItems; ++anId)
+  {
+    if (aIndxMap.FindIndex (aItems[anId]) != aIndxs[anId])
+    {
+      std::cout << "failed FindIndex\n";
+    }
+
+    if (aIndxMap.FindKey (aIndxs[anId]) != aItems[anId])
+    {
+      std::cout << "failed FindKey\n";
+    }
+  }
+  aTimer.Stop();
+
+  const Standard_Real aTime1 = aTimer.ElapsedTime();
+
+  aTimer.Reset();
+  aTimer.Start();
+  for (Standard_Integer anId = 0; anId < aNbItems / 30; ++anId)
+  {
+    const Standard_Integer anId2 = Min (aNbItems - 1,
+      static_cast<Standard_Integer> (rand() / float (RAND_MAX) * aNbItems));
+
+    aIndxMap.Swap (aIndxs[anId], aIndxs[anId2]);
+
+    std::swap (aIndxs[anId], aIndxs[anId2]);
+  }
+  aTimer.Stop();
+
+  const Standard_Real aTime2 = aTimer.ElapsedTime();
+
+  aTimer.Reset();
+  aTimer.Start();
+  for (Standard_Integer anId = 0; anId < aNbItems; ++anId)
+  {
+    if (aIndxMap.FindIndex (aItems[anId]) != aIndxs[anId])
+    {
+      std::cout << "failed FindIndex\n";
+    }
+
+    if (aIndxMap.FindKey (aIndxs[anId]) != aItems[anId])
+    {
+      std::cout << "failed FindKey\n";
+    }
+  }
+  aTimer.Stop();
+
+  const Standard_Real aTime3 = aTimer.ElapsedTime();
+
+  aTimer.Reset();
+  aTimer.Start();
+  for (Standard_Integer anId = 0; anId < aNbItems; ++anId)
+  {
+    aIndxMap.RemoveLast();
+  }
+  aTimer.Stop();
+
+  const Standard_Real aTime4 = aTimer.ElapsedTime();
+
+  di << "Search time 1: " << aTime1 << "\n"
+     << "Swapping time: " << aTime2 << "\n"
+     << "Search time 2: " << aTime3 << "\n"
+     << "Remove   time: " << aTime4 << "\n";
+
+  return 0;
+}
+
+//=======================================================================
+//function : QANTestNCollectionIndexedDataMap
+//purpose  :
+//=======================================================================
+static Standard_Integer QANTestNCollectionIndexedDataMap (Draw_Interpretor& di, Standard_Integer, const char**)
+{
+  OSD_Timer aTimer;
+
+  std::vector<Standard_Integer>                                  aIndxs;
+  std::vector<Standard_Integer>                                  aItems;
+  NCollection_IndexedDataMap<Standard_Integer, Standard_Integer> aIndxMap;
+
+  const Standard_Integer aNbItems = 1000000;
+
+  srand (1);
+  for (Standard_Integer anId = 1; anId <= aNbItems; ++anId)
+  {
+    const Standard_Integer aVal = anId * 2;
+
+    aIndxs.push_back (anId);
+    aItems.push_back (aVal);
+
+    aIndxMap.Add  (aVal, aVal * 2);
+  }
+
+  aTimer.Start();
+  for (Standard_Integer anId = 0; anId < aNbItems; ++anId)
+  {
+    if (aIndxMap.FindIndex (aItems[anId]) != aIndxs[anId])
+    {
+      std::cout << "failed FindIndex\n";
+    }
+
+    if (aIndxMap.FindKey (aIndxs[anId]) != aItems[anId])
+    {
+      std::cout << "failed FindKey\n";
+    }
+  }
+  aTimer.Stop();
+
+  const Standard_Real aTime1 = aTimer.ElapsedTime();
+
+  aTimer.Reset();
+  aTimer.Start();
+  for (Standard_Integer anId = 0; anId < aNbItems / 30; ++anId)
+  {
+    const Standard_Integer anId2 = Min (aNbItems - 1,
+      static_cast<Standard_Integer> (rand() / float (RAND_MAX) * aNbItems));
+
+    aIndxMap.Swap (aIndxs[anId], aIndxs[anId2]);
+
+    std::swap (aIndxs[anId], aIndxs[anId2]);
+  }
+  aTimer.Stop();
+
+  const Standard_Real aTime2 = aTimer.ElapsedTime();
+
+  aTimer.Reset();
+  aTimer.Start();
+  for (Standard_Integer anId = 0; anId < aNbItems; ++anId)
+  {
+    if (aIndxMap.FindIndex (aItems[anId]) != aIndxs[anId])
+    {
+      std::cout << "failed FindIndex\n";
+    }
+
+    if (aIndxMap.FindKey (aIndxs[anId]) != aItems[anId])
+    {
+      std::cout << "failed FindKey\n";
+    }
+  }
+  aTimer.Stop();
+
+  const Standard_Real aTime3 = aTimer.ElapsedTime();
+
+  aTimer.Reset();
+  aTimer.Start();
+  for (Standard_Integer anId = 0; anId < aNbItems; ++anId)
+  {
+    aIndxMap.RemoveLast();
+  }
+  aTimer.Stop();
+
+  const Standard_Real aTime4 = aTimer.ElapsedTime();
+
+  di << "Search time 1: " << aTime1 << "\n"
+     << "Swapping time: " << aTime2 << "\n"
+     << "Search time 2: " << aTime3 << "\n"
+     << "Remove   time: " << aTime4 << "\n";
+
   return 0;
 }
 
@@ -1239,5 +1425,17 @@ void QANCollection::CommandsStl (Draw_Interpretor& theCommands)
                    QANTestNCollectionPerformance,
                    aGroup);
 
+  theCommands.Add ("QANTestNCollectionIndexedMap",
+                   "QANTestNCollectionIndexedMap",
+                   __FILE__,
+                   QANTestNCollectionIndexedMap,
+                   aGroup);
+
+  theCommands.Add ("QANTestNCollectionIndexedDataMap",
+                   "QANTestNCollectionIndexedDataMap",
+                   __FILE__,
+                   QANTestNCollectionIndexedDataMap,
+                   aGroup);
+
   return;
 }
diff --git a/tests/bugs/fclasses/bug24831 b/tests/bugs/fclasses/bug24831
new file mode 100644 (file)
index 0000000..90d6d8d
--- /dev/null
@@ -0,0 +1,3 @@
+pload QAcommands
+
+QANTestStlIterators
diff --git a/tests/perf/ncollection/A2 b/tests/perf/ncollection/A2
new file mode 100644 (file)
index 0000000..e7286d0
--- /dev/null
@@ -0,0 +1,41 @@
+pload QAcommands
+
+set info [QANTestNCollectionIndexedMap]
+
+set keys {}
+set values {}
+foreach line [split $info "\n"] {
+  set key [string trim [string range $line 0 [expr {[string first ":" $line] - 1}]]]
+  set value [string trim [string range $line [expr {[string first ":" $line] + 1}] [expr {[string length $line] - 1}]]]
+  if {[string length $key] != 0} {
+    if {[string length $value] != 0} {
+      lappend keys $key
+      lappend values $value
+    }
+  }
+}
+
+if { [string compare $tcl_platform(platform) "windows"] != 0 } {
+  set check_values  { 0.1540285
+                      0.1286995
+                      0.1607561
+                      0.3624441
+                    }
+} else {
+  set check_values  { 0.018136771
+                      0.008694706
+                      0.019123649
+                      0.784462745
+                    }
+}
+
+set index 0
+foreach key $keys {
+  set value [lindex $values $index]
+  if { $value > [lindex $check_values $index] } {
+    puts "ERROR: performance of $key become worse"
+  } else {
+    puts "OK: performance of $key is OK"
+  }
+  incr index
+}
diff --git a/tests/perf/ncollection/A3 b/tests/perf/ncollection/A3
new file mode 100644 (file)
index 0000000..8847bad
--- /dev/null
@@ -0,0 +1,41 @@
+pload QAcommands
+
+set info [QANTestNCollectionIndexedDataMap]
+
+set keys {}
+set values {}
+foreach line [split $info "\n"] {
+  set key [string trim [string range $line 0 [expr {[string first ":" $line] - 1}]]]
+  set value [string trim [string range $line [expr {[string first ":" $line] + 1}] [expr {[string length $line] - 1}]]]
+  if {[string length $key] != 0} {
+    if {[string length $value] != 0} {
+      lappend keys $key
+      lappend values $value
+    }
+  }
+}
+
+if { [string compare $tcl_platform(platform) "windows"] != 0 } {
+  set check_values  { 0.1549615
+                      0.1290805
+                      0.1602191
+                      0.3487175
+                    }
+} else {
+  set check_values  { 0.017762852
+                      0.008435507
+                      0.018746851
+                      0.079263713
+                    }
+}
+
+set index 0
+foreach key $keys {
+  set value [lindex $values $index]
+  if { $value > [lindex $check_values $index] } {
+    puts "ERROR: performance of $key become worse"
+  } else {
+    puts "OK: performance of $key is OK"
+  }
+  incr index
+}