[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