This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
contribution to glibc
- From: "djamel anonymous" <djam8193ah at hotmail dot com>
- To: libc-alpha at sources dot redhat dot com
- Date: Tue, 13 Jun 2006 14:03:34 +0000
- Subject: contribution to glibc
- Bcc:
first i present myself, i am a computer scienc engineer.the reason for this
email is to make two suggestion about the qsort function inside glibc.by
reading the source code of glibc i noted that qsort could easily be made to
use allocate half the size it is currently allocating to do merge sort.the
modification to the file msort.c consists of a few lines.
the the idea came to me by reading the following website:
http://www.inf.fh-flensburg.de/lang/algorithmen/sortieren/merge/mergen.htm
the performance is also increased because less copying is done inside the
function
msort_with_tmp().
the performance could be further inmproved by a simple modification to the
function msort_with_tmp() by reducing the depth of the recursion; by
treating the special case for n==2 in addition to the case n==1. this will
eliminate the overhead of many function calls that do nothing.
i have tested my two suggestions on on different integer vectors and
performance was increased between 8% and 25%.i have enclosed with this email
both the patch and the modified file.
_________________________________________________________________
MSN Hotmail : créez votre adresse e-mail gratuite & à vie !
http://www.msn.fr/newhotmail/Default.asp?Ath=f
39c39,54
< if (n <= 1)
---
> if (n <= 2) {
> if(n<=1)
> return;
> b1=b;
> b2= (char *) b + s;
> if ((*cmp) (b1, b2) > 0) {
> if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0) {
> *((op_t *) t) = *((op_t *) b1);
> *((op_t *) b1) = *((op_t *) b2);
> *((op_t *) b2) = *((op_t *) t);
> } else {
> memcpy (t, b1, s);
> memcpy (b1, b2, s);
> memcpy (b2, t, s);
> };
> };
40a56
> };
46c62
<
---
>
49,50c65,67
<
< tmp = t;
---
> memcpy (t, b, n1 * s);
> b1=t;
> tmp = b;
89d105
< memcpy (b, t, (n - n2) * s);
99c115
< void *buf = __alloca (size);
---
> void *buf = __alloca (size/2);
124c140
< phys_pages /= 4;
---
> phys_pages /= 3;
137c153
< if (size / pagesize > (size_t) phys_pages)
---
> if (size / pagesize) > (size_t) phys_pages)
143c159
< char *tmp = malloc (size);
---
> char *tmp = malloc (size/2);
/* An alternative to qsort, with an identical interface.
This file is part of the GNU C Library.
Copyright (C) 1992,95-97,99,2000,01,02,04 Free Software Foundation, Inc.
Written by Mike Haertel, September 1988.
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. */
#include <alloca.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <memcopy.h>
#include <errno.h>
static void msort_with_tmp (void *b, size_t n, size_t s,
__compar_fn_t cmp, char *t);
static void
msort_with_tmp (void *b, size_t n, size_t s, __compar_fn_t cmp,
char *t)
{
char *tmp;
char *b1, *b2;
size_t n1, n2;
if (n <= 2) {
if(n<=1)
return;
b1=b;
b2= (char *) b + s;
if ((*cmp) (b1, b2) > 0) {
if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0) {
*((op_t *) t) = *((op_t *) b1);
*((op_t *) b1) = *((op_t *) b2);
*((op_t *) b2) = *((op_t *) t);
} else {
memcpy (t, b1, s);
memcpy (b1, b2, s);
memcpy (b2, t, s);
};
};
return;
};
n1 = n / 2;
n2 = n - n1;
b1 = b;
b2 = (char *) b + (n1 * s);
msort_with_tmp (b1, n1, s, cmp, t);
msort_with_tmp (b2, n2, s, cmp, t);
memcpy (t, b, n1 * s);
b1=t;
tmp = b;
if (s == OPSIZ && (b1 - (char *) 0) % OPSIZ == 0)
/* We are operating on aligned words. Use direct word stores. */
while (n1 > 0 && n2 > 0)
{
if ((*cmp) (b1, b2) <= 0)
{
--n1;
*((op_t *) tmp) = *((op_t *) b1);
tmp += sizeof (op_t);
b1 += sizeof (op_t);
}
else
{
--n2;
*((op_t *) tmp) = *((op_t *) b2);
tmp += sizeof (op_t);
b2 += sizeof (op_t);
}
}
else
while (n1 > 0 && n2 > 0)
{
if ((*cmp) (b1, b2) <= 0)
{
tmp = (char *) __mempcpy (tmp, b1, s);
b1 += s;
--n1;
}
else
{
tmp = (char *) __mempcpy (tmp, b2, s);
b2 += s;
--n2;
}
}
if (n1 > 0)
memcpy (tmp, b1, n1 * s);
}
void
qsort (void *b, size_t n, size_t s, __compar_fn_t cmp)
{
const size_t size = n * s;
if (size < 1024)
{
void *buf = __alloca (size/2);
/* The temporary array is small, so put it on the stack. */
msort_with_tmp (b, n, s, cmp, buf);
}
else
{
/* We should avoid allocating too much memory since this might
have to be backed up by swap space. */
static long int phys_pages;
static int pagesize;
if (phys_pages == 0)
{
phys_pages = __sysconf (_SC_PHYS_PAGES);
if (phys_pages == -1)
/* Error while determining the memory size. So let's
assume there is enough memory. Otherwise the
implementer should provide a complete implementation of
the `sysconf' function. */
phys_pages = (long int) (~0ul >> 1);
/* The following determines that we will never use more than
a quarter of the physical memory. */
phys_pages /= 3;
pagesize = __sysconf (_SC_PAGESIZE);
}
/* Just a comment here. We cannot compute
phys_pages * pagesize
and compare the needed amount of memory against this value.
The problem is that some systems might have more physical
memory then can be represented with a `size_t' value (when
measured in bytes. */
/* If the memory requirements are too high don't allocate memory. */
if (size / pagesize) > (size_t) phys_pages)
_quicksort (b, n, s, cmp);
else
{
/* It's somewhat large, so malloc it. */
int save = errno;
char *tmp = malloc (size/2);
if (tmp == NULL)
{
/* Couldn't get space, so use the slower algorithm
that doesn't need a temporary array. */
__set_errno (save);
_quicksort (b, n, s, cmp);
}
else
{
__set_errno (save);
msort_with_tmp (b, n, s, cmp, tmp);
free (tmp);
}
}
}
}
libc_hidden_def (qsort)