mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-10 18:51:21 +03:00
0026203: Foundation Classes - provide method ::Swap() for NCollection_IndexedMap and NCollection_IndexedDataMap to transpose map elements
Add new tests in group "perf ncollection".
This commit is contained in:
parent
14cda02f82
commit
9e50612044
@ -70,7 +70,7 @@ class NCollection_IndexedDataMap : public NCollection_BaseMap
|
|||||||
TheKeyType& Key1 (void)
|
TheKeyType& Key1 (void)
|
||||||
{ return myKey1; }
|
{ return myKey1; }
|
||||||
//! Key2
|
//! Key2
|
||||||
const Standard_Integer& Key2 (void)
|
Standard_Integer& Key2 (void)
|
||||||
{ return myKey2; }
|
{ return myKey2; }
|
||||||
//! Next2
|
//! Next2
|
||||||
IndexedDataMapNode*& Next2 (void)
|
IndexedDataMapNode*& Next2 (void)
|
||||||
@ -345,6 +345,58 @@ class NCollection_IndexedDataMap : public NCollection_BaseMap
|
|||||||
myData1[iK1] = p;
|
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
|
//! RemoveLast
|
||||||
void RemoveLast (void)
|
void RemoveLast (void)
|
||||||
{
|
{
|
||||||
|
@ -60,7 +60,7 @@ class NCollection_IndexedMap : public NCollection_BaseMap
|
|||||||
TheKeyType& Key1 (void)
|
TheKeyType& Key1 (void)
|
||||||
{ return this->ChangeValue(); }
|
{ return this->ChangeValue(); }
|
||||||
//! Key2
|
//! Key2
|
||||||
const Standard_Integer& Key2 (void)
|
Standard_Integer& Key2 (void)
|
||||||
{ return myKey2; }
|
{ return myKey2; }
|
||||||
//! Next2
|
//! Next2
|
||||||
IndexedMapNode*& Next2 (void)
|
IndexedMapNode*& Next2 (void)
|
||||||
@ -314,6 +314,58 @@ class NCollection_IndexedMap : public NCollection_BaseMap
|
|||||||
myData1[iK1] = p;
|
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
|
//! RemoveLast
|
||||||
void RemoveLast (void)
|
void RemoveLast (void)
|
||||||
{
|
{
|
||||||
|
@ -1143,13 +1143,13 @@ static Standard_Integer QANTestNCollectionPerformance (Draw_Interpretor& di, Sta
|
|||||||
|
|
||||||
di << "\n" << "std::vector vs NCollection_Array1 (sort):" << "\n\n";
|
di << "\n" << "std::vector vs NCollection_Array1 (sort):" << "\n\n";
|
||||||
TestPerformanceRandomIterator<NCollection_Array1<double>, std::vector<double> >(di);
|
TestPerformanceRandomIterator<NCollection_Array1<double>, std::vector<double> >(di);
|
||||||
|
|
||||||
di << "\n" << "std::vector vs NCollection_Vector (sort):" << "\n\n";
|
di << "\n" << "std::vector vs NCollection_Vector (sort):" << "\n\n";
|
||||||
TestPerformanceRandomIterator<NCollection_Vector<double>, std::vector<double> >(di);
|
TestPerformanceRandomIterator<NCollection_Vector<double>, std::vector<double> >(di);
|
||||||
|
|
||||||
di << "\n" << "std::vector vs NCollection_Array1 (replace):" << "\n\n";
|
di << "\n" << "std::vector vs NCollection_Array1 (replace):" << "\n\n";
|
||||||
TestPerformanceForwardIterator<NCollection_Array1<double>, std::vector<double> >(di);
|
TestPerformanceForwardIterator<NCollection_Array1<double>, std::vector<double> >(di);
|
||||||
|
|
||||||
di << "\n" << "std::vector vs NCollection_Vector (replace):" << "\n\n";
|
di << "\n" << "std::vector vs NCollection_Vector (replace):" << "\n\n";
|
||||||
TestPerformanceForwardIterator<NCollection_Vector<double>, std::vector<double> >(di);
|
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";
|
di << "\n" << "std::set vs NCollection_IndexedMap (search):" << "\n\n";
|
||||||
TestPerformanceMapAccess<NCollection_IndexedMap<int>, int>(di);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1239,5 +1425,17 @@ void QANCollection::CommandsStl (Draw_Interpretor& theCommands)
|
|||||||
QANTestNCollectionPerformance,
|
QANTestNCollectionPerformance,
|
||||||
aGroup);
|
aGroup);
|
||||||
|
|
||||||
|
theCommands.Add ("QANTestNCollectionIndexedMap",
|
||||||
|
"QANTestNCollectionIndexedMap",
|
||||||
|
__FILE__,
|
||||||
|
QANTestNCollectionIndexedMap,
|
||||||
|
aGroup);
|
||||||
|
|
||||||
|
theCommands.Add ("QANTestNCollectionIndexedDataMap",
|
||||||
|
"QANTestNCollectionIndexedDataMap",
|
||||||
|
__FILE__,
|
||||||
|
QANTestNCollectionIndexedDataMap,
|
||||||
|
aGroup);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
3
tests/bugs/fclasses/bug24831
Normal file
3
tests/bugs/fclasses/bug24831
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pload QAcommands
|
||||||
|
|
||||||
|
QANTestStlIterators
|
41
tests/perf/ncollection/A2
Normal file
41
tests/perf/ncollection/A2
Normal file
@ -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
|
||||||
|
}
|
41
tests/perf/ncollection/A3
Normal file
41
tests/perf/ncollection/A3
Normal file
@ -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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user