[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] Optimise memset on i386
From: |
Vladimir 'φ-coder/phcoder' Serbinenko |
Subject: |
Re: [PATCH] Optimise memset on i386 |
Date: |
Wed, 28 Jul 2010 17:21:37 +0300 |
User-agent: |
Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.10) Gecko/20100620 Icedove/3.0.5 |
On 07/23/2010 02:14 PM, Colin Watson wrote:
> On Fri, Jun 25, 2010 at 08:27:20PM +0200, Vladimir 'φ-coder/phcoder'
> Serbinenko wrote:
>
>>> +void *
>>> +grub_memset (void *s, int c, grub_size_t n)
>>> +{
>>> + unsigned char *p = (unsigned char *) s;
>>> +
>>> + while (n--)
>>> + *p++ = (unsigned char) c;
>>> +
>>> + return s;
>>> +}
>>>
>> Attached is a possible generic implementation. Not even compile-tested.
>> Could you test it and compare disasm of this version on i386 and glibc
>> i386 version. Perhaps they are equivalent. If they are for maintainance
>> reasons it's better to always use generic one.
>>
> Thanks for this, and sorry for my delay.
>
> I haven't compared the disassembly, but once I fixed up your code it
> performed within about 10% of the optimised version I posted before, so
> about 640ms original, 160ms with i386-specific memset, and 176ms with
> your generic memset. Even though that isn't quite equivalent, I don't
> think that 16ms is going to be a major problem, and so I would suggest
> going with the generic version. Please check the following.
>
> 2010-07-23 Vladimir Serbinenko <address@hidden>
> 2010-07-23 Colin Watson <address@hidden>
>
> * kern/misc.c (grub_memset): Optimise to reduce cache stalls.
>
>
Go ahead.
> === modified file 'kern/misc.c'
> --- kern/misc.c 2010-07-02 17:35:07 +0000
> +++ kern/misc.c 2010-07-23 11:05:32 +0000
> @@ -518,12 +518,39 @@ grub_strndup (const char *s, grub_size_t
> }
>
> void *
> -grub_memset (void *s, int c, grub_size_t n)
> +grub_memset (void *s, int c, grub_size_t len)
> {
> - unsigned char *p = (unsigned char *) s;
> + void *p = s;
> + grub_uint8_t pattern8 = c;
>
> - while (n--)
> - *p++ = (unsigned char) c;
> + if (len >= 3 * sizeof (unsigned long))
> + {
> + unsigned long patternl = 0;
> + grub_size_t i;
> +
> + for (i = 0; i < sizeof (unsigned long); i++)
> + patternl |= ((unsigned long) pattern8) << (8 * i);
> +
> + while (len > 0 && (((grub_addr_t) p) & (sizeof (unsigned long) - 1)))
> + {
> + *(grub_uint8_t *) p = pattern8;
> + p = (grub_uint8_t *) p + 1;
> + len--;
> + }
> + while (len >= sizeof (unsigned long))
> + {
> + *(unsigned long *) p = patternl;
> + p = (unsigned long *) p + 1;
> + len -= sizeof (unsigned long);
> + }
> + }
> +
> + while (len > 0)
> + {
> + *(grub_uint8_t *) p = pattern8;
> + p = (grub_uint8_t *) p + 1;
> + len--;
> + }
>
> return s;
> }
>
>
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
signature.asc
Description: OpenPGP digital signature