Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tue, 2005-01-25 at 20:33, Trond Myklebust wrote:
> ty den 25.01.2005 Klokka 19:12 (+0100) skreiv Andreas Gruenbacher:
> 
> > Ah, I see now what you mean. The setxattr syscall only accepts
> > well-formed acls (that is, sorted plus a few other restrictions), and
> > user-space is expected to take care of that. In turn, getxattr returns
> > only well-formed acls. We could lift that guarantee specifically for
> > nfs, but I don't think it would be a good idea.
> 
> Note that if you really want to add a qsort to the kernel you might as
> well drop the setxattr sorting requirement too. If the kernel can qsort
> for getxattr, then might as well do it for the case of setxattr too.

There is no need to sort anything in the kernel for acls except for the
NFSACL case, so that's where we need it, and nowhere else. What would be
the point in making setxattr accept unsorted acls? It's just not
necessary; userspace can do it just as well.

> > Entry order in POSIX acls doesn't convey a meaning by the way.
> 
> Precisely. Are there really any existing programs out there that are
> using the raw xattr output and making assumptions about entry order?

I don't know. Anyway, it's a nice feature to have a unique canonical
form.

> > The server must have sorted lists.
> 
> So, I realize that the on-disk format is already defined, but looking at
> routines like posix_acl_permission(), it looks like the only order the
> kernel (at least) actually cares about is that of the "e_tag" field.
> Unless I missed something, nothing there cares about the order of the
> "e_id" fields.

Correct. But posix_acl_valid() does care about the i_id order as well.

