[Aptitude-svn-commit] r4005 - in branches/aptitude-0.3/aptitude: .
src/generic src/generic/problemresolver tests
Daniel Burrows
dburrows at costa.debian.org
Tue Aug 30 23:49:38 UTC 2005
Author: dburrows
Date: Tue Aug 30 23:49:34 2005
New Revision: 4005
Modified:
branches/aptitude-0.3/aptitude/ChangeLog
branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h
branches/aptitude-0.3/aptitude/src/generic/setset.h
branches/aptitude-0.3/aptitude/tests/test_setset.cc
Log:
Index setsets using a hash table instead of a tree.
Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog (original)
+++ branches/aptitude-0.3/aptitude/ChangeLog Tue Aug 30 23:49:34 2005
@@ -1,5 +1,13 @@
2005-08-30 Daniel Burrows <dburrows at debian.org>
+ * src/generic/problemresolver/problemresolver.h, src/generic/setset.h, tests/test_setset.cc:
+
+ Use a hash table to represent the by-value indexing in a setset.
+ This appears to significantly speed up the setset structure --
+ by which I mean that finds go from being a major time sink (over
+ 20% of the time in my test case) to taking negligible amounts of
+ time.
+
* src/generic/setset.h:
Use a vector instead of a set to store the sets containing an
Modified: branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h (original)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/problemresolver.h Tue Aug 30 23:49:34 2005
@@ -177,6 +177,16 @@
typedef typename solution::action action;
private:
+ /** Hash function for packages: */
+ struct PackageHash
+ {
+ public:
+ size_t operator()(const package &p) const
+ {
+ return p.get_id();
+ }
+ };
+
/** Compares solutions according to their "goodness". */
struct solution_goodness_compare
{
@@ -303,10 +313,12 @@
*/
std::set<solution, solution_contents_compare> deferred;
+ typedef mapset<package, action, PackageHash> conflictset;
+
/** Stores conflicts: sets of installations that have been
* determined to be mutually incompatible.
*/
- mapset<package, action> conflicts;
+ mapset<package, action, PackageHash> conflicts;
/** The initial set of broken dependencies. Kept here for use in
* the stupid-elimination algorithm.
@@ -394,7 +406,7 @@
* \return a conflict matched by m, or conflicts.end() if no such
* conflict exists.
*/
- typename mapset<package, action>::const_iterator
+ typename conflictset::const_iterator
find_matching_conflict(const imm::map<package, action> &m) const
{
return conflicts.find_submap(m, &conflictor_matches);
@@ -403,7 +415,7 @@
/** Test whether the given solution contains a conflict. */
bool contains_conflict(const solution &s) const
{
- typename mapset<package, action>::const_iterator
+ typename conflictset::const_iterator
found = find_matching_conflict(s.get_actions());
bool rval = (found != conflicts.end());
@@ -426,7 +438,7 @@
*/
void add_conflict(const imm::map<package, action> &conflict)
{
- typename mapset<package, action>::const_iterator
+ typename conflictset::const_iterator
found = find_matching_conflict(conflict);
if(found != conflicts.end())
@@ -1579,7 +1591,7 @@
imm::map<package, action> new_acts = s.get_actions();
new_acts.put(v.get_package(), act);
- typename mapset<package, action>::const_iterator
+ typename conflictset::const_iterator
found = find_matching_conflict(new_acts);
if(found == conflicts.end())
Modified: branches/aptitude-0.3/aptitude/src/generic/setset.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/setset.h (original)
+++ branches/aptitude-0.3/aptitude/src/generic/setset.h Tue Aug 30 23:49:34 2005
@@ -28,17 +28,34 @@
#ifndef SETSET_H
#define SETSET_H
+#ifdef HAVE_CONFIG_H
+#include "../../config.h"
+#endif
+
#include <map>
#include <set>
#include <vector>
#include "immset.h"
+#ifdef HAVE_HASH_MAP
+#include <hash_map>
+#else
+#ifdef HAVE_EXT_HASH_MAP
+#include <ext/hash_map>
+#else
+// D'oh.
+#error "Need hash_map for setset."
+#endif
+#endif
+
/** Maintains a set of imm::sets of Val objects, arranged so that
* quick answers to the query "does the set S subsume any element of
* this set?" can be produced. At the moment this object increases
* monotonically, to keep things simple.
+ *
+ * For efficiency, requires that Val be hashable.
*/
-template<typename Val, typename Compare = std::less<Val> >
+template<typename Val, typename HashFcn = HASH_NAMESPACE::hash<Val>, typename EqualFcn = std::equal_to<Val>, typename Compare = std::less<Val> >
class setset
{
private:
@@ -48,7 +65,7 @@
typedef std::pair<typename entries_list::size_type, Val> index_entry;
- typedef std::map<Val, std::vector<index_entry>, Compare> index_type;
+ typedef HASH_NAMESPACE::hash_map<Val, std::vector<index_entry>, HashFcn, EqualFcn> index_type;
index_type sets_by_key;
@@ -133,8 +150,14 @@
};
public:
- setset(const Compare &c = Compare())
- :sets_by_key(c)
+ setset()
+ {
+ }
+
+ setset(size_type n,
+ const HashFcn &hasher = HashFcn(),
+ const EqualFcn &keyequal = EqualFcn())
+ :sets_by_key(n, hasher, keyequal)
{
}
@@ -191,10 +214,45 @@
}
};
-template<typename Key, typename Val, typename Compare = std::less<Key> >
+template<typename Key, typename Val,
+ typename HashFcn = HASH_NAMESPACE::hash<Key>,
+ typename EqualKey = std::equal_to<Key>,
+ typename Compare = std::less<Key> >
class mapset
{
- typedef setset<std::pair<Key, Val>, imm::key_compare<Key, Val, Compare> > mapset_type;
+ struct hash_key
+ {
+ HashFcn hasher;
+ public:
+ hash_key(const HashFcn &f)
+ :hasher(f)
+ {
+ }
+
+ size_t operator()(const std::pair<Key, Val> &p) const
+ {
+ return hasher(p.first);
+ }
+ };
+
+ struct key_equal_to
+ {
+ EqualKey eq;
+ public:
+ key_equal_to(const EqualKey &_eq)
+ :eq(_eq)
+ {
+ }
+
+ size_t operator()(const std::pair<Key, Val> &p1,
+ const std::pair<Key, Val> &p2) const
+ {
+ return p1.first == p2.first;
+ }
+ };
+
+ typedef setset<std::pair<Key, Val>, hash_key, key_equal_to,
+ imm::key_compare<Key, Val, Compare> > mapset_type;
mapset_type S;
@@ -289,8 +347,10 @@
}
};
- mapset(const Compare &c = Compare())
- :S(imm::key_compare<Key, Val, Compare>(c))
+ mapset(size_type n = 0,
+ const HashFcn &hasher = HashFcn(),
+ const EqualKey &keyequal = EqualKey())
+ :S(n, hash_key(hasher), key_equal_to(keyequal))
{
}
Modified: branches/aptitude-0.3/aptitude/tests/test_setset.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/tests/test_setset.cc (original)
+++ branches/aptitude-0.3/aptitude/tests/test_setset.cc Tue Aug 30 23:49:34 2005
@@ -120,12 +120,30 @@
}
};
+ struct HalfHash
+ {
+ public:
+ size_t operator()(int a) const
+ {
+ return a/2;
+ }
+ };
+
+ struct HalfEqualTo
+ {
+ public:
+ size_t operator()(int a, int b) const
+ {
+ return a/2 == b/2;
+ }
+ };
+
// Test searching for subsets of a set using subsumption.
void testSubsetPredicateSearch()
{
imm::set<int, HalfCmp> s1, s2, s3;
- setset<int, HalfCmp> S;
+ setset<int, HalfHash, HalfEqualTo, HalfCmp> S;
s1.insert(5);
CPPUNIT_ASSERT(s1.contains(5));
@@ -146,7 +164,7 @@
t.insert(5);
- setset<int, HalfCmp>::const_iterator found = S.find_subset(t);
+ setset<int, HalfHash, HalfEqualTo, HalfCmp>::const_iterator found = S.find_subset(t);
CPPUNIT_ASSERT(found != S.end());
CPPUNIT_ASSERT_EQUAL(s1, *found);
More information about the Aptitude-svn-commit
mailing list