All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Beulich <jbeulich@suse.com>
To: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: "Roger Pau Monné" <roger.pau@citrix.com>, "Wei Liu" <wl@xen.org>,
	"Stefano Stabellini" <sstabellini@kernel.org>,
	"Julien Grall" <julien@xen.org>,
	"Volodymyr Babchuk" <Volodymyr_Babchuk@epam.com>,
	"Bertrand Marquis" <bertrand.marquis@arm.com>,
	Xen-devel <xen-devel@lists.xenproject.org>
Subject: Re: [PATCH 3/5] xen/sort: Switch to an extern inline implementation
Date: Fri, 12 Nov 2021 11:25:52 +0100	[thread overview]
Message-ID: <6672a9ef-5e60-d91d-4f11-78f0d7ca8e5c@suse.com> (raw)
In-Reply-To: <20211111175740.23480-4-andrew.cooper3@citrix.com>

On 11.11.2021 18:57, Andrew Cooper wrote:
> There are exactly 3 callers of sort() in the hypervisor.
> 
> Both arm callers pass in NULL for the swap function.  While this might seem
> like an attractive option at first, it causes generic_swap() to be used which
> forced a byte-wise copy.  Provide real swap functions which the compiler can
> optimise sensibly.
> 
> Furthermore, use of function pointers in tight loops like that can be very bad
> for performance.  Implement sort() as extern inline, so the optimiser can
> judge whether to inline things or not.
> 
> On x86, the diffstat shows how much of a better job the compiler can do when
> it is able to see the cmp/swap implementations.
> 
>   $ ../scripts/bloat-o-meter xen-syms-before xen-syms-after
>   add/remove: 0/5 grow/shrink: 1/1 up/down: 505/-735 (-230)
>   Function                                     old     new   delta
>   sort_exception_table                          31     536    +505
>   u32_swap                                       9       -      -9
>   generic_swap                                  34       -     -34
>   cmp_ex                                        36       -     -36
>   swap_ex                                       41       -     -41
>   sort_exception_tables                         90      38     -52
>   sort                                         563       -    -563
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>

Technically
Reviewed-by: Jan Beulich <jbeulich@suse.com>

Yet again without the intention of overriding Julien's concerns in any
way. To address one of them, how about retaining generic_swap() (as an
inline function), ...

> --- a/xen/include/xen/sort.h
> +++ b/xen/include/xen/sort.h
> @@ -3,8 +3,61 @@
>  
>  #include <xen/types.h>
>  
> +/*
> + * sort - sort an array of elements
> + * @base: pointer to data to sort
> + * @num: number of elements
> + * @size: size of each element
> + * @cmp: pointer to comparison function
> + * @swap: pointer to swap function or NULL
> + *
> + * This function does a heapsort on the given array. You may provide a
> + * swap function optimized to your element type.
> + *
> + * Sorting time is O(n log n) both on average and worst-case. While
> + * qsort is about 20% faster on average, it suffers from exploitable
> + * O(n*n) worst-case behavior and extra memory requirements that make
> + * it less suitable for kernel use.
> + */
> +#ifndef SORT_IMPLEMENTATION
> +extern gnu_inline
> +#endif
>  void sort(void *base, size_t num, size_t size,
>            int (*cmp)(const void *, const void *),
> -          void (*swap)(void *, void *, size_t));
> +          void (*swap)(void *, void *, size_t))
> +{
> +    /* pre-scale counters for performance */
> +    size_t i = (num / 2) * size, n = num * size, c, r;
> +
> +    /* heapify */
> +    while ( i > 0 )
> +    {
> +        for ( r = i -= size; r * 2 + size < n; r = c )
> +        {
> +            c = r * 2 + size;
> +            if ( (c < n - size) && (cmp(base + c, base + c + size) < 0) )
> +                c += size;
> +            if ( cmp(base + r, base + c) >= 0 )
> +                break;
> +            swap(base + r, base + c, size);

... doing

            if ( swap )
                swap(base + r, base + c, size);
            else
                generic_swap(base + r, base + c, size);

here and below. The compiler would then still be able to eliminate the
indirect calls (as well as the added conditional), I think.

Jan



  parent reply	other threads:[~2021-11-12 10:26 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-11 17:57 [PATCH 0/5] xen: various function pointer cleanups Andrew Cooper
2021-11-11 17:57 ` [PATCH 1/5] xen/domain: Remove function pointers from domain pause helpers Andrew Cooper
2021-11-12  9:36   ` Julien Grall
2021-11-18  1:47     ` Andrew Cooper
2021-11-18  9:28       ` Julien Grall
2021-11-12  9:57   ` Jan Beulich
2021-11-17 23:31     ` Andrew Cooper
2021-11-15 10:13   ` Bertrand Marquis
2021-11-15 10:20     ` Jan Beulich
2021-11-15 10:23       ` Bertrand Marquis
2021-11-15 10:55         ` Jan Beulich
2021-11-15 11:23           ` Bertrand Marquis
2021-11-15 14:11             ` Julien Grall
2021-11-15 14:45               ` Bertrand Marquis
2021-11-16  0:41           ` Stefano Stabellini
2021-11-16  7:15             ` Jan Beulich
2021-11-11 17:57 ` [PATCH 2/5] xen/domain: Improve pirq handling Andrew Cooper
2021-11-12 10:16   ` Jan Beulich
2021-11-11 17:57 ` [PATCH 3/5] xen/sort: Switch to an extern inline implementation Andrew Cooper
2021-11-11 18:15   ` Julien Grall
2021-11-16  0:36     ` Stefano Stabellini
2021-11-16  0:41       ` Andrew Cooper
2021-12-17 15:56         ` Andrew Cooper
2021-12-17 16:15           ` Julien Grall
2021-11-12  9:39   ` Julien Grall
2021-11-12 10:25   ` Jan Beulich [this message]
2021-11-11 17:57 ` [PATCH 4/5] xen/wait: Remove indirect jump Andrew Cooper
2021-11-12 10:35   ` Jan Beulich
2021-11-11 17:57 ` [PATCH 5/5] x86/ioapic: Drop function pointers from __ioapic_{read,write}_entry() Andrew Cooper
2021-11-12 10:43   ` Jan Beulich
2021-11-18  0:32     ` Andrew Cooper
2021-11-18  9:06       ` Jan Beulich
2021-11-18  9:07         ` Jan Beulich
2021-11-18 17:33           ` Andrew Cooper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6672a9ef-5e60-d91d-4f11-78f0d7ca8e5c@suse.com \
    --to=jbeulich@suse.com \
    --cc=Volodymyr_Babchuk@epam.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=bertrand.marquis@arm.com \
    --cc=julien@xen.org \
    --cc=roger.pau@citrix.com \
    --cc=sstabellini@kernel.org \
    --cc=wl@xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.