> Given that you only have 6 possible values there, it seems a shame in
> hindsight that we didn't choose to just use a 6 bucket hashtable (the
> value of e_id being the hash value), and leave the order of the e_id
> fields undefined. 8-(

Checking for duplicate e_id fields would become expensive. I really
don't see any benefit.

Cheers,
-- 
Andreas Gruenbacher <[EMAIL PROTECTED]>
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Trond Myklebust
ty den 25.01.2005 Klokka 19:12 (+0100) skreiv Andreas Gruenbacher:

> Ah, I see now what you mean. The setxattr syscall only accepts
> well-formed acls (that is, sorted plus a few other restrictions), and
> user-space is expected to take care of that. In turn, getxattr returns
> only well-formed acls. We could lift that guarantee specifically for
> nfs, but I don't think it would be a good idea.

Note that if you really want to add a qsort to the kernel you might as
well drop the setxattr sorting requirement too. If the kernel can qsort
for getxattr, then might as well do it for the case of setxattr too.

> Entry order in POSIX acls doesn't convey a meaning by the way.

Precisely. Are there really any existing programs out there that are
using the raw xattr output and making assumptions about entry order?

> The server must have sorted lists.

So, I realize that the on-disk format is already defined, but looking at
routines like posix_acl_permission(), it looks like the only order the
kernel (at least) actually cares about is that of the "e_tag" field.
Unless I missed something, nothing there cares about the order of the
"e_id" fields.
Given that you only have 6 possible values there, it seems a shame in
hindsight that we didn't choose to just use a 6 bucket hashtable (the
value of e_id being the hash value), and leave the order of the e_id
fields undefined. 8-(

Cheers,
  Trond


-- 
Trond Myklebust <[EMAIL PROTECTED]>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tue, 2005-01-25 at 18:37, Trond Myklebust wrote:
> ty den 25.01.2005 Klokka 18:16 (+0100) skreiv Andreas Gruenbacher:
> 
> > > Whatever Sun chooses to do or not do changes nothing to the question of
> > > why our client would want to do a quicksort in the kernel.
> > 
> > Well, it determines what we must accept, both on the server side and the
> > client side.
> 
> I can see why you might want it on the server side, but I repeat: why
> does the client need to do this in the kernel? The client code should
> not be overriding the server when it comes to what is acceptable or not
> acceptable. That's just wrong...

Ah, I see now what you mean. The setxattr syscall only accepts
well-formed acls (that is, sorted plus a few other restrictions), and
user-space is expected to take care of that. In turn, getxattr returns
only well-formed acls. We could lift that guarantee specifically for
nfs, but I don't think it would be a good idea. Entry order in POSIX
acls doesn't convey a meaning by the way, and the nfs client never
rejects what the server sends.

> I can also see that if the server _must_ have a sorted list, then doing
> a sort on the client is a good thing since it will cut down on the work
> that said server will need to do, and so it will scale better with the
> number of clients (though note that, conversely, this server will scale
> poorly with the Sun clients or others if they do not sort the lists).

The server must have sorted lists. Linux clients send well-formed acls
except when they fake up a mask entry; they insert the mask entry at the
end instead of in the right position (this is the three-entry acl
problem I described in [patch 0/13]). We could insert the mask in the
right position, but the protocol doesn't require it. We must sort on the
server anyway, and the server can as easily swap the two entries.

> I'm asking 'cos if the client doesn't need this code, then it seems to
> me you can move helper routines like the quicksort and posix checking
> routines into the nfsd module rather than having to keeping it in the
> VFS (unless you foresee that other modules will want to use the same
> routines???).

That would cause getxattr to return an "invalid" result. libacl doesn't
care, but other users might exist that rely on the current format. In
addition, comparing acls becomes non-trivial: currently xattr values are
equal iff acls are equal.

Cheers,
-- 
Andreas Gruenbacher <[EMAIL PROTECTED]>
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Trond Myklebust
ty den 25.01.2005 Klokka 18:16 (+0100) skreiv Andreas Gruenbacher:

> > Whatever Sun chooses to do or not do changes nothing to the question of
> > why our client would want to do a quicksort in the kernel.
> 
> Well, it determines what we must accept, both on the server side and the
> client side.

I can see why you might want it on the server side, but I repeat: why
does the client need to do this in the kernel? The client code should
not be overriding the server when it comes to what is acceptable or not
acceptable. That's just wrong...

I can also see that if the server _must_ have a sorted list, then doing
a sort on the client is a good thing since it will cut down on the work
that said server will need to do, and so it will scale better with the
number of clients (though note that, conversely, this server will scale
poorly with the Sun clients or others if they do not sort the lists).

I'm asking 'cos if the client doesn't need this code, then it seems to
me you can move helper routines like the quicksort and posix checking
routines into the nfsd module rather than having to keeping it in the
VFS (unless you foresee that other modules will want to use the same
routines???).

Cheers,
 Trond
-- 
Trond Myklebust <[EMAIL PROTECTED]>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tue, 2005-01-25 at 18:03, Trond Myklebust wrote:
> ty den 25.01.2005 Klokka 17:53 (+0100) skreiv Andreas Gruenbacher:
> > On Tue, 2005-01-25 at 17:52, Trond Myklebust wrote:
> > > So here's an iconoclastic question or two:
> > > 
> > >   Why can't clients sort the list in userland, before they call down to
> > > the kernel?
> > 
> > Tell that to Sun Microsystems.
> 
> Whatever Sun chooses to do or not do changes nothing to the question of
> why our client would want to do a quicksort in the kernel.

Well, it determines what we must accept, both on the server side and the
client side.

Cheers,
-- 
Andreas Gruenbacher <[EMAIL PROTECTED]>
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Trond Myklebust
ty den 25.01.2005 Klokka 17:53 (+0100) skreiv Andreas Gruenbacher:
> On Tue, 2005-01-25 at 17:52, Trond Myklebust wrote:
> > So here's an iconoclastic question or two:
> > 
> >   Why can't clients sort the list in userland, before they call down to
> > the kernel?
> 
> Tell that to Sun Microsystems.

Whatever Sun chooses to do or not do changes nothing to the question of
why our client would want to do a quicksort in the kernel.

Cheers,
  Trond
-- 
Trond Myklebust <[EMAIL PROTECTED]>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tue, 2005-01-25 at 17:52, Trond Myklebust wrote:
> So here's an iconoclastic question or two:
> 
>   Why can't clients sort the list in userland, before they call down to
> the kernel?

Tell that to Sun Microsystems.

Regards,
-- 
Andreas Gruenbacher <[EMAIL PROTECTED]>
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Trond Myklebust
ty den 25.01.2005 Klokka 13:05 (+0100) skreiv Olaf Kirch:
> On Tue, Jan 25, 2005 at 01:00:23PM +0100, Andi Kleen wrote:
> > group initialization is not time critical, it typically only happens
> > at login.  Also it's doubleful you'll even be able to measure the 
> > difference.
> 
> nfsd updates its group list for every request it processes, so you don't want
> to make that too slow.

So here's an iconoclastic question or two:

  Why can't clients sort the list in userland, before they call down to
the kernel?

  If clients are sorting their lists, why would we need to sort the same
list on the server side. Detecting out-of-order list entries is much
less of a hassle than actually sorting, so if the protocol calls for
sorted elements, you can return an EINVAL or something in the case where
some client sends an unsorted list.

Cheers,
  Trond

-- 
Trond Myklebust <[EMAIL PROTECTED]>

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Olaf Kirch
On Tue, Jan 25, 2005 at 01:00:23PM +0100, Andi Kleen wrote:
> group initialization is not time critical, it typically only happens
> at login.  Also it's doubleful you'll even be able to measure the difference.

nfsd updates its group list for every request it processes, so you don't want
to make that too slow.

Olaf
-- 
Olaf Kirch | Things that make Monday morning interesting, #2:
[EMAIL PROTECTED]   |"We have 8,000 NFS mount points, why do we keep
---+ running out of privileged ports?"
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andi Kleen
> It would slow down the groups case (unless we leave the specialized version 
> in). Gcc doesn't inline a cmp function pointer, and a C preprocessor 
> templatized version would be really ugly. A variant with of this routine with 
> qsort like interface should be good enough for nfsacl and xfs though.

group initialization is not time critical, it typically only happens
at login.  Also it's doubleful you'll even be able to measure the difference.

-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tuesday 25 January 2005 07:51, Andi Kleen wrote:
> > FWIW, we already have a Shell sort for the ngroups stuff in
> > kernel/sys.c:groups_sort() that could be made generic.
>
> Sounds like a good plan. Any takers?

It would slow down the groups case (unless we leave the specialized version 
in). Gcc doesn't inline a cmp function pointer, and a C preprocessor 
templatized version would be really ugly. A variant with of this routine with 
qsort like interface should be good enough for nfsacl and xfs though.

Nevertheless, xfs and nfsacl have very similar requirements:

nfsacl: at most 1024 elements; 8-byte elements (16 on 64-bit archs)

xfs (from Nathan): at most 1024 elements (with 64K blocksize); 8-byte or 
larger elements

Cheers.
-- 
Andreas Gruenbacher <[EMAIL PROTECTED]>
SUSE Labs, SUSE LINUX PRODUCTS GMBH
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tuesday 25 January 2005 07:51, Andi Kleen wrote:
  FWIW, we already have a Shell sort for the ngroups stuff in
  kernel/sys.c:groups_sort() that could be made generic.

 Sounds like a good plan. Any takers?

It would slow down the groups case (unless we leave the specialized version 
in). Gcc doesn't inline a cmp function pointer, and a C preprocessor 
templatized version would be really ugly. A variant with of this routine with 
qsort like interface should be good enough for nfsacl and xfs though.

Nevertheless, xfs and nfsacl have very similar requirements:

nfsacl: at most 1024 elements; 8-byte elements (16 on 64-bit archs)

xfs (from Nathan): at most 1024 elements (with 64K blocksize); 8-byte or 
larger elements

Cheers.
-- 
Andreas Gruenbacher [EMAIL PROTECTED]
SUSE Labs, SUSE LINUX PRODUCTS GMBH
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andi Kleen
 It would slow down the groups case (unless we leave the specialized version 
 in). Gcc doesn't inline a cmp function pointer, and a C preprocessor 
 templatized version would be really ugly. A variant with of this routine with 
 qsort like interface should be good enough for nfsacl and xfs though.

group initialization is not time critical, it typically only happens
at login.  Also it's doubleful you'll even be able to measure the difference.

-Andi
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Olaf Kirch
On Tue, Jan 25, 2005 at 01:00:23PM +0100, Andi Kleen wrote:
 group initialization is not time critical, it typically only happens
 at login.  Also it's doubleful you'll even be able to measure the difference.

nfsd updates its group list for every request it processes, so you don't want
to make that too slow.

Olaf
-- 
Olaf Kirch | Things that make Monday morning interesting, #2:
[EMAIL PROTECTED]   |We have 8,000 NFS mount points, why do we keep
---+ running out of privileged ports?
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Trond Myklebust
ty den 25.01.2005 Klokka 13:05 (+0100) skreiv Olaf Kirch:
 On Tue, Jan 25, 2005 at 01:00:23PM +0100, Andi Kleen wrote:
  group initialization is not time critical, it typically only happens
  at login.  Also it's doubleful you'll even be able to measure the 
  difference.
 
 nfsd updates its group list for every request it processes, so you don't want
 to make that too slow.

So here's an iconoclastic question or two:

  Why can't clients sort the list in userland, before they call down to
the kernel?

  If clients are sorting their lists, why would we need to sort the same
list on the server side. Detecting out-of-order list entries is much
less of a hassle than actually sorting, so if the protocol calls for
sorted elements, you can return an EINVAL or something in the case where
some client sends an unsorted list.

Cheers,
  Trond

-- 
Trond Myklebust [EMAIL PROTECTED]

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tue, 2005-01-25 at 17:52, Trond Myklebust wrote:
 So here's an iconoclastic question or two:
 
   Why can't clients sort the list in userland, before they call down to
 the kernel?

Tell that to Sun Microsystems.

Regards,
-- 
Andreas Gruenbacher [EMAIL PROTECTED]
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Trond Myklebust
ty den 25.01.2005 Klokka 17:53 (+0100) skreiv Andreas Gruenbacher:
 On Tue, 2005-01-25 at 17:52, Trond Myklebust wrote:
  So here's an iconoclastic question or two:
  
Why can't clients sort the list in userland, before they call down to
  the kernel?
 
 Tell that to Sun Microsystems.

Whatever Sun chooses to do or not do changes nothing to the question of
why our client would want to do a quicksort in the kernel.

Cheers,
  Trond
-- 
Trond Myklebust [EMAIL PROTECTED]

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tue, 2005-01-25 at 18:03, Trond Myklebust wrote:
 ty den 25.01.2005 Klokka 17:53 (+0100) skreiv Andreas Gruenbacher:
  On Tue, 2005-01-25 at 17:52, Trond Myklebust wrote:
   So here's an iconoclastic question or two:
   
 Why can't clients sort the list in userland, before they call down to
   the kernel?
  
  Tell that to Sun Microsystems.
 
 Whatever Sun chooses to do or not do changes nothing to the question of
 why our client would want to do a quicksort in the kernel.

Well, it determines what we must accept, both on the server side and the
client side.

Cheers,
-- 
Andreas Gruenbacher [EMAIL PROTECTED]
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Trond Myklebust
ty den 25.01.2005 Klokka 18:16 (+0100) skreiv Andreas Gruenbacher:

  Whatever Sun chooses to do or not do changes nothing to the question of
  why our client would want to do a quicksort in the kernel.
 
 Well, it determines what we must accept, both on the server side and the
 client side.

I can see why you might want it on the server side, but I repeat: why
does the client need to do this in the kernel? The client code should
not be overriding the server when it comes to what is acceptable or not
acceptable. That's just wrong...

I can also see that if the server _must_ have a sorted list, then doing
a sort on the client is a good thing since it will cut down on the work
that said server will need to do, and so it will scale better with the
number of clients (though note that, conversely, this server will scale
poorly with the Sun clients or others if they do not sort the lists).

I'm asking 'cos if the client doesn't need this code, then it seems to
me you can move helper routines like the quicksort and posix checking
routines into the nfsd module rather than having to keeping it in the
VFS (unless you foresee that other modules will want to use the same
routines???).

Cheers,
 Trond
-- 
Trond Myklebust [EMAIL PROTECTED]

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tue, 2005-01-25 at 18:37, Trond Myklebust wrote:
 ty den 25.01.2005 Klokka 18:16 (+0100) skreiv Andreas Gruenbacher:
 
   Whatever Sun chooses to do or not do changes nothing to the question of
   why our client would want to do a quicksort in the kernel.
  
  Well, it determines what we must accept, both on the server side and the
  client side.
 
 I can see why you might want it on the server side, but I repeat: why
 does the client need to do this in the kernel? The client code should
 not be overriding the server when it comes to what is acceptable or not
 acceptable. That's just wrong...

Ah, I see now what you mean. The setxattr syscall only accepts
well-formed acls (that is, sorted plus a few other restrictions), and
user-space is expected to take care of that. In turn, getxattr returns
only well-formed acls. We could lift that guarantee specifically for
nfs, but I don't think it would be a good idea. Entry order in POSIX
acls doesn't convey a meaning by the way, and the nfs client never
rejects what the server sends.

 I can also see that if the server _must_ have a sorted list, then doing
 a sort on the client is a good thing since it will cut down on the work
 that said server will need to do, and so it will scale better with the
 number of clients (though note that, conversely, this server will scale
 poorly with the Sun clients or others if they do not sort the lists).

The server must have sorted lists. Linux clients send well-formed acls
except when they fake up a mask entry; they insert the mask entry at the
end instead of in the right position (this is the three-entry acl
problem I described in [patch 0/13]). We could insert the mask in the
right position, but the protocol doesn't require it. We must sort on the
server anyway, and the server can as easily swap the two entries.

 I'm asking 'cos if the client doesn't need this code, then it seems to
 me you can move helper routines like the quicksort and posix checking
 routines into the nfsd module rather than having to keeping it in the
 VFS (unless you foresee that other modules will want to use the same
 routines???).

That would cause getxattr to return an invalid result. libacl doesn't
care, but other users might exist that rely on the current format. In
addition, comparing acls becomes non-trivial: currently xattr values are
equal iff acls are equal.

Cheers,
-- 
Andreas Gruenbacher [EMAIL PROTECTED]
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Trond Myklebust
ty den 25.01.2005 Klokka 19:12 (+0100) skreiv Andreas Gruenbacher:

 Ah, I see now what you mean. The setxattr syscall only accepts
 well-formed acls (that is, sorted plus a few other restrictions), and
 user-space is expected to take care of that. In turn, getxattr returns
 only well-formed acls. We could lift that guarantee specifically for
 nfs, but I don't think it would be a good idea.

Note that if you really want to add a qsort to the kernel you might as
well drop the setxattr sorting requirement too. If the kernel can qsort
for getxattr, then might as well do it for the case of setxattr too.

 Entry order in POSIX acls doesn't convey a meaning by the way.

Precisely. Are there really any existing programs out there that are
using the raw xattr output and making assumptions about entry order?

 The server must have sorted lists.

So, I realize that the on-disk format is already defined, but looking at
routines like posix_acl_permission(), it looks like the only order the
kernel (at least) actually cares about is that of the e_tag field.
Unless I missed something, nothing there cares about the order of the
e_id fields.
Given that you only have 6 possible values there, it seems a shame in
hindsight that we didn't choose to just use a 6 bucket hashtable (the
value of e_id being the hash value), and leave the order of the e_id
fields undefined. 8-(

Cheers,
  Trond


-- 
Trond Myklebust [EMAIL PROTECTED]

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-25 Thread Andreas Gruenbacher
On Tue, 2005-01-25 at 20:33, Trond Myklebust wrote:
 ty den 25.01.2005 Klokka 19:12 (+0100) skreiv Andreas Gruenbacher:
 
  Ah, I see now what you mean. The setxattr syscall only accepts
  well-formed acls (that is, sorted plus a few other restrictions), and
  user-space is expected to take care of that. In turn, getxattr returns
  only well-formed acls. We could lift that guarantee specifically for
  nfs, but I don't think it would be a good idea.
 
 Note that if you really want to add a qsort to the kernel you might as
 well drop the setxattr sorting requirement too. If the kernel can qsort
 for getxattr, then might as well do it for the case of setxattr too.

There is no need to sort anything in the kernel for acls except for the
NFSACL case, so that's where we need it, and nowhere else. What would be
the point in making setxattr accept unsorted acls? It's just not
necessary; userspace can do it just as well.

  Entry order in POSIX acls doesn't convey a meaning by the way.
 
 Precisely. Are there really any existing programs out there that are
 using the raw xattr output and making assumptions about entry order?

I don't know. Anyway, it's a nice feature to have a unique canonical
form.

  The server must have sorted lists.
 
 So, I realize that the on-disk format is already defined, but looking at
 routines like posix_acl_permission(), it looks like the only order the
 kernel (at least) actually cares about is that of the e_tag field.
 Unless I missed something, nothing there cares about the order of the
 e_id fields.

Correct. But posix_acl_valid() does care about the i_id order as well.

 Given that you only have 6 possible values there, it seems a shame in
 hindsight that we didn't choose to just use a 6 bucket hashtable (the
 value of e_id being the hash value), and leave the order of the e_id
 fields undefined. 8-(

Checking for duplicate e_id fields would become expensive. I really
don't see any benefit.

Cheers,
-- 
Andreas Gruenbacher [EMAIL PROTECTED]
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Andi Kleen
> FWIW, we already have a Shell sort for the ngroups stuff in
> kernel/sys.c:groups_sort() that could be made generic.

Sounds like a good plan. Any takers?

-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Eric St-Laurent
On Mon, 2005-01-24 at 21:43 -0300, Horst von Brand wrote:
> AFAICS, this is just a badly implemented Shellsort (the 10/13 increment
> sequence starting with the number of elements is probably not very good,
> besides swapping stuff is inefficient (just juggling like Shellsort does
> gives you almost a third less copies)).
> 
> Have you found a proof for the O(n log n) claim?

"Why a Comb Sort is NOT a Shell Sort

A shell sort completely sorts the data for each gap size. A comb sort
takes a more optimistic approach and doesn't require data be completely
sorted at a gap size. The comb sort assumes that out-of-order data will
be cleaned-up by smaller gap sizes as the sort proceeds. "

Reference:

http://world.std.com/~jdveale/combsort.htm

Another good reference:

http://yagni.com/combsort/index.php

Personally, i've used it in the past because of it's small size.  With
C++ templates you can have a copy of the routine generated for a
specific datatype, thus skipping the costly function call used for each
compare.  With some C macro magic, i presume something similar can be
done, for time-critical applications.

Best regards,

Eric St-Laurent


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Horst von Brand
[EMAIL PROTECTED] (H. Peter Anvin) said:

[...]

> In klibc, I use combsort:
> 
> /*
>  * qsort.c
>  *
>  * This is actually combsort.  It's an O(n log n) algorithm with
>  * simplicity/small code size being its main virtue.
>  */
> 
> #include 
> #include 
> 
> static inline size_t newgap(size_t gap)
> {
>   gap = (gap*10)/13;
>   if ( gap == 9 || gap == 10 )
> gap = 11;
> 
>   if ( gap < 1 )
> gap = 1;
>   return gap;
> }
> 
> void qsort(void *base, size_t nmemb, size_t size,
>int (*compar)(const void *, const void *))
> {
>   size_t gap = nmemb;
>   size_t i, j;
>   char *p1, *p2;
>   int swapped;
> 
>   do {
> gap = newgap(gap);
> swapped = 0;
> 
> for ( i = 0, p1 = base ; i < nmemb-gap ; i++, p1 += size ) {
>   j = i+gap;
>   if ( compar(p1, p2 = (char *)base+j*size) > 0 ) {
> memswap(p1, p2, size);
> swapped = 1;
>   }
> }
>   } while ( gap > 1 || swapped );
> }

AFAICS, this is just a badly implemented Shellsort (the 10/13 increment
sequence starting with the number of elements is probably not very good,
besides swapping stuff is inefficient (just juggling like Shellsort does
gives you almost a third less copies)).

Have you found a proof for the O(n log n) claim?

I'd write as attached (careful, a local element on stack!)

/*
 * shellsort.c: Shell sort
 *
 * Copyright (c) 2005, Horst H. von Brand <[EMAIL PROTECTED]>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 * * Neither the name of Horst H. von Brand nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include 

void qsort(void *base, size_t nmemb, size_t size, 
   int (*compar)(const void *, const void *))

{
  int i, j, h;
  char tmp[size];

  for(h = 1; h < nmemb; h = 3 * h + 1)
;

  do {
h /= 3;
for(i = h; i < nmemb; i++) {
  memcpy(tmp, base + i * size, size);
  for(j = i - h; j >= 0 && compar(tmp, base + j * size); j -= h)
	memcpy(base + (j + h) * size, base + j * size, size);
  memcpy(base + (j + h) * size, tmp, size);
}
  } while(h > 1);
}
-- 
Dr. Horst H. von Brand   User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria  +56 32 654239
Casilla 110-V, Valparaiso, ChileFax:  +56 32 797513


Re: [patch 1/13] Qsort

2005-01-24 Thread Mike Waychison
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Andi Kleen wrote:
>>How about a shell sort?  if the data is mostly sorted shell sort beats 
>>qsort lots of times, and since the data sets are often small in-kernel, 
>>shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
>>faster if the data is already completely sorted. Shell sort is certainly 
>>not the simplest algorithm around, but I think (without having done any 
>>tests) that it would probably do pretty well for in-kernel use... Then 
>>again, I've known to be wrong :)
> 
> 
> I like shell sort for small data sets too. And I agree it would be 
> appropiate for the kernel.
> 

FWIW, we already have a Shell sort for the ngroups stuff in
kernel/sys.c:groups_sort() that could be made generic.

- --
Mike Waychison
Sun Microsystems, Inc.
1 (650) 352-5299 voice
1 (416) 202-8336 voice

~~
NOTICE:  The opinions expressed in this email are held by me,
and may not represent the views of Sun Microsystems, Inc.
~~
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.2.5 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFB9XDzdQs4kOxk3/MRAs2ZAJ4if1XRFAiWsgb1wvTInFLUVGHesgCfWxCJ
Efyrr4PkG/KrqefAVAQjt+c=
=/OPh
-END PGP SIGNATURE-
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Matt Mackall
On Mon, Jan 24, 2005 at 01:02:44AM -0300, Horst von Brand wrote:
> Matt Mackall <[EMAIL PROTECTED]> said:
> > On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:
> 
> [...]
> 
> > > -Andi (who thinks the glibc qsort is vast overkill for kernel purposes
> > > where there are only small data sets and it would be better to use a 
> > > simpler one optimized for code size)
> 
> > Mostly agreed. Except:
> > 
> > a) the glibc version is not actually all that optimized
> > b) it's nice that it's not recursive
> > c) the three-way median selection does help avoid worst-case O(n^2)
> > behavior, which might potentially be triggerable by users in places
> > like XFS where this is used
> 
> Shellsort is much simpler, and not much slower for small datasets. Plus no
> extra space for stacks.
> 
> > I'll probably whip up a simpler version tomorrow or Monday and do some
> > size/space benchmarking. I've been meaning to contribute a qsort for
> > doubly-linked lists I've got lying around as well.
> 
> Qsort is OK as long as you have direct access to each element. In case of
> lists, it is better to just use mergesort.

Qsort does not need to do random access. I posted an efficient
doubly-linked list version here four years ago:

template
void list::qsort(iter l, iter r, cmpfunc *cmp, void *data)
{
if(l==r) return;

iter i(l), p(l);

for(i++; i!=r; i++)
if(cmp(*i, *l, data)<0)
i.swap(++p);

l.swap(p);
qsort(l, p, cmp, data);
qsort(++p, r, cmp, data);
}

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread vlobanov
On Mon, 24 Jan 2005, Matt Mackall wrote:

> On Sun, Jan 23, 2005 at 05:58:00AM +0100, Felipe Alfaro Solana wrote:
> > On 23 Jan 2005, at 03:39, Andi Kleen wrote:
> >
> > >Felipe Alfaro Solana <[EMAIL PROTECTED]> writes:
> > >>
> > >>AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
> > >>operatings. Also, since the original patch uses 3 MOVs to perform the
> > >>swapping, and your version uses 3 XOR operations, I don't see any
> > >>gains.
> > >
> > >Both are one cycle latency for register<->register on all x86 cores
> > >I've looked at. What makes you think differently?
> >
> > I thought XOR was more expensie. Anyways, I still don't see any
> > advantage in replacing 3 MOVs with 3 XORs.
>
> Again, no temporaries needed.
>
> But I benched it and it was quite a bit slower.
>
> --
> Mathematics is the supreme nostalgia of our time.

Yep, it's a difference of four instructions (when using one or two
temporary variables and swapping using assignments) versus six
instructions (when using xors, since IA32 can't do an xor with both
arguments in memory).

I originally pitched this idea out to the list just for discussion
purposes. Most considered it, and said that the advantages don't
outweigh the disadvantages. And that's fine -- it means that the chosen
way is that much better considered. Always a good thing. :)

-Vadim Lobanov

> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [EMAIL PROTECTED]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Matt Mackall
On Sun, Jan 23, 2005 at 05:58:00AM +0100, Felipe Alfaro Solana wrote:
> On 23 Jan 2005, at 03:39, Andi Kleen wrote:
> 
> >Felipe Alfaro Solana <[EMAIL PROTECTED]> writes:
> >>
> >>AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
> >>operatings. Also, since the original patch uses 3 MOVs to perform the
> >>swapping, and your version uses 3 XOR operations, I don't see any
> >>gains.
> >
> >Both are one cycle latency for register<->register on all x86 cores
> >I've looked at. What makes you think differently?
> 
> I thought XOR was more expensie. Anyways, I still don't see any 
> advantage in replacing 3 MOVs with 3 XORs.

Again, no temporaries needed.

But I benched it and it was quite a bit slower.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread H. Peter Anvin
Followup to:  <[EMAIL PROTECTED]>
By author:Jesper Juhl <[EMAIL PROTECTED]>
In newsgroup: linux.dev.kernel
>
> On Sun, 23 Jan 2005, Andi Kleen wrote:
> 
> > > How about a shell sort?  if the data is mostly sorted shell sort beats 
> > > qsort lots of times, and since the data sets are often small in-kernel, 
> > > shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
> > > faster if the data is already completely sorted. Shell sort is certainly 
> > > not the simplest algorithm around, but I think (without having done any 
> > > tests) that it would probably do pretty well for in-kernel use... Then 
> > > again, I've known to be wrong :)
> > 
> > I like shell sort for small data sets too. And I agree it would be 
> > appropiate for the kernel.
> > 
> Even with large data sets that are mostly unsorted shell sorts performance 
> is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
> runtime (IIRC), and another nice property is that it's iterative so it 
> doesn't eat up stack space (as oposed to qsort which is recursive and eats 
> stack like )...
> Yeah, I think shell sort would be good for the kernel.
> 

In klibc, I use combsort:

/*
 * qsort.c
 *
 * This is actually combsort.  It's an O(n log n) algorithm with
 * simplicity/small code size being its main virtue.
 */

#include 
#include 

static inline size_t newgap(size_t gap)
{
  gap = (gap*10)/13;
  if ( gap == 9 || gap == 10 )
gap = 11;

  if ( gap < 1 )
gap = 1;
  return gap;
}

void qsort(void *base, size_t nmemb, size_t size,
   int (*compar)(const void *, const void *))
{
  size_t gap = nmemb;
  size_t i, j;
  char *p1, *p2;
  int swapped;

  do {
gap = newgap(gap);
swapped = 0;

for ( i = 0, p1 = base ; i < nmemb-gap ; i++, p1 += size ) {
  j = i+gap;
  if ( compar(p1, p2 = (char *)base+j*size) > 0 ) {
memswap(p1, p2, size);
swapped = 1;
  }
}
  } while ( gap > 1 || swapped );
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Alan Cox
On Sul, 2005-01-23 at 05:05, Jesper Juhl wrote:
> On Sun, 23 Jan 2005, Andi Kleen wrote:
> Even with large data sets that are mostly unsorted shell sorts performance 
> is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
> runtime (IIRC), and another nice property is that it's iterative so it 
> doesn't eat up stack space (as oposed to qsort which is recursive and eats 
> stack like )...

qsort also has bad worst case performance which matters if you are
sorting data provided by a hostile source.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Alan Cox
On Sul, 2005-01-23 at 05:05, Jesper Juhl wrote:
 On Sun, 23 Jan 2005, Andi Kleen wrote:
 Even with large data sets that are mostly unsorted shell sorts performance 
 is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
 runtime (IIRC), and another nice property is that it's iterative so it 
 doesn't eat up stack space (as oposed to qsort which is recursive and eats 
 stack like )...

