Re: [PATCH] Improve loading performance by 80% using dynamic resizing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hmm, it looks like this email never made it to the list (spamfilter
maybe?)  I'm re-forwarding it here:

Cheers,
Kyle Moffett

On Fri, Jul 16, 2010 at 17:50, Matthew Robertson
<Matthew.L.Robertson@xxxxxxxxxx> wrote:
> After spending a lot of developer time recently doing repeated relinks of
> policies after making minor changes we put some time into tracking down avenues
> for improving performance in the SELinux libraries. On a reasonably modern HP
> server a 'make load' of a precompiled SELinux Reference Policy takes roughly 96
> seconds. The 'perf' tool pointed us to some undersized and overpopulated hash
> tables in libsepol's hashtab.c and avtab.c. By implementing dynamic resizing for
> those structures we were able to bring that down to a 19 second runtime (80%
> performance improvement) at the cost of ~6% more memory overhead.
>
> After applying this fix, bzip2 takes up a disproportionate percentage of the
> time for a policy load. By effectively disabling bzip2 (changing bzip_blocksize
> in libsemanage to 0) we reduced load time to about 11 seconds--disabling
> compression might not be a tenable solution but supporting a faster compression
> option like gzip could be worth the trouble if the other fixes check out.
>
> For reference, here are the numbers and perf reports we're looking at for the
> policy loading step after a compile/install:
>
> SELinux Reference Policy        v2.20091117
> libsepol                        v2.0.41
> libsemanage                     v2.0.45
> libselinux                      v2.0.94
> libbz2                          v1.0.5-4
>
> ORIGINAL LIBRARIES: 96.0s
> [full compile + load: 142s]
>
>    54.34%  semodule  /lib/libc-2.11.2.so            [.] __strcmp_sse42
>    16.08%  semodule  /lib/libsepol.so.1             [.] hashtab_search
>     4.74%  semodule  /lib/libsepol.so.1             [.] symcmp
>     3.98%  semodule  /lib/libsepol.so.1             [.] strcmp@plt
>     3.76%  semodule  /lib/libbz2.so.1.0.4           [.] 0x0000000000b0bc
>     2.80%  semodule  /lib/libsepol.so.1             [.] avtab_search_node
>     2.72%  semodule  /lib/libbz2.so.1.0.4           [.] 0x000000000022d0
>     1.51%  semodule  /lib/libsepol.so.1             [.] ebitmap_set_bit
>     1.12%  semodule  /lib/libsepol.so.1             [.] hashtab_map
>     1.00%  semodule  /lib/libsepol.so.1             [.] symhash
>     0.95%  semodule  /lib/libbz2.so.1.0.4           [.] BZ2_decompress
>     0.90%  semodule  /lib/libbz2.so.1.0.4           [.] BZ2_compressBlock
>     0.68%  semodule  /lib/libc-2.11.2.so            [.] __strlen_sse42
>     0.57%  semodule  /lib/libbz2.so.1.0.4           [.] BZ2_bzDecompress
>
> DYNAMIC HASHING ENABLED, BZIP2 LEFT ENABLED: 19s, 80% improvement
> [full compile + load: 70.5s, ~50% improvement]
>
>    28.57%  semodule  /lib/libbz2.so.1.0.4           [.] 0x0000000000b539
>     7.53%  semodule  /lib/libsepol.so.1             [.] ebitmap_set_bit
>     7.24%  semodule  /lib/libc-2.11.2.so            [.] __strcmp_sse42
>     5.91%  semodule  /lib/libsepol.so.1             [.] hashtab_map
>     4.91%  semodule  /lib/libsepol.so.1             [.] symhash
>     4.66%  semodule  /lib/libsepol.so.1             [.] hashtab_search
>     4.58%  semodule  /lib/libbz2.so.1.0.4           [.] BZ2_decompress
>     4.46%  semodule  /lib/libbz2.so.1.0.4           [.] BZ2_compressBlock
>     4.38%  semodule  /lib/libsepol.so.1             [.] avtab_search_node
>     3.40%  semodule  /lib/libbz2.so.1.0.4           [.] 0x0000000000d1f9
>     2.29%  semodule  /lib/libbz2.so.1.0.4           [.] BZ2_bzDecompress
>
> DYNAMIC HASHING ENABLED, BZIP2 DISABLED: 11 seconds, 88% improvement
> [full compile + load: 62s, ~55% improvement]
>
>    13.39%  semodule  /lib/libsepol.so.1             [.] ebitmap_set_bit
>    12.77%  semodule  /lib/libc-2.11.2.so            [.] __strcmp_sse42
>    10.44%  semodule  /lib/libsepol.so.1             [.] hashtab_map
>     8.91%  semodule  /lib/libsepol.so.1             [.] symhash
>     8.28%  semodule  /lib/libsepol.so.1             [.] hashtab_search
>     7.74%  semodule  /lib/libsepol.so.1             [.] avtab_search_node
>
> Signed-off-by:  Matthew Robertson <Matthew.L.Robertson@xxxxxxxxxx>
> ---
>  src/avtab.c   |   52 +++++++++++++++++++++++++++-----
>  src/hashtab.c |   91 +++++++++++++++++++++++++++++++++++++++-----------------
>  2 files changed, 106 insertions(+), 37 deletions(-)
>
> diff --git a/src/avtab.c b/src/avtab.c
> index ea947cb..2db931e 100644
> --- a/src/avtab.c
> +++ b/src/avtab.c
> @@ -78,17 +78,13 @@ avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key,
>        return newnode;
>  }
>
> -int avtab_insert(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum)
> +int avtab_insert__(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum)
>  {
> -       int hvalue;
> -       avtab_ptr_t prev, cur, newnode;
> +       avtab_ptr_t prev, cur;
> +       int hvalue = avtab_hash(key, h->mask);
>        uint16_t specified =
>            key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
> -
> -       if (!h || !h->htable)
> -               return SEPOL_ENOMEM;
> -
> -       hvalue = avtab_hash(key, h->mask);
> +
>        for (prev = NULL, cur = h->htable[hvalue];
>             cur; prev = cur, cur = cur->next) {
>                if (key->source_type == cur->key.source_type &&
> @@ -110,8 +106,46 @@ int avtab_insert(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum)
>        newnode = avtab_insert_node(h, hvalue, prev, key, datum);
>        if (!newnode)
>                return SEPOL_ENOMEM;
> +       return SEPOL_OK;
> +}
>
> -       return 0;
> +int avtab_insert(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum)
> +{
> +        int oldsize, i;
> +       avtab_ptr_t prev, cur, newnode, *oldtbl, *newtbl;
> +
> +       if (!h || !h->htable)
> +               return SEPOL_ENOMEM;
> +
> +       /* If we don't need to resize, just insert the new entry */
> +       if (h->nslot * 3/4 > h->nel)
> +               return avtab_insert__(h, key, datum);
> +
> +       /* Attempt to allocate a bigger table */
> +       newtbl = (avtab_ptr_t*) calloc(sizeof(avtab_ptr_t), h->nslot * 2);
> +       if (newtbl == NULL)
> +               return avtab_insert__(h, key, datum);
> +
> +       /* Reinsert all elements into the new table */
> +       h->nel = 0;
> +       oldsize = h->nslot;
> +       h->nslot *= 2;
> +       h->mask = h->nslot - 1;
> +       oldtbl = h->htable;
> +       h->htable = newtbl;
> +
> +       for (i = 0; i < oldsize; i++) {
> +               cur = oldtbl[i];
> +               while (cur != NULL) {
> +                       avtab_insert(h, &(cur->key), &(cur->datum));
> +                       prev = cur;
> +                       cur = cur->next;
> +                       free (prev);
> +               }
> +       }
> +       free (oldtbl);
> +
> +       return avtab_insert__(h, key, datum);
>  }
>
>  /* Unlike avtab_insert(), this function allow multiple insertions of the same
> diff --git a/src/hashtab.c b/src/hashtab.c
> index c4be72c..e06d808 100644
> --- a/src/hashtab.c
> +++ b/src/hashtab.c
> @@ -63,41 +63,76 @@ hashtab_t hashtab_create(unsigned int (*hash_value) (hashtab_t h,
>        return p;
>  }
>
> -int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
> +int hashtab_insert__(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
>  {
> -       int hvalue;
> -       hashtab_ptr_t prev, cur, newnode;
> +        int hvalue = h->hash_value(h, key);
> +        hashtab_ptr_t prev = NULL;
> +        hashtab_ptr_t cur = h->htable[hvalue];
> +        hashtab_ptr_t newnode;
> +
> +        while (cur && h->keycmp(h, key, cur->key) > 0) {
> +                prev = cur;
> +                cur = cur->next;
> +        }
> +
> +        if (cur && (h->keycmp(h, key, cur->key) == 0))
> +                return SEPOL_EEXIST;
> +
> +        newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
> +        if (newnode == NULL)
> +                return SEPOL_ENOMEM;
> +        memset(newnode, 0, sizeof(struct hashtab_node));
> +        newnode->key = key;
> +        newnode->datum = datum;
> +        if (prev) {
> +                newnode->next = prev->next;
> +                prev->next = newnode;
> +        } else {
> +                newnode->next = h->htable[hvalue];
> +                h->htable[hvalue] = newnode;
> +        }
> +
> +        h->nel++;
> +        return SEPOL_OK;
> +}
>
> +int hashtab_insert(hashtab_t h, hashtab_key_t key, hashtab_datum_t datum)
> +{
> +       hashtab_ptr_t *oldtbl, *newtbl;
> +       int oldsize, i;
> +
>        if (!h)
>                return SEPOL_ENOMEM;
>
> -       hvalue = h->hash_value(h, key);
> -       prev = NULL;
> -       cur = h->htable[hvalue];
> -       while (cur && h->keycmp(h, key, cur->key) > 0) {
> -               prev = cur;
> -               cur = cur->next;
> -       }
> -
> -       if (cur && (h->keycmp(h, key, cur->key) == 0))
> -               return SEPOL_EEXIST;
> -
> -       newnode = (hashtab_ptr_t) malloc(sizeof(hashtab_node_t));
> -       if (newnode == NULL)
> -               return SEPOL_ENOMEM;
> -       memset(newnode, 0, sizeof(struct hashtab_node));
> -       newnode->key = key;
> -       newnode->datum = datum;
> -       if (prev) {
> -               newnode->next = prev->next;
> -               prev->next = newnode;
> -       } else {
> -               newnode->next = h->htable[hvalue];
> -               h->htable[hvalue] = newnode;
> +       /* If we don't need to resize, just insert the new entry */
> +       if (h->size > h->nel)
> +               return hashtab_insert__(h, key, datum);
> +
> +       /* Attempt to allocate a bigger table */
> +       newtbl = (hashtab_ptr_t*) calloc(sizeof(hashtab_ptr_t), h->size * 8);
> +       if (newtbl == NULL)
> +               return hashtab_insert__(h, key, datum);
> +
> +       /* Reinsert all elements into the new table */
> +       oldtbl = h->htable;
> +       oldsize = h->size;
> +       h->nel = 0;
> +       h->size *= 8;
> +       h->htable = newtbl;
> +
> +       for (i = 0; i < oldsize; i++) {
> +               hashtab_ptr_t prev = NULL;
> +               hashtab_ptr_t cur = oldtbl[i];
> +               while (cur != NULL) {
> +                       hashtab_insert__(h, cur->key, cur->datum);
> +                       prev = cur;
> +                       cur = cur->next;
> +                       free(prev);
> +               }
>        }
> +       free(oldtbl);
>
> -       h->nel++;
> -       return SEPOL_OK;
> +       return hashtab_insert__(h, key, datum);
>  }
>
>  int hashtab_remove(hashtab_t h, hashtab_key_t key,
> --
> 1.7.0
>
>


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.


[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux