Просмотр исходного кода

link DependencyData structs together

Cache generation needs a way of quickly iterating over the unique potion
of the dependencies to be able to share them. By linking them together
we can reduce the speed penality (~ 80%) with only a small reduction in
saved size (~ 20%).

Git-Dch: Ignore
David Kalnischkies лет назад: 11
Родитель
Сommit
b291aa59ee
4 измененных файлов с 47 добавлено и 47 удалено
  1. 3 2
      apt-pkg/cacheiterators.h
  2. 3 1
      apt-pkg/pkgcache.h
  3. 37 40
      apt-pkg/pkgcachegen.cc
  4. 4 4
      test/integration/test-apt-cache

+ 3 - 2
apt-pkg/cacheiterators.h

@@ -318,11 +318,12 @@ class pkgCache::DepIterator : public Iterator<Dependency, DepIterator> {
 	   map_pointer_t &DependencyData;
 	   map_pointer_t &DependencyData;
 	   map_pointer_t &NextRevDepends;
 	   map_pointer_t &NextRevDepends;
 	   map_pointer_t &NextDepends;
 	   map_pointer_t &NextDepends;
+	   map_pointer_t &NextData;
 	   DependencyProxy const * operator->() const { return this; }
 	   DependencyProxy const * operator->() const { return this; }
 	   DependencyProxy * operator->() { return this; }
 	   DependencyProxy * operator->() { return this; }
 	};
 	};