qsort also has bad worst case performance which matters if you are
sorting data provided by a hostile source.

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread H. Peter Anvin
Followup to:  [EMAIL PROTECTED]
By author:Jesper Juhl [EMAIL PROTECTED]
In newsgroup: linux.dev.kernel

 On Sun, 23 Jan 2005, Andi Kleen wrote:
 
   How about a shell sort?  if the data is mostly sorted shell sort beats 
   qsort lots of times, and since the data sets are often small in-kernel, 
   shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
   faster if the data is already completely sorted. Shell sort is certainly 
   not the simplest algorithm around, but I think (without having done any 
   tests) that it would probably do pretty well for in-kernel use... Then 
   again, I've known to be wrong :)
  
  I like shell sort for small data sets too. And I agree it would be 
  appropiate for the kernel.
  
 Even with large data sets that are mostly unsorted shell sorts performance 
 is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
 runtime (IIRC), and another nice property is that it's iterative so it 
 doesn't eat up stack space (as oposed to qsort which is recursive and eats 
 stack like )...
 Yeah, I think shell sort would be good for the kernel.
 

In klibc, I use combsort:

/*
 * qsort.c
 *
 * This is actually combsort.  It's an O(n log n) algorithm with
 * simplicity/small code size being its main virtue.
 */

#include stddef.h
#include string.h

static inline size_t newgap(size_t gap)
{
  gap = (gap*10)/13;
  if ( gap == 9 || gap == 10 )
gap = 11;

  if ( gap  1 )
gap = 1;
  return gap;
}

void qsort(void *base, size_t nmemb, size_t size,
   int (*compar)(const void *, const void *))
{
  size_t gap = nmemb;
  size_t i, j;
  char *p1, *p2;
  int swapped;

  do {
gap = newgap(gap);
swapped = 0;

for ( i = 0, p1 = base ; i  nmemb-gap ; i++, p1 += size ) {
  j = i+gap;
  if ( compar(p1, p2 = (char *)base+j*size)  0 ) {
memswap(p1, p2, size);
swapped = 1;
  }
}
  } while ( gap  1 || swapped );
}
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Matt Mackall
On Sun, Jan 23, 2005 at 05:58:00AM +0100, Felipe Alfaro Solana wrote:
 On 23 Jan 2005, at 03:39, Andi Kleen wrote:
 
 Felipe Alfaro Solana [EMAIL PROTECTED] writes:
 
 AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
 operatings. Also, since the original patch uses 3 MOVs to perform the
 swapping, and your version uses 3 XOR operations, I don't see any
 gains.
 
 Both are one cycle latency for register-register on all x86 cores
 I've looked at. What makes you think differently?
 
 I thought XOR was more expensie. Anyways, I still don't see any 
 advantage in replacing 3 MOVs with 3 XORs.

Again, no temporaries needed.

But I benched it and it was quite a bit slower.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread vlobanov
On Mon, 24 Jan 2005, Matt Mackall wrote:

 On Sun, Jan 23, 2005 at 05:58:00AM +0100, Felipe Alfaro Solana wrote:
  On 23 Jan 2005, at 03:39, Andi Kleen wrote:
 
  Felipe Alfaro Solana [EMAIL PROTECTED] writes:
  
  AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
  operatings. Also, since the original patch uses 3 MOVs to perform the
  swapping, and your version uses 3 XOR operations, I don't see any
  gains.
  
  Both are one cycle latency for register-register on all x86 cores
  I've looked at. What makes you think differently?
 
  I thought XOR was more expensie. Anyways, I still don't see any
  advantage in replacing 3 MOVs with 3 XORs.

 Again, no temporaries needed.

 But I benched it and it was quite a bit slower.

 --
 Mathematics is the supreme nostalgia of our time.

Yep, it's a difference of four instructions (when using one or two
temporary variables and swapping using assignments) versus six
instructions (when using xors, since IA32 can't do an xor with both
arguments in memory).

I originally pitched this idea out to the list just for discussion
purposes. Most considered it, and said that the advantages don't
outweigh the disadvantages. And that's fine -- it means that the chosen
way is that much better considered. Always a good thing. :)

-Vadim Lobanov

 -
 To unsubscribe from this list: send the line unsubscribe linux-kernel in
 the body of a message to [EMAIL PROTECTED]
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
 Please read the FAQ at  http://www.tux.org/lkml/

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Matt Mackall
On Mon, Jan 24, 2005 at 01:02:44AM -0300, Horst von Brand wrote:
 Matt Mackall [EMAIL PROTECTED] said:
  On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:
 
 [...]
 
   -Andi (who thinks the glibc qsort is vast overkill for kernel purposes
   where there are only small data sets and it would be better to use a 
   simpler one optimized for code size)
 
  Mostly agreed. Except:
  
  a) the glibc version is not actually all that optimized
  b) it's nice that it's not recursive
  c) the three-way median selection does help avoid worst-case O(n^2)
  behavior, which might potentially be triggerable by users in places
  like XFS where this is used
 
 Shellsort is much simpler, and not much slower for small datasets. Plus no
 extra space for stacks.
 
  I'll probably whip up a simpler version tomorrow or Monday and do some
  size/space benchmarking. I've been meaning to contribute a qsort for
  doubly-linked lists I've got lying around as well.
 
 Qsort is OK as long as you have direct access to each element. In case of
 lists, it is better to just use mergesort.

Qsort does not need to do random access. I posted an efficient
doubly-linked list version here four years ago:

templateclass T
void listT::qsort(iter l, iter r, cmpfunc *cmp, void *data)
{
if(l==r) return;

iter i(l), p(l);

for(i++; i!=r; i++)
if(cmp(*i, *l, data)0)
i.swap(++p);

l.swap(p);
qsort(l, p, cmp, data);
qsort(++p, r, cmp, data);
}

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Mike Waychison
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

Andi Kleen wrote:
How about a shell sort?  if the data is mostly sorted shell sort beats 
qsort lots of times, and since the data sets are often small in-kernel, 
shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
faster if the data is already completely sorted. Shell sort is certainly 
not the simplest algorithm around, but I think (without having done any 
tests) that it would probably do pretty well for in-kernel use... Then 
again, I've known to be wrong :)
 
 
 I like shell sort for small data sets too. And I agree it would be 
 appropiate for the kernel.
 

FWIW, we already have a Shell sort for the ngroups stuff in
kernel/sys.c:groups_sort() that could be made generic.

- --
Mike Waychison
Sun Microsystems, Inc.
1 (650) 352-5299 voice
1 (416) 202-8336 voice

~~
NOTICE:  The opinions expressed in this email are held by me,
and may not represent the views of Sun Microsystems, Inc.
~~
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.2.5 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFB9XDzdQs4kOxk3/MRAs2ZAJ4if1XRFAiWsgb1wvTInFLUVGHesgCfWxCJ
Efyrr4PkG/KrqefAVAQjt+c=
=/OPh
-END PGP SIGNATURE-
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Horst von Brand
[EMAIL PROTECTED] (H. Peter Anvin) said:

[...]

 In klibc, I use combsort:
 
 /*
  * qsort.c
  *
  * This is actually combsort.  It's an O(n log n) algorithm with
  * simplicity/small code size being its main virtue.
  */
 
 #include stddef.h
 #include string.h
 
 static inline size_t newgap(size_t gap)
 {
   gap = (gap*10)/13;
   if ( gap == 9 || gap == 10 )
 gap = 11;
 
   if ( gap  1 )
 gap = 1;
   return gap;
 }
 
 void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
 {
   size_t gap = nmemb;
   size_t i, j;
   char *p1, *p2;
   int swapped;
 
   do {
 gap = newgap(gap);
 swapped = 0;
 
 for ( i = 0, p1 = base ; i  nmemb-gap ; i++, p1 += size ) {
   j = i+gap;
   if ( compar(p1, p2 = (char *)base+j*size)  0 ) {
 memswap(p1, p2, size);
 swapped = 1;
   }
 }
   } while ( gap  1 || swapped );
 }

AFAICS, this is just a badly implemented Shellsort (the 10/13 increment
sequence starting with the number of elements is probably not very good,
besides swapping stuff is inefficient (just juggling like Shellsort does
gives you almost a third less copies)).

Have you found a proof for the O(n log n) claim?

I'd write as attached (careful, a local element on stack!)

/*
 * shellsort.c: Shell sort
 *
 * Copyright (c) 2005, Horst H. von Brand [EMAIL PROTECTED]
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 * * Neither the name of Horst H. von Brand nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include string.h

void qsort(void *base, size_t nmemb, size_t size, 
   int (*compar)(const void *, const void *))

{
  int i, j, h;
  char tmp[size];

  for(h = 1; h  nmemb; h = 3 * h + 1)
;

  do {
h /= 3;
for(i = h; i  nmemb; i++) {
  memcpy(tmp, base + i * size, size);
  for(j = i - h; j = 0  compar(tmp, base + j * size); j -= h)
	memcpy(base + (j + h) * size, base + j * size, size);
  memcpy(base + (j + h) * size, tmp, size);
}
  } while(h  1);
}
-- 
Dr. Horst H. von Brand   User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria  +56 32 654239
Casilla 110-V, Valparaiso, ChileFax:  +56 32 797513


Re: [patch 1/13] Qsort

2005-01-24 Thread Eric St-Laurent
On Mon, 2005-01-24 at 21:43 -0300, Horst von Brand wrote:
 AFAICS, this is just a badly implemented Shellsort (the 10/13 increment
 sequence starting with the number of elements is probably not very good,
 besides swapping stuff is inefficient (just juggling like Shellsort does
 gives you almost a third less copies)).
 
 Have you found a proof for the O(n log n) claim?

Why a Comb Sort is NOT a Shell Sort

A shell sort completely sorts the data for each gap size. A comb sort
takes a more optimistic approach and doesn't require data be completely
sorted at a gap size. The comb sort assumes that out-of-order data will
be cleaned-up by smaller gap sizes as the sort proceeds. 

Reference:

http://world.std.com/~jdveale/combsort.htm

Another good reference:

http://yagni.com/combsort/index.php

Personally, i've used it in the past because of it's small size.  With
C++ templates you can have a copy of the routine generated for a
specific datatype, thus skipping the costly function call used for each
compare.  With some C macro magic, i presume something similar can be
done, for time-critical applications.

Best regards,

Eric St-Laurent


-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-24 Thread Andi Kleen
 FWIW, we already have a Shell sort for the ngroups stuff in
 kernel/sys.c:groups_sort() that could be made generic.

Sounds like a good plan. Any takers?

-Andi
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Horst von Brand
"Rafael J. Wysocki" <[EMAIL PROTECTED]> said:

[...]

> To be precise, one needs ~(log N) of stack space for qsort, and frankly, one
> should use something like the shell (or should I say Shell?)

Shell. It is named for a person.

>  sort for sorting
> small sets of elements in qsort as well.

It makes no sense for smallish sets, insertion sort is better.
-- 
Dr. Horst H. von Brand   User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria  +56 32 654239
Casilla 110-V, Valparaiso, ChileFax:  +56 32 797513
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Horst von Brand
Matt Mackall <[EMAIL PROTECTED]> said:
> On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:

[...]

> > -Andi (who thinks the glibc qsort is vast overkill for kernel purposes
> > where there are only small data sets and it would be better to use a 
> > simpler one optimized for code size)

> Mostly agreed. Except:
> 
> a) the glibc version is not actually all that optimized
> b) it's nice that it's not recursive
> c) the three-way median selection does help avoid worst-case O(n^2)
> behavior, which might potentially be triggerable by users in places
> like XFS where this is used

Shellsort is much simpler, and not much slower for small datasets. Plus no
extra space for stacks.

> I'll probably whip up a simpler version tomorrow or Monday and do some
> size/space benchmarking. I've been meaning to contribute a qsort for
> doubly-linked lists I've got lying around as well.

Qsort is OK as long as you have direct access to each element. In case of
lists, it is better to just use mergesort.
-- 
Dr. Horst H. von Brand   User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria  +56 32 654239
Casilla 110-V, Valparaiso, ChileFax:  +56 32 797513
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Horst von Brand
Andreas Gruenbacher <[EMAIL PROTECTED]> said:
> Signed-off-by: Andreas Gruenbacher <[EMAIL PROTECTED]>
> Acked-by: Olaf Kirch <[EMAIL PROTECTED]>

[...]

> +/* Order size using quicksort.  This implementation incorporates
> +   four optimizations discussed in Sedgewick:
> +
> +   1. Non-recursive, using an explicit stack of pointer that store the
> +  next array partition to sort.  To save time, this maximum amount
> +  of space required to store an array of SIZE_MAX is allocated on the
> +  stack.  Assuming a 32-bit (64 bit) integer for size_t, this needs
> +  only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
> +  Pretty cheap, actually.

Not really, given the strict size restrictions in-kernel.

Has there been any comparison between the original and this one? Code size,
stack use, speed, ...?
-- 
Dr. Horst H. von Brand   User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria  +56 32 654239
Casilla 110-V, Valparaiso, ChileFax:  +56 32 797513
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Charles R Harris
Here are semi-templated versions of quicksort and heapsort, just for
completeness. The quicksort uses the median of three.

Chuck

void  quicksort0( *pl,  *pr)
{
 vp, SWAP_temp;
 *stack[100], **sptr = stack, *pm, *pi, *pj, *pt;

for(;;) {
while ((pr - pl) > 15) {
/* quicksort partition */
pm = pl + ((pr - pl) >> 1);
if ((*pm,*pl)) SWAP(*pm,*pl);
if ((*pr,*pm)) SWAP(*pr,*pm);
if ((*pm,*pl)) SWAP(*pm,*pl);
vp = *pm;
pi = pl;
pj = pr - 1;
SWAP(*pm,*pj);
for(;;) {
do ++pi; while ((*pi,vp));
do --pj; while ((vp,*pj));
if (pi >= pj)  break;
SWAP(*pi,*pj);
}
SWAP(*pi,*(pr-1));
/* push largest partition on stack */
if (pi - pl < pr - pi) {
*sptr++ = pi + 1;
*sptr++ = pr;
pr = pi - 1;
}else{
*sptr++ = pl;
*sptr++ = pi - 1;
pl = pi + 1;
}
}
/* insertion sort */
for(pi = pl + 1; pi <= pr; ++pi) {
vp = *pi;
for(pj = pi, pt = pi - 1; pj > pl && (vp, 
*pt);) {
*pj-- = *pt--;
}
*pj = vp;
}
if (sptr == stack) break;
pr = *(--sptr);
pl = *(--sptr);
}
}

void heapsort0( *a, long n)
{
 tmp;
long i,j,l;

/* The array needs to be offset by one for heapsort indexing */
a -= 1;

for (l = n>>1; l > 0; --l) {
tmp = a[l];
for (i = l, j = l<<1; j <= n;) {
if (j < n && (a[j], a[j+1])) 
j += 1;
if ((tmp, a[j])) {
a[i] = a[j];
i = j;
j += j;
}else
break;
}
a[i] = tmp;
} 

for (; n > 1;) {
tmp = a[n];
a[n] = a[1];
n -= 1;
for (i = 1, j = 2; j <= n;) {
if (j < n && (a[j], a[j+1]))
j++;
if ((tmp, a[j])) {
a[i] = a[j];
i = j;
j += j;
}else
break;
}
a[i] = tmp;
}
}



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Matt Mackall
On Mon, Jan 24, 2005 at 11:21:29AM +1100, Nathan Scott wrote:
> On Sat, Jan 22, 2005 at 08:29:30PM -0800, Matt Mackall wrote:
> > On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:
> > 
> > c) the three-way median selection does help avoid worst-case O(n^2)
> > behavior, which might potentially be triggerable by users in places
> > like XFS where this is used
> 
> XFS's needs are simple - we're just sorting dirents within a
> single directory block or smaller, and sorting EA lists/ACLs -
> all of which are small arrays, so a qsort optimised for small
> arrays suits XFS well. 

Ok, I've worked up a much smaller, cleaner version that wins on lists
of 1 entries or less and is still within 5% at 1M entries (ie well
past what any kernel code has any business doing). More after I've
fiddled around a bit more with the benchmarks.

> Take care not to put any arrays on the
> stack though, else the CONFIG_4KSTACKS punters won't be happy.

I'm afraid I'm one of those punters - 4k stacks were getting cleaned up and
tested in my -tiny tree long before mainline.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread James Lamanna
> On Sunday, January 23, 2005, Rafael J. Wysocki wrote:
> > On Sunday, 23 of January 2005 06:05, Jesper Juhl wrote:
> > > On Sun, 23 Jan 2005, Andi Kleen wrote:
> > Even with large data sets that are mostly unsorted shell sorts performance 
> > is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
> > runtime (IIRC),
>
> Yes, there is.

After doing a small amount of research into this, according to the abstract at
http://www.cs.princeton.edu/~rs/shell/paperF.pdf you can get O(n^(4/3)) 
with different increment sequences. (1, 8, 23, 77, 281 ...)

So I guess the sort function could look something like this for XFS use
(for reference only!):

void shellsort(void *array, size_t total_elems, size_t size, 
int (*cmp)(const void *, const void *))
{
size_t i, j;
int k, h;
register char *a = array;  
const int incs[3] = {23, 8, 1};

for (k = 0; k < 3; k++) {
for (h = incs[k], i = h; i < total_elems; i++) {
j = i;
while (j >= h && cmp(a + (j-h) * size, a + j * size) > 0) {
swap(a + j * size, a + (j-h) * size);
j -= h;
}
}
}
}

-- James Lamanna
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Nathan Scott
On Sat, Jan 22, 2005 at 08:29:30PM -0800, Matt Mackall wrote:
> On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:
> 
> c) the three-way median selection does help avoid worst-case O(n^2)
> behavior, which might potentially be triggerable by users in places
> like XFS where this is used

XFS's needs are simple - we're just sorting dirents within a
single directory block or smaller, and sorting EA lists/ACLs -
all of which are small arrays, so a qsort optimised for small
arrays suits XFS well.  Take care not to put any arrays on the
stack though, else the CONFIG_4KSTACKS punters won't be happy.

cheers.

-- 
Nathan
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Richard Henderson
On Sat, Jan 22, 2005 at 01:00:24PM -0800, vlobanov wrote:
> #define SWAP(a, b, size)  \
> do {  \
>   register size_t __size = (size);\
>   register char * __a = (a), * __b = (b); \
>   do {\
>   *__a ^= *__b;   \
>   *__b ^= *__a;   \
>   *__a ^= *__b;   \
>   __a++;  \
>   __b++;  \
>   } while ((--__size) > 0);   \
> } while (0)
> 
> What do you think? :)

I think you'll confuse the compiler and get worse results.


r~
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Matt Mackall
On Sun, Jan 23, 2005 at 01:22:13PM +0100, Andreas Gruenbacher wrote:
> On Sunday 23 January 2005 06:32, Matt Mackall wrote:
> > Yes, indeed. Though I think even here, we'd prefer to use kmalloc
> > because gcc generates suboptimal code for variable-sized stack vars.
> 
> That's ridiculous. kmalloc isn't even close to whatever suboptimal
> code gcc might produce here. Also I'm not convinced that gcc
> generates bad code in the first place. The code I get makes perfect
> sense.

