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;
}
|