summaryrefslogtreecommitdiff
path: root/debian/patches/libports-reduce-overhead.patch
blob: 624e267266b3b35bc177fbb6702630947dfa6ae5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
commit a7c6b5d7b1b669355439361a2a8eecf52dc78538
Author: Justus Winter <4winter@informatik.uni-hamburg.de>
Date:   Sat Apr 26 12:20:20 2014 +0200

    libports: reduce malloc overhead in _ports_bucket_class_iterate
    
    _ports_bucket_class_iterate creates a snapshot of the buckets hash
    table.  This is done so that the lock protecting the hash table can be
    released while we iterate over the snapshot.
    
    Formerly, a linked list was used to store the snapshot.  As the
    maximal number of items is known, using an array is much simpler.
    
    _ports_bucket_class_iterate implements both ports_bucket_iterate and
    ports_class_iterate.  For this change might make ports_class_iterate
    less efficient memory-wise if the number of ports belonging to the
    class is low with respect to the number of ports in the bucket.
    However, the array representation is more compact.  Furthermore a
    survey of the Hurd code revealed that ports_class_iterate is rarely
    used, while ports_bucket_iterate is used more often, most prominently
    in paging code.
    
    * libports/bucket-iterate.c (_ports_bucket_class_iterate): Use an
    array instead of a linked list.

diff --git a/libports/bucket-iterate.c b/libports/bucket-iterate.c
index dc1c7b1..8e6bdc4 100644
--- a/libports/bucket-iterate.c
+++ b/libports/bucket-iterate.c
@@ -31,40 +31,45 @@ _ports_bucket_class_iterate (struct port_bucket *bucket,
 {
   /* This is obscenely ineffecient.  ihash and ports need to cooperate
      more closely to do it efficiently. */
-  struct item
-    {
-      struct item *next;
-      void *p;
-    } *list = 0;
-  struct item *i, *nxt;
+  void **p;
+  size_t i, n;
   error_t err;
 
   pthread_mutex_lock (&_ports_lock);
+
+  if (bucket->htable.nr_items == 0)
+    {
+      pthread_mutex_unlock (&_ports_lock);
+      return 0;
+    }
+
+  p = malloc (bucket->htable.nr_items * sizeof *p);
+  if (p == NULL)
+    return ENOMEM;
+
+  n = 0;
   HURD_IHASH_ITERATE (&bucket->htable, arg)
     {
       struct port_info *const pi = arg;
-      struct item *j;
 
       if (class == 0 || pi->class == class)
 	{
-	  j = malloc (sizeof (struct item));
-	  j->next = list;
-	  j->p = pi;
-	  list = j;
 	  pi->refcnt++;
+	  p[n] = pi;
+	  n++;
 	}
     }
   pthread_mutex_unlock (&_ports_lock);
 
   err = 0;
-  for (i = list; i; i = nxt)
+  for (i = 0; i < n; i++)
     {
       if (!err)
-	err = (*fun)(i->p);
-      ports_port_deref (i->p);
-      nxt = i->next;
-      free (i);
+	err = (*fun)(p[i]);
+      ports_port_deref (p[i]);
     }
+
+  free (p);
   return err;
 }