Fixed-sized slab-based kmalloc is O(1) (and pretty darn fast). If we
take a constant overhead for every local variable lookup in qsort,
that's O(n log n). Putting the stack vars last might fix that, but I
think it needs testing. I'll try it.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Andreas Gruenbacher
On Sunday 23 January 2005 06:32, Matt Mackall wrote:
> Yes, indeed. Though I think even here, we'd prefer to use kmalloc
> because gcc generates suboptimal code for variable-sized stack vars.

That's ridiculous. kmalloc isn't even close to whatever suboptimal code gcc 
might produce here. Also I'm not convinced that gcc generates bad code in the 
first place. The code I get makes perfect sense.

-- Andreas.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Rafael J. Wysocki
On Sunday, 23 of January 2005 06:05, Jesper Juhl wrote:
> On Sun, 23 Jan 2005, Andi Kleen wrote:
> 
> > > How about a shell sort?  if the data is mostly sorted shell sort beats 
> > > qsort lots of times, and since the data sets are often small in-kernel, 
> > > shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
> > > faster if the data is already completely sorted. Shell sort is certainly 
> > > not the simplest algorithm around, but I think (without having done any 
> > > tests) that it would probably do pretty well for in-kernel use... Then 
> > > again, I've known to be wrong :)
> > 
> > I like shell sort for small data sets too. And I agree it would be 
> > appropiate for the kernel.
> > 
> Even with large data sets that are mostly unsorted shell sorts performance 
> is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
> runtime (IIRC),

Yes, there is.

> and another nice property is that it's iterative so it  
> doesn't eat up stack space (as oposed to qsort which is recursive and eats 
> stack like )...

To be precise, one needs ~(log N) of stack space for qsort, and frankly, one
should use something like the shell (or should I say Shell?) sort for sorting
small sets of elements in qsort as well.

> Yeah, I think shell sort would be good for the kernel.

I agree.

Greets,
RJW


-- 
- Would you tell me, please, which way I ought to go from here?
- That depends a good deal on where you want to get to.
-- Lewis Carroll "Alice's Adventures in Wonderland"
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Rafael J. Wysocki
On Sunday, 23 of January 2005 06:05, Jesper Juhl wrote:
 On Sun, 23 Jan 2005, Andi Kleen wrote:
 
   How about a shell sort?  if the data is mostly sorted shell sort beats 
   qsort lots of times, and since the data sets are often small in-kernel, 
   shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
   faster if the data is already completely sorted. Shell sort is certainly 
   not the simplest algorithm around, but I think (without having done any 
   tests) that it would probably do pretty well for in-kernel use... Then 
   again, I've known to be wrong :)
  
  I like shell sort for small data sets too. And I agree it would be 
  appropiate for the kernel.
  
 Even with large data sets that are mostly unsorted shell sorts performance 
 is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
 runtime (IIRC),

Yes, there is.

 and another nice property is that it's iterative so it  
 doesn't eat up stack space (as oposed to qsort which is recursive and eats 
 stack like )...

To be precise, one needs ~(log N) of stack space for qsort, and frankly, one
should use something like the shell (or should I say Shell?) sort for sorting
small sets of elements in qsort as well.

 Yeah, I think shell sort would be good for the kernel.

I agree.

Greets,
RJW


-- 
- Would you tell me, please, which way I ought to go from here?
- That depends a good deal on where you want to get to.
-- Lewis Carroll Alice's Adventures in Wonderland
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Andreas Gruenbacher
On Sunday 23 January 2005 06:32, Matt Mackall wrote:
 Yes, indeed. Though I think even here, we'd prefer to use kmalloc
 because gcc generates suboptimal code for variable-sized stack vars.

That's ridiculous. kmalloc isn't even close to whatever suboptimal code gcc 
might produce here. Also I'm not convinced that gcc generates bad code in the 
first place. The code I get makes perfect sense.

-- Andreas.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Matt Mackall
On Sun, Jan 23, 2005 at 01:22:13PM +0100, Andreas Gruenbacher wrote:
 On Sunday 23 January 2005 06:32, Matt Mackall wrote:
  Yes, indeed. Though I think even here, we'd prefer to use kmalloc
  because gcc generates suboptimal code for variable-sized stack vars.
 
 That's ridiculous. kmalloc isn't even close to whatever suboptimal
 code gcc might produce here. Also I'm not convinced that gcc
 generates bad code in the first place. The code I get makes perfect
 sense.

Fixed-sized slab-based kmalloc is O(1) (and pretty darn fast). If we
take a constant overhead for every local variable lookup in qsort,
that's O(n log n). Putting the stack vars last might fix that, but I
think it needs testing. I'll try it.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Nathan Scott
On Sat, Jan 22, 2005 at 08:29:30PM -0800, Matt Mackall wrote:
 On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:
 
 c) the three-way median selection does help avoid worst-case O(n^2)
 behavior, which might potentially be triggerable by users in places
 like XFS where this is used

XFS's needs are simple - we're just sorting dirents within a
single directory block or smaller, and sorting EA lists/ACLs -
all of which are small arrays, so a qsort optimised for small
arrays suits XFS well.  Take care not to put any arrays on the
stack though, else the CONFIG_4KSTACKS punters won't be happy.

cheers.

-- 
Nathan
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread James Lamanna
 On Sunday, January 23, 2005, Rafael J. Wysocki wrote:
  On Sunday, 23 of January 2005 06:05, Jesper Juhl wrote:
   On Sun, 23 Jan 2005, Andi Kleen wrote:
  Even with large data sets that are mostly unsorted shell sorts performance 
  is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
  runtime (IIRC),

 Yes, there is.

After doing a small amount of research into this, according to the abstract at
http://www.cs.princeton.edu/~rs/shell/paperF.pdf you can get O(n^(4/3)) 
with different increment sequences. (1, 8, 23, 77, 281 ...)

So I guess the sort function could look something like this for XFS use
(for reference only!):

void shellsort(void *array, size_t total_elems, size_t size, 
int (*cmp)(const void *, const void *))
{
size_t i, j;
int k, h;
register char *a = array;  
const int incs[3] = {23, 8, 1};

for (k = 0; k  3; k++) {
for (h = incs[k], i = h; i  total_elems; i++) {
j = i;
while (j = h  cmp(a + (j-h) * size, a + j * size)  0) {
swap(a + j * size, a + (j-h) * size);
j -= h;
}
}
}
}

-- James Lamanna
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Matt Mackall
On Mon, Jan 24, 2005 at 11:21:29AM +1100, Nathan Scott wrote:
 On Sat, Jan 22, 2005 at 08:29:30PM -0800, Matt Mackall wrote:
  On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:
  
  c) the three-way median selection does help avoid worst-case O(n^2)
  behavior, which might potentially be triggerable by users in places
  like XFS where this is used
 
 XFS's needs are simple - we're just sorting dirents within a
 single directory block or smaller, and sorting EA lists/ACLs -
 all of which are small arrays, so a qsort optimised for small
 arrays suits XFS well. 

Ok, I've worked up a much smaller, cleaner version that wins on lists
of 1 entries or less and is still within 5% at 1M entries (ie well
past what any kernel code has any business doing). More after I've
fiddled around a bit more with the benchmarks.

 Take care not to put any arrays on the
 stack though, else the CONFIG_4KSTACKS punters won't be happy.

I'm afraid I'm one of those punters - 4k stacks were getting cleaned up and
tested in my -tiny tree long before mainline.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Charles R Harris
Here are semi-templated versions of quicksort and heapsort, just for
completeness. The quicksort uses the median of three.

Chuck

void  quicksort0typename(typename *pl, typename *pr)
{
typename vp, SWAP_temp;
typename *stack[100], **sptr = stack, *pm, *pi, *pj, *pt;

for(;;) {
while ((pr - pl)  15) {
/* quicksort partition */
pm = pl + ((pr - pl)  1);
if (lessthan(*pm,*pl)) SWAP(*pm,*pl);
if (lessthan(*pr,*pm)) SWAP(*pr,*pm);
if (lessthan(*pm,*pl)) SWAP(*pm,*pl);
vp = *pm;
pi = pl;
pj = pr - 1;
SWAP(*pm,*pj);
for(;;) {
do ++pi; while (lessthan(*pi,vp));
do --pj; while (lessthan(vp,*pj));
if (pi = pj)  break;
SWAP(*pi,*pj);
}
SWAP(*pi,*(pr-1));
/* push largest partition on stack */
if (pi - pl  pr - pi) {
*sptr++ = pi + 1;
*sptr++ = pr;
pr = pi - 1;
}else{
*sptr++ = pl;
*sptr++ = pi - 1;
pl = pi + 1;
}
}
/* insertion sort */
for(pi = pl + 1; pi = pr; ++pi) {
vp = *pi;
for(pj = pi, pt = pi - 1; pj  pl  lessthan(vp, 
*pt);) {
*pj-- = *pt--;
}
*pj = vp;
}
if (sptr == stack) break;
pr = *(--sptr);
pl = *(--sptr);
}
}

void heapsort0typename(typename *a, long n)
{
typename tmp;
long i,j,l;

/* The array needs to be offset by one for heapsort indexing */
a -= 1;

for (l = n1; l  0; --l) {
tmp = a[l];
for (i = l, j = l1; j = n;) {
if (j  n  lessthan(a[j], a[j+1])) 
j += 1;
if (lessthan(tmp, a[j])) {
a[i] = a[j];
i = j;
j += j;
}else
break;
}
a[i] = tmp;
} 

for (; n  1;) {
tmp = a[n];
a[n] = a[1];
n -= 1;
for (i = 1, j = 2; j = n;) {
if (j  n  lessthan(a[j], a[j+1]))
j++;
if (lessthan(tmp, a[j])) {
a[i] = a[j];
i = j;
j += j;
}else
break;
}
a[i] = tmp;
}
}



-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Horst von Brand
Andreas Gruenbacher [EMAIL PROTECTED] said:
 Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED]
 Acked-by: Olaf Kirch [EMAIL PROTECTED]

