[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: vprintf performance
From: |
Bruno Haible |
Subject: |
Re: vprintf performance |
Date: |
Fri, 4 Feb 2011 19:23:33 +0100 |
User-agent: |
KMail/1.9.9 |
Hi Pádraig,
> There was lots of heap interaction going on,
> and by using the attached patch (only illustrative, may leak,
> is not thread safe, ...) to cache the PRINTF_PARSE result
> it increases the throughput to 5.8MB/s
Adding a global cache like this is hairy. Maybe we could get a
speedup by letting the application allocate and manage a hash
table that is used as a cache...?
Anyway, the immediate need to malloc() should be reduced with this patch.
It trades malloc() against a bit more room on the stack. With it, I see
a performance improvement in my test case of a factor 1.75. How much does
it help on yours?
2011-02-04 Bruno Haible <address@hidden>
vasnprintf: Reduce use of malloc for small format strings.
* lib/printf-args.h (N_DIRECT_ALLOC_ARGUMENTS): New macro.
(arguments): Add room for the first 7 arguments.
* lib/printf-parse.h (N_DIRECT_ALLOC_DIRECTIVES): New macro.
(char_directives, u8_directives, u16_directives, u32_directives): Add
room for the first 7 directives.
* lib/printf-parse.c: Include <string.h>.
(PRINTF_PARSE): Change memory handling code so that it uses the first
7 preallocated elements in an 'arguments' or 'DIRECTIVES' struct.
* lib/vasnprintf.c (VASNPRINTF): Update memory handling code.
Reported by Pádraig Brady <address@hidden>.
--- lib/printf-args.h.orig Fri Feb 4 19:09:25 2011
+++ lib/printf-args.h Fri Feb 4 17:35:19 2011
@@ -1,5 +1,5 @@
/* Decomposed printf argument list.
- Copyright (C) 1999, 2002-2003, 2006-2007, 2009-2011 Free Software
+ Copyright (C) 1999, 2002-2003, 2006-2007, 2011 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -136,10 +136,14 @@
}
argument;
+/* Number of directly allocated arguments (no malloc() needed). */
+#define N_DIRECT_ALLOC_ARGUMENTS 7
+
typedef struct
{
size_t count;
argument *arg;
+ argument direct_alloc_arg[N_DIRECT_ALLOC_ARGUMENTS];
}
arguments;
--- lib/printf-parse.h.orig Fri Feb 4 19:09:25 2011
+++ lib/printf-parse.h Fri Feb 4 17:36:35 2011
@@ -1,5 +1,5 @@
/* Parse printf format string.
- Copyright (C) 1999, 2002-2003, 2005, 2007, 2009-2011 Free Software
+ Copyright (C) 1999, 2002-2003, 2005, 2007, 2010-2011 Free Software
Foundation, Inc.
This program is free software; you can redistribute it and/or modify
@@ -47,6 +47,9 @@
/* xxx_directive: A parsed directive.
xxx_directives: A parsed format string. */
+/* Number of directly allocated directives (no malloc() needed). */
+#define N_DIRECT_ALLOC_DIRECTIVES 7
+
/* A parsed directive. */
typedef struct
{
@@ -71,6 +74,7 @@
char_directive *dir;
size_t max_width_length;
size_t max_precision_length;
+ char_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES];
}
char_directives;
@@ -100,6 +104,7 @@
u8_directive *dir;
size_t max_width_length;
size_t max_precision_length;
+ u8_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES];
}
u8_directives;
@@ -127,6 +132,7 @@
u16_directive *dir;
size_t max_width_length;
size_t max_precision_length;
+ u16_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES];
}
u16_directives;
@@ -154,6 +160,7 @@
u32_directive *dir;
size_t max_width_length;
size_t max_precision_length;
+ u32_directive direct_alloc_dir[N_DIRECT_ALLOC_DIRECTIVES];
}
u32_directives;
--- lib/printf-parse.c.orig Fri Feb 4 19:09:25 2011
+++ lib/printf-parse.c Fri Feb 4 17:24:05 2011
@@ -63,6 +63,9 @@
/* malloc(), realloc(), free(). */
#include <stdlib.h>
+/* memcpy(). */
+#include <string.h>
+
/* errno. */
#include <errno.h>
@@ -80,23 +83,20 @@
int
PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
{
- const CHAR_T *cp = format; /* pointer into format */
+ const CHAR_T *cp = format; /* pointer into format */
size_t arg_posn = 0; /* number of regular arguments consumed */
- size_t d_allocated; /* allocated elements of d->dir */
- size_t a_allocated; /* allocated elements of a->arg */
+ size_t d_allocated; /* allocated elements of d->dir */
+ size_t a_allocated; /* allocated elements of a->arg */
size_t max_width_length = 0;
size_t max_precision_length = 0;
d->count = 0;
- d_allocated = 1;
- d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE));
- if (d->dir == NULL)
- /* Out of memory. */
- goto out_of_memory_1;
+ d_allocated = N_DIRECT_ALLOC_DIRECTIVES;
+ d->dir = d->direct_alloc_dir;
a->count = 0;
- a_allocated = 0;
- a->arg = NULL;
+ a_allocated = N_DIRECT_ALLOC_ARGUMENTS;
+ a->arg = a->direct_alloc_arg;
#define REGISTER_ARG(_index_,_type_) \
{ \
@@ -113,12 +113,14 @@
if (size_overflow_p (memory_size)) \
/* Overflow, would lead to out of memory. */ \
goto out_of_memory; \
- memory = (argument *) (a->arg \
+ memory = (argument *) (a->arg != a->direct_alloc_arg \
? realloc (a->arg, memory_size) \
: malloc (memory_size)); \
if (memory == NULL) \
/* Out of memory. */ \
goto out_of_memory; \
+ if (a->arg == a->direct_alloc_arg) \
+ memcpy (memory, a->arg, a->count * sizeof (argument)); \
a->arg = memory; \
} \
while (a->count <= n) \
@@ -588,10 +590,14 @@
if (size_overflow_p (memory_size))
/* Overflow, would lead to out of memory. */
goto out_of_memory;
- memory = (DIRECTIVE *) realloc (d->dir, memory_size);
+ memory = (DIRECTIVE *) (d->dir != d->direct_alloc_dir
+ ? realloc (d->dir, memory_size)
+ : malloc (memory_size));
if (memory == NULL)
/* Out of memory. */
goto out_of_memory;
+ if (d->dir == d->direct_alloc_dir)
+ memcpy (memory, d->dir, d->count * sizeof (DIRECTIVE));
d->dir = memory;
}
}
@@ -610,19 +616,18 @@
return 0;
error:
- if (a->arg)
+ if (a->arg != a->direct_alloc_arg)
free (a->arg);
- if (d->dir)
+ if (d->dir != d->direct_alloc_dir)
free (d->dir);
errno = EINVAL;
return -1;
out_of_memory:
- if (a->arg)
+ if (a->arg != a->direct_alloc_arg)
free (a->arg);
- if (d->dir)
+ if (d->dir != d->direct_alloc_dir)
free (d->dir);
-out_of_memory_1:
errno = ENOMEM;
return -1;
}
--- lib/vasnprintf.c.orig Fri Feb 4 19:09:25 2011
+++ lib/vasnprintf.c Fri Feb 4 17:23:17 2011
@@ -1753,8 +1753,9 @@
return NULL;
#define CLEANUP() \
- free (d.dir); \
- if (a.arg) \
+ if (d.dir != d.direct_alloc_dir) \
+ free (d.dir); \
+ if (a.arg != a.direct_alloc_arg) \
free (a.arg);
if (PRINTF_FETCHARGS (args, &a) < 0)
--
In memoriam Amadou Diallo <http://en.wikipedia.org/wiki/Amadou_Diallo>