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