[...]

 +/* Order size using quicksort.  This implementation incorporates
 +   four optimizations discussed in Sedgewick:
 +
 +   1. Non-recursive, using an explicit stack of pointer that store the
 +  next array partition to sort.  To save time, this maximum amount
 +  of space required to store an array of SIZE_MAX is allocated on the
 +  stack.  Assuming a 32-bit (64 bit) integer for size_t, this needs
 +  only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
 +  Pretty cheap, actually.

Not really, given the strict size restrictions in-kernel.

Has there been any comparison between the original and this one? Code size,
stack use, speed, ...?
-- 
Dr. Horst H. von Brand   User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria  +56 32 654239
Casilla 110-V, Valparaiso, ChileFax:  +56 32 797513
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Horst von Brand
Matt Mackall [EMAIL PROTECTED] said:
 On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:

[...]

  -Andi (who thinks the glibc qsort is vast overkill for kernel purposes
  where there are only small data sets and it would be better to use a 
  simpler one optimized for code size)

 Mostly agreed. Except:
 
 a) the glibc version is not actually all that optimized
 b) it's nice that it's not recursive
 c) the three-way median selection does help avoid worst-case O(n^2)
 behavior, which might potentially be triggerable by users in places
 like XFS where this is used

Shellsort is much simpler, and not much slower for small datasets. Plus no
extra space for stacks.

 I'll probably whip up a simpler version tomorrow or Monday and do some
 size/space benchmarking. I've been meaning to contribute a qsort for
 doubly-linked lists I've got lying around as well.

Qsort is OK as long as you have direct access to each element. In case of
lists, it is better to just use mergesort.
-- 
Dr. Horst H. von Brand   User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria  +56 32 654239
Casilla 110-V, Valparaiso, ChileFax:  +56 32 797513
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-23 Thread Horst von Brand
Rafael J. Wysocki [EMAIL PROTECTED] said:

[...]

 To be precise, one needs ~(log N) of stack space for qsort, and frankly, one
 should use something like the shell (or should I say Shell?)

Shell. It is named for a person.

  sort for sorting
 small sets of elements in qsort as well.

It makes no sense for smallish sets, insertion sort is better.
-- 
Dr. Horst H. von Brand   User #22616 counter.li.org
Departamento de Informatica Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria  +56 32 654239
Casilla 110-V, Valparaiso, ChileFax:  +56 32 797513
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Willy Tarreau
Hi,

On Sun, Jan 23, 2005 at 03:03:32AM +0100, Felipe Alfaro Solana wrote:
> On 22 Jan 2005, at 22:00, vlobanov wrote:
> >#define SWAP(a, b, size) \
> >do { \
> > register size_t __size = (size);\
> > register char * __a = (a), * __b = (b); \
> > do {\
> > *__a ^= *__b;   \
> > *__b ^= *__a;   \
> > *__a ^= *__b;   \
> > __a++;  \
> > __b++;  \
> > } while ((--__size) > 0);   \
> >} while (0)
> >
> >What do you think? :)
> 
> AFAIK, XOR is quite expensive on IA32 when compared to simple MOV 
> operatings. Also, since the original patch uses 3 MOVs to perform the 
> swapping, and your version uses 3 XOR operations, I don't see any 
> gains.

It will even be worse because we are accessing memory, and most architectures
will not be able to use a memory reference for both operands of the XOR.
Basically, what will be generated will look like this :

  tmp = *b
  *a ^= tmp
  tmp ^= *a
  *b = tmp
  *a ^= tmp

which is 5 cycles, or 4 if the two last instructions get merged. And there's
3 memory reads + 3 memory writes (assuming that the CPU will be smart enough
to reuse *a without accessing memory at instruction 3).

The move is quite faster :

   tmp1 = *a
   tmp2 = *b
   *a = tmp2
   *b = tmp1

This is 4 cycles on simple CPUs, or even 2 cycles on most of todays CPUs
which can do the first two fetches at once, and the last two writes at once.
And there are only two reads and two writes.

Clearly this one is better.

Regards,
Willy

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sun, Jan 23, 2005 at 06:08:36AM +0100, Andreas Gruenbacher wrote:
> On Sunday 23 January 2005 00:28, Matt Mackall wrote:
> > So the stack is going to be either 256 or 1024 bytes. Seems like we
> > ought to kmalloc it.
> 
> This will do. I didn't check if the +1 is strictly needed.
> 
> -  stack_node stack[STACK_SIZE];
> +  stack_node stack[fls(size) - fls(MAX_THRESH) + 1];

Yes, indeed. Though I think even here, we'd prefer to use kmalloc
because gcc generates suboptimal code for variable-sized stack vars.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Andreas Gruenbacher
On Sunday 23 January 2005 00:28, Matt Mackall wrote:
> So the stack is going to be either 256 or 1024 bytes. Seems like we
> ought to kmalloc it.

This will do. I didn't check if the +1 is strictly needed.

-  stack_node stack[STACK_SIZE];
+  stack_node stack[fls(size) - fls(MAX_THRESH) + 1];

-- 
Andreas Gruenbacher <[EMAIL PROTECTED]>
SUSE Labs, SUSE LINUX PRODUCTS GMBH
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Jesper Juhl
On Sun, 23 Jan 2005, Andi Kleen wrote:

> > How about a shell sort?  if the data is mostly sorted shell sort beats 
> > qsort lots of times, and since the data sets are often small in-kernel, 
> > shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
> > faster if the data is already completely sorted. Shell sort is certainly 
> > not the simplest algorithm around, but I think (without having done any 
> > tests) that it would probably do pretty well for in-kernel use... Then 
> > again, I've known to be wrong :)
> 
> I like shell sort for small data sets too. And I agree it would be 
> appropiate for the kernel.
> 
Even with large data sets that are mostly unsorted shell sorts performance 
is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
runtime (IIRC), and another nice property is that it's iterative so it 
doesn't eat up stack space (as oposed to qsort which is recursive and eats 
stack like )...
Yeah, I think shell sort would be good for the kernel.


-- 
Jesper Juhl



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Felipe Alfaro Solana
On 23 Jan 2005, at 03:39, Andi Kleen wrote:
Felipe Alfaro Solana <[EMAIL PROTECTED]> writes:
AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
operatings. Also, since the original patch uses 3 MOVs to perform the
swapping, and your version uses 3 XOR operations, I don't see any
gains.
Both are one cycle latency for register<->register on all x86 cores
I've looked at. What makes you think differently?
I thought XOR was more expensie. Anyways, I still don't see any 
advantage in replacing 3 MOVs with 3 XORs.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Andi Kleen
> How about a shell sort?  if the data is mostly sorted shell sort beats 
> qsort lots of times, and since the data sets are often small in-kernel, 
> shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
> faster if the data is already completely sorted. Shell sort is certainly 
> not the simplest algorithm around, but I think (without having done any 
> tests) that it would probably do pretty well for in-kernel use... Then 
> again, I've known to be wrong :)

I like shell sort for small data sets too. And I agree it would be 
appropiate for the kernel.

-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:
> Felipe Alfaro Solana <[EMAIL PROTECTED]> writes:
> >
> > AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
> > operatings. Also, since the original patch uses 3 MOVs to perform the
> > swapping, and your version uses 3 XOR operations, I don't see any
> > gains.
> 
> Both are one cycle latency for register<->register on all x86 cores
> I've looked at. What makes you think differently?
> 
> -Andi (who thinks the glibc qsort is vast overkill for kernel purposes
> where there are only small data sets and it would be better to use a 
> simpler one optimized for code size)

Mostly agreed. Except:

a) the glibc version is not actually all that optimized
b) it's nice that it's not recursive
c) the three-way median selection does help avoid worst-case O(n^2)
behavior, which might potentially be triggerable by users in places
like XFS where this is used

I'll probably whip up a simpler version tomorrow or Monday and do some
size/space benchmarking. I've been meaning to contribute a qsort for
doubly-linked lists I've got lying around as well.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sun, Jan 23, 2005 at 03:03:32AM +0100, Felipe Alfaro Solana wrote:
> On 22 Jan 2005, at 22:00, vlobanov wrote:
> 
> >Hi,
> >
> >I was just reading over the patch, and had a quick question/comment 
> >upon
> >the SWAP macro defined below. I think it's possible to do a tiny bit
> >better (better, of course, being subjective), as follows:
> >
> >#define SWAP(a, b, size) \
> >do { \
> > register size_t __size = (size);\
> > register char * __a = (a), * __b = (b); \
> > do {\
> > *__a ^= *__b;   \
> > *__b ^= *__a;   \
> > *__a ^= *__b;   \
> > __a++;  \
> > __b++;  \
> > } while ((--__size) > 0);   \
> >} while (0)
> >
> >What do you think? :)
> 
> AFAIK, XOR is quite expensive on IA32 when compared to simple MOV 
> operatings. Also, since the original patch uses 3 MOVs to perform the 
> swapping, and your version uses 3 XOR operations, I don't see any 
> gains.
> 
> Am I missing something?

No temporary variable needed in the xor version. mov and xor are
roughly the same speed, but xor modifies flags.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Jesper Juhl
On Sun, 23 Jan 2005, Andi Kleen wrote:

> Felipe Alfaro Solana <[EMAIL PROTECTED]> writes:
> >
> > AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
> > operatings. Also, since the original patch uses 3 MOVs to perform the
> > swapping, and your version uses 3 XOR operations, I don't see any
> > gains.
> 
> Both are one cycle latency for register<->register on all x86 cores
> I've looked at. What makes you think differently?
> 
> -Andi (who thinks the glibc qsort is vast overkill for kernel purposes
> where there are only small data sets and it would be better to use a 
> simpler one optimized for code size)
> 
How about a shell sort?  if the data is mostly sorted shell sort beats 
qsort lots of times, and since the data sets are often small in-kernel, 
shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
faster if the data is already completely sorted. Shell sort is certainly 
not the simplest algorithm around, but I think (without having done any 
tests) that it would probably do pretty well for in-kernel use... Then 
again, I've known to be wrong :)


-- 
Jesper Juhl

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Andi Kleen
Felipe Alfaro Solana <[EMAIL PROTECTED]> writes:
>
> AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
> operatings. Also, since the original patch uses 3 MOVs to perform the
> swapping, and your version uses 3 XOR operations, I don't see any
> gains.

Both are one cycle latency for register<->register on all x86 cores
I've looked at. What makes you think differently?

-Andi (who thinks the glibc qsort is vast overkill for kernel purposes
where there are only small data sets and it would be better to use a 
simpler one optimized for code size)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Felipe Alfaro Solana
On 22 Jan 2005, at 22:00, vlobanov wrote:
Hi,
I was just reading over the patch, and had a quick question/comment 
upon
the SWAP macro defined below. I think it's possible to do a tiny bit
better (better, of course, being subjective), as follows:

#define SWAP(a, b, size)\
do {\
register size_t __size = (size);\
register char * __a = (a), * __b = (b); \
do {\
*__a ^= *__b;   \
*__b ^= *__a;   \
*__a ^= *__b;   \
__a++;  \
__b++;  \
} while ((--__size) > 0);\
} while (0)
What do you think? :)
AFAIK, XOR is quite expensive on IA32 when compared to simple MOV 
operatings. Also, since the original patch uses 3 MOVs to perform the 
swapping, and your version uses 3 XOR operations, I don't see any 
gains.

Am I missing something?
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sat, Jan 22, 2005 at 03:28:14PM -0800, Matt Mackall wrote:
> On Sat, Jan 22, 2005 at 09:34:01PM +0100, Andreas Gruenbacher wrote:
> > Add a quicksort from glibc as a kernel library function, and switch
> > xfs over to using it. The implementations are equivalent. The nfsacl
> > protocol also requires a sort function, so it makes more sense in
> > the common code.
> 
> Please update this to kernel formatting standards and try to modernize
> it a bit.

I started working on this with an eye to doing some performance
testing of the insertion sort threshold in userspace, but I'm about to
head out for the day. Here's what I've got so far, compiles but
untested. Note the insertion sort at the end really ought to be using
memmove as well.

/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
   Written by Douglas C. Schmidt ([EMAIL PROTECTED]).

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

/* If you consider tuning this algorithm, you should consult first:
   Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
   Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993.  */

#include 
#include 

#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y);\
_x < _y ? _x : _y; })

/* Byte-wise swap two items of size SIZE. */
#define SWAP(a, b, size)  \
  do  \
{ \
  size_t __size = (size); \
  char *__a = (a), *__b = (b);\
  do  \
{ \
  char __tmp = *__a;  \
  *__a++ = *__b;  \
  *__b++ = __tmp; \
} while (--__size > 0);   \
} while (0)

/* Discontinue quicksort algorithm when partition gets below this size.
   This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 4

/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
void *lo;
void *hi;
} stack_node;

/* Order size using quicksort.  This implementation incorporates
   four optimizations discussed in Sedgewick:

   1. Non-recursive, using an explicit stack of pointer that store the
  next array partition to sort.  To save time, this maximum amount
  of space required to store an array of SIZE_MAX is allocated on the
  stack.  Assuming a 32-bit (64 bit) integer for size_t, this needs
  only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
  Pretty cheap, actually.

   2. Chose the pivot element using a median-of-three decision tree.
  This reduces the probability of selecting a bad pivot value and
  eliminates certain extraneous comparisons.

   3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
  insertion sort to order the MAX_THRESH items within each partition.
  This is a big win, since insertion sort is faster for small, mostly
  sorted array segments.

   4. The larger of the two sub-partitions is always pushed onto the
  stack first, with the algorithm then concentrating on the
  smaller partition.  This *guarantees* no more than log (total_elems)
  stack size is needed (actually O(1) in this case)!  */

void qsort(void *base, size_t num, size_t size,
   int (*cmp) (const void *, const void *))
{
const size_t max_thresh = MAX_THRESH * size;
void *hi, *lo, *mid, *left, *right;
void *end = base + (size * (num - 1));
void *tmp = base;
void *thresh = min(end, base + max_thresh);
void *run, *trav;
stack_node *stack, *top;

if (num == 0)
return;

lo = base;
hi = lo + size * (num - 1);
if (num > MAX_THRESH) {

Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sat, Jan 22, 2005 at 09:34:01PM +0100, Andreas Gruenbacher wrote:
> Add a quicksort from glibc as a kernel library function, and switch
> xfs over to using it. The implementations are equivalent. The nfsacl
> protocol also requires a sort function, so it makes more sense in
> the common code.

Please update this to kernel formatting standards and try to modernize
it a bit.

> +/* Byte-wise swap two items of size SIZE. */
> +#define SWAP(a, b, size)   \
> +  do   \
> +{
>   \
> +  register size_t __size = (size);   
>   \
> +  register char *__a = (a), *__b = (b);\
> +  do   \
> + { \
> +   char __tmp = *__a;  \
> +   *__a++ = *__b;  \
> +   *__b++ = __tmp; \
> + } while (--__size > 0);   \
> +} while (0)

Inline, please? Register keyword?!

> +typedef struct
> +  {
> +char *lo;
> +char *hi;
> +  } stack_node;

void *, please

> +
> +/* The next 5 #defines implement a very fast in-line stack abstraction. */
> +/* The stack needs log (total_elements) entries (we could even subtract
> +   log(MAX_THRESH)).  Since total_elements has type size_t, we get as
> +   upper bound for log (total_elements):
> +   bits per byte (CHAR_BIT) * sizeof(size_t).  */
> +#define CHAR_BIT 8
> +#define STACK_SIZE   (CHAR_BIT * sizeof(size_t))

So the stack is going to be either 256 or 1024 bytes. Seems like we
ought to kmalloc it.

> +#define PUSH(low, high)  ((void) ((top->lo = (low)), (top->hi = (high)), 
> ++top))
> +#define  POP(low, high)  ((void) (--top, (low = top->lo), (high = 
> top->hi)))
> +#define  STACK_NOT_EMPTY (stack < top)

There's only one usage of POP, one of STACK_NOT_EMPTY and two of PUSH
that can trivially be made one. Please kill these macros.