-	inline DependencyProxy operator->() const {return { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends };}
-	inline DependencyProxy operator->() {return { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends };}
+	inline DependencyProxy operator->() const {return { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends, S2->NextData };}
+	inline DependencyProxy operator->() {return { S2->Version, S2->Package, S->ID, S2->Type, S2->CompareOp, S->ParentVer, S->DependencyData, S->NextRevDepends, S->NextDepends, S2->NextData };}
 	void ReMap(void const * const oldMap, void const * const newMap)
 	void ReMap(void const * const oldMap, void const * const newMap)
 	{
 	{
 		Iterator<Dependency, DepIterator>::ReMap(oldMap, newMap);
 		Iterator<Dependency, DepIterator>::ReMap(oldMap, newMap);

+ 3 - 1
apt-pkg/pkgcache.h

@@ -366,7 +366,7 @@ struct pkgCache::Header
        the same number of pools as there are structure types. The generator
        the same number of pools as there are structure types. The generator
        stores this information so future additions can make use of any unused pool
        stores this information so future additions can make use of any unused pool
        blocks. */
        blocks. */
-   DynamicMMap::Pool Pools[9];
+   DynamicMMap::Pool Pools[12];
 
 
    /** \brief hash tables providing rapid group/package name lookup
    /** \brief hash tables providing rapid group/package name lookup
 
 
@@ -731,6 +731,8 @@ struct pkgCache::DependencyData
 
 
        If the high bit is set then it is a logical OR with the previous record. */
        If the high bit is set then it is a logical OR with the previous record. */
    unsigned char CompareOp;
    unsigned char CompareOp;
+
+   map_pointer_t NextData;
 };
 };
 struct pkgCache::Dependency
 struct pkgCache::Dependency
 {
 {

+ 37 - 40
apt-pkg/pkgcachegen.cc

@@ -952,33 +952,30 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
 
 
    bool isDuplicate = false;
    bool isDuplicate = false;
    map_pointer_t DependencyData = 0;
    map_pointer_t DependencyData = 0;
-   map_pointer_t * PkgRevDepends = &Pkg->RevDepends;
-   map_pointer_t previous_id = 0;
-
-   while (*PkgRevDepends != 0)
+   map_pointer_t PreviousData = 0;
+   if (Pkg->RevDepends != 0)
    {
    {
-      pkgCache::Dependency * const L = Cache.DepP + *PkgRevDepends;
-      PkgRevDepends = &L->NextRevDepends;
-      if (L->DependencyData == previous_id)
-	 break;
-      previous_id = L->DependencyData;
-      pkgCache::DependencyData const * const D = Cache.DepDataP + previous_id;
-      if (D->Type == Type && D->CompareOp == Op && D->Version == Version)
-      {
-	 DependencyData = previous_id;
-	 isDuplicate = true;
-	 break;
-      }
+      pkgCache::Dependency const * const L = Cache.DepP + Pkg->RevDepends;
+      DependencyData = L->DependencyData;
+      do {
+	 pkgCache::DependencyData const * const D = Cache.DepDataP + DependencyData;
+	 if (Version > D->Version)
+	    break;
+	 if (D->Version == Version && D->Type == Type && D->CompareOp == Op)
+	 {
+	    isDuplicate = true;
+	    break;
+	 }
+	 PreviousData = DependencyData;
+	 DependencyData = D->NextData;
+      } while (DependencyData != 0);
    }
    }
 
 
    if (isDuplicate == false)
    if (isDuplicate == false)
    {
    {
-      void const * const oldMap2 = Map.Data();
       DependencyData = AllocateInMap(sizeof(pkgCache::DependencyData));
       DependencyData = AllocateInMap(sizeof(pkgCache::DependencyData));
       if (unlikely(DependencyData == 0))
       if (unlikely(DependencyData == 0))
         return false;
         return false;
-      if (oldMap2 != Map.Data())
-	 PkgRevDepends += (map_pointer_t const * const) Map.Data() - (map_pointer_t const * const) oldMap2;
    }
    }
 
 
    pkgCache::Dependency * Link = Cache.DepP + Dependency;
    pkgCache::Dependency * Link = Cache.DepP + Dependency;
@@ -987,7 +984,6 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
    Link->ID = Cache.HeaderP->DependsCount++;
    Link->ID = Cache.HeaderP->DependsCount++;
 
 
    pkgCache::DepIterator Dep(Cache, Link);
    pkgCache::DepIterator Dep(Cache, Link);
-   Dynamic<pkgCache::DepIterator> DynDep(Dep);
    if (isDuplicate == false)
    if (isDuplicate == false)
    {
    {
       Dep->Type = Type;
       Dep->Type = Type;
@@ -995,31 +991,32 @@ bool pkgCacheGenerator::NewDepends(pkgCache::PkgIterator &Pkg,
       Dep->Version = Version;
       Dep->Version = Version;
       Dep->Package = Pkg.Index();
       Dep->Package = Pkg.Index();
       ++Cache.HeaderP->DependsDataCount;
       ++Cache.HeaderP->DependsDataCount;
-      Link->NextRevDepends = Pkg->RevDepends;
-      Pkg->RevDepends = Dependency;
+      if (PreviousData != 0)
+      {
+	 pkgCache::DependencyData * const D = Cache.DepDataP + PreviousData;
+	 Dep->NextData = D->NextData;
+	 D->NextData = DependencyData;
+      }
+      else if (Pkg->RevDepends != 0)
+      {
+	 pkgCache::Dependency const * const D = Cache.DepP + Pkg->RevDepends;
+	 Dep->NextData = D->DependencyData;
+      }
+   }
+
+   if (isDuplicate == true || PreviousData != 0)
+   {
+      pkgCache::Dependency * const L = Cache.DepP + Pkg->RevDepends;
+      Link->NextRevDepends = L->NextRevDepends;
+      L->NextRevDepends = Dependency;
    }
    }
    else
    else
    {
    {
-      // dependency data is already fine, we just set the reverse link
-      // and in such a way that the loop above can finish fast, so we keep
-      // non-duplicates at the front and for the duplicates we:
-      // a) move to the end of the list, b) insert before another own duplicate
-      // or c) find two duplicates behind each other.
-      map_pointer_t const own_id = Link->DependencyData;
-      while (*PkgRevDepends != 0)
-      {
-        pkgCache::Dependency * const L = Cache.DepP + *PkgRevDepends;
-        PkgRevDepends = &L->NextRevDepends;
-        if (L->DependencyData == own_id || L->DependencyData == previous_id)
-        {
-           Link->NextRevDepends = L->NextRevDepends;
-           break;
-        }
-        previous_id = L->DependencyData;
-      }
-      *PkgRevDepends = Dependency;
+      Link->NextRevDepends = Pkg->RevDepends;
+      Pkg->RevDepends = Dependency;
    }
    }
 
 
+
    // Do we know where to link the Dependency to?
    // Do we know where to link the Dependency to?
    if (OldDepLast == NULL)
    if (OldDepLast == NULL)
    {
    {

+ 4 - 4
test/integration/test-apt-cache

@@ -113,12 +113,12 @@ Reverse Depends:
   bar' aptcache rdepends foo
   bar' aptcache rdepends foo
 testsuccessequal 'foo
 testsuccessequal 'foo
 Reverse Depends:
 Reverse Depends:
-  Replaces: bar
-  Breaks: bar' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1
+  Breaks: bar
+  Replaces: bar' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1
 testsuccessequal 'foo
 testsuccessequal 'foo
 Reverse Depends:
 Reverse Depends:
-  Replaces: bar (<< 1)
-  Breaks: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1
+  Breaks: bar (<< 1)
+  Replaces: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1
 testsuccessequal 'foo
 testsuccessequal 'foo
 Reverse Depends:
 Reverse Depends:
   Breaks: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 --important --breaks
   Breaks: bar (<< 1)' aptcache rdepends foo -o APT::Cache::ShowDependencyType=1 -o APT::Cache::ShowVersion=1 --important --breaks