inline auto filterRepetitions (IT&& source) { using SrcIT = typename std::remove_reference<IT>::type; using Val = typename SrcIT::value_type; return filterIterator (forward<IT>(source), SkipRepetition<Val>() ); }
void testFiltering() { clock_t stdTime = 0; clock_t algoTime = 0; clock_t treeAlgoTime = 0; clock_t treeAlgoVisitorTime = 0; clock_t insertionStdTime = 0; clock_t insertionAlgoTime = 0; clock_t insertionTreeAlgoTime = 0; typedef Utils::StorableSet<TestItem, TestItemConversion, StaticRepository> RepositorySet; const uint cycles = 3000; const uint setSize = 1500; uint totalItems = 0, totalFilteredItems = 0; srand(time(nullptr)); for(uint a = 0; a < cycles; ++a) { KDevelop::ConvenientFreeListSet<TestItem, TestItemHandler> set1; std::set<uint> testSet1; KDevelop::ConvenientFreeListSet<TestItem, TestItemHandler> set2; std::set<uint> testSet2; RepositorySet repSet2; if(a % (cycles / 10) == 0) { qDebug() << "cycle" << a; } //Build the sets extractor_div_with = (rand() % 10) + 1; for(uint a = 0; a < setSize; ++a) { uint value = rand() % 3000; uint divValue = value/extractor_div_with; if(!divValue) continue; // qDebug() << "inserting" << value; std::set<uint>::const_iterator it = testSet1.lower_bound(value); int pos = set1.iterator().lowerBound(TestItem(value)); //This tests the upperBound functionality if (pos != -1) { QVERIFY(it != testSet1.end()); QVERIFY(set1.data()[pos].value == *it); } else { QVERIFY(it == testSet1.end()); } if((rand() % 10) == 0) { set1.insert(TestItem(value)); testSet1.insert(value); } //This is tuned so in the end, about 99% of all declarations are filtered out, like in the symbol table. if((rand() % (extractor_div_with*100)) == 0) { clock_t start = clock(); set2.insert(TestItem(divValue)); insertionStdTime += clock() - start; start = clock(); testSet2.insert(divValue); insertionAlgoTime += clock() - start; start = clock(); repSet2.insert(TestItem(divValue)); insertionTreeAlgoTime += clock() - start; start = clock(); } } std::set<uint> verifySet1; for(KDevelop::ConvenientFreeListSet<TestItem, TestItemHandler>::Iterator it = set1.iterator(); it; ++it) verifySet1.insert(it->value); std::set<uint> verifySet2; for(KDevelop::ConvenientFreeListSet<TestItem, TestItemHandler>::Iterator it = set2.iterator(); it; ++it) verifySet2.insert(it->value); std::set<uint> verifyRepSet2; for(RepositorySet::Iterator it = repSet2.iterator(); it; ++it) verifyRepSet2.insert((*it).value); QCOMPARE(verifySet1, testSet1); QCOMPARE(verifySet2, testSet2); QCOMPARE(verifyRepSet2, testSet2); std::set<uint> algoFiltered; std::set<uint> treeAlgoFiltered; std::set<uint> treeAlgoVisitorFiltered; { //Do the filtering once without actions on the filtered items, just for calculating the time clock_t start = clock(); { KDevelop::ConvenientEmbeddedSetFilterIterator<TestItem, TestItemHandler, TestItem, TestItemHandler, Extractor> filterIterator(set1.iterator(), set2.iterator()); while(filterIterator) ++filterIterator; algoTime += clock() - start; } start = clock(); { KDevelop::ConvenientEmbeddedSetTreeFilterIterator<TestItem, TestItemHandler, TestItem, RepositorySet, Extractor> filterIterator(set1.iterator(), repSet2); while(filterIterator) ++filterIterator; treeAlgoTime += clock() - start; } { start = clock(); NothingDoVisitor v; KDevelop::ConvenientEmbeddedSetTreeFilterVisitor<TestItem, TestItemHandler, TestItem, RepositorySet, Extractor, NothingDoVisitor> visit(v, set1.iterator(), repSet2); treeAlgoVisitorTime += clock() - start; } start = clock(); for(std::set<uint>::const_iterator it = testSet1.begin(); it != testSet1.end(); ++it) { if(testSet2.count((*it) / extractor_div_with) == 1) { } } stdTime += clock() - start; } { KDevelop::ConvenientEmbeddedSetFilterIterator<TestItem, TestItemHandler, TestItem, TestItemHandler, Extractor> filterIterator(set1.iterator(), set2.iterator()); while(filterIterator) { algoFiltered.insert(filterIterator->value); ++filterIterator; } } { KDevelop::ConvenientEmbeddedSetTreeFilterIterator<TestItem, TestItemHandler, TestItem, RepositorySet, Extractor> filterIterator(set1.iterator(), repSet2); while(filterIterator) { treeAlgoFiltered.insert((*filterIterator).value); ++filterIterator; } } { UintSetVisitor v(treeAlgoVisitorFiltered); KDevelop::ConvenientEmbeddedSetTreeFilterVisitor<TestItem, TestItemHandler, TestItem, RepositorySet, Extractor, UintSetVisitor> visit(v, set1.iterator(), repSet2); } totalItems += testSet1.size(); totalFilteredItems += algoFiltered.size(); std::set<uint> stdFiltered; for(std::set<uint>::const_iterator it = testSet1.begin(); it != testSet1.end(); ++it) { if(testSet2.count((*it) / extractor_div_with) == 1) { stdFiltered.insert(*it); } } QCOMPARE(algoFiltered, stdFiltered); QCOMPARE(treeAlgoFiltered, stdFiltered); QCOMPARE(treeAlgoVisitorFiltered, stdFiltered); } qDebug() << "Filtering performance: embedded-list filtering:" << toSeconds(algoTime) << "set-repository filtering:" << toSeconds(treeAlgoTime) << "set-repository visitor filtering:" << toSeconds(treeAlgoVisitorTime) << "std::set filtering:" << toSeconds(stdTime) << "Normal -> Embedded speedup ratio:" << (toSeconds(stdTime) / toSeconds(algoTime)) << "Normal -> Repository speedup ratio:" << (toSeconds(stdTime) / toSeconds(treeAlgoVisitorTime)) << "total processed items:" << totalItems << "total items after filtering:" << totalFilteredItems; qDebug() << "Insertion: embedded-list:" << toSeconds(insertionAlgoTime) << "set-repository:" << toSeconds(insertionTreeAlgoTime) << "std::set:" << toSeconds(insertionStdTime); }
inline FilterIter<IT> filterRepetitions (IT const& source) { typedef typename IT::value_type Val; return filterIterator(source, SkipRepetition<Val>() ); }
inline auto filterRepetitions (IT const& source) { using Val = typename IT::value_type; return filterIterator (source, SkipRepetition<Val>()); }