> +   3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
> +  insertion sort to order the MAX_THRESH items within each partition.
> +  This is a big win, since insertion sort is faster for small, mostly
> +  sorted array segments.

This observation may be dated, instruction cache issues may dominate now.

> +   char *mid = lo + size * ((hi - lo) / size >> 1);

Get rid of all this char* stuff, please. It makes for lots of ugly and
unnecessary casting.

> +   if ((*cmp) ((void *) mid, (void *) lo) < 0)
> + SWAP (mid, lo, size);

cmp(mid, lo)

> +   if ((*cmp) ((void *) hi, (void *) mid) < 0)
> + SWAP (mid, hi, size);
> +   else
> + goto jump_over;
> +   if ((*cmp) ((void *) mid, (void *) lo) < 0)
> + SWAP (mid, lo, size);
> + jump_over:;

?!

> +  /* Once the BASE_PTR array is partially sorted by quicksort the rest
> + is completely sorted using insertion sort, since this is efficient
> + for partitions below MAX_THRESH size. BASE_PTR points to the beginning
> + of the array to sort, and END_PTR points at the very last element in
> + the array (*not* one beyond it!). */
> +
> +  {
> +char *end_ptr = _ptr[size * (total_elems - 1)];
> +char *tmp_ptr = base_ptr;
> +char *thresh = min(end_ptr, base_ptr + max_thresh);
> +register char *run_ptr;

Move these vars to the top or better yet, split this into two functions.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Andreas Gruenbacher
On Sat, 2005-01-22 at 23:06, Arjan van de Ven wrote:
> since you took the glibc one.. the glibc authors have repeatedly asked
> if glibc code that goes into the kernel will be export_symbol_gpl only
> due to their view of the gpl and lgpl

Sure, no big deal. We could equally well take the xfs one instead.

Cheers,
-- 
Andreas Gruenbacher <[EMAIL PROTECTED]>
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread vlobanov
Hi,

I was just reading over the patch, and had a quick question/comment upon
the SWAP macro defined below. I think it's possible to do a tiny bit
better (better, of course, being subjective), as follows:

#define SWAP(a, b, size)\
do {\
register size_t __size = (size);\
register char * __a = (a), * __b = (b); \
do {\
*__a ^= *__b;   \
*__b ^= *__a;   \
*__a ^= *__b;   \
__a++;  \
__b++;  \
} while ((--__size) > 0);   \
} while (0)

What do you think? :)

-Vadim Lobanov

On Sat, 22 Jan 2005, Andreas Gruenbacher wrote:

> Add a quicksort from glibc as a kernel library function, and switch
> xfs over to using it. The implementations are equivalent. The nfsacl
> protocol also requires a sort function, so it makes more sense in
> the common code.
>
> Signed-off-by: Andreas Gruenbacher <[EMAIL PROTECTED]>
> Acked-by: Olaf Kirch <[EMAIL PROTECTED]>
>
> Index: linux-2.6.11-rc2/include/linux/kernel.h
> ===
> --- linux-2.6.11-rc2.orig/include/linux/kernel.h
> +++ linux-2.6.11-rc2/include/linux/kernel.h
> @@ -93,6 +93,8 @@ extern int sscanf(const char *, const ch
>   __attribute__ ((format (scanf,2,3)));
>  extern int vsscanf(const char *, const char *, va_list);
>
> +extern void qsort(void *, size_t, size_t, int (*)(const void *,const void 
> *));
> +
>  extern int get_option(char **str, int *pint);
>  extern char *get_options(const char *str, int nints, int *ints);
>  extern unsigned long long memparse(char *ptr, char **retptr);
> Index: linux-2.6.11-rc2/lib/Kconfig
> ===
> --- linux-2.6.11-rc2.orig/lib/Kconfig
> +++ linux-2.6.11-rc2/lib/Kconfig
> @@ -30,6 +30,9 @@ config LIBCRC32C
> require M here.  See Castagnoli93.
> Module will be libcrc32c.
>
> +config QSORT
> + bool "Quick Sort"
> +
>  #
>  # compression support is select'ed if needed
>  #
> Index: linux-2.6.11-rc2/lib/Makefile
> ===
> --- linux-2.6.11-rc2.orig/lib/Makefile
> +++ linux-2.6.11-rc2/lib/Makefile
> @@ -25,6 +25,7 @@ obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
>  obj-$(CONFIG_CRC32)  += crc32.o
>  obj-$(CONFIG_LIBCRC32C)  += libcrc32c.o
>  obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
> +obj-$(CONFIG_QSORT)  += qsort.o
>
>  obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
>  obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
> Index: linux-2.6.11-rc2/lib/qsort.c
> ===
> --- /dev/null
> +++ linux-2.6.11-rc2/lib/qsort.c
> @@ -0,0 +1,249 @@
> +/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +   Written by Douglas C. Schmidt ([EMAIL PROTECTED]).
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, write to the Free
> +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
> +   02111-1307 USA.  */
> +
> +/* If you consider tuning this algorithm, you should consult first:
> +   Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
> +   Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993.  */
> +
> +# include 
> +# include 
> +# include 
> +
> +MODULE_LICENSE("GPL");
> +
> +/* Byte-wise swap two items of size SIZE. */
> +#define SWAP(a, b, size)   \
> +  do   \
> +{
>   \
> +  register size_t __size = (size);   
>   \
> +  register char *__a = (a), *__b = (b);\
> +  do   \
> + { \
> +   char __tmp = *__a;  \
> +   *__a++ = *__b; 

Re: [patch 1/13] Qsort

2005-01-22 Thread vlobanov
Hi,

I was just reading over the patch, and had a quick question/comment upon
the SWAP macro defined below. I think it's possible to do a tiny bit
better (better, of course, being subjective), as follows:

#define SWAP(a, b, size)\
do {\
register size_t __size = (size);\
register char * __a = (a), * __b = (b); \
do {\
*__a ^= *__b;   \
*__b ^= *__a;   \
*__a ^= *__b;   \
__a++;  \
__b++;  \
} while ((--__size)  0);   \
} while (0)

What do you think? :)

-Vadim Lobanov

On Sat, 22 Jan 2005, Andreas Gruenbacher wrote:

 Add a quicksort from glibc as a kernel library function, and switch
 xfs over to using it. The implementations are equivalent. The nfsacl
 protocol also requires a sort function, so it makes more sense in
 the common code.

 Signed-off-by: Andreas Gruenbacher [EMAIL PROTECTED]
 Acked-by: Olaf Kirch [EMAIL PROTECTED]

 Index: linux-2.6.11-rc2/include/linux/kernel.h
 ===
 --- linux-2.6.11-rc2.orig/include/linux/kernel.h
 +++ linux-2.6.11-rc2/include/linux/kernel.h
 @@ -93,6 +93,8 @@ extern int sscanf(const char *, const ch
   __attribute__ ((format (scanf,2,3)));
  extern int vsscanf(const char *, const char *, va_list);

 +extern void qsort(void *, size_t, size_t, int (*)(const void *,const void 
 *));
 +
  extern int get_option(char **str, int *pint);
  extern char *get_options(const char *str, int nints, int *ints);
  extern unsigned long long memparse(char *ptr, char **retptr);
 Index: linux-2.6.11-rc2/lib/Kconfig
 ===
 --- linux-2.6.11-rc2.orig/lib/Kconfig
 +++ linux-2.6.11-rc2/lib/Kconfig
 @@ -30,6 +30,9 @@ config LIBCRC32C
 require M here.  See Castagnoli93.
 Module will be libcrc32c.

 +config QSORT
 + bool Quick Sort
 +
  #
  # compression support is select'ed if needed
  #
 Index: linux-2.6.11-rc2/lib/Makefile
 ===
 --- linux-2.6.11-rc2.orig/lib/Makefile
 +++ linux-2.6.11-rc2/lib/Makefile
 @@ -25,6 +25,7 @@ obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
  obj-$(CONFIG_CRC32)  += crc32.o
  obj-$(CONFIG_LIBCRC32C)  += libcrc32c.o
  obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
 +obj-$(CONFIG_QSORT)  += qsort.o

  obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
  obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
 Index: linux-2.6.11-rc2/lib/qsort.c
 ===
 --- /dev/null
 +++ linux-2.6.11-rc2/lib/qsort.c
 @@ -0,0 +1,249 @@
 +/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
 +   This file is part of the GNU C Library.
 +   Written by Douglas C. Schmidt ([EMAIL PROTECTED]).
 +
 +   The GNU C Library is free software; you can redistribute it and/or
 +   modify it under the terms of the GNU Lesser General Public
 +   License as published by the Free Software Foundation; either
 +   version 2.1 of the License, or (at your option) any later version.
 +
 +   The GNU C Library is distributed in the hope that it will be useful,
 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 +   Lesser General Public License for more details.
 +
 +   You should have received a copy of the GNU Lesser General Public
 +   License along with the GNU C Library; if not, write to the Free
 +   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 +   02111-1307 USA.  */
 +
 +/* If you consider tuning this algorithm, you should consult first:
 +   Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
 +   Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993.  */
 +
 +# include linux/module.h
 +# include linux/slab.h
 +# include linux/string.h
 +
 +MODULE_LICENSE(GPL);
 +
 +/* Byte-wise swap two items of size SIZE. */
 +#define SWAP(a, b, size)   \
 +  do   \
 +{
   \
 +  register size_t __size = (size);   
   \
 +  register char *__a = (a), *__b = (b);\
 +  do   \
 + { \
 +   char __tmp = *__a;  \
 +   *__a++ = *__b;  \
 +   *__b++ = __tmp;

Re: [patch 1/13] Qsort

2005-01-22 Thread Andreas Gruenbacher
On Sat, 2005-01-22 at 23:06, Arjan van de Ven wrote:
 since you took the glibc one.. the glibc authors have repeatedly asked
 if glibc code that goes into the kernel will be export_symbol_gpl only
 due to their view of the gpl and lgpl

Sure, no big deal. We could equally well take the xfs one instead.

Cheers,
-- 
Andreas Gruenbacher [EMAIL PROTECTED]
SUSE Labs, SUSE LINUX GMBH

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sat, Jan 22, 2005 at 09:34:01PM +0100, Andreas Gruenbacher wrote:
 Add a quicksort from glibc as a kernel library function, and switch
 xfs over to using it. The implementations are equivalent. The nfsacl
 protocol also requires a sort function, so it makes more sense in
 the common code.

Please update this to kernel formatting standards and try to modernize
it a bit.

 +/* Byte-wise swap two items of size SIZE. */
 +#define SWAP(a, b, size)   \
 +  do   \
 +{
   \
 +  register size_t __size = (size);   
   \
 +  register char *__a = (a), *__b = (b);\
 +  do   \
 + { \
 +   char __tmp = *__a;  \
 +   *__a++ = *__b;  \
 +   *__b++ = __tmp; \
 + } while (--__size  0);   \
 +} while (0)

Inline, please? Register keyword?!

 +typedef struct
 +  {
 +char *lo;
 +char *hi;
 +  } stack_node;

void *, please

 +
 +/* The next 5 #defines implement a very fast in-line stack abstraction. */
 +/* The stack needs log (total_elements) entries (we could even subtract
 +   log(MAX_THRESH)).  Since total_elements has type size_t, we get as
 +   upper bound for log (total_elements):
 +   bits per byte (CHAR_BIT) * sizeof(size_t).  */
 +#define CHAR_BIT 8
 +#define STACK_SIZE   (CHAR_BIT * sizeof(size_t))

So the stack is going to be either 256 or 1024 bytes. Seems like we
ought to kmalloc it.

 +#define PUSH(low, high)  ((void) ((top-lo = (low)), (top-hi = (high)), 
 ++top))
 +#define  POP(low, high)  ((void) (--top, (low = top-lo), (high = 
 top-hi)))
 +#define  STACK_NOT_EMPTY (stack  top)

There's only one usage of POP, one of STACK_NOT_EMPTY and two of PUSH
that can trivially be made one. Please kill these macros.

 +   3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
 +  insertion sort to order the MAX_THRESH items within each partition.
 +  This is a big win, since insertion sort is faster for small, mostly
 +  sorted array segments.

This observation may be dated, instruction cache issues may dominate now.

 +   char *mid = lo + size * ((hi - lo) / size  1);

Get rid of all this char* stuff, please. It makes for lots of ugly and
unnecessary casting.

 +   if ((*cmp) ((void *) mid, (void *) lo)  0)
 + SWAP (mid, lo, size);

cmp(mid, lo)

 +   if ((*cmp) ((void *) hi, (void *) mid)  0)
 + SWAP (mid, hi, size);
 +   else
 + goto jump_over;
 +   if ((*cmp) ((void *) mid, (void *) lo)  0)
 + SWAP (mid, lo, size);
 + jump_over:;

?!

 +  /* Once the BASE_PTR array is partially sorted by quicksort the rest
 + is completely sorted using insertion sort, since this is efficient
 + for partitions below MAX_THRESH size. BASE_PTR points to the beginning
 + of the array to sort, and END_PTR points at the very last element in
 + the array (*not* one beyond it!). */
 +
 +  {
 +char *end_ptr = base_ptr[size * (total_elems - 1)];
 +char *tmp_ptr = base_ptr;
 +char *thresh = min(end_ptr, base_ptr + max_thresh);
 +register char *run_ptr;

Move these vars to the top or better yet, split this into two functions.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sat, Jan 22, 2005 at 03:28:14PM -0800, Matt Mackall wrote:
 On Sat, Jan 22, 2005 at 09:34:01PM +0100, Andreas Gruenbacher wrote:
  Add a quicksort from glibc as a kernel library function, and switch
  xfs over to using it. The implementations are equivalent. The nfsacl
  protocol also requires a sort function, so it makes more sense in
  the common code.
 
 Please update this to kernel formatting standards and try to modernize
 it a bit.

I started working on this with an eye to doing some performance
testing of the insertion sort threshold in userspace, but I'm about to
head out for the day. Here's what I've got so far, compiles but
untested. Note the insertion sort at the end really ought to be using
memmove as well.

/* Copyright (C) 1991, 1992, 1996, 1997, 1999 Free Software Foundation, Inc.
   Written by Douglas C. Schmidt ([EMAIL PROTECTED]).

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

/* If you consider tuning this algorithm, you should consult first:
   Engineering a sort function; Jon Bentley and M. Douglas McIlroy;
   Software - Practice and Experience; Vol. 23 (11), 1249-1265, 1993.  */

#include unistd.h
#include stdlib.h

#define min(x,y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (_x == _y);\
_x  _y ? _x : _y; })

/* Byte-wise swap two items of size SIZE. */
#define SWAP(a, b, size)  \
  do  \
{ \
  size_t __size = (size); \
  char *__a = (a), *__b = (b);\
  do  \
{ \
  char __tmp = *__a;  \
  *__a++ = *__b;  \
  *__b++ = __tmp; \
} while (--__size  0);   \
} while (0)

/* Discontinue quicksort algorithm when partition gets below this size.
   This particular magic number was chosen to work best on a Sun 4/260. */
#define MAX_THRESH 4

/* Stack node declarations used to store unfulfilled partition obligations. */
typedef struct {
void *lo;
void *hi;
} stack_node;

/* Order size using quicksort.  This implementation incorporates
   four optimizations discussed in Sedgewick:

   1. Non-recursive, using an explicit stack of pointer that store the
  next array partition to sort.  To save time, this maximum amount
  of space required to store an array of SIZE_MAX is allocated on the
  stack.  Assuming a 32-bit (64 bit) integer for size_t, this needs
  only 32 * sizeof(stack_node) == 256 bytes (for 64 bit: 1024 bytes).
  Pretty cheap, actually.

   2. Chose the pivot element using a median-of-three decision tree.
  This reduces the probability of selecting a bad pivot value and
  eliminates certain extraneous comparisons.

   3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving
  insertion sort to order the MAX_THRESH items within each partition.
  This is a big win, since insertion sort is faster for small, mostly
  sorted array segments.

   4. The larger of the two sub-partitions is always pushed onto the
  stack first, with the algorithm then concentrating on the
  smaller partition.  This *guarantees* no more than log (total_elems)
  stack size is needed (actually O(1) in this case)!  */

void qsort(void *base, size_t num, size_t size,
   int (*cmp) (const void *, const void *))
{
const size_t max_thresh = MAX_THRESH * size;
void *hi, *lo, *mid, *left, *right;
void *end = base + (size * (num - 1));
void *tmp = base;
void *thresh = min(end, base + max_thresh);
void *run, *trav;
stack_node *stack, *top;

if (num == 0)
return;

lo = base;
hi = lo + size * (num - 1);
if (num  MAX_THRESH) {
 

Re: [patch 1/13] Qsort

2005-01-22 Thread Felipe Alfaro Solana
On 22 Jan 2005, at 22:00, vlobanov wrote:
Hi,
I was just reading over the patch, and had a quick question/comment 
upon
the SWAP macro defined below. I think it's possible to do a tiny bit
better (better, of course, being subjective), as follows:

#define SWAP(a, b, size)\
do {\
register size_t __size = (size);\
register char * __a = (a), * __b = (b); \
do {\
*__a ^= *__b;   \
*__b ^= *__a;   \
*__a ^= *__b;   \
__a++;  \
__b++;  \
} while ((--__size)  0);\
} while (0)
What do you think? :)
AFAIK, XOR is quite expensive on IA32 when compared to simple MOV 
operatings. Also, since the original patch uses 3 MOVs to perform the 
swapping, and your version uses 3 XOR operations, I don't see any 
gains.

Am I missing something?
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Andi Kleen
Felipe Alfaro Solana [EMAIL PROTECTED] writes:

 AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
 operatings. Also, since the original patch uses 3 MOVs to perform the
 swapping, and your version uses 3 XOR operations, I don't see any
 gains.

Both are one cycle latency for register-register on all x86 cores
I've looked at. What makes you think differently?

-Andi (who thinks the glibc qsort is vast overkill for kernel purposes
where there are only small data sets and it would be better to use a 
simpler one optimized for code size)

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Jesper Juhl
On Sun, 23 Jan 2005, Andi Kleen wrote:

 Felipe Alfaro Solana [EMAIL PROTECTED] writes:
 
  AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
  operatings. Also, since the original patch uses 3 MOVs to perform the
  swapping, and your version uses 3 XOR operations, I don't see any
  gains.
 
 Both are one cycle latency for register-register on all x86 cores
 I've looked at. What makes you think differently?
 
 -Andi (who thinks the glibc qsort is vast overkill for kernel purposes
 where there are only small data sets and it would be better to use a 
 simpler one optimized for code size)
 
How about a shell sort?  if the data is mostly sorted shell sort beats 
qsort lots of times, and since the data sets are often small in-kernel, 
shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
faster if the data is already completely sorted. Shell sort is certainly 
not the simplest algorithm around, but I think (without having done any 
tests) that it would probably do pretty well for in-kernel use... Then 
again, I've known to be wrong :)


-- 
Jesper Juhl

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sun, Jan 23, 2005 at 03:03:32AM +0100, Felipe Alfaro Solana wrote:
 On 22 Jan 2005, at 22:00, vlobanov wrote:
 
 Hi,
 
 I was just reading over the patch, and had a quick question/comment 
 upon
 the SWAP macro defined below. I think it's possible to do a tiny bit
 better (better, of course, being subjective), as follows:
 
 #define SWAP(a, b, size) \
 do { \
  register size_t __size = (size);\
  register char * __a = (a), * __b = (b); \
  do {\
  *__a ^= *__b;   \
  *__b ^= *__a;   \
  *__a ^= *__b;   \
  __a++;  \
  __b++;  \
  } while ((--__size)  0);   \
 } while (0)
 
 What do you think? :)
 
 AFAIK, XOR is quite expensive on IA32 when compared to simple MOV 
 operatings. Also, since the original patch uses 3 MOVs to perform the 
 swapping, and your version uses 3 XOR operations, I don't see any 
 gains.
 
 Am I missing something?

No temporary variable needed in the xor version. mov and xor are
roughly the same speed, but xor modifies flags.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sun, Jan 23, 2005 at 03:39:34AM +0100, Andi Kleen wrote:
 Felipe Alfaro Solana [EMAIL PROTECTED] writes:
 
  AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
  operatings. Also, since the original patch uses 3 MOVs to perform the
  swapping, and your version uses 3 XOR operations, I don't see any
  gains.
 
 Both are one cycle latency for register-register on all x86 cores
 I've looked at. What makes you think differently?
 
 -Andi (who thinks the glibc qsort is vast overkill for kernel purposes
 where there are only small data sets and it would be better to use a 
 simpler one optimized for code size)

Mostly agreed. Except:

a) the glibc version is not actually all that optimized
b) it's nice that it's not recursive
c) the three-way median selection does help avoid worst-case O(n^2)
behavior, which might potentially be triggerable by users in places
like XFS where this is used

I'll probably whip up a simpler version tomorrow or Monday and do some
size/space benchmarking. I've been meaning to contribute a qsort for
doubly-linked lists I've got lying around as well.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Andi Kleen
 How about a shell sort?  if the data is mostly sorted shell sort beats 
 qsort lots of times, and since the data sets are often small in-kernel, 
 shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
 faster if the data is already completely sorted. Shell sort is certainly 
 not the simplest algorithm around, but I think (without having done any 
 tests) that it would probably do pretty well for in-kernel use... Then 
 again, I've known to be wrong :)

I like shell sort for small data sets too. And I agree it would be 
appropiate for the kernel.

-Andi
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Felipe Alfaro Solana
On 23 Jan 2005, at 03:39, Andi Kleen wrote:
Felipe Alfaro Solana [EMAIL PROTECTED] writes:
AFAIK, XOR is quite expensive on IA32 when compared to simple MOV
operatings. Also, since the original patch uses 3 MOVs to perform the
swapping, and your version uses 3 XOR operations, I don't see any
gains.
Both are one cycle latency for register-register on all x86 cores
I've looked at. What makes you think differently?
I thought XOR was more expensie. Anyways, I still don't see any 
advantage in replacing 3 MOVs with 3 XORs.

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Jesper Juhl
On Sun, 23 Jan 2005, Andi Kleen wrote:

  How about a shell sort?  if the data is mostly sorted shell sort beats 
  qsort lots of times, and since the data sets are often small in-kernel, 
  shell sorts O(n^2) behaviour won't harm it too much, shell sort is also 
  faster if the data is already completely sorted. Shell sort is certainly 
  not the simplest algorithm around, but I think (without having done any 
  tests) that it would probably do pretty well for in-kernel use... Then 
  again, I've known to be wrong :)
 
 I like shell sort for small data sets too. And I agree it would be 
 appropiate for the kernel.
 
Even with large data sets that are mostly unsorted shell sorts performance 
is close to qsort, and there's an optimization that gives it O(n^(3/2)) 
runtime (IIRC), and another nice property is that it's iterative so it 
doesn't eat up stack space (as oposed to qsort which is recursive and eats 
stack like )...
Yeah, I think shell sort would be good for the kernel.


-- 
Jesper Juhl



-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Andreas Gruenbacher
On Sunday 23 January 2005 00:28, Matt Mackall wrote:
 So the stack is going to be either 256 or 1024 bytes. Seems like we
 ought to kmalloc it.

This will do. I didn't check if the +1 is strictly needed.

-  stack_node stack[STACK_SIZE];
+  stack_node stack[fls(size) - fls(MAX_THRESH) + 1];

-- 
Andreas Gruenbacher [EMAIL PROTECTED]
SUSE Labs, SUSE LINUX PRODUCTS GMBH
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Matt Mackall
On Sun, Jan 23, 2005 at 06:08:36AM +0100, Andreas Gruenbacher wrote:
 On Sunday 23 January 2005 00:28, Matt Mackall wrote:
  So the stack is going to be either 256 or 1024 bytes. Seems like we
  ought to kmalloc it.
 
 This will do. I didn't check if the +1 is strictly needed.
 
 -  stack_node stack[STACK_SIZE];
 +  stack_node stack[fls(size) - fls(MAX_THRESH) + 1];

Yes, indeed. Though I think even here, we'd prefer to use kmalloc
because gcc generates suboptimal code for variable-sized stack vars.

-- 
Mathematics is the supreme nostalgia of our time.
-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 1/13] Qsort

2005-01-22 Thread Willy Tarreau
Hi,

On Sun, Jan 23, 2005 at 03:03:32AM +0100, Felipe Alfaro Solana wrote:
 On 22 Jan 2005, at 22:00, vlobanov wrote:
 #define SWAP(a, b, size) \
 do { \
  register size_t __size = (size);\
  register char * __a = (a), * __b = (b); \
  do {\
  *__a ^= *__b;   \
  *__b ^= *__a;   \
  *__a ^= *__b;   \
  __a++;  \
  __b++;  \
  } while ((--__size)  0);   \
 } while (0)
 
 What do you think? :)
 
 AFAIK, XOR is quite expensive on IA32 when compared to simple MOV 
 operatings. Also, since the original patch uses 3 MOVs to perform the 
 swapping, and your version uses 3 XOR operations, I don't see any 
 gains.

It will even be worse because we are accessing memory, and most architectures
will not be able to use a memory reference for both operands of the XOR.
Basically, what will be generated will look like this :

  tmp = *b
  *a ^= tmp
  tmp ^= *a
  *b = tmp
  *a ^= tmp

which is 5 cycles, or 4 if the two last instructions get merged. And there's
3 memory reads + 3 memory writes (assuming that the CPU will be smart enough
to reuse *a without accessing memory at instruction 3).

The move is quite faster :

   tmp1 = *a
   tmp2 = *b
   *a = tmp2
   *b = tmp1

This is 4 cycles on simple CPUs, or even 2 cycles on most of todays CPUs
which can do the first two fetches at once, and the last two writes at once.
And there are only two reads and two writes.

Clearly this one is better.

Regards,
Willy